diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 2f49eb5c2a54..55ceacb108e9 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -4658,12 +4658,12 @@ static void bgp_packet_nhc(struct stream *s, struct peer *peer, afi_t afi, safi_ if (!bpi) return; - if (bgp_path_info_mpath_count(bpi) < 2 && !nhc) + if (bgp_path_info_mpath_count(bpi->net) < 2 && !nhc) return; prefix = bgp_dest_get_prefix(bpi->net); - total = bgp_path_info_mpath_count(bpi) * IPV4_MAX_BYTELEN; + total = bgp_path_info_mpath_count(bpi->net) * IPV4_MAX_BYTELEN; total += IPV4_MAX_BYTELEN; /* Next-hop BGP ID */ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS); @@ -4705,7 +4705,7 @@ static void bgp_packet_nhc(struct stream *s, struct peer *peer, afi_t afi, safi_ * | Next-next-hop BGP IDs (variable) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - if (bgp_path_info_mpath_count(bpi) > 1) { + if (bgp_path_info_mpath_count(bpi->net) > 1) { if (bgp_debug_update(peer, NULL, NULL, 1)) zlog_debug("%pBP: Sending NHC TLV (%d) for %pFX", peer, BGP_ATTR_NHC_TLV_NNHN, prefix); diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index c54cfd59953c..ea3b4db1555e 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -227,23 +227,23 @@ void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath) /* * bgp_path_info_mpath_get * - * Fetch the mpath element for the given bgp_path_info. Used for + * Fetch the mpath element for the given bgp_dest. Used for * doing lazy allocation. */ static struct bgp_path_info_mpath * -bgp_path_info_mpath_get(struct bgp_path_info *path) +bgp_path_info_mpath_get(struct bgp_dest *dest) { struct bgp_path_info_mpath *mpath; - if (!path) + if (!dest) return NULL; - if (!path->mpath) { + if (!dest->mpath) { mpath = bgp_path_info_mpath_new(); - path->mpath = mpath; - mpath->mp_info = path; + dest->mpath = mpath; + mpath->mp_dest = dest; } - return path->mpath; + return dest->mpath; } /* @@ -278,28 +278,28 @@ struct bgp_path_info *bgp_path_info_mpath_first(struct bgp_path_info *path) /* * bgp_path_info_mpath_count * - * Given the bestpath bgp_path_info, return the number of multipath entries + * Given the bgp_dest, return the number of multipath entries */ -uint32_t bgp_path_info_mpath_count(struct bgp_path_info *path) +uint32_t bgp_path_info_mpath_count(struct bgp_dest *dest) { - if (!path->mpath) + if (!dest->mpath) return 1; - return path->mpath->mp_count; + return dest->mpath->mp_count; } /* * bgp_path_info_mpath_count_set * - * Sets the count of multipaths into bestpath's mpath element + * Sets the count of multipaths into bgp_dest's mpath element */ -static void bgp_path_info_mpath_count_set(struct bgp_path_info *path, +static void bgp_path_info_mpath_count_set(struct bgp_dest *dest, uint16_t count) { struct bgp_path_info_mpath *mpath; - if (!count && !path->mpath) + if (!count && !dest->mpath) return; - mpath = bgp_path_info_mpath_get(path); + mpath = bgp_path_info_mpath_get(dest); if (!mpath) return; mpath->mp_count = count; @@ -310,21 +310,21 @@ static void bgp_path_info_mpath_count_set(struct bgp_path_info *path, * * Update cumulative info related to link-bandwidth * - * This is only set on the first mpath of the list - * as such we should UNSET the flags when removing + * This is set on mpath of the bgp_dest, + * we should UNSET the flags when removing * to ensure nothing accidently happens */ -static void bgp_path_info_mpath_lb_update(struct bgp_path_info *path, bool set, +static void bgp_path_info_mpath_lb_update(struct bgp_dest *dest, bool set, bool all_paths_lb, uint64_t cum_bw) { struct bgp_path_info_mpath *mpath; - mpath = path->mpath; + mpath = dest->mpath; if (mpath == NULL) { if (!set || (cum_bw == 0 && !all_paths_lb)) return; - mpath = bgp_path_info_mpath_get(path); + mpath = bgp_path_info_mpath_get(dest); if (!mpath) return; } @@ -347,33 +347,33 @@ static void bgp_path_info_mpath_lb_update(struct bgp_path_info *path, bool set, /* * bgp_path_info_mpath_attr * - * Given bestpath bgp_path_info, return aggregated attribute set used + * Given bgp_dest, return aggregated attribute set used * for advertising the multipath route */ -struct attr *bgp_path_info_mpath_attr(struct bgp_path_info *path) +struct attr *bgp_path_info_mpath_attr(struct bgp_dest *dest) { - if (!path->mpath) + if (!dest->mpath) return NULL; - return path->mpath->mp_attr; + return dest->mpath->mp_attr; } /* * bgp_path_info_chkwtd * * Return if we should attempt to do weighted ECMP or not - * The path passed in is the bestpath. + * Pass the bgp_dest in. */ -enum bgp_wecmp_behavior bgp_path_info_mpath_chkwtd(struct bgp *bgp, struct bgp_path_info *path) +enum bgp_wecmp_behavior bgp_path_info_mpath_chkwtd(struct bgp *bgp, struct bgp_dest *dest) { /* Check if not multipath */ - if (!path->mpath) + if (!dest->mpath) return BGP_WECMP_BEHAVIOR_NONE; /* If link bandwidth is to be ignored, check if we have Next-Next Hop Nodes * characteristic and do weighted ECMP based on that. */ if (bgp->lb_handling == BGP_LINK_BW_IGNORE_BW) { - if (CHECK_FLAG(path->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NHC))) + if (CHECK_FLAG(bgp_dest_get_bgp_path_info(dest)->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NHC))) return BGP_WECMP_BEHAVIOR_NNHN_COUNT; } @@ -382,13 +382,13 @@ enum bgp_wecmp_behavior bgp_path_info_mpath_chkwtd(struct bgp *bgp, struct bgp_p */ if (bgp->lb_handling != BGP_LINK_BW_SKIP_MISSING && bgp->lb_handling != BGP_LINK_BW_DEFWT_4_MISSING) { - if (CHECK_FLAG(path->mpath->mp_flags, BGP_MP_LB_ALL)) + if (CHECK_FLAG(dest->mpath->mp_flags, BGP_MP_LB_ALL)) return BGP_WECMP_BEHAVIOR_LINK_BW; else return BGP_WECMP_BEHAVIOR_NONE; } - if (CHECK_FLAG(path->mpath->mp_flags, BGP_MP_LB_PRESENT)) + if (CHECK_FLAG(dest->mpath->mp_flags, BGP_MP_LB_PRESENT)) return BGP_WECMP_BEHAVIOR_LINK_BW; return BGP_WECMP_BEHAVIOR_NONE; @@ -397,28 +397,28 @@ enum bgp_wecmp_behavior bgp_path_info_mpath_chkwtd(struct bgp *bgp, struct bgp_p /* * bgp_path_info_mpath_attr * - * Given bestpath bgp_path_info, return cumulative bandwidth + * Given bgp_dest, return cumulative bandwidth * computed for all multipaths with bandwidth info */ -uint64_t bgp_path_info_mpath_cumbw(struct bgp_path_info *path) +uint64_t bgp_path_info_mpath_cumbw(struct bgp_dest *dest) { - if (!path->mpath) + if (!dest->mpath) return 0; - return path->mpath->cum_bw; + return dest->mpath->cum_bw; } /* * bgp_path_info_mpath_attr_set * - * Sets the aggregated attribute into bestpath's mpath element + * Sets the aggregated attribute into bgp_dest's mpath element */ -static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path, +static void bgp_path_info_mpath_attr_set(struct bgp_dest *dest, struct attr *attr) { struct bgp_path_info_mpath *mpath; - if (!attr && !path->mpath) + if (!attr && !dest->mpath) return; - mpath = bgp_path_info_mpath_get(path); + mpath = bgp_path_info_mpath_get(dest); if (!mpath) return; mpath->mp_attr = attr; @@ -451,14 +451,14 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, debug = bgp_debug_bestpath(dest); if (old_best) { - old_mpath_count = bgp_path_info_mpath_count(old_best); + old_mpath_count = bgp_path_info_mpath_count(old_best->net); if (old_mpath_count == 1) SET_FLAG(old_best->flags, BGP_PATH_MULTIPATH); - old_cum_bw = bgp_path_info_mpath_cumbw(old_best); - bgp_path_info_mpath_count_set(old_best, 0); - bgp_path_info_mpath_lb_update(old_best, false, false, 0); - bgp_path_info_mpath_free(&old_best->mpath); - old_best->mpath = NULL; + old_cum_bw = bgp_path_info_mpath_cumbw(old_best->net); + bgp_path_info_mpath_count_set(old_best->net, 0); + bgp_path_info_mpath_lb_update(old_best->net, false, false, 0); + bgp_path_info_mpath_free(&old_best->net->mpath); + old_best->net->mpath = NULL; } if (new_best) { @@ -564,9 +564,9 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, } if (new_best) { - if (mpath_count > 1 || new_best->mpath) { - bgp_path_info_mpath_count_set(new_best, mpath_count); - bgp_path_info_mpath_lb_update(new_best, true, all_paths_lb, cum_bw); + if (mpath_count > 1 || new_best->net->mpath) { + bgp_path_info_mpath_count_set(new_best->net, mpath_count); + bgp_path_info_mpath_lb_update(new_best->net, true, all_paths_lb, cum_bw); } if (debug) zlog_debug("%pBD(%s): New mpath count (incl newbest) %d mpath-change %s all_paths_lb %d cum_bw %" PRIu64, @@ -577,7 +577,7 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest, if (mpath_count == 1) UNSET_FLAG(new_best->flags, BGP_PATH_MULTIPATH); if (mpath_changed - || (bgp_path_info_mpath_count(new_best) != old_mpath_count)) + || (bgp_path_info_mpath_count(new_best->net) != old_mpath_count)) SET_FLAG(new_best->flags, BGP_PATH_MULTIPATH_CHG); if ((mpath_count) != old_mpath_count || old_cum_bw != cum_bw) SET_FLAG(new_best->flags, BGP_PATH_LINK_BW_CHG); @@ -610,18 +610,18 @@ void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best, struct attr attr = {0}; if (old_best && (old_best != new_best) - && (old_attr = bgp_path_info_mpath_attr(old_best))) { + && (old_attr = bgp_path_info_mpath_attr(old_best->net))) { bgp_attr_unintern(&old_attr); - bgp_path_info_mpath_attr_set(old_best, NULL); + bgp_path_info_mpath_attr_set(old_best->net, NULL); } if (!new_best) return; - if (bgp_path_info_mpath_count(new_best) == 1) { - if ((new_attr = bgp_path_info_mpath_attr(new_best))) { + if (bgp_path_info_mpath_count(new_best->net) == 1) { + if ((new_attr = bgp_path_info_mpath_attr(new_best->net))) { bgp_attr_unintern(&new_attr); - bgp_path_info_mpath_attr_set(new_best, NULL); + bgp_path_info_mpath_attr_set(new_best->net, NULL); SET_FLAG(new_best->flags, BGP_PATH_ATTR_CHANGED); } return; @@ -716,10 +716,10 @@ void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best, new_attr = bgp_attr_intern(&attr); - if (new_attr != bgp_path_info_mpath_attr(new_best)) { - if ((old_attr = bgp_path_info_mpath_attr(new_best))) + if (new_attr != bgp_path_info_mpath_attr(new_best->net)) { + if ((old_attr = bgp_path_info_mpath_attr(new_best->net))) bgp_attr_unintern(&old_attr); - bgp_path_info_mpath_attr_set(new_best, new_attr); + bgp_path_info_mpath_attr_set(new_best->net, new_attr); SET_FLAG(new_best->flags, BGP_PATH_ATTR_CHANGED); } else bgp_attr_unintern(&new_attr); diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h index c45255128975..46287fa5d71e 100644 --- a/bgpd/bgp_mpath.h +++ b/bgpd/bgp_mpath.h @@ -16,12 +16,12 @@ enum bgp_wecmp_behavior { BGP_WECMP_BEHAVIOR_NNHN_COUNT = 2 }; -/* Supplemental information linked to bgp_path_info for keeping track of +/* Supplemental information linked to bgp_dest for keeping track of * multipath selections, lazily allocated to save memory */ struct bgp_path_info_mpath { - /* Points to bgp_path_info associated with this multipath info */ - struct bgp_path_info *mp_info; + /* Points to bgp_dest associated with this multipath info */ + struct bgp_dest *mp_dest; /* When attached to best path, the number of selected multipaths */ uint16_t mp_count; @@ -70,10 +70,10 @@ extern struct bgp_path_info * bgp_path_info_mpath_next(struct bgp_path_info *path); /* Accessors for multipath information */ -extern uint32_t bgp_path_info_mpath_count(struct bgp_path_info *path); -extern struct attr *bgp_path_info_mpath_attr(struct bgp_path_info *path); +extern uint32_t bgp_path_info_mpath_count(struct bgp_dest *dest); +extern struct attr *bgp_path_info_mpath_attr(struct bgp_dest *dest); extern enum bgp_wecmp_behavior bgp_path_info_mpath_chkwtd(struct bgp *bgp, - struct bgp_path_info *path); -extern uint64_t bgp_path_info_mpath_cumbw(struct bgp_path_info *path); + struct bgp_dest *dest); +extern uint64_t bgp_path_info_mpath_cumbw(struct bgp_dest *dest); #endif /* _FRR_BGP_MPATH_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 6fe6c96169e6..c6f404a363d8 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -379,7 +379,6 @@ void bgp_path_info_free_with_caller(const char *name, bgp_unlink_nexthop(path); bgp_path_info_extra_free(&path->extra); - bgp_path_info_mpath_free(&path->mpath); if (path->net) bgp_addpath_free_info_data(&path->tx_addpath, &path->net->tx_addpath); @@ -2187,7 +2186,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, from = pi->peer; filter = &peer->filter[afi][safi]; bgp = SUBGRP_INST(subgrp); - piattr = bgp_path_info_mpath_count(pi) > 1 ? bgp_path_info_mpath_attr(pi) : pi->attr; + piattr = bgp_path_info_mpath_count(pi->net) > 1 ? bgp_path_info_mpath_attr(pi->net) : pi->attr; if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) && peer->pmax_out[afi][safi] != 0 && @@ -2862,8 +2861,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, * the most sense. However, don't modify if the link-bandwidth has * been explicitly set by user policy. */ - if (nh_reset && bgp_path_info_mpath_chkwtd(bgp, pi) == BGP_WECMP_BEHAVIOR_LINK_BW && - (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 && + if (nh_reset && bgp_path_info_mpath_chkwtd(bgp, pi->net) == BGP_WECMP_BEHAVIOR_LINK_BW && + (cum_bw = bgp_path_info_mpath_cumbw(pi->net)) != 0 && !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET)) { if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) bgp_attr_set_ipv6_ecommunity( @@ -12284,7 +12283,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, } if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH) || - (CHECK_FLAG(path->flags, BGP_PATH_SELECTED) && bgp_path_info_mpath_count(path) > 1)) { + (CHECK_FLAG(path->flags, BGP_PATH_SELECTED) && bgp_path_info_mpath_count(path->net) > 1)) { if (json_paths) json_object_boolean_true_add(json_path, "multipath"); else diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 07f4880dfc4d..57743bc0e8d7 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -294,10 +294,6 @@ struct bgp_path_info { /* Extra information */ struct bgp_path_info_extra *extra; - - /* Multipath information */ - struct bgp_path_info_mpath *mpath; - /* Uptime. */ time_t uptime; @@ -667,7 +663,6 @@ static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi, dst_pi->flags = src_pi->flags; dst_pi->type = src_pi->type; dst_pi->sub_type = src_pi->sub_type; - dst_pi->mpath = src_pi->mpath; if (src_pi->extra) { memcpy(dst_pie, src_pi->extra, sizeof(struct bgp_path_info_extra)); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 0747cfbb7ceb..3d1e38ccf653 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -3414,7 +3414,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object) if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) return RMAP_OKAY; - bw_bytes = bgp_path_info_mpath_cumbw(path); + bw_bytes = bgp_path_info_mpath_cumbw(path->net); if (!bw_bytes) return RMAP_OKAY; @@ -3425,7 +3425,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object) return RMAP_OKAY; bw_bytes = (peer->bgp->lb_ref_bw * 1000 * 1000) / 8; - mpath_count = bgp_path_info_mpath_count(path); + mpath_count = bgp_path_info_mpath_count(path->net); bw_bytes *= mpath_count; } diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index ac84ec77a960..cb9820d41473 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -113,6 +113,11 @@ static void bgp_node_destroy(route_table_delegate_t *delegate, &dest->tx_addpath, rt->afi, rt->safi); } + + /* Free mpath if exists */ + if (dest->mpath) + bgp_path_info_mpath_free(&dest->mpath); + XFREE(MTYPE_BGP_NODE, dest); node->info = NULL; } diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 54c8edd8612a..eca8b35957fc 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -106,6 +106,9 @@ struct bgp_dest { struct bgp_addpath_node_data tx_addpath; enum bgp_path_selection_reason reason; + + /* Multipath information */ + struct bgp_path_info_mpath *mpath; }; DECLARE_LIST(zebra_announce, struct bgp_dest, zai); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 6869045a5806..9b6bcd01a4a9 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1265,7 +1265,7 @@ static void bgp_zebra_announce_parse_nexthop( struct bgp_route_evpn *bre = NULL; /* Determine if we're doing weighted ECMP or not */ - do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info); + do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info->net); /* * vrf leaking support (will have only one nexthop)