diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index f1c953f21d..eeb0ac5c6a 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -691,6 +691,8 @@ unsigned int attrhash_key_make(const void *p) key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key); MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance); MIX(attr->rmap_table_id); + MIX(attr->nh_type); + MIX(attr->bh_type); return key; } @@ -747,7 +749,9 @@ bool attrhash_cmp(const void *p1, const void *p2) && attr1->distance == attr2->distance && srv6_l3vpn_same(attr1->srv6_l3vpn, attr2->srv6_l3vpn) && srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) - && attr1->srte_color == attr2->srte_color) + && attr1->srte_color == attr2->srte_color + && attr1->nh_type == attr2->nh_type + && attr1->bh_type == attr2->bh_type) return true; } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index a583581030..6c49cf509f 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -307,6 +307,12 @@ struct attr { /* EVPN DF preference and algorithm for DF election on local ESs */ uint16_t df_pref; uint8_t df_alg; + + /* Nexthop type */ + enum nexthop_types_t nh_type; + + /* If NEXTHOP_TYPE_BLACKHOLE, then blackhole type */ + enum blackhole_type bh_type; }; /* rmap_change_flags definition */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index b164d710a5..db0ee58e72 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8066,8 +8066,9 @@ DEFPY(aggregate_addressv6, aggregate_addressv6_cmd, void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, const union g_addr *nexthop, ifindex_t ifindex, enum nexthop_types_t nhtype, uint8_t distance, - uint32_t metric, uint8_t type, - unsigned short instance, route_tag_t tag) + enum blackhole_type bhtype, uint32_t metric, + uint8_t type, unsigned short instance, + route_tag_t tag) { struct bgp_path_info *new; struct bgp_path_info *bpi; @@ -8109,8 +8110,10 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; break; } + attr.bh_type = bhtype; break; } + attr.nh_type = nhtype; attr.nh_ifindex = ifindex; attr.med = metric; diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 75da2723e6..d052a3f408 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -642,8 +642,9 @@ extern bool bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int); extern void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, const union g_addr *nexthop, ifindex_t ifindex, enum nexthop_types_t nhtype, uint8_t distance, - uint32_t metric, uint8_t type, - unsigned short instance, route_tag_t tag); + enum blackhole_type bhtype, uint32_t metric, + uint8_t type, unsigned short instance, + route_tag_t tag); extern void bgp_redistribute_delete(struct bgp *, struct prefix *, uint8_t, unsigned short); extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, unsigned short); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 5ef49e5108..b0d0c844f3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -472,8 +472,9 @@ static int bgp_interface_vrf_update(ZAPI_CALLBACK_ARGS) static int zebra_read_route(ZAPI_CALLBACK_ARGS) { enum nexthop_types_t nhtype; + enum blackhole_type bhtype = BLACKHOLE_UNSPEC; struct zapi_route api; - union g_addr nexthop; + union g_addr nexthop = {}; ifindex_t ifindex; int add, i; struct bgp *bgp; @@ -494,10 +495,16 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS) && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6)) return 0; - nexthop = api.nexthops[0].gate; ifindex = api.nexthops[0].ifindex; nhtype = api.nexthops[0].type; + /* api_nh structure has union of gate and bh_type */ + if (nhtype == NEXTHOP_TYPE_BLACKHOLE) { + /* bh_type is only applicable if NEXTHOP_TYPE_BLACKHOLE*/ + bhtype = api.nexthops[0].bh_type; + } else + nexthop = api.nexthops[0].gate; + add = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD); if (add) { /* @@ -517,8 +524,8 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS) /* Now perform the add/update. */ bgp_redistribute_add(bgp, &api.prefix, &nexthop, ifindex, - nhtype, api.distance, api.metric, api.type, - api.instance, api.tag); + nhtype, bhtype, api.distance, api.metric, + api.type, api.instance, api.tag); } else { bgp_redistribute_delete(bgp, &api.prefix, api.type, api.instance); @@ -1076,8 +1083,10 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, * a VRF (which are programmed as onlink on l3-vni SVI) as well as * connected routes leaked into a VRF. */ - if (is_evpn) { - + if (attr->nh_type == NEXTHOP_TYPE_BLACKHOLE) { + api_nh->type = attr->nh_type; + api_nh->bh_type = attr->bh_type; + } else if (is_evpn) { /* * If the nexthop is EVPN overlay index gateway IP, * treat the nexthop as NEXTHOP_TYPE_IPV4 @@ -1090,8 +1099,7 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); api_nh->ifindex = nh_bgp->l3vni_svi_ifindex; } - } else if (nh_othervrf && - api_nh->gate.ipv4.s_addr == INADDR_ANY) { + } else if (nh_othervrf && api_nh->gate.ipv4.s_addr == INADDR_ANY) { api_nh->type = NEXTHOP_TYPE_IFINDEX; api_nh->ifindex = attr->nh_ifindex; } else @@ -1113,8 +1121,10 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, attr = pi->attr; api_nh->vrf_id = nh_bgp->vrf_id; - if (is_evpn) { - + if (attr->nh_type == NEXTHOP_TYPE_BLACKHOLE) { + api_nh->type = attr->nh_type; + api_nh->bh_type = attr->bh_type; + } else if (is_evpn) { /* * If the nexthop is EVPN overlay index gateway IP, * treat the nexthop as NEXTHOP_TYPE_IPV4 @@ -1169,7 +1179,8 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, api_nh->ifindex = 0; } } - if (nexthop) + /* api_nh structure has union of gate and bh_type */ + if (nexthop && api_nh->type != NEXTHOP_TYPE_BLACKHOLE) api_nh->gate.ipv6 = *nexthop; return true; diff --git a/lib/nexthop.c b/lib/nexthop.c index 23e3a2b733..98409c76c5 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -519,12 +519,13 @@ struct nexthop *nexthop_from_ipv6_ifindex(const struct in6_addr *ipv6, return nexthop; } -struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type) +struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type, + vrf_id_t nh_vrf_id) { struct nexthop *nexthop; nexthop = nexthop_new(); - nexthop->vrf_id = VRF_DEFAULT; + nexthop->vrf_id = nh_vrf_id; nexthop->type = NEXTHOP_TYPE_BLACKHOLE; nexthop->bh_type = bh_type; diff --git a/lib/nexthop.h b/lib/nexthop.h index dd65509aec..320b46315e 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -182,7 +182,8 @@ struct nexthop *nexthop_from_ipv6(const struct in6_addr *ipv6, vrf_id_t vrf_id); struct nexthop *nexthop_from_ipv6_ifindex(const struct in6_addr *ipv6, ifindex_t ifindex, vrf_id_t vrf_id); -struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type); +struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type, + vrf_id_t nh_vrf_id); /* * Hash a nexthop. Suitable for use with hash tables. diff --git a/tests/lib/test_nexthop.c b/tests/lib/test_nexthop.c index 659d207b4e..7cf687dffe 100644 --- a/tests/lib/test_nexthop.c +++ b/tests/lib/test_nexthop.c @@ -112,15 +112,15 @@ static void test_run_first(void) nexthop_free(nh2); /* Blackhole */ - nh1 = nexthop_from_blackhole(BLACKHOLE_REJECT); - nh2 = nexthop_from_blackhole(BLACKHOLE_REJECT); + nh1 = nexthop_from_blackhole(BLACKHOLE_REJECT, 0); + nh2 = nexthop_from_blackhole(BLACKHOLE_REJECT, 0); ret = nexthop_cmp_basic(nh1, nh2); assert(ret == 0); nexthop_free(nh2); - nh2 = nexthop_from_blackhole(BLACKHOLE_NULL); + nh2 = nexthop_from_blackhole(BLACKHOLE_NULL, 0); ret = nexthop_cmp_basic(nh1, nh2); assert(ret != 0); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 72c7071502..9ffbcc9223 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1611,7 +1611,8 @@ static struct nexthop *nexthop_from_zapi(const struct zapi_nexthop *api_nh, zlog_debug("%s: nh blackhole %d", __func__, api_nh->bh_type); - nexthop = nexthop_from_blackhole(api_nh->bh_type); + nexthop = + nexthop_from_blackhole(api_nh->bh_type, api_nh->vrf_id); break; } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b204b30ca7..1c8a1ad09a 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -357,9 +357,11 @@ static void show_nexthop_detail_helper(struct vty *vty, break; } - if ((re->vrf_id != nexthop->vrf_id) - && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) - vty_out(vty, "(vrf %s)", vrf_id_to_name(nexthop->vrf_id)); + if (re->vrf_id != nexthop->vrf_id) { + struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); + + vty_out(vty, "(vrf %s)", VRF_LOGNAME(vrf)); + } if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) vty_out(vty, " (duplicate nexthop removed)"); @@ -607,8 +609,7 @@ static void show_route_nexthop_helper(struct vty *vty, break; } - if ((re == NULL || (nexthop->vrf_id != re->vrf_id)) - && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) + if ((re == NULL || (nexthop->vrf_id != re->vrf_id))) vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id)); if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) @@ -780,8 +781,7 @@ static void show_nexthop_json_helper(json_object *json_nexthop, break; } - if ((nexthop->vrf_id != re->vrf_id) - && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) + if (nexthop->vrf_id != re->vrf_id) json_object_string_add(json_nexthop, "vrf", vrf_id_to_name(nexthop->vrf_id));