diff --git a/lib/nexthop.c b/lib/nexthop.c index d05fa8e6d..f314fea69 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -33,6 +33,7 @@ #include "mpls.h" #include "jhash.h" #include "printfrr.h" +#include "vrf.h" DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop") DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label") @@ -281,6 +282,93 @@ bool nexthop_same_no_labels(const struct nexthop *nh1, return true; } +/* + * Allocate a new nexthop object and initialize it from various args. + */ +struct nexthop *nexthop_from_ifindex(ifindex_t ifindex, vrf_id_t vrf_id) +{ + struct nexthop *nexthop; + + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IFINDEX; + nexthop->ifindex = ifindex; + nexthop->vrf_id = vrf_id; + + return nexthop; +} + +struct nexthop *nexthop_from_ipv4(const struct in_addr *ipv4, + const struct in_addr *src, + vrf_id_t vrf_id) +{ + struct nexthop *nexthop; + + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV4; + nexthop->vrf_id = vrf_id; + nexthop->gate.ipv4 = *ipv4; + if (src) + nexthop->src.ipv4 = *src; + + return nexthop; +} + +struct nexthop *nexthop_from_ipv4_ifindex(const struct in_addr *ipv4, + const struct in_addr *src, + ifindex_t ifindex, vrf_id_t vrf_id) +{ + struct nexthop *nexthop; + + nexthop = nexthop_new(); + nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX; + nexthop->vrf_id = vrf_id; + nexthop->gate.ipv4 = *ipv4; + if (src) + nexthop->src.ipv4 = *src; + nexthop->ifindex = ifindex; + + return nexthop; +} + +struct nexthop *nexthop_from_ipv6(const struct in6_addr *ipv6, + vrf_id_t vrf_id) +{ + struct nexthop *nexthop; + + nexthop = nexthop_new(); + nexthop->vrf_id = vrf_id; + nexthop->type = NEXTHOP_TYPE_IPV6; + nexthop->gate.ipv6 = *ipv6; + + return nexthop; +} + +struct nexthop *nexthop_from_ipv6_ifindex(const struct in6_addr *ipv6, + ifindex_t ifindex, vrf_id_t vrf_id) +{ + struct nexthop *nexthop; + + nexthop = nexthop_new(); + nexthop->vrf_id = vrf_id; + nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; + nexthop->gate.ipv6 = *ipv6; + nexthop->ifindex = ifindex; + + return nexthop; +} + +struct nexthop *nexthop_from_blackhole(enum blackhole_type bh_type) +{ + struct nexthop *nexthop; + + nexthop = nexthop_new(); + nexthop->vrf_id = VRF_DEFAULT; + nexthop->type = NEXTHOP_TYPE_BLACKHOLE; + nexthop->bh_type = bh_type; + + return nexthop; +} + /* Update nexthop with label information. */ void nexthop_add_labels(struct nexthop *nexthop, enum lsp_types_t type, uint8_t num_labels, mpls_label_t *label) diff --git a/lib/nexthop.h b/lib/nexthop.h index fe029f186..72a4acedb 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -121,6 +121,22 @@ void nexthop_add_labels(struct nexthop *, enum lsp_types_t, uint8_t, mpls_label_t *); void nexthop_del_labels(struct nexthop *); +/* + * Allocate a new nexthop object and initialize it from various args. + */ +struct nexthop *nexthop_from_ifindex(ifindex_t ifindex, vrf_id_t vrf_id); +struct nexthop *nexthop_from_ipv4(const struct in_addr *ipv4, + const struct in_addr *src, + vrf_id_t vrf_id); +struct nexthop *nexthop_from_ipv4_ifindex(const struct in_addr *ipv4, + const struct in_addr *src, + ifindex_t ifindex, vrf_id_t vrf_id); +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); + /* * Hash a nexthop. Suitable for use with hash tables. * diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 9552f8956..3e08f1811 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -233,8 +233,8 @@ void _nexthop_add(struct nexthop **target, struct nexthop *nexthop) nexthop->prev = last; } -void _nexthop_group_add_sorted(struct nexthop_group *nhg, - struct nexthop *nexthop) +void nexthop_group_add_sorted(struct nexthop_group *nhg, + struct nexthop *nexthop) { struct nexthop *position, *prev, *tail; diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h index 391775c69..5105cbf18 100644 --- a/lib/nexthop_group.h +++ b/lib/nexthop_group.h @@ -50,6 +50,8 @@ void copy_nexthops(struct nexthop **tnh, const struct nexthop *nh, uint32_t nexthop_group_hash_no_recurse(const struct nexthop_group *nhg); uint32_t nexthop_group_hash(const struct nexthop_group *nhg); void nexthop_group_mark_duplicates(struct nexthop_group *nhg); +void nexthop_group_add_sorted(struct nexthop_group *nhg, + struct nexthop *nexthop); /* The following for loop allows to iterate over the nexthop * structure of routes. diff --git a/lib/nexthop_group_private.h b/lib/nexthop_group_private.h index cdd0df0ab..4abda624a 100644 --- a/lib/nexthop_group_private.h +++ b/lib/nexthop_group_private.h @@ -35,8 +35,6 @@ extern "C" { void _nexthop_add(struct nexthop **target, struct nexthop *nexthop); void _nexthop_del(struct nexthop_group *nhg, struct nexthop *nexthop); -void _nexthop_group_add_sorted(struct nexthop_group *nhg, - struct nexthop *nexthop); #ifdef __cplusplus } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 98603c969..6aa52bcb6 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -637,13 +637,15 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *newre; struct route_entry *same; struct prefix p; + struct nexthop_group *ng; route_map_result_t ret = RMAP_PERMITMATCH; afi_t afi; afi = family2afi(rn->p.family); if (rmap_name) ret = zebra_import_table_route_map_check( - afi, re->type, re->instance, &rn->p, re->ng->nexthop, + afi, re->type, re->instance, &rn->p, + re->nhe->nhg->nexthop, zvrf->vrf->vrf_id, re->tag, rmap_name); if (ret != RMAP_PERMITMATCH) { @@ -678,10 +680,11 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, newre->table = zvrf->table_id; newre->uptime = monotime(NULL); newre->instance = re->table; - newre->ng = nexthop_group_new(); - route_entry_copy_nexthops(newre, re->ng->nexthop); - rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre); + ng = nexthop_group_new(); + copy_nexthops(&ng->nexthop, re->nhe->nhg->nexthop, NULL); + + rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre, ng); return 0; } @@ -696,8 +699,9 @@ int zebra_del_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn, prefix_copy(&p, &rn->p); rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_TABLE, - re->table, re->flags, &p, NULL, re->ng->nexthop, re->nhe_id, - zvrf->table_id, re->metric, re->distance, false); + re->table, re->flags, &p, NULL, re->nhe->nhg->nexthop, + re->nhe_id, zvrf->table_id, re->metric, re->distance, + false); return 0; } diff --git a/zebra/rib.h b/zebra/rib.h index 35aa011c0..927675e3d 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -35,6 +35,7 @@ #include "if.h" #include "mpls.h" #include "srcdest_table.h" +#include "zebra/zebra_nhg.h" #ifdef __cplusplus extern "C" { @@ -87,10 +88,14 @@ struct route_entry { /* Link list. */ struct re_list_item next; - /* Nexthop structure (from RIB) */ - struct nexthop_group *ng; + /* Nexthop group, shared/refcounted, based on the nexthop(s) + * provided by the owner of the route + */ + struct nhg_hash_entry *nhe; - /* Nexthop group from FIB (optional) */ + /* Nexthop group from FIB (optional), reflecting what is actually + * installed in the FIB if that differs. + */ struct nexthop_group fib_ng; /* Nexthop group hash entry ID */ @@ -307,33 +312,9 @@ typedef enum { RIB_UPDATE_MAX } rib_update_event_t; -extern struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re, - ifindex_t ifindex, - vrf_id_t nh_vrf_id); -extern struct nexthop * -route_entry_nexthop_blackhole_add(struct route_entry *re, - enum blackhole_type bh_type); -extern struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re, - struct in_addr *ipv4, - struct in_addr *src, - vrf_id_t nh_vrf_id); -extern struct nexthop * -route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re, - struct in_addr *ipv4, struct in_addr *src, - ifindex_t ifindex, vrf_id_t nh_vrf_id); -extern void route_entry_nexthop_delete(struct route_entry *re, - struct nexthop *nexthop); -extern struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re, - struct in6_addr *ipv6, - vrf_id_t nh_vrf_id); -extern struct nexthop * -route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re, - struct in6_addr *ipv6, ifindex_t ifindex, - vrf_id_t nh_vrf_id); -extern void route_entry_nexthop_add(struct route_entry *re, - struct nexthop *nexthop); extern void route_entry_copy_nexthops(struct route_entry *re, struct nexthop *nh); +int route_entry_update_nhe(struct route_entry *re, struct nhg_hash_entry *new); #define route_entry_dump(prefix, src, re) _route_entry_dump(__func__, prefix, src, re) extern void _route_entry_dump(const char *func, union prefixconstptr pp, @@ -368,7 +349,8 @@ extern int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, uint32_t mtu, uint8_t distance, route_tag_t tag); extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct route_entry *re); + struct prefix_ipv6 *src_p, struct route_entry *re, + struct nexthop_group *ng); extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, unsigned short instance, int flags, struct prefix *p, @@ -533,7 +515,7 @@ static inline struct nexthop_group *rib_active_nhg(struct route_entry *re) if (re->fib_ng.nexthop) return &(re->fib_ng); else - return re->ng; + return re->nhe->nhg; } extern void zebra_vty_init(void); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 5e328b827..f3a255fd2 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -390,7 +390,7 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb, } static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, - struct route_entry *re, + struct nexthop_group *ng, struct rtmsg *rtm, struct rtnexthop *rtnh, struct rtattr **tb, @@ -407,8 +407,6 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, int len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); vrf_id_t nh_vrf_id = vrf_id; - re->ng = nexthop_group_new(); - for (;;) { struct nexthop *nh = NULL; @@ -454,21 +452,19 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, if (gate && rtm->rtm_family == AF_INET) { if (index) - nh = route_entry_nexthop_ipv4_ifindex_add( - re, gate, prefsrc, index, nh_vrf_id); + nh = nexthop_from_ipv4_ifindex( + gate, prefsrc, index, nh_vrf_id); else - nh = route_entry_nexthop_ipv4_add( - re, gate, prefsrc, nh_vrf_id); + nh = nexthop_from_ipv4(gate, prefsrc, + nh_vrf_id); } else if (gate && rtm->rtm_family == AF_INET6) { if (index) - nh = route_entry_nexthop_ipv6_ifindex_add( - re, gate, index, nh_vrf_id); + nh = nexthop_from_ipv6_ifindex( + gate, index, nh_vrf_id); else - nh = route_entry_nexthop_ipv6_add(re, gate, - nh_vrf_id); + nh = nexthop_from_ipv6(gate, nh_vrf_id); } else - nh = route_entry_nexthop_ifindex_add(re, index, - nh_vrf_id); + nh = nexthop_from_ifindex(index, nh_vrf_id); if (nh) { if (num_labels) @@ -477,6 +473,9 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, if (rtnh->rtnh_flags & RTNH_F_ONLINK) SET_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK); + + /* Add to temporary list */ + nexthop_group_add_sorted(ng, nh); } if (rtnh->rtnh_len == 0) @@ -486,10 +485,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id, rtnh = RTNH_NEXT(rtnh); } - uint8_t nhop_num = nexthop_group_nexthop_num(re->ng); - - if (!nhop_num) - nexthop_group_delete(&re->ng); + uint8_t nhop_num = nexthop_group_nexthop_num(ng); return nhop_num; } @@ -737,6 +733,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, } else { /* This is a multipath route */ struct route_entry *re; + struct nexthop_group *ng = NULL; struct rtnexthop *rtnh = (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]); @@ -753,19 +750,30 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, re->nhe_id = nhe_id; if (!nhe_id) { - uint8_t nhop_num = + uint8_t nhop_num; + + /* Use temporary list of nexthops; parse + * message payload's nexthops. + */ + ng = nexthop_group_new(); + nhop_num = parse_multipath_nexthops_unicast( - ns_id, re, rtm, rtnh, tb, + ns_id, ng, rtm, rtnh, tb, prefsrc, vrf_id); zserv_nexthop_num_warn( __func__, (const struct prefix *)&p, nhop_num); + + if (nhop_num == 0) { + nexthop_group_delete(&ng); + ng = NULL; + } } - if (nhe_id || re->ng) + if (nhe_id || ng) rib_add_multipath(afi, SAFI_UNICAST, &p, - &src_p, re); + &src_p, re, ng); else XFREE(MTYPE_RE, re); } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index e6a06ff95..bf29bda77 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -559,7 +559,8 @@ int zsend_redistribute_route(int cmd, struct zserv *client, memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix)); } - for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) { + for (nexthop = re->nhe->nhg->nexthop; + nexthop; nexthop = nexthop->next) { if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) continue; @@ -666,7 +667,7 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, * nexthop we are looking up. Therefore, we will just iterate * over the top chain of nexthops. */ - for (nexthop = re->ng->nexthop; nexthop; + for (nexthop = re->nhe->nhg->nexthop; nexthop; nexthop = nexthop->next) if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) num += zserv_encode_nexthop(s, nexthop); @@ -1393,6 +1394,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) struct prefix_ipv6 *src_p = NULL; struct route_entry *re; struct nexthop *nexthop = NULL; + struct nexthop_group *ng = NULL; int i, ret; vrf_id_t vrf_id = 0; struct ipaddr vtep_ip; @@ -1424,7 +1426,6 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) re->flags = api.flags; re->uptime = monotime(NULL); re->vrf_id = vrf_id; - re->ng = nexthop_group_new(); if (api.tableid) re->table = api.tableid; @@ -1438,11 +1439,13 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) __func__, &api.prefix, zebra_route_string(client->proto)); - nexthop_group_delete(&re->ng); XFREE(MTYPE_RE, re); return; } + /* Use temporary list of nexthops */ + ng = nexthop_group_new(); + /* * TBD should _all_ of the nexthop add operations use * api_nh->vrf_id instead of re->vrf_id ? I only changed @@ -1457,8 +1460,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) switch (api_nh->type) { case NEXTHOP_TYPE_IFINDEX: - nexthop = route_entry_nexthop_ifindex_add( - re, api_nh->ifindex, api_nh->vrf_id); + nexthop = nexthop_from_ifindex(api_nh->ifindex, + api_nh->vrf_id); break; case NEXTHOP_TYPE_IPV4: if (IS_ZEBRA_DEBUG_RECV) { @@ -1469,8 +1472,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) zlog_debug("%s: nh=%s, vrf_id=%d", __func__, nhbuf, api_nh->vrf_id); } - nexthop = route_entry_nexthop_ipv4_add( - re, &api_nh->gate.ipv4, NULL, api_nh->vrf_id); + nexthop = nexthop_from_ipv4(&api_nh->gate.ipv4, + NULL, api_nh->vrf_id); break; case NEXTHOP_TYPE_IPV4_IFINDEX: @@ -1486,8 +1489,8 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) __func__, nhbuf, api_nh->vrf_id, re->vrf_id, ifindex); } - nexthop = route_entry_nexthop_ipv4_ifindex_add( - re, &api_nh->gate.ipv4, NULL, ifindex, + nexthop = nexthop_from_ipv4_ifindex( + &api_nh->gate.ipv4, NULL, ifindex, api_nh->vrf_id); /* Special handling for IPv4 routes sourced from EVPN: @@ -1504,15 +1507,15 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) } break; case NEXTHOP_TYPE_IPV6: - nexthop = route_entry_nexthop_ipv6_add( - re, &api_nh->gate.ipv6, api_nh->vrf_id); + nexthop = nexthop_from_ipv6(&api_nh->gate.ipv6, + api_nh->vrf_id); break; case NEXTHOP_TYPE_IPV6_IFINDEX: memset(&vtep_ip, 0, sizeof(struct ipaddr)); ifindex = api_nh->ifindex; - nexthop = route_entry_nexthop_ipv6_ifindex_add( - re, &api_nh->gate.ipv6, ifindex, - api_nh->vrf_id); + nexthop = nexthop_from_ipv6_ifindex(&api_nh->gate.ipv6, + ifindex, + api_nh->vrf_id); /* Special handling for IPv6 routes sourced from EVPN: * the nexthop and associated MAC need to be installed. @@ -1527,8 +1530,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) } break; case NEXTHOP_TYPE_BLACKHOLE: - nexthop = route_entry_nexthop_blackhole_add( - re, api_nh->bh_type); + nexthop = nexthop_from_blackhole(api_nh->bh_type); break; } @@ -1537,10 +1539,11 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) EC_ZEBRA_NEXTHOP_CREATION_FAILED, "%s: Nexthops Specified: %d but we failed to properly create one", __PRETTY_FUNCTION__, api.nexthop_num); - nexthop_group_delete(&re->ng); + nexthop_group_delete(&ng); XFREE(MTYPE_RE, re); return; } + if (api_nh->onlink) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); @@ -1563,6 +1566,9 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) api_nh->label_num, &api_nh->labels[0]); } + + /* Add new nexthop to temporary list */ + nexthop_group_add_sorted(ng, nexthop); } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) @@ -1579,14 +1585,14 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) flog_warn(EC_ZEBRA_RX_SRCDEST_WRONG_AFI, "%s: Received SRC Prefix but afi is not v6", __PRETTY_FUNCTION__); - nexthop_group_delete(&re->ng); + nexthop_group_delete(&ng); XFREE(MTYPE_RE, re); return; } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) src_p = &api.src_prefix; - ret = rib_add_multipath(afi, api.safi, &api.prefix, src_p, re); + ret = rib_add_multipath(afi, api.safi, &api.prefix, src_p, re, ng); /* Stats */ switch (api.prefix.family) { diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index aecadfadf..bc4f51f70 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -1508,7 +1508,8 @@ static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, ctx->u.rinfo.zd_safi = info->safi; /* Copy nexthops; recursive info is included too */ - copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), re->ng->nexthop, NULL); + copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), + re->nhe->nhg->nexthop, NULL); /* Ensure that the dplane's nexthops flags are clear. */ for (ALL_NEXTHOPS(ctx->u.rinfo.zd_ng, nexthop)) @@ -1748,7 +1749,7 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx, if (re) copy_nexthops(&(ctx->u.pw.nhg.nexthop), - re->ng->nexthop, NULL); + re->nhe->nhg->nexthop, NULL); route_unlock_node(rn); } @@ -1844,7 +1845,7 @@ dplane_route_update_internal(struct route_node *rn, * We'll need these to do per-nexthop deletes. */ copy_nexthops(&(ctx->u.rinfo.zd_old_ng.nexthop), - old_re->ng->nexthop, NULL); + old_re->nhe->nhg->nexthop, NULL); #endif /* !HAVE_NETLINK */ } diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c index debcf60ee..389781d4f 100644 --- a/zebra/zebra_fpm_dt.c +++ b/zebra/zebra_fpm_dt.c @@ -90,7 +90,7 @@ static int zfpm_dt_find_route(rib_dest_t **dest_p, struct route_entry **re_p) if (!re) continue; - if (nexthop_group_active_nexthop_num(re->ng) == 0) + if (nexthop_group_active_nexthop_num(re->nhe->nhg) == 0) continue; *dest_p = dest; diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index b54d8fbc1..7786dc246 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -314,7 +314,7 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd, ri->rtm_type = RTN_UNICAST; ri->metric = &re->metric; - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) { if (ri->num_nhs >= zrouter.multipath_num) break; diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index a11517ab8..c09fa1c65 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -173,7 +173,7 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator, * Figure out the set of nexthops to be added to the message. */ num_nhs = 0; - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) { if (num_nhs >= zrouter.multipath_num) break; diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 5146311c6..d5d424732 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -186,7 +186,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label, * the label advertised by the recursive nexthop (plus we don't have the * logic yet to push multiple labels). */ - for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) { + for (nexthop = re->nhe->nhg->nexthop; + nexthop; nexthop = nexthop->next) { /* Skip inactive and recursive entries. */ if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) continue; @@ -637,7 +638,7 @@ static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, || !CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED)) continue; - for (match_nh = match->ng->nexthop; match_nh; + for (match_nh = match->nhe->nhg->nexthop; match_nh; match_nh = match_nh->next) { if (match->type == ZEBRA_ROUTE_CONNECT || nexthop->ifindex == match_nh->ifindex) { @@ -688,10 +689,10 @@ static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe, break; } - if (!match || !match->ng->nexthop) + if (!match || !match->nhe->nhg->nexthop) return 0; - nexthop->ifindex = match->ng->nexthop->ifindex; + nexthop->ifindex = match->nhe->nhg->nexthop->ifindex; return 1; } @@ -2577,7 +2578,7 @@ static void mpls_zebra_nhg_update(struct route_entry *re, afi_t afi, nhe = zebra_nhg_rib_find(0, new_grp, afi); - zebra_nhg_re_update_ref(re, nhe); + route_entry_update_nhe(re, nhe); } static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop, @@ -2631,7 +2632,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, * We can't just change the values here since we are hashing * on labels. We need to create a whole new group */ - nexthop_group_copy(&new_grp, re->ng); + nexthop_group_copy(&new_grp, re->nhe->nhg); found = false; for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) { @@ -2712,7 +2713,7 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, if (re == NULL) return -1; - nexthop_group_copy(&new_grp, re->ng); + nexthop_group_copy(&new_grp, re->nhe->nhg); for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) nexthop_del_labels(nexthop); @@ -2949,7 +2950,7 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf, RNODE_FOREACH_RE (rn, re) { struct nexthop_group new_grp = {}; - nexthop_group_copy(&new_grp, re->ng); + nexthop_group_copy(&new_grp, re->nhe->nhg); for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) { diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index f06ff44f2..1a7025062 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -299,13 +299,22 @@ zebra_nhg_connect_depends(struct nhg_hash_entry *nhe, } } -static struct nhg_hash_entry *zebra_nhg_copy(struct nhg_hash_entry *copy, - uint32_t id) +struct nhg_hash_entry *zebra_nhg_alloc(void) { struct nhg_hash_entry *nhe; nhe = XCALLOC(MTYPE_NHG, sizeof(struct nhg_hash_entry)); + return nhe; +} + +static struct nhg_hash_entry *zebra_nhg_copy(const struct nhg_hash_entry *copy, + uint32_t id) +{ + struct nhg_hash_entry *nhe; + + nhe = zebra_nhg_alloc(); + nhe->id = id; nhe->nhg = nexthop_group_new(); @@ -468,7 +477,7 @@ static void handle_recursive_depend(struct nhg_connected_tree_head *nhg_depends, struct nhg_hash_entry *depend = NULL; struct nexthop_group resolved_ng = {}; - _nexthop_group_add_sorted(&resolved_ng, nh); + nexthop_group_add_sorted(&resolved_ng, nh); depend = zebra_nhg_rib_find(0, &resolved_ng, afi); depends_add(nhg_depends, depend); @@ -582,7 +591,7 @@ zebra_nhg_find_nexthop(uint32_t id, struct nexthop *nh, afi_t afi, int type) struct nhg_hash_entry *nhe = NULL; struct nexthop_group nhg = {}; - _nexthop_group_add_sorted(&nhg, nh); + nexthop_group_add_sorted(&nhg, nh); zebra_nhg_find(&nhe, id, &nhg, NULL, nh->vrf_id, afi, 0); @@ -1128,12 +1137,8 @@ static void zebra_nhg_free_members(struct nhg_hash_entry *nhe) nhg_connected_tree_free(&nhe->nhg_dependents); } -void zebra_nhg_free(void *arg) +void zebra_nhg_free(struct nhg_hash_entry *nhe) { - struct nhg_hash_entry *nhe = NULL; - - nhe = (struct nhg_hash_entry *)arg; - if (nhe->refcnt) zlog_debug("nhe_id=%u hash refcnt=%d", nhe->id, nhe->refcnt); @@ -1142,6 +1147,11 @@ void zebra_nhg_free(void *arg) XFREE(MTYPE_NHG, nhe); } +void zebra_nhg_hash_free(void *p) +{ + zebra_nhg_free((struct nhg_hash_entry *)p); +} + void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe) { nhe->refcnt--; @@ -1447,7 +1457,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, if (match->type == ZEBRA_ROUTE_CONNECT) { /* Directly point connected route. */ - newhop = match->ng->nexthop; + newhop = match->nhe->nhg->nexthop; if (newhop) { if (nexthop->type == NEXTHOP_TYPE_IPV4 || nexthop->type == NEXTHOP_TYPE_IPV6) @@ -1456,7 +1466,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, return 1; } else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) { resolved = 0; - for (ALL_NEXTHOPS_PTR(match->ng, newhop)) { + for (ALL_NEXTHOPS_PTR(match->nhe->nhg, newhop)) { if (!CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED)) continue; @@ -1477,7 +1487,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re, return resolved; } else if (re->type == ZEBRA_ROUTE_STATIC) { resolved = 0; - for (ALL_NEXTHOPS_PTR(match->ng, newhop)) { + for (ALL_NEXTHOPS_PTR(match->nhe->nhg, newhop)) { if (!CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED)) continue; @@ -1668,7 +1678,7 @@ int nexthop_active_update(struct route_node *rn, struct route_entry *re) UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED); /* Copy over the nexthops in current state */ - nexthop_group_copy(&new_grp, re->ng); + nexthop_group_copy(&new_grp, re->nhe->nhg); for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) { @@ -1718,7 +1728,7 @@ int nexthop_active_update(struct route_node *rn, struct route_entry *re) new_nhe = zebra_nhg_rib_find(0, &new_grp, rt_afi); - zebra_nhg_re_update_ref(re, new_nhe); + route_entry_update_nhe(re, new_nhe); } if (curr_active) { @@ -1744,40 +1754,6 @@ int nexthop_active_update(struct route_node *rn, struct route_entry *re) return curr_active; } -static void zebra_nhg_re_attach_ref(struct route_entry *re, - struct nhg_hash_entry *new) -{ - re->ng = new->nhg; - re->nhe_id = new->id; - - zebra_nhg_increment_ref(new); -} - -int zebra_nhg_re_update_ref(struct route_entry *re, struct nhg_hash_entry *new) -{ - struct nhg_hash_entry *old = NULL; - int ret = 0; - - if (new == NULL) { - re->ng = NULL; - goto done; - } - - if (re->nhe_id != new->id) { - old = zebra_nhg_lookup_id(re->nhe_id); - - zebra_nhg_re_attach_ref(re, new); - - if (old) - zebra_nhg_decrement_ref(old); - } else if (!re->ng) - /* This is the first time it's being attached */ - zebra_nhg_re_attach_ref(re, new); - -done: - return ret; -} - /* Convert a nhe into a group array */ uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe, int max_num) diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h index 1f695433c..522ec1e9d 100644 --- a/zebra/zebra_nhg.h +++ b/zebra/zebra_nhg.h @@ -23,11 +23,9 @@ #ifndef __ZEBRA_NHG_H__ #define __ZEBRA_NHG_H__ -#include "zebra/rib.h" +#include "lib/nexthop.h" #include "lib/nexthop_group.h" -#include "zebra/zebra_dplane.h" - /* This struct is used exclusively for dataplane * interaction via a dataplane context. * @@ -160,6 +158,11 @@ struct nhg_ctx { * NHE abstracted tree functions. * Use these where possible instead of the direct ones access ones. */ +struct nhg_hash_entry *zebra_nhg_alloc(void); +void zebra_nhg_free(struct nhg_hash_entry *nhe); +/* In order to clear a generic hash, we need a generic api, sigh. */ +void zebra_nhg_hash_free(void *p); + extern struct nhg_hash_entry *zebra_nhg_resolve(struct nhg_hash_entry *nhe); extern unsigned int zebra_nhg_depends_count(const struct nhg_hash_entry *nhe); @@ -201,8 +204,6 @@ zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi); /* Reference counter functions */ extern void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe); extern void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe); -extern int zebra_nhg_re_update_ref(struct route_entry *re, - struct nhg_hash_entry *nhe); /* Check validity of nhe, if invalid will update dependents as well */ extern void zebra_nhg_check_valid(struct nhg_hash_entry *nhe); @@ -224,5 +225,6 @@ extern void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx); extern void zebra_nhg_sweep_table(struct hash *hash); /* Nexthop resolution processing */ +struct route_entry; /* Forward ref to avoid circular includes */ extern int nexthop_active_update(struct route_node *rn, struct route_entry *re); #endif diff --git a/zebra/zebra_nhg_private.h b/zebra/zebra_nhg_private.h index 170e2357e..79107b047 100644 --- a/zebra/zebra_nhg_private.h +++ b/zebra/zebra_nhg_private.h @@ -57,6 +57,4 @@ extern void nhg_connected_tree_del_nhe(struct nhg_connected_tree_head *head, extern void nhg_connected_tree_add_nhe(struct nhg_connected_tree_head *head, struct nhg_hash_entry *nhe); -extern void zebra_nhg_free(void *arg); - #endif /* __ZEBRA_NHG_PRIVATE_H__ */ diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index 3f1567a95..618a23240 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -259,7 +259,7 @@ static int zebra_pw_check_reachability(struct zebra_pw *pw) * Need to ensure that there's a label binding for all nexthops. * Otherwise, ECMP for this route could render the pseudowire unusable. */ - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) { if (!nexthop->nh_label) { if (IS_ZEBRA_DEBUG_PW) zlog_debug("%s: unlabeled route for %s", diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 605311769..d525da26e 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -193,144 +193,47 @@ int zebra_check_addr(const struct prefix *p) return 1; } -/* Add nexthop to the end of a rib node's nexthop list */ -void route_entry_nexthop_add(struct route_entry *re, struct nexthop *nexthop) -{ - _nexthop_group_add_sorted(re->ng, nexthop); -} - - /** * copy_nexthop - copy a nexthop to the rib structure. */ void route_entry_copy_nexthops(struct route_entry *re, struct nexthop *nh) { - assert(!re->ng->nexthop); - copy_nexthops(&re->ng->nexthop, nh, NULL); + assert(!re->nhe->nhg->nexthop); + copy_nexthops(&re->nhe->nhg->nexthop, nh, NULL); } -/* Delete specified nexthop from the list. */ -void route_entry_nexthop_delete(struct route_entry *re, struct nexthop *nexthop) +static void route_entry_attach_ref(struct route_entry *re, + struct nhg_hash_entry *new) { - if (nexthop->next) - nexthop->next->prev = nexthop->prev; - if (nexthop->prev) - nexthop->prev->next = nexthop->next; - else - re->ng->nexthop = nexthop->next; + re->nhe = new; + re->nhe_id = new->id; + + zebra_nhg_increment_ref(new); } - -struct nexthop *route_entry_nexthop_ifindex_add(struct route_entry *re, - ifindex_t ifindex, - vrf_id_t nh_vrf_id) +int route_entry_update_nhe(struct route_entry *re, struct nhg_hash_entry *new) { - struct nexthop *nexthop; + struct nhg_hash_entry *old = NULL; + int ret = 0; - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IFINDEX; - nexthop->ifindex = ifindex; - nexthop->vrf_id = nh_vrf_id; + if (new == NULL) { + re->nhe->nhg = NULL; + goto done; + } - route_entry_nexthop_add(re, nexthop); + if (re->nhe_id != new->id) { + old = zebra_nhg_lookup_id(re->nhe_id); - return nexthop; -} + route_entry_attach_ref(re, new); -struct nexthop *route_entry_nexthop_ipv4_add(struct route_entry *re, - struct in_addr *ipv4, - struct in_addr *src, - vrf_id_t nh_vrf_id) -{ - struct nexthop *nexthop; + if (old) + zebra_nhg_decrement_ref(old); + } else if (!re->nhe->nhg) + /* This is the first time it's being attached */ + route_entry_attach_ref(re, new); - nexthop = nexthop_new(); - nexthop->type = NEXTHOP_TYPE_IPV4; - nexthop->vrf_id = nh_vrf_id; - nexthop->gate.ipv4 = *ipv4; - if (src) - nexthop->src.ipv4 = *src; - - route_entry_nexthop_add(re, nexthop); - - return nexthop; -} - -struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re, - struct in_addr *ipv4, - struct in_addr *src, - ifindex_t ifindex, - vrf_id_t nh_vrf_id) -{ - struct nexthop *nexthop; - struct interface *ifp; - - nexthop = nexthop_new(); - nexthop->vrf_id = nh_vrf_id; - nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX; - nexthop->gate.ipv4 = *ipv4; - if (src) - nexthop->src.ipv4 = *src; - nexthop->ifindex = ifindex; - ifp = if_lookup_by_index(nexthop->ifindex, nh_vrf_id); - /*Pending: need to think if null ifp here is ok during bootup? - There was a crash because ifp here was coming to be NULL */ - if (ifp) - if (connected_is_unnumbered(ifp)) - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); - - route_entry_nexthop_add(re, nexthop); - - return nexthop; -} - -struct nexthop *route_entry_nexthop_ipv6_add(struct route_entry *re, - struct in6_addr *ipv6, - vrf_id_t nh_vrf_id) -{ - struct nexthop *nexthop; - - nexthop = nexthop_new(); - nexthop->vrf_id = nh_vrf_id; - nexthop->type = NEXTHOP_TYPE_IPV6; - nexthop->gate.ipv6 = *ipv6; - - route_entry_nexthop_add(re, nexthop); - - return nexthop; -} - -struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re, - struct in6_addr *ipv6, - ifindex_t ifindex, - vrf_id_t nh_vrf_id) -{ - struct nexthop *nexthop; - - nexthop = nexthop_new(); - nexthop->vrf_id = nh_vrf_id; - nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; - nexthop->gate.ipv6 = *ipv6; - nexthop->ifindex = ifindex; - - route_entry_nexthop_add(re, nexthop); - - return nexthop; -} - -struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re, - enum blackhole_type bh_type) -{ - struct nexthop *nexthop; - - nexthop = nexthop_new(); - nexthop->vrf_id = VRF_DEFAULT; - nexthop->type = NEXTHOP_TYPE_BLACKHOLE; - nexthop->bh_type = bh_type; - - route_entry_nexthop_add(re, nexthop); - - return nexthop; +done: + return ret; } struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id, @@ -501,7 +404,7 @@ int zebra_rib_labeled_unicast(struct route_entry *re) if (re->type != ZEBRA_ROUTE_BGP) return 0; - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) if (!nexthop->nh_label || !nexthop->nh_label->num_labels) return 0; @@ -525,7 +428,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, srcdest_rnode_prefixes(rn, &p, &src_p); if (info->safi != SAFI_UNICAST) { - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); return; } @@ -603,7 +506,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) if (info->safi != SAFI_UNICAST) { UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); return; } @@ -663,7 +566,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re) re->fib_ng.nexthop = NULL; } - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); } @@ -839,7 +742,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn, /* Update real nexthop. This may actually determine if nexthop is active * or not. */ - if (!nexthop_group_active_nexthop_num(new->ng)) { + if (!nexthop_group_active_nexthop_num(new->nhe->nhg)) { UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED); return; } @@ -908,7 +811,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf, /* Update the nexthop; we could determine here that nexthop is * inactive. */ - if (nexthop_group_active_nexthop_num(new->ng)) + if (nexthop_group_active_nexthop_num(new->nhe->nhg)) nh_active = 1; /* If nexthop is active, install the selected route, if @@ -1026,7 +929,7 @@ static struct route_entry *rib_choose_best(struct route_entry *current, /* both are connected. are either loop or vrf? */ struct nexthop *nexthop = NULL; - for (ALL_NEXTHOPS_PTR(alternate->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(alternate->nhe->nhg, nexthop)) { struct interface *ifp = if_lookup_by_index( nexthop->ifindex, alternate->vrf_id); @@ -1034,7 +937,7 @@ static struct route_entry *rib_choose_best(struct route_entry *current, return alternate; } - for (ALL_NEXTHOPS_PTR(current->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(current->nhe->nhg, nexthop)) { struct interface *ifp = if_lookup_by_index( nexthop->ifindex, current->vrf_id); @@ -1365,7 +1268,7 @@ static void zebra_rib_fixup_system(struct route_node *rn) SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); - for (ALL_NEXTHOPS_PTR(re->ng, nhop)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nhop)) { if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; @@ -1468,13 +1371,13 @@ static bool rib_update_re_from_ctx(struct route_entry *re, /* Get the first `installed` one to check against. * If the dataplane doesn't set these to be what was actually installed, - * it will just be whatever was in re->ng? + * it will just be whatever was in re->nhe->nhg? */ if (CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_RECURSIVE) || !CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_ACTIVE)) ctx_nexthop = nexthop_next_active_resolved(ctx_nexthop); - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; @@ -2421,8 +2324,8 @@ void rib_unlink(struct route_node *rn, struct route_entry *re) nhe = zebra_nhg_lookup_id(re->nhe_id); if (nhe) zebra_nhg_decrement_ref(nhe); - } else if (re->ng) - nexthop_group_delete(&re->ng); + } else if (re->nhe->nhg) + nexthop_group_delete(&re->nhe->nhg); nexthops_free(re->fib_ng.nexthop); @@ -2489,10 +2392,10 @@ void _route_entry_dump(const char *func, union prefixconstptr pp, "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u", straddr, re->metric, re->mtu, re->distance, re->flags, re->status); zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr, - nexthop_group_nexthop_num(re->ng), - nexthop_group_active_nexthop_num(re->ng)); + nexthop_group_nexthop_num(re->nhe->nhg), + nexthop_group_active_nexthop_num(re->nhe->nhg)); - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) { struct interface *ifp; struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id); @@ -2641,7 +2544,8 @@ void rib_lookup_and_pushup(struct prefix_ipv4 *p, vrf_id_t vrf_id) } int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct route_entry *re) + struct prefix_ipv6 *src_p, struct route_entry *re, + struct nexthop_group *ng) { struct nhg_hash_entry *nhe = NULL; struct route_table *table; @@ -2658,8 +2562,8 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, table = zebra_vrf_get_table_with_table_id(afi, safi, re->vrf_id, re->table); if (!table) { - if (re->ng) - nexthop_group_delete(&re->ng); + if (ng) + nexthop_group_delete(&ng); XFREE(MTYPE_RE, re); return 0; } @@ -2676,13 +2580,13 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, return -1; } } else { - nhe = zebra_nhg_rib_find(0, re->ng, afi); + nhe = zebra_nhg_rib_find(0, ng, afi); /* * The nexthops got copied over into an nhe, * so free them now. */ - nexthop_group_delete(&re->ng); + nexthop_group_delete(&ng); if (!nhe) { char buf[PREFIX_STRLEN] = ""; @@ -2708,7 +2612,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, * level protocols, as the refcnt might be wrong, since it checks * if old_id != new_id. */ - zebra_nhg_re_update_ref(re, nhe); + route_entry_update_nhe(re, nhe); /* Make it sure prefixlen is applied to the prefix. */ apply_mask(p); @@ -2851,7 +2755,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, if (re->type == ZEBRA_ROUTE_KERNEL && re->metric != metric) continue; - if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = re->ng->nexthop) + if (re->type == ZEBRA_ROUTE_CONNECT && + (rtnh = re->nhe->nhg->nexthop) && rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) { if (rtnh->ifindex != nh->ifindex) continue; @@ -2869,7 +2774,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, same = re; break; } - for (ALL_NEXTHOPS_PTR(re->ng, rtnh)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, rtnh)) { /* * No guarantee all kernel send nh with labels * on delete. @@ -2911,7 +2816,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, if (allow_delete) { UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED); /* Unset flags. */ - for (rtnh = fib->ng->nexthop; rtnh; + for (rtnh = fib->nhe->nhg->nexthop; rtnh; rtnh = rtnh->next) UNSET_FLAG(rtnh->flags, NEXTHOP_FLAG_FIB); @@ -2967,7 +2872,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) { struct nexthop *tmp_nh; - for (ALL_NEXTHOPS_PTR(re->ng, tmp_nh)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, tmp_nh)) { struct ipaddr vtep_ip; memset(&vtep_ip, 0, sizeof(struct ipaddr)); @@ -3007,6 +2912,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, { struct route_entry *re = NULL; struct nexthop *nexthop = NULL; + struct nexthop_group *ng = NULL; /* Allocate new route_entry structure. */ re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); @@ -3022,16 +2928,19 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, re->tag = tag; re->nhe_id = nhe_id; + /* If the owner of the route supplies a shared nexthop-group id, + * we'll use that. Otherwise, pass the nexthop along directly. + */ if (!nhe_id) { - re->ng = nexthop_group_new(); + ng = nexthop_group_new(); /* Add nexthop. */ nexthop = nexthop_new(); *nexthop = *nh; - route_entry_nexthop_add(re, nexthop); + nexthop_group_add_sorted(ng, nexthop); } - return rib_add_multipath(afi, safi, p, src_p, re); + return rib_add_multipath(afi, safi, p, src_p, re, ng); } static const char *rib_update_event2str(rib_update_event_t event) @@ -3289,7 +3198,7 @@ void rib_sweep_table(struct route_table *table) * this decision needs to be revisited */ SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); rib_uninstall_kernel(rn, re); diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 60e23cc4d..9a6631a59 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -384,7 +384,7 @@ static void zebra_rnh_clear_nexthop_rnh_filters(struct route_entry *re) struct nexthop *nexthop; if (re) { - for (nexthop = re->ng->nexthop; nexthop; + for (nexthop = re->nhe->nhg->nexthop; nexthop; nexthop = nexthop->next) { UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RNH_FILTERED); } @@ -403,7 +403,7 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf, route_map_result_t ret; if (prn && re) { - for (nexthop = re->ng->nexthop; nexthop; + for (nexthop = re->nhe->nhg->nexthop; nexthop; nexthop = nexthop->next) { ret = zebra_nht_route_map_check( afi, proto, &prn->p, zvrf, re, nexthop); @@ -688,7 +688,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, /* Just being SELECTED isn't quite enough - must * have an installed nexthop to be useful. */ - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) { if (rnh_nexthop_valid(re, nexthop)) break; } @@ -707,7 +707,8 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, break; if (re->type == ZEBRA_ROUTE_NHRP) { - for (nexthop = re->ng->nexthop; nexthop; + for (nexthop = re->nhe->nhg->nexthop; + nexthop; nexthop = nexthop->next) if (nexthop->type == NEXTHOP_TYPE_IFINDEX) @@ -940,7 +941,7 @@ static void free_state(vrf_id_t vrf_id, struct route_entry *re, return; /* free RE and nexthops */ - nexthop_group_delete(&re->ng); + zebra_nhg_free(re->nhe); XFREE(MTYPE_RE, re); } @@ -963,9 +964,11 @@ static void copy_state(struct rnh *rnh, struct route_entry *re, state->metric = re->metric; state->vrf_id = re->vrf_id; state->status = re->status; - state->ng = nexthop_group_new(); - route_entry_copy_nexthops(state, re->ng->nexthop); + state->nhe = zebra_nhg_alloc(); + state->nhe->nhg = nexthop_group_new(); + + nexthop_group_copy(state->nhe->nhg, re->nhe->nhg); rnh->state = state; } @@ -983,11 +986,12 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2) if (r1->metric != r2->metric) return 1; - if (nexthop_group_nexthop_num(r1->ng) - != nexthop_group_nexthop_num(r2->ng)) + if (nexthop_group_nexthop_num(r1->nhe->nhg) + != nexthop_group_nexthop_num(r2->nhe->nhg)) return 1; - if (nexthop_group_hash(r1->ng) != nexthop_group_hash(r2->ng)) + if (nexthop_group_hash(r1->nhe->nhg) != + nexthop_group_hash(r2->nhe->nhg)) return 1; return 0; @@ -1037,7 +1041,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, num = 0; nump = stream_get_endp(s); stream_putc(s, 0); - for (ALL_NEXTHOPS_PTR(re->ng, nh)) + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nh)) if (rnh_nexthop_valid(re, nh)) { stream_putl(s, nh->vrf_id); stream_putc(s, nh->type); @@ -1137,7 +1141,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty) if (rnh->state) { vty_out(vty, " resolved via %s\n", zebra_route_string(rnh->state->type)); - for (nexthop = rnh->state->ng->nexthop; nexthop; + for (nexthop = rnh->state->nhe->nhg->nexthop; nexthop; nexthop = nexthop->next) print_nh(nexthop, vty); } else diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index e573093b7..a891ffb76 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -29,7 +29,7 @@ #include "zebra_pbr.h" #include "zebra_vxlan.h" #include "zebra_mlag.h" -#include "zebra_nhg_private.h" +#include "zebra_nhg.h" #include "debug.h" DEFINE_MTYPE_STATIC(ZEBRA, RIB_TABLE_INFO, "RIB table info") @@ -223,7 +223,7 @@ void zebra_router_terminate(void) zebra_vxlan_disable(); zebra_mlag_terminate(); - hash_clean(zrouter.nhgs, zebra_nhg_free); + hash_clean(zrouter.nhgs, zebra_nhg_hash_free); hash_free(zrouter.nhgs); hash_clean(zrouter.nhgs_id, NULL); hash_free(zrouter.nhgs_id); diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c index 56c766432..4c5265198 100644 --- a/zebra/zebra_snmp.c +++ b/zebra/zebra_snmp.c @@ -285,8 +285,8 @@ static void check_replace(struct route_node *np2, struct route_entry *re2, return; } - if (in_addr_cmp((uint8_t *)&(*re)->ng->nexthop->gate.ipv4, - (uint8_t *)&re2->ng->nexthop->gate.ipv4) + if (in_addr_cmp((uint8_t *)&(*re)->nhe->nhg->nexthop->gate.ipv4, + (uint8_t *)&re2->nhe->nhg->nexthop->gate.ipv4) <= 0) return; @@ -371,9 +371,9 @@ static void get_fwtable_route_node(struct variable *v, oid objid[], if (!in_addr_cmp(&(*np)->p.u.prefix, (uint8_t *)&dest)) { RNODE_FOREACH_RE (*np, *re) { - if (!in_addr_cmp((uint8_t *)&(*re) - ->ng->nexthop - ->gate.ipv4, + if (!in_addr_cmp((uint8_t *)&(*re)->nhe + ->nhg->nexthop + ->gate.ipv4, (uint8_t *)&nexthop)) if (proto == proto_trans((*re)->type)) @@ -406,8 +406,8 @@ static void get_fwtable_route_node(struct variable *v, oid objid[], || ((policy == policy2) && (proto < proto2)) || ((policy == policy2) && (proto == proto2) && (in_addr_cmp( - (uint8_t *)&re2->ng->nexthop - ->gate.ipv4, + (uint8_t *)&re2->nhe + ->nhg->nexthop->gate.ipv4, (uint8_t *)&nexthop) >= 0))) check_replace(np2, re2, np, re); @@ -432,7 +432,7 @@ static void get_fwtable_route_node(struct variable *v, oid objid[], { struct nexthop *nexthop; - nexthop = (*re)->ng->nexthop; + nexthop = (*re)->nhe->nhg->nexthop; if (nexthop) { pnt = (uint8_t *)&nexthop->gate.ipv4; for (i = 0; i < 4; i++) @@ -462,7 +462,7 @@ static uint8_t *ipFwTable(struct variable *v, oid objid[], size_t *objid_len, if (!np) return NULL; - nexthop = re->ng->nexthop; + nexthop = re->nhe->nhg->nexthop; if (!nexthop) return NULL; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 8a7c7e359..eca86d5fe 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -263,7 +263,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, if (show_ng) vty_out(vty, " Nexthop Group ID: %u\n", re->nhe_id); - for (ALL_NEXTHOPS_PTR(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) { char addrstr[32]; vty_out(vty, " %c%s", @@ -413,7 +413,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, if (is_fib) nhg = rib_active_nhg(re); else - nhg = re->ng; + nhg = re->nhe->nhg; if (json) { json_route = json_object_new_object(); @@ -466,9 +466,10 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object_int_add(json_route, "internalFlags", re->flags); json_object_int_add(json_route, "internalNextHopNum", - nexthop_group_nexthop_num(re->ng)); + nexthop_group_nexthop_num(re->nhe->nhg)); json_object_int_add(json_route, "internalNextHopActiveNum", - nexthop_group_active_nexthop_num(re->ng)); + nexthop_group_active_nexthop_num( + re->nhe->nhg)); if (uptime < ONE_DAY_SECOND) sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -1833,7 +1834,7 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty, fib_cnt[ZEBRA_ROUTE_TOTAL]++; fib_cnt[re->type]++; } - for (nexthop = re->ng->nexthop; (!cnt && nexthop); + for (nexthop = re->nhe->nhg->nexthop; (!cnt && nexthop); nexthop = nexthop->next) { cnt++; rib_cnt[ZEBRA_ROUTE_TOTAL]++;