summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_ecommunity.c20
-rw-r--r--bgpd/bgp_ecommunity.h4
-rw-r--r--bgpd/bgp_flowspec_vty.c3
-rw-r--r--bgpd/bgp_pbr.c54
4 files changed, 73 insertions, 8 deletions
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 802916418..ed0900a72 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -688,9 +688,23 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
/* Low-order octet of type. */
sub_type = *pnt++;
if (sub_type != ECOMMUNITY_ROUTE_TARGET
- && sub_type != ECOMMUNITY_SITE_ORIGIN)
- unk_ecom = 1;
- else
+ && sub_type != ECOMMUNITY_SITE_ORIGIN) {
+ if (sub_type ==
+ ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 &&
+ type == ECOMMUNITY_ENCODE_IP) {
+ struct in_addr *ipv4 =
+ (struct in_addr *)pnt;
+ char ipv4str[INET_ADDRSTRLEN];
+
+ inet_ntop(AF_INET, ipv4,
+ ipv4str,
+ INET_ADDRSTRLEN);
+ len = sprintf(str_buf + str_pnt,
+ "NH:%s:%d",
+ ipv4str, pnt[5]);
+ } else
+ unk_ecom = 1;
+ } else
len = ecommunity_rt_soo_str(str_buf + str_pnt,
pnt, type, sub_type,
format);
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index d43403ed8..519991da5 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -41,6 +41,10 @@
#define ECOMMUNITY_REDIRECT_VRF 0x08
#define ECOMMUNITY_TRAFFIC_MARKING 0x09
#define ECOMMUNITY_REDIRECT_IP_NH 0x00
+/* from IANA: bgp-extended-communities/bgp-extended-communities.xhtml
+ * 0x0c Flow-spec Redirect to IPv4 - draft-ietf-idr-flowspec-redirect
+ */
+#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 0x0c
/* Low-order octet of the Extended Communities type field for EVPN types */
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index 4fb055bcc..9c230d112 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -315,7 +315,8 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
}
if (attr->nexthop.s_addr != 0 &&
display == NLRI_STRING_FORMAT_LARGE)
- vty_out(vty, "\tNH %-16s\n", inet_ntoa(attr->nexthop));
+ vty_out(vty, "\tNLRI NH %-16s\n",
+ inet_ntoa(attr->nexthop));
XFREE(MTYPE_ECOMMUNITY_STR, s);
}
peer_uptime(path->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL);
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index 4e050df3e..f0a0e615e 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -638,6 +638,7 @@ static int bgp_pbr_build_and_validate_entry(struct prefix *p,
struct prefix *src = NULL, *dst = NULL;
int valid_prefix = 0;
afi_t afi = AFI_IP;
+ struct bgp_pbr_entry_action *api_action_redirect_ip = NULL;
/* extract match from flowspec entries */
ret = bgp_flowspec_match_rules_fill((uint8_t *)p->u.prefix_flowspec.ptr,
@@ -688,10 +689,55 @@ static int bgp_pbr_build_and_validate_entry(struct prefix *p,
(char)ECOMMUNITY_ENCODE_REDIRECT_IP_NH) &&
(ecom_eval->val[1] ==
(char)ECOMMUNITY_REDIRECT_IP_NH)) {
- api_action->action = ACTION_REDIRECT_IP;
- api_action->u.zr.redirect_ip_v4.s_addr =
- path->attr->nexthop.s_addr;
- api_action->u.zr.duplicate = ecom_eval->val[7];
+ /* in case the 2 ecom present,
+ * do not overwrite
+ * draft-ietf-idr-flowspec-redirect
+ */
+ if (api_action_redirect_ip) {
+ if (api_action_redirect_ip->u
+ .zr.redirect_ip_v4.s_addr)
+ continue;
+ if (!path->attr->nexthop.s_addr)
+ continue;
+ api_action_redirect_ip->u
+ .zr.redirect_ip_v4.s_addr =
+ path->attr->nexthop.s_addr;
+ api_action_redirect_ip->u.zr.duplicate
+ = ecom_eval->val[7];
+ continue;
+ } else {
+ api_action->action = ACTION_REDIRECT_IP;
+ api_action->u.zr.redirect_ip_v4.s_addr =
+ path->attr->nexthop.s_addr;
+ api_action->u.zr.duplicate =
+ ecom_eval->val[7];
+ api_action_redirect_ip = api_action;
+ }
+ } else if ((ecom_eval->val[0] ==
+ (char)ECOMMUNITY_ENCODE_IP) &&
+ (ecom_eval->val[1] ==
+ (char)ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4)) {
+ /* in case the 2 ecom present,
+ * overwrite simpson draft
+ * update redirect ip fields
+ */
+ if (api_action_redirect_ip) {
+ memcpy(&(api_action_redirect_ip->u
+ .zr.redirect_ip_v4.s_addr),
+ (ecom_eval->val+2), 4);
+ api_action_redirect_ip->u
+ .zr.duplicate =
+ ecom_eval->val[7];
+ continue;
+ } else {
+ api_action->action = ACTION_REDIRECT_IP;
+ memcpy(&(api_action->u
+ .zr.redirect_ip_v4.s_addr),
+ (ecom_eval->val+2), 4);
+ api_action->u.zr.duplicate =
+ ecom_eval->val[7];
+ api_action_redirect_ip = api_action;
+ }
} else {
if (ecom_eval->val[0] !=
(char)ECOMMUNITY_ENCODE_TRANS_EXP)