diff options
-rw-r--r-- | bgpd/bgp_ecommunity.c | 20 | ||||
-rw-r--r-- | bgpd/bgp_ecommunity.h | 4 | ||||
-rw-r--r-- | bgpd/bgp_flowspec_vty.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_pbr.c | 54 |
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) |