diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 255a7f238b..e9d7c9e8aa 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -2692,7 +2692,8 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi, bgp_fs_nlri_get_string((unsigned char *)fs->prefix.ptr, fs->prefix.prefixlen, return_string, - NLRI_STRING_FORMAT_DEBUG, NULL); + NLRI_STRING_FORMAT_DEBUG, NULL, + family2afi(fs->prefix.family)); snprintf(str, size, "FS %s Match{%s}", afi2str(afi), return_string); } else diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c index 17c41636de..03fc1f52c3 100644 --- a/bgpd/bgp_flowspec.c +++ b/bgpd/bgp_flowspec.c @@ -33,7 +33,8 @@ #include "bgpd/bgp_debug.h" #include "bgpd/bgp_errors.h" -static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len) +static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len, + afi_t afi) { uint32_t offset = 0; int type; @@ -48,7 +49,8 @@ static int bgp_fs_nlri_validate(uint8_t *nlri_content, uint32_t len) ret = bgp_flowspec_ip_address( BGP_FLOWSPEC_VALIDATE_ONLY, nlri_content + offset, - len - offset, NULL, &error); + len - offset, NULL, &error, + afi); break; case FLOWSPEC_IP_PROTOCOL: case FLOWSPEC_PORT: @@ -103,11 +105,6 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, afi = packet->afi; safi = packet->safi; - if (afi == AFI_IP6) { - flog_err(EC_LIB_DEVELOPMENT, "BGP flowspec IPv6 not supported"); - return BGP_NLRI_PARSE_ERROR_FLOWSPEC_IPV6_NOT_SUPPORTED; - } - if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT_EXTENDED) { flog_err(EC_BGP_FLOWSPEC_PACKET, "BGP flowspec nlri length maximum reached (%u)", @@ -137,7 +134,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, psize); return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW; } - if (bgp_fs_nlri_validate(pnt, psize) < 0) { + if (bgp_fs_nlri_validate(pnt, psize, afi) < 0) { flog_err( EC_BGP_FLOWSPEC_PACKET, "Bad flowspec format or NLRI options not supported"); @@ -147,6 +144,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, p.prefixlen = 0; /* Flowspec encoding is in bytes */ p.u.prefix_flowspec.prefixlen = psize; + p.u.prefix_flowspec.family = afi2family(afi); temp = XCALLOC(MTYPE_TMP, psize); memcpy(temp, pnt, psize); p.u.prefix_flowspec.ptr = (uintptr_t) temp; @@ -161,7 +159,8 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, p.u.prefix_flowspec.ptr, p.u.prefix_flowspec.prefixlen, return_string, - NLRI_STRING_FORMAT_MIN, NULL); + NLRI_STRING_FORMAT_MIN, NULL, + afi); snprintf(ec_string, sizeof(ec_string), "EC{none}"); if (attr && attr->ecommunity) { diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h index 94c571f2fc..d1a59a672d 100644 --- a/bgpd/bgp_flowspec.h +++ b/bgpd/bgp_flowspec.h @@ -41,7 +41,8 @@ extern int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi, extern void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len, char *return_string, int format, - json_object *json_path); + json_object *json_path, + afi_t afi); extern void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index 764d2f87ae..0e879e8168 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -76,6 +76,7 @@ static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len, return ret; } + bool bgp_flowspec_contains_prefix(const struct prefix *pfs, struct prefix *input, int prefix_check) { @@ -84,6 +85,7 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs, int ret = 0, error = 0; uint8_t *nlri_content = (uint8_t *)pfs->u.prefix_flowspec.ptr; size_t len = pfs->u.prefix_flowspec.prefixlen; + afi_t afi = family2afi(pfs->u.prefix_flowspec.family); struct prefix compare; error = 0; @@ -98,7 +100,8 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs, BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE, nlri_content+offset, len - offset, - &compare, &error); + &compare, &error, + afi); if (ret <= 0) break; if (prefix_check && @@ -158,7 +161,8 @@ bool bgp_flowspec_contains_prefix(const struct prefix *pfs, int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type, uint8_t *nlri_ptr, uint32_t max_len, - void *result, int *error) + void *result, int *error, + afi_t afi) { char *display = (char *)result; /* for return_string */ struct prefix *prefix = (struct prefix *)result; @@ -417,7 +421,8 @@ int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type, } int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, - struct bgp_pbr_entry_main *bpem) + struct bgp_pbr_entry_main *bpem, + afi_t afi) { int offset = 0, error = 0; struct prefix *prefix; @@ -444,7 +449,8 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE, nlri_content + offset, len - offset, - prefix, &error); + prefix, &error, + afi); if (error < 0) flog_err(EC_BGP_FLOWSPEC_PACKET, "%s: flowspec_ip_address error %d", @@ -599,7 +605,7 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, /* return 1 if FS entry invalid or no NH IP */ bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi, - struct prefix *p) + struct prefix *p, afi_t afi) { struct bgp_pbr_entry_main api; int i; @@ -615,9 +621,15 @@ bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi, api_action = &api.actions[i]; if (api_action->action != ACTION_REDIRECT_IP) continue; - p->family = AF_INET; - p->prefixlen = IPV4_MAX_BITLEN; - p->u.prefix4 = api_action->u.zr.redirect_ip_v4; + p->family = afi2family(afi); + if (afi == AFI_IP) { + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4 = api_action->u.zr.redirect_ip_v4; + } else { + p->prefixlen = IPV6_MAX_BITLEN; + memcpy(&p->u.prefix6, &api_action->u.zr.redirect_ip_v6, + sizeof(struct in6_addr)); + } return false; } return true; diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h index 0e78c7a53c..26d919d7d2 100644 --- a/bgpd/bgp_flowspec_util.h +++ b/bgpd/bgp_flowspec_util.h @@ -39,7 +39,8 @@ extern int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type, extern int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type, uint8_t *nlri_ptr, uint32_t max_len, - void *result, int *error); + void *result, int *error, + afi_t afi); extern int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type, uint8_t *nlri_ptr, @@ -48,13 +49,14 @@ extern int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type, struct bgp_pbr_entry_main; extern int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, - struct bgp_pbr_entry_main *bpem); + struct bgp_pbr_entry_main *bpem, + afi_t afi); extern bool bgp_flowspec_contains_prefix(const struct prefix *pfs, struct prefix *input, int prefix_check); extern bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi, - struct prefix *nh); + struct prefix *nh, afi_t afi); #endif /* _FRR_BGP_FLOWSPEC_UTIL_H */ diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index e309fa948e..5703d86be3 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -93,7 +93,8 @@ static const struct message bgp_flowspec_display_min[] = { */ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len, char *return_string, int format, - json_object *json_path) + json_object *json_path, + afi_t afi) { uint32_t offset = 0; int type; @@ -127,7 +128,8 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len, type_util, nlri_content+offset, len - offset, - local_string, &error); + local_string, &error, + afi); if (ret <= 0) break; if (json_path) { @@ -263,7 +265,12 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, json_object *json_ecom_path = NULL; json_object *json_time_path = NULL; char timebuf[BGP_UPTIME_LEN]; + struct bgp_dest *dest = NULL; + if (path) + dest = path->net; + if (dest) + bgp_dest_get_bgp_table_info(dest); /* Print prefix */ if (p != NULL) { if (p->family != AF_FLOWSPEC) @@ -282,7 +289,9 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, p->u.prefix_flowspec.prefixlen, return_string, display, - json_nlri_path); + json_nlri_path, + family2afi(p->u.prefix_flowspec + .family)); if (display == NLRI_STRING_FORMAT_LARGE) vty_out(vty, "%s", return_string); else if (display == NLRI_STRING_FORMAT_DEBUG) diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index a74b5f91ac..a780fb7347 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -544,7 +544,7 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p) if (!pi->peer) return -1; return bgp_flowspec_get_first_nh(pi->peer->bgp, - pi, p); + pi, p, afi); } memset(p, 0, sizeof(struct prefix)); switch (afi) { diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 7c3e8cd70e..38b1ae4da9 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -668,6 +668,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) } /* return -1 if build or validation failed */ + int bgp_pbr_build_and_validate_entry(const struct prefix *p, struct bgp_path_info *path, struct bgp_pbr_entry_main *api) @@ -679,13 +680,13 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p, struct bgp_pbr_entry_action *api_action; 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; bool discard_action_found = false; + afi_t afi = family2afi(p->u.prefix_flowspec.family); /* extract match from flowspec entries */ ret = bgp_flowspec_match_rules_fill((uint8_t *)p->u.prefix_flowspec.ptr, - p->u.prefix_flowspec.prefixlen, api); + p->u.prefix_flowspec.prefixlen, api, afi); if (ret < 0) return -1; /* extract actiosn from flowspec ecom list */ @@ -2598,8 +2599,6 @@ void bgp_pbr_update_entry(struct bgp *bgp, const struct prefix *p, { struct bgp_pbr_entry_main api; - if (afi == AFI_IP6) - return; /* IPv6 not supported */ if (safi != SAFI_FLOWSPEC) return; /* not supported */ /* Make Zebra API structure. */ diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index 043853a157..52bb3b5410 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -79,6 +79,7 @@ struct bgp_pbr_entry_action { vrf_id_t redirect_vrf; struct _pbr_redirect_ip { struct in_addr redirect_ip_v4; + struct in6_addr redirect_ip_v6; uint8_t duplicate; } zr; uint8_t marking_dscp; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 3a627b4486..eefff4bef8 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -10008,11 +10008,13 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, if (dest_p->family == AF_FLOWSPEC) { char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX]; + bgp_fs_nlri_get_string( (unsigned char *) dest_p->u.prefix_flowspec.ptr, dest_p->u.prefix_flowspec.prefixlen, - retstr, NLRI_STRING_FORMAT_MIN, NULL); + retstr, NLRI_STRING_FORMAT_MIN, NULL, + family2afi(dest_p->u.prefix_flowspec.family)); if (first) vty_out(vty, "\"%s/%d\": ", retstr, dest_p->u.prefix_flowspec diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 97153cfb72..5644daba62 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -594,10 +594,14 @@ route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist, memset(&api, 0, sizeof(api)); + if (family2afi(p->u.prefix_flowspec.family) != afi) + return RMAP_NOMATCH; + /* extract match from flowspec entries */ ret = bgp_flowspec_match_rules_fill( (uint8_t *)p->u.prefix_flowspec.ptr, - p->u.prefix_flowspec.prefixlen, &api); + p->u.prefix_flowspec.prefixlen, &api, + afi); if (ret < 0) return RMAP_NOMATCH; if (api.match_bitmask & PREFIX_DST_PRESENT ||