From 98efa5bc6bac9e3917afe2fa206ec795ddf86b87 Mon Sep 17 00:00:00 2001 From: Valerian_He <1826906282@qq.com> Date: Tue, 8 Aug 2023 10:47:29 +0000 Subject: [PATCH] bgpd: bgp_path_info_extra memory optimization Even if some of the attributes in bgp_path_info_extra are not used, their memory is still allocated every time. It cause a waste of memory. This commit code deletes all unnecessary attributes and changes the optional attributes to pointer storage. Memory will only be allocated when they are actually used. After optimization, extra info related memory is reduced by about half(~400B -> ~200B). Signed-off-by: Valerian_He <1826906282@qq.com> --- bgpd/bgp_evpn.c | 32 +++++--- bgpd/bgp_evpn.h | 19 +++-- bgpd/bgp_evpn_mh.c | 45 ++++++----- bgpd/bgp_evpn_private.h | 16 ++-- bgpd/bgp_flowspec_vty.c | 12 +-- bgpd/bgp_memory.c | 3 + bgpd/bgp_memory.h | 3 + bgpd/bgp_mpath.c | 9 ++- bgpd/bgp_mplsvpn.c | 161 +++++++++------------------------------ bgpd/bgp_mplsvpn.h | 7 +- bgpd/bgp_nht.c | 5 +- bgpd/bgp_pbr.c | 16 ++-- bgpd/bgp_route.c | 163 +++++++++++++++------------------------- bgpd/bgp_route.h | 104 +++++++++++++------------ bgpd/bgp_routemap.c | 9 ++- bgpd/bgp_vty.c | 23 ++++++ bgpd/bgp_zebra.c | 55 ++++++++++---- bgpd/bgp_zebra.h | 7 +- bgpd/rfapi/rfapi_vty.c | 21 ++++-- 19 files changed, 330 insertions(+), 380 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index a33f59cf5b..35f2438929 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1924,7 +1924,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, /* Mark route as self type-2 route */ if (flags && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP)) - tmp_pi->extra->af_flags = BGP_EVPN_MACIP_TYPE_SVI_IP; + tmp_pi->extra->evpn->af_flags = + BGP_EVPN_MACIP_TYPE_SVI_IP; bgp_path_info_add(dest, tmp_pi); } else { tmp_pi = local_pi; @@ -2390,7 +2391,8 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn, attr.router_flag = 1; } memcpy(&attr.esi, &local_pi->attr->esi, sizeof(esi_t)); - bgp_evpn_get_rmac_nexthop(vpn, &evp, &attr, local_pi->extra->af_flags); + bgp_evpn_get_rmac_nexthop(vpn, &evp, &attr, + local_pi->extra->evpn->af_flags); vni2label(vpn->vni, &(attr.label)); /* Add L3 VNI RTs and RMAC for non IPv6 link-local if * using L3 VNI for type-2 routes also. @@ -2829,7 +2831,11 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi, attr_new, dest); SET_FLAG(pi->flags, BGP_PATH_VALID); bgp_path_info_extra_get(pi); - pi->extra->parent = bgp_path_info_lock(parent_pi); + if (!pi->extra->vrfleak) + pi->extra->vrfleak = + XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK, + sizeof(struct bgp_path_info_extra_vrfleak)); + pi->extra->vrfleak->parent = bgp_path_info_lock(parent_pi); bgp_dest_lock_node((struct bgp_dest *)parent_pi->net); if (parent_pi->extra) { memcpy(&pi->extra->label, &parent_pi->extra->label, @@ -2935,8 +2941,9 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, /* Check if route entry is already present. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) - if (pi->extra - && (struct bgp_path_info *)pi->extra->parent == parent_pi) + if (pi->extra && pi->extra->vrfleak && + (struct bgp_path_info *)pi->extra->vrfleak->parent == + parent_pi) break; if (!pi) { @@ -3031,8 +3038,9 @@ static int install_evpn_route_entry_in_vni_common( /* Check if route entry is already present. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) - if (pi->extra - && (struct bgp_path_info *)pi->extra->parent == parent_pi) + if (pi->extra && pi->extra->vrfleak && + (struct bgp_path_info *)pi->extra->vrfleak->parent == + parent_pi) break; if (!pi) { @@ -3127,8 +3135,9 @@ static int uninstall_evpn_route_entry_in_vni_common( /* Find matching route entry. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) - if (pi->extra && - (struct bgp_path_info *)pi->extra->parent == parent_pi) + if (pi->extra && pi->extra->vrfleak && + (struct bgp_path_info *)pi->extra->vrfleak->parent == + parent_pi) break; if (!pi) @@ -3305,8 +3314,9 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, /* Find matching route entry. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) - if (pi->extra - && (struct bgp_path_info *)pi->extra->parent == parent_pi) + if (pi->extra && pi->extra->vrfleak && + (struct bgp_path_info *)pi->extra->vrfleak->parent == + parent_pi) break; if (!pi) { diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 076248c9f7..55474464e5 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -51,15 +51,15 @@ get_route_parent_evpn(struct bgp_path_info *ri) struct bgp_path_info *parent_ri; /* If not imported (or doesn't have a parent), bail. */ - if (ri->sub_type != BGP_ROUTE_IMPORTED || - !ri->extra || - !ri->extra->parent) + if (ri->sub_type != BGP_ROUTE_IMPORTED || !ri->extra || + !ri->extra->vrfleak || !ri->extra->vrfleak->parent) return NULL; /* Determine parent recursively */ - for (parent_ri = ri->extra->parent; - parent_ri->extra && parent_ri->extra->parent; - parent_ri = parent_ri->extra->parent) + for (parent_ri = ri->extra->vrfleak->parent; + parent_ri->extra && parent_ri->extra->vrfleak && + parent_ri->extra->vrfleak->parent; + parent_ri = parent_ri->extra->vrfleak->parent) ; return parent_ri; @@ -103,12 +103,11 @@ static inline bool is_route_injectable_into_evpn(struct bgp_path_info *pi) struct bgp_table *table; struct bgp_dest *dest; - if (pi->sub_type != BGP_ROUTE_IMPORTED || - !pi->extra || - !pi->extra->parent) + if (pi->sub_type != BGP_ROUTE_IMPORTED || !pi->extra || + !pi->extra->vrfleak || !pi->extra->vrfleak->parent) return true; - parent_pi = (struct bgp_path_info *)pi->extra->parent; + parent_pi = (struct bgp_path_info *)pi->extra->vrfleak->parent; dest = parent_pi->net; if (!dest) return true; diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index efadda17b8..36bf752d48 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -185,8 +185,9 @@ static int bgp_evpn_es_route_install(struct bgp *bgp, /* Check if route entry is already present. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) - if (pi->extra && - (struct bgp_path_info *)pi->extra->parent == parent_pi) + if (pi->extra && pi->extra->vrfleak && + (struct bgp_path_info *)pi->extra->vrfleak->parent == + parent_pi) break; if (!pi) { @@ -198,7 +199,11 @@ static int bgp_evpn_es_route_install(struct bgp *bgp, parent_pi->peer, attr_new, dest); SET_FLAG(pi->flags, BGP_PATH_VALID); bgp_path_info_extra_get(pi); - pi->extra->parent = bgp_path_info_lock(parent_pi); + if (!pi->extra->vrfleak) + pi->extra->vrfleak = + XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK, + sizeof(struct bgp_path_info_extra_vrfleak)); + pi->extra->vrfleak->parent = bgp_path_info_lock(parent_pi); bgp_dest_lock_node((struct bgp_dest *)parent_pi->net); bgp_path_info_add(dest, pi); } else { @@ -253,9 +258,9 @@ static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es, /* Find matching route entry. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) - if (pi->extra - && (struct bgp_path_info *)pi->extra->parent == - parent_pi) + if (pi->extra && pi->extra->vrfleak && + (struct bgp_path_info *)pi->extra->vrfleak->parent == + parent_pi) break; if (!pi) { @@ -1548,10 +1553,11 @@ bgp_evpn_path_es_info_new(struct bgp_path_info *pi, vni_t vni) e = bgp_path_info_extra_get(pi); /* If mh_info doesn't exist allocate it */ - mh_info = e->mh_info; + mh_info = e->evpn->mh_info; if (!mh_info) - e->mh_info = mh_info = XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO, - sizeof(struct bgp_path_mh_info)); + e->evpn->mh_info = mh_info = + XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO, + sizeof(struct bgp_path_mh_info)); /* If es_info doesn't exist allocate it */ es_info = mh_info->es_info; @@ -1604,8 +1610,8 @@ void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi) struct bgp_evpn_es *es; struct bgp *bgp_evpn; - es_info = (pi->extra && pi->extra->mh_info) - ? pi->extra->mh_info->es_info + es_info = (pi->extra && pi->extra->evpn && pi->extra->evpn->mh_info) + ? pi->extra->evpn->mh_info->es_info : NULL; /* if the esi is zero just unlink the path from the old es */ if (!esi || !memcmp(esi, zero_esi, sizeof(*esi))) { @@ -3163,7 +3169,7 @@ bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf, struct bgp_path_info *pi, *nhg_p = 0; /* we don't support NHG for routes leaked from another VRF yet */ - if (pi->extra && pi->extra->bgp_orig) + if (pi->extra && pi->extra->vrfleak && pi->extra->vrfleak->bgp_orig) return false; parent_pi = get_route_parent_evpn(pi); @@ -4670,10 +4676,11 @@ bgp_evpn_path_nh_info_new(struct bgp_path_info *pi) e = bgp_path_info_extra_get(pi); /* If mh_info doesn't exist allocate it */ - mh_info = e->mh_info; + mh_info = e->evpn->mh_info; if (!mh_info) - e->mh_info = mh_info = XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO, - sizeof(struct bgp_path_mh_info)); + e->evpn->mh_info = mh_info = + XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO, + sizeof(struct bgp_path_mh_info)); /* If nh_info doesn't exist allocate it */ nh_info = mh_info->nh_info; @@ -4738,8 +4745,8 @@ static void bgp_evpn_path_nh_link(struct bgp *bgp_vrf, struct bgp_path_info *pi) return; } - nh_info = (pi->extra && pi->extra->mh_info) - ? pi->extra->mh_info->nh_info + nh_info = (pi->extra && pi->extra->evpn && pi->extra->evpn->mh_info) + ? pi->extra->evpn->mh_info->nh_info : NULL; /* if NHG is not being used for this path we don't need to manage the @@ -4805,8 +4812,8 @@ void bgp_evpn_path_nh_del(struct bgp *bgp_vrf, struct bgp_path_info *pi) { struct bgp_path_evpn_nh_info *nh_info; - nh_info = (pi->extra && pi->extra->mh_info) - ? pi->extra->mh_info->nh_info + nh_info = (pi->extra && pi->extra->evpn && pi->extra->evpn->mh_info) + ? pi->extra->evpn->mh_info->nh_info : NULL; if (!nh_info) diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 8cee048b69..f141ddd6ef 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -581,32 +581,32 @@ evpn_type2_prefix_vni_mac_copy(struct prefix_evpn *vni_p, static inline struct ethaddr * evpn_type2_path_info_get_mac(const struct bgp_path_info *local_pi) { - assert(local_pi->extra); - return &local_pi->extra->vni_info.mac; + assert(local_pi->extra && local_pi->extra->evpn); + return &local_pi->extra->evpn->vni_info.mac; } /* Get IP of path_info prefix */ static inline struct ipaddr * evpn_type2_path_info_get_ip(const struct bgp_path_info *local_pi) { - assert(local_pi->extra); - return &local_pi->extra->vni_info.ip; + assert(local_pi->extra && local_pi->extra->evpn); + return &local_pi->extra->evpn->vni_info.ip; } /* Set MAC of path_info prefix */ static inline void evpn_type2_path_info_set_mac(struct bgp_path_info *local_pi, const struct ethaddr mac) { - assert(local_pi->extra); - local_pi->extra->vni_info.mac = mac; + assert(local_pi->extra && local_pi->extra->evpn); + local_pi->extra->evpn->vni_info.mac = mac; } /* Set IP of path_info prefix */ static inline void evpn_type2_path_info_set_ip(struct bgp_path_info *local_pi, const struct ipaddr ip) { - assert(local_pi->extra); - local_pi->extra->vni_info.ip = ip; + assert(local_pi->extra && local_pi->extra->evpn); + local_pi->extra->evpn->vni_info.ip = ip; } /* Is the IP empty for the RT's dest? */ diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index 7df1423e59..a295ec5a14 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -355,7 +355,8 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, bgp_path_info_extra_get(path); bool list_began = false; - if (extra->bgp_fs_pbr && listcount(extra->bgp_fs_pbr)) { + if (extra->flowspec && extra->flowspec->bgp_fs_pbr && + listcount(extra->flowspec->bgp_fs_pbr)) { struct listnode *node; struct bgp_pbr_match_entry *bpme; struct bgp_pbr_match *bpm; @@ -363,8 +364,8 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, list_bpm = list_new(); vty_out(vty, "\tinstalled in PBR"); - for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_pbr, - node, bpme)) { + for (ALL_LIST_ELEMENTS_RO(extra->flowspec->bgp_fs_pbr, node, + bpme)) { bpm = bpme->backpointer; if (listnode_lookup(list_bpm, bpm)) continue; @@ -378,13 +379,14 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, } list_delete(&list_bpm); } - if (extra->bgp_fs_iprule && listcount(extra->bgp_fs_iprule)) { + if (extra->flowspec && extra->flowspec->bgp_fs_iprule && + listcount(extra->flowspec->bgp_fs_iprule)) { struct listnode *node; struct bgp_pbr_rule *bpr; if (!list_began) vty_out(vty, "\tinstalled in PBR"); - for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_iprule, + for (ALL_LIST_ELEMENTS_RO(extra->flowspec->bgp_fs_iprule, node, bpr)) { if (!bpr->action) continue; diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index d7b18de676..edaaef6021 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -37,6 +37,9 @@ DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table"); DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node"); DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route"); DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info"); +DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_EVPN, "BGP extra info for EVPN"); +DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_FS, "BGP extra info for flowspec"); +DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_VRFLEAK, "BGP extra info for vrf leaking"); DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected"); DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static"); DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr"); diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h index 7b00497714..1256eafd00 100644 --- a/bgpd/bgp_memory.h +++ b/bgpd/bgp_memory.h @@ -33,6 +33,9 @@ DECLARE_MTYPE(BGP_TABLE); DECLARE_MTYPE(BGP_NODE); DECLARE_MTYPE(BGP_ROUTE); DECLARE_MTYPE(BGP_ROUTE_EXTRA); +DECLARE_MTYPE(BGP_ROUTE_EXTRA_EVPN); +DECLARE_MTYPE(BGP_ROUTE_EXTRA_FS); +DECLARE_MTYPE(BGP_ROUTE_EXTRA_VRFLEAK); DECLARE_MTYPE(BGP_CONN); DECLARE_MTYPE(BGP_STATIC); DECLARE_MTYPE(BGP_ADVERTISE_ATTR); diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c index e920d5753e..f2d1ee0bf3 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -173,10 +173,11 @@ int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, * if they belong to same VRF */ if (!compare && bpi1->attr->nh_type != NEXTHOP_TYPE_BLACKHOLE) { - if (bpi1->extra && bpi1->extra->bgp_orig && bpi2->extra - && bpi2->extra->bgp_orig) { - if (bpi1->extra->bgp_orig->vrf_id - != bpi2->extra->bgp_orig->vrf_id) { + if (bpi1->extra && bpi1->extra->vrfleak && + bpi1->extra->vrfleak->bgp_orig && bpi2->extra && + bpi2->extra->vrfleak && bpi2->extra->vrfleak->bgp_orig) { + if (bpi1->extra->vrfleak->bgp_orig->vrf_id != + bpi2->extra->vrfleak->bgp_orig->vrf_id) { compare = 1; } } diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index da599688ea..ad66720512 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -996,41 +996,6 @@ static void setlabels(struct bgp_path_info *bpi, extra->num_labels = num_labels; } -/* - * make encoded route SIDs match specified encoded sid set - */ -static void setsids(struct bgp_path_info *bpi, - struct in6_addr *sid, - uint32_t num_sids) -{ - uint32_t i; - struct bgp_path_info_extra *extra; - - if (num_sids) - assert(sid); - assert(num_sids <= BGP_MAX_SIDS); - - if (!num_sids) { - if (bpi->extra) - bpi->extra->num_sids = 0; - return; - } - - extra = bgp_path_info_extra_get(bpi); - for (i = 0; i < num_sids; i++) - memcpy(&extra->sid[i].sid, &sid[i], sizeof(struct in6_addr)); - extra->num_sids = num_sids; -} - -static void unsetsids(struct bgp_path_info *bpi) -{ - struct bgp_path_info_extra *extra; - - extra = bgp_path_info_extra_get(bpi); - extra->num_sids = 0; - memset(extra->sid, 0, sizeof(extra->sid)); -} - static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn, struct attr *new_attr, afi_t afi, safi_t safi, @@ -1045,8 +1010,8 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn, bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi); - if (bpi->extra && bpi->extra->bgp_orig) - bgp_nexthop = bpi->extra->bgp_orig; + if (bpi->extra && bpi->extra->vrfleak && bpi->extra->vrfleak->bgp_orig) + bgp_nexthop = bpi->extra->vrfleak->bgp_orig; else bgp_nexthop = bgp_orig; @@ -1098,12 +1063,8 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, struct bgp_path_info *bpi; struct bgp_path_info *new; struct bgp_path_info_extra *extra; - uint32_t num_sids = 0; struct bgp_path_info *parent = source_bpi; - if (new_attr->srv6_l3vpn || new_attr->srv6_vpn) - num_sids = 1; - if (debug) zlog_debug( "%s: entry: leak-to=%s, p=%pBD, type=%d, sub_type=%d", @@ -1132,7 +1093,8 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, * match parent */ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { - if (bpi->extra && bpi->extra->parent == parent) + if (bpi->extra && bpi->extra->vrfleak && + bpi->extra->vrfleak->parent == parent) break; } @@ -1200,34 +1162,6 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, if (!labelssame) setlabels(bpi, label, num_labels); - /* - * rewrite sid - */ - if (num_sids) { - if (new_attr->srv6_l3vpn) { - setsids(bpi, &new_attr->srv6_l3vpn->sid, - num_sids); - - extra = bgp_path_info_extra_get(bpi); - - extra->sid[0].loc_block_len = - new_attr->srv6_l3vpn->loc_block_len; - extra->sid[0].loc_node_len = - new_attr->srv6_l3vpn->loc_node_len; - extra->sid[0].func_len = - new_attr->srv6_l3vpn->func_len; - extra->sid[0].arg_len = - new_attr->srv6_l3vpn->arg_len; - extra->sid[0].transposition_len = - new_attr->srv6_l3vpn->transposition_len; - extra->sid[0].transposition_offset = - new_attr->srv6_l3vpn - ->transposition_offset; - } else if (new_attr->srv6_vpn) - setsids(bpi, &new_attr->srv6_vpn->sid, - num_sids); - } else - unsetsids(bpi); if (nexthop_self_flag) bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF); @@ -1267,9 +1201,15 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0, to_bgp->peer_self, new_attr, bn); + bgp_path_info_extra_get(new); + if (!new->extra->vrfleak) + new->extra->vrfleak = + XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK, + sizeof(struct bgp_path_info_extra_vrfleak)); + if (source_bpi->peer) { extra = bgp_path_info_extra_get(new); - extra->peer_orig = peer_lock(source_bpi->peer); + extra->vrfleak->peer_orig = peer_lock(source_bpi->peer); } if (nexthop_self_flag) @@ -1278,42 +1218,16 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN)) bgp_path_info_set_flag(bn, new, BGP_PATH_ACCEPT_OWN); - bgp_path_info_extra_get(new); - - /* - * rewrite sid - */ - if (num_sids) { - if (new_attr->srv6_l3vpn) { - setsids(new, &new_attr->srv6_l3vpn->sid, num_sids); - - extra = bgp_path_info_extra_get(new); - - extra->sid[0].loc_block_len = - new_attr->srv6_l3vpn->loc_block_len; - extra->sid[0].loc_node_len = - new_attr->srv6_l3vpn->loc_node_len; - extra->sid[0].func_len = new_attr->srv6_l3vpn->func_len; - extra->sid[0].arg_len = new_attr->srv6_l3vpn->arg_len; - extra->sid[0].transposition_len = - new_attr->srv6_l3vpn->transposition_len; - extra->sid[0].transposition_offset = - new_attr->srv6_l3vpn->transposition_offset; - } else if (new_attr->srv6_vpn) - setsids(new, &new_attr->srv6_vpn->sid, num_sids); - } else - unsetsids(new); - if (num_labels) setlabels(new, label, num_labels); - new->extra->parent = bgp_path_info_lock(parent); + new->extra->vrfleak->parent = bgp_path_info_lock(parent); bgp_dest_lock_node( (struct bgp_dest *)parent->net); if (bgp_orig) - new->extra->bgp_orig = bgp_lock(bgp_orig); + new->extra->vrfleak->bgp_orig = bgp_lock(bgp_orig); if (nexthop_orig) - new->extra->nexthop_orig = *nexthop_orig; + new->extra->vrfleak->nexthop_orig = *nexthop_orig; if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi, source_bpi, new, bgp_orig, p, debug)) @@ -1554,8 +1468,8 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi, /* Check the next-hop reachability. * Get the bgp instance where the bgp_path_info originates. */ - if (pi->extra && pi->extra->bgp_orig) - bgp_nexthop = pi->extra->bgp_orig; + if (pi->extra && pi->extra->vrfleak && pi->extra->vrfleak->bgp_orig) + bgp_nexthop = pi->extra->vrfleak->bgp_orig; else bgp_nexthop = from_bgp; @@ -1986,7 +1900,8 @@ void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */ * match original bpi imported from */ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { - if (bpi->extra && bpi->extra->parent == path_vrf) { + if (bpi->extra && bpi->extra->vrfleak && + bpi->extra->vrfleak->parent == path_vrf) { break; } } @@ -2039,9 +1954,9 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp, bpi->sub_type); if (bpi->sub_type != BGP_ROUTE_IMPORTED) continue; - if (!bpi->extra) + if (!bpi->extra || !bpi->extra->vrfleak) continue; - if ((struct bgp *)bpi->extra->bgp_orig == + if ((struct bgp *)bpi->extra->vrfleak->bgp_orig == from_bgp) { /* delete route */ if (debug) @@ -2055,7 +1970,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp, bgp_path_info_delete(bn, bpi); bgp_process(to_bgp, bn, afi, safi); bgp_mplsvpn_path_nh_label_unlink( - bpi->extra->parent); + bpi->extra->vrfleak->parent); } } } @@ -2162,8 +2077,9 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ */ struct bgp *src_bgp = bgp_lookup_by_rd(path_vpn, prd, afi); - if (path_vpn->extra && path_vpn->extra->bgp_orig) - src_vrf = path_vpn->extra->bgp_orig; + if (path_vpn->extra && path_vpn->extra->vrfleak && + path_vpn->extra->vrfleak->bgp_orig) + src_vrf = path_vpn->extra->vrfleak->bgp_orig; else if (src_bgp) src_vrf = src_bgp; else @@ -2429,9 +2345,8 @@ void vpn_leak_to_vrf_update(struct bgp *from_bgp, /* Loop over VRFs */ for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { - - if (!path_vpn->extra - || path_vpn->extra->bgp_orig != bgp) { /* no loop */ + if (!path_vpn->extra || !path_vpn->extra->vrfleak || + path_vpn->extra->vrfleak->bgp_orig != bgp) { /* no loop */ vpn_leak_to_vrf_update_onevrf(bgp, from_bgp, path_vpn, prd); } @@ -2504,9 +2419,9 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn) for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { - if (bpi->extra - && (struct bgp_path_info *)bpi->extra->parent - == path_vpn) { + if (bpi->extra && bpi->extra->vrfleak && + (struct bgp_path_info *)bpi->extra->vrfleak->parent == + path_vpn) { break; } } @@ -2540,10 +2455,10 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi) for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { - if (bpi->extra && bpi->extra->bgp_orig != to_bgp && - bpi->extra->parent && - is_pi_family_vpn(bpi->extra->parent)) { - + if (bpi->extra && bpi->extra->vrfleak && + bpi->extra->vrfleak->bgp_orig != to_bgp && + bpi->extra->vrfleak->parent && + is_pi_family_vpn(bpi->extra->vrfleak->parent)) { /* delete route */ bgp_aggregate_decrement(to_bgp, bgp_dest_get_prefix(bn), @@ -2580,9 +2495,8 @@ void vpn_leak_no_retain(struct bgp *to_bgp, struct bgp *vpn_from, afi_t afi) for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) { for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { - - if (bpi->extra && - bpi->extra->bgp_orig == to_bgp) + if (bpi->extra && bpi->extra->vrfleak && + bpi->extra->vrfleak->bgp_orig == to_bgp) continue; if (bpi->sub_type != BGP_ROUTE_NORMAL) @@ -2627,9 +2541,8 @@ void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from, for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { - - if (bpi->extra && - bpi->extra->bgp_orig == to_bgp) + if (bpi->extra && bpi->extra->vrfleak && + bpi->extra->vrfleak->bgp_orig == to_bgp) continue; vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from, diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index dcde42146c..62748a9e56 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -298,12 +298,11 @@ static inline bool is_route_injectable_into_vpn(struct bgp_path_info *pi) struct bgp_table *table; struct bgp_dest *dest; - if (pi->sub_type != BGP_ROUTE_IMPORTED || - !pi->extra || - !pi->extra->parent) + if (pi->sub_type != BGP_ROUTE_IMPORTED || !pi->extra || + !pi->extra->vrfleak || !pi->extra->vrfleak->parent) return true; - parent_pi = (struct bgp_path_info *)pi->extra->parent; + parent_pi = (struct bgp_path_info *)pi->extra->vrfleak->parent; dest = parent_pi->net; if (!dest) return true; diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 02cfd9c2af..bbc30365c7 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -56,10 +56,11 @@ static int bgp_isvalid_nexthop_for_ebgp(struct bgp_nexthop_cache *bnc, struct bgp_interface *iifp; struct peer *peer; - if (!path->extra || !path->extra->peer_orig) + if (!path->extra || !path->extra->vrfleak || + !path->extra->vrfleak->peer_orig) return false; - peer = path->extra->peer_orig; + peer = path->extra->vrfleak->peer_orig; /* only connected ebgp peers are valid */ if (peer->sort != BGP_PEER_EBGP || peer->ttl != BGP_DEFAULT_TTL || diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index bc9ecff7d9..43682de413 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -1667,8 +1667,8 @@ static void bgp_pbr_flush_iprule(struct bgp *bgp, struct bgp_pbr_action *bpa, /* unlink path to bpme */ path = (struct bgp_path_info *)bpr->path; extra = bgp_path_info_extra_get(path); - if (extra->bgp_fs_iprule) - listnode_delete(extra->bgp_fs_iprule, bpr); + if (extra->flowspec && extra->flowspec->bgp_fs_iprule) + listnode_delete(extra->flowspec->bgp_fs_iprule, bpr); bpr->path = NULL; } } @@ -1696,8 +1696,8 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa, /* unlink path to bpme */ path = (struct bgp_path_info *)bpme->path; extra = bgp_path_info_extra_get(path); - if (extra->bgp_fs_pbr) - listnode_delete(extra->bgp_fs_pbr, bpme); + if (extra->flowspec && extra->flowspec->bgp_fs_pbr) + listnode_delete(extra->flowspec->bgp_fs_pbr, bpme); bpme->path = NULL; } } @@ -2342,8 +2342,8 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, struct bgp_path_info_extra *extra = bgp_path_info_extra_get(path); - if (extra && - listnode_lookup_nocheck(extra->bgp_fs_iprule, + if (extra && extra->flowspec && + listnode_lookup_nocheck(extra->flowspec->bgp_fs_iprule, bpr)) { if (BGP_DEBUG(pbr, PBR_ERROR)) zlog_err("%s: entry %p/%p already installed in bgp pbr iprule", @@ -2501,8 +2501,8 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, struct bgp_path_info_extra *extra = bgp_path_info_extra_get(path); - if (extra && - listnode_lookup_nocheck(extra->bgp_fs_pbr, bpme)) { + if (extra && extra->flowspec && + listnode_lookup_nocheck(extra->flowspec->bgp_fs_pbr, bpme)) { if (BGP_DEBUG(pbr, PBR_ERROR)) zlog_err( "%s: entry %p/%p already installed in bgp pbr", diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 5f923c598f..839f6d3669 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -188,8 +188,7 @@ static struct bgp_path_info_extra *bgp_path_info_extra_new(void) sizeof(struct bgp_path_info_extra)); new->label[0] = MPLS_INVALID_LABEL; new->num_labels = 0; - new->bgp_fs_pbr = NULL; - new->bgp_fs_iprule = NULL; + new->flowspec = NULL; return new; } @@ -206,8 +205,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra) e->damp_info->safi); e->damp_info = NULL; - if (e->parent) { - struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent; + if (e->vrfleak && e->vrfleak->parent) { + struct bgp_path_info *bpi = + (struct bgp_path_info *)e->vrfleak->parent; if (bpi->net) { /* FIXME: since multiple e may have the same e->parent @@ -227,26 +227,34 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra) bpi->net = NULL; bgp_path_info_unlock(bpi); } - bgp_path_info_unlock(e->parent); - e->parent = NULL; + bgp_path_info_unlock(e->vrfleak->parent); + e->vrfleak->parent = NULL; } - if (e->bgp_orig) - bgp_unlock(e->bgp_orig); + if (e->vrfleak && e->vrfleak->bgp_orig) + bgp_unlock(e->vrfleak->bgp_orig); - if (e->peer_orig) - peer_unlock(e->peer_orig); + if (e->vrfleak && e->vrfleak->peer_orig) + peer_unlock(e->vrfleak->peer_orig); if (e->aggr_suppressors) list_delete(&e->aggr_suppressors); - if (e->mh_info) - bgp_evpn_path_mh_info_free(e->mh_info); + if (e->evpn && e->evpn->mh_info) + bgp_evpn_path_mh_info_free(e->evpn->mh_info); + + if ((*extra)->flowspec && (*extra)->flowspec->bgp_fs_iprule) + list_delete(&((*extra)->flowspec->bgp_fs_iprule)); + if ((*extra)->flowspec && (*extra)->flowspec->bgp_fs_pbr) + list_delete(&((*extra)->flowspec->bgp_fs_pbr)); + + if (e->evpn) + XFREE(MTYPE_BGP_ROUTE_EXTRA_EVPN, e->evpn); + if (e->flowspec) + XFREE(MTYPE_BGP_ROUTE_EXTRA_FS, e->flowspec); + if (e->vrfleak) + XFREE(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK, e->vrfleak); - if ((*extra)->bgp_fs_iprule) - list_delete(&((*extra)->bgp_fs_iprule)); - if ((*extra)->bgp_fs_pbr) - list_delete(&((*extra)->bgp_fs_pbr)); XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra); } @@ -257,6 +265,10 @@ struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi) { if (!pi->extra) pi->extra = bgp_path_info_extra_new(); + if (!pi->extra->evpn && pi->net && pi->net->p.family == AF_EVPN) + pi->extra->evpn = + XCALLOC(MTYPE_BGP_ROUTE_EXTRA_EVPN, + sizeof(struct bgp_path_info_extra_evpn)); return pi->extra; } @@ -570,8 +582,9 @@ struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info) return info; for (bpi_ultimate = info; - bpi_ultimate->extra && bpi_ultimate->extra->parent; - bpi_ultimate = bpi_ultimate->extra->parent) + bpi_ultimate->extra && bpi_ultimate->extra->vrfleak && + bpi_ultimate->extra->vrfleak->parent; + bpi_ultimate = bpi_ultimate->extra->vrfleak->parent) ; return bpi_ultimate; @@ -4674,49 +4687,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, bgp_set_valid_label(&extra->label[0]); } - /* Update SRv6 SID */ - if (attr->srv6_l3vpn) { - extra = bgp_path_info_extra_get(pi); - if (sid_diff(&extra->sid[0].sid, - &attr->srv6_l3vpn->sid)) { - sid_copy(&extra->sid[0].sid, - &attr->srv6_l3vpn->sid); - extra->num_sids = 1; - - extra->sid[0].loc_block_len = 0; - extra->sid[0].loc_node_len = 0; - extra->sid[0].func_len = 0; - extra->sid[0].arg_len = 0; - extra->sid[0].transposition_len = 0; - extra->sid[0].transposition_offset = 0; - - if (attr->srv6_l3vpn->loc_block_len != 0) { - extra->sid[0].loc_block_len = - attr->srv6_l3vpn->loc_block_len; - extra->sid[0].loc_node_len = - attr->srv6_l3vpn->loc_node_len; - extra->sid[0].func_len = - attr->srv6_l3vpn->func_len; - extra->sid[0].arg_len = - attr->srv6_l3vpn->arg_len; - extra->sid[0].transposition_len = - attr->srv6_l3vpn - ->transposition_len; - extra->sid[0].transposition_offset = - attr->srv6_l3vpn - ->transposition_offset; - } - } - } else if (attr->srv6_vpn) { - extra = bgp_path_info_extra_get(pi); - if (sid_diff(&extra->sid[0].sid, - &attr->srv6_vpn->sid)) { - sid_copy(&extra->sid[0].sid, - &attr->srv6_vpn->sid); - extra->num_sids = 1; - } - } - #ifdef ENABLE_BGP_VNC if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { @@ -4771,8 +4741,9 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, struct bgp *bgp_nexthop = bgp; - if (pi->extra && pi->extra->bgp_orig) - bgp_nexthop = pi->extra->bgp_orig; + if (pi->extra && pi->extra->vrfleak && + pi->extra->vrfleak->bgp_orig) + bgp_nexthop = pi->extra->vrfleak->bgp_orig; nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr); @@ -4901,29 +4872,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, bgp_set_valid_label(&extra->label[0]); } - /* Update SRv6 SID */ - if (safi == SAFI_MPLS_VPN) { - extra = bgp_path_info_extra_get(new); - if (attr->srv6_l3vpn) { - sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid); - extra->num_sids = 1; - - extra->sid[0].loc_block_len = - attr->srv6_l3vpn->loc_block_len; - extra->sid[0].loc_node_len = - attr->srv6_l3vpn->loc_node_len; - extra->sid[0].func_len = attr->srv6_l3vpn->func_len; - extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len; - extra->sid[0].transposition_len = - attr->srv6_l3vpn->transposition_len; - extra->sid[0].transposition_offset = - attr->srv6_l3vpn->transposition_offset; - } else if (attr->srv6_vpn) { - sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid); - extra->num_sids = 1; - } - } - /* Nexthop reachability check. */ if (((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST || @@ -9167,26 +9115,27 @@ void route_vty_out(struct vty *vty, const struct prefix *p, * If vrf id of nexthop is different from that of prefix, * set up printable string to append */ - if (path->extra && path->extra->bgp_orig) { + if (path->extra && path->extra->vrfleak && + path->extra->vrfleak->bgp_orig) { const char *self = ""; if (nexthop_self) self = "<"; nexthop_othervrf = true; - nexthop_vrfid = path->extra->bgp_orig->vrf_id; + nexthop_vrfid = path->extra->vrfleak->bgp_orig->vrf_id; - if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN) + if (path->extra->vrfleak->bgp_orig->vrf_id == VRF_UNKNOWN) snprintf(vrf_id_str, sizeof(vrf_id_str), "@%s%s", VRFID_NONE_STR, self); else snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s", - path->extra->bgp_orig->vrf_id, self); + path->extra->vrfleak->bgp_orig->vrf_id, self); - if (path->extra->bgp_orig->inst_type - != BGP_INSTANCE_TYPE_DEFAULT) + if (path->extra->vrfleak->bgp_orig->inst_type != + BGP_INSTANCE_TYPE_DEFAULT) - nexthop_vrfname = path->extra->bgp_orig->name; + nexthop_vrfname = path->extra->vrfleak->bgp_orig->name; } else { const char *self = ""; @@ -10301,11 +10250,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, vty_out(vty, "\n"); - if (path->extra && path->extra->parent && !json_paths) { + if (path->extra && path->extra->vrfleak && + path->extra->vrfleak->parent && !json_paths) { struct bgp_path_info *parent_ri; struct bgp_dest *dest, *pdest; - parent_ri = (struct bgp_path_info *)path->extra->parent; + parent_ri = + (struct bgp_path_info *)path->extra->vrfleak->parent; dest = parent_ri->net; if (dest && dest->pdest) { pdest = dest->pdest; @@ -10608,17 +10559,18 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, /* * Note when vrfid of nexthop is different from that of prefix */ - if (path->extra && path->extra->bgp_orig) { - vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id; + if (path->extra && path->extra->vrfleak && + path->extra->vrfleak->bgp_orig) { + vrf_id_t nexthop_vrfid = path->extra->vrfleak->bgp_orig->vrf_id; if (json_paths) { const char *vn; - if (path->extra->bgp_orig->inst_type - == BGP_INSTANCE_TYPE_DEFAULT) + if (path->extra->vrfleak->bgp_orig->inst_type == + BGP_INSTANCE_TYPE_DEFAULT) vn = VRF_DEFAULT_NAME; else - vn = path->extra->bgp_orig->name; + vn = path->extra->vrfleak->bgp_orig->name; json_object_string_add(json_path, "nhVrfName", vn); @@ -11013,13 +10965,16 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, } /* Remote SID */ - if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) { + if ((path->attr->srv6_l3vpn || path->attr->srv6_vpn) && + safi != SAFI_EVPN) { + struct in6_addr *sid_tmp = + path->attr->srv6_l3vpn ? (&path->attr->srv6_l3vpn->sid) + : (&path->attr->srv6_vpn->sid); if (json_paths) json_object_string_addf(json_path, "remoteSid", "%pI6", - &path->extra->sid[0].sid); + sid_tmp); else - vty_out(vty, " Remote SID: %pI6\n", - &path->extra->sid[0].sid); + vty_out(vty, " Remote SID: %pI6\n", sid_tmp); } /* Label Index */ diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 265587c424..0a6f535b22 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -145,6 +145,54 @@ struct bgp_sid_info { uint8_t transposition_offset; }; +/* new structure for EVPN */ +struct bgp_path_info_extra_evpn { +#define BGP_EVPN_MACIP_TYPE_SVI_IP (1 << 0) + /* af specific flags */ + uint16_t af_flags; + union { + struct ethaddr mac; /* MAC set here for VNI IP table */ + struct ipaddr ip; /* IP set here for VNI MAC table */ + } vni_info; + /* Destination Ethernet Segment links for EVPN MH */ + struct bgp_path_mh_info *mh_info; +}; + +/* new structure for flowspec*/ +struct bgp_path_info_extra_fs { + /* presence of FS pbr firewall based entry */ + struct list *bgp_fs_pbr; + /* presence of FS pbr iprule based entry */ + struct list *bgp_fs_iprule; +}; + +/* new structure for vrfleak*/ +struct bgp_path_info_extra_vrfleak { + void *parent; /* parent from global table */ + /* + * Original bgp instance for imported routes. Needed for: + * 1. Find all routes from a specific vrf for deletion + * 2. vrf context of original nexthop + * + * Store pointer to bgp instance rather than bgp->vrf_id because + * bgp->vrf_id is not always valid (or may change?). + * + * Set to NULL if route is not imported from another bgp instance. + */ + struct bgp *bgp_orig; + /* + * Original bgp session to know if the session is a + * connected EBGP session or not + */ + struct peer *peer_orig; + /* + * Nexthop in context of original bgp instance. Needed + * for label resolution of core mpls routes exported to a vrf. + * Set nexthop_orig.family to 0 if not valid. + */ + struct prefix nexthop_orig; +}; + /* Ancillary information to struct bgp_path_info, * used for uncommonly used data (aggregation, MPLS, etc.) * and lazily allocated to save memory. @@ -163,13 +211,8 @@ struct bgp_path_info_extra { mpls_label_t label[BGP_MAX_LABELS]; uint32_t num_labels; - /* af specific flags */ - uint16_t af_flags; -#define BGP_EVPN_MACIP_TYPE_SVI_IP (1 << 0) - - /* SRv6 SID(s) for SRv6-VPN */ - struct bgp_sid_info sid[BGP_MAX_SIDS]; - uint32_t num_sids; + /*For EVPN*/ + struct bgp_path_info_extra_evpn *evpn; #ifdef ENABLE_BGP_VNC union { @@ -200,50 +243,11 @@ struct bgp_path_info_extra { } vnc; #endif - /* - * For imported routes into a VNI (or VRF) - */ - void *parent; /* parent from global table */ - union { - struct ethaddr mac; /* MAC set here for VNI IP table */ - struct ipaddr ip; /* IP set here for VNI MAC table */ - } vni_info; - - /* - * Some tunnelish parameters follow. Maybe consolidate into an - * internal tunnel structure? - */ - - /* - * Original bgp instance for imported routes. Needed for: - * 1. Find all routes from a specific vrf for deletion - * 2. vrf context of original nexthop - * - * Store pointer to bgp instance rather than bgp->vrf_id because - * bgp->vrf_id is not always valid (or may change?). - * - * Set to NULL if route is not imported from another bgp instance. - */ - struct bgp *bgp_orig; - - /* - * Original bgp session to know if the session is a - * connected EBGP session or not - */ - struct peer *peer_orig; + /* For flowspec*/ + struct bgp_path_info_extra_fs *flowspec; - /* - * Nexthop in context of original bgp instance. Needed - * for label resolution of core mpls routes exported to a vrf. - * Set nexthop_orig.family to 0 if not valid. - */ - struct prefix nexthop_orig; - /* presence of FS pbr firewall based entry */ - struct list *bgp_fs_pbr; - /* presence of FS pbr iprule based entry */ - struct list *bgp_fs_iprule; - /* Destination Ethernet Segment links for EVPN MH */ - struct bgp_path_mh_info *mh_info; + /* For vrf leaking*/ + struct bgp_path_info_extra_vrfleak *vrfleak; }; struct bgp_mplsvpn_label_nh { diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 0990567776..8fa0a4d4f3 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1313,12 +1313,13 @@ route_match_vrl_source_vrf(void *rule, const struct prefix *prefix, if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0) return RMAP_NOMATCH; - if (path->extra == NULL || path->extra->bgp_orig == NULL) + if (path->extra == NULL || path->extra->vrfleak == NULL || + path->extra->vrfleak->bgp_orig == NULL) return RMAP_NOMATCH; - if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id), - VRF_NAMSIZ) - == 0) + if (strncmp(vrf_name, + vrf_id_to_name(path->extra->vrfleak->bgp_orig->vrf_id), + VRF_NAMSIZ) == 0) return RMAP_MATCH; return RMAP_NOMATCH; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 4f773f21a5..f5bee8110e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -10959,6 +10959,29 @@ DEFUN (show_bgp_memory, memstrbuf, sizeof(memstrbuf), count * sizeof(struct bgp_path_info_extra))); + count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_EVPN); + if (count) + vty_out(vty, "%ld BGP extra info for EVPN, using %s of memory\n", + count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_path_info_extra_evpn))); + + count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_FS); + if (count) + vty_out(vty, + "%ld BGP extra info for flowspec, using %s of memory\n", + count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_path_info_extra_fs))); + + count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK); + if (count) + vty_out(vty, + "%ld BGP extra info for vrf leaking, using %s of memory\n", + count, + mtype_memstr(memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_path_info_extra_vrfleak))); + if ((count = mtype_stats_alloc(MTYPE_BGP_STATIC))) vty_out(vty, "%ld Static routes, using %s of memory\n", count, mtype_memstr(memstrbuf, sizeof(memstrbuf), diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index becd99167f..ac5aef6515 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1308,7 +1308,6 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, struct bgp_path_info local_info; struct bgp_path_info *mpinfo_cp = &local_info; route_tag_t tag; - struct bgp_sid_info *sid_info; mpls_label_t *labels; uint32_t num_labels = 0; mpls_label_t nh_label; @@ -1348,7 +1347,8 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, /* * vrf leaking support (will have only one nexthop) */ - if (info->extra && info->extra->bgp_orig) + if (info->extra && info->extra->vrfleak && + info->extra->vrfleak->bgp_orig) nh_othervrf = 1; /* Make Zebra API structure. */ @@ -1364,8 +1364,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, && info->sub_type == BGP_ROUTE_IMPORTED) { /* Obtain peer from parent */ - if (info->extra && info->extra->parent) - peer = ((struct bgp_path_info *)(info->extra->parent)) + if (info->extra && info->extra->vrfleak && + info->extra->vrfleak->parent) + peer = ((struct bgp_path_info *)(info->extra->vrfleak + ->parent)) ->peer; } @@ -1553,15 +1555,21 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, api_nh->weight = nh_weight; - if (mpinfo->extra && !is_evpn && - bgp_is_valid_label(&labels[0]) && - !sid_zero(&mpinfo->extra->sid[0].sid)) { - sid_info = &mpinfo->extra->sid[0]; - - memcpy(&api_nh->seg6_segs, &sid_info->sid, + if (((mpinfo->attr->srv6_l3vpn && + !sid_zero(&mpinfo->attr->srv6_l3vpn->sid)) || + (mpinfo->attr->srv6_vpn && + !sid_zero(&mpinfo->attr->srv6_vpn->sid))) && + !is_evpn && bgp_is_valid_label(&labels[0])) { + struct in6_addr *sid_tmp = + mpinfo->attr->srv6_l3vpn + ? (&mpinfo->attr->srv6_l3vpn->sid) + : (&mpinfo->attr->srv6_vpn->sid); + + memcpy(&api_nh->seg6_segs, sid_tmp, sizeof(api_nh->seg6_segs)); - if (sid_info->transposition_len != 0) { + if (mpinfo->attr->srv6_l3vpn && + mpinfo->attr->srv6_l3vpn->transposition_len != 0) { mpls_lse_decode(labels[0], &nh_label, &ttl, &exp, &bos); @@ -1573,8 +1581,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, } transpose_sid(&api_nh->seg6_segs, nh_label, - sid_info->transposition_offset, - sid_info->transposition_len); + mpinfo->attr->srv6_l3vpn + ->transposition_offset, + mpinfo->attr->srv6_l3vpn + ->transposition_len); } SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6); @@ -2436,8 +2446,14 @@ static int rule_notify_owner(ZAPI_CALLBACK_ARGS) /* link bgp_info to bgp_pbr */ path = (struct bgp_path_info *)bgp_pbr->path; extra = bgp_path_info_extra_get(path); - listnode_add_force(&extra->bgp_fs_iprule, - bgp_pbr); + if (!extra->flowspec) { + extra->flowspec = + XCALLOC(MTYPE_BGP_ROUTE_EXTRA_FS, + sizeof(struct bgp_path_info_extra_fs)); + extra->flowspec->bgp_fs_iprule = NULL; + extra->flowspec->bgp_fs_pbr = NULL; + } + listnode_add_force(&extra->flowspec->bgp_fs_iprule, bgp_pbr); } if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("%s: Received RULE_INSTALLED", __func__); @@ -2539,7 +2555,14 @@ static int ipset_entry_notify_owner(ZAPI_CALLBACK_ARGS) /* link bgp_path_info to bpme */ path = (struct bgp_path_info *)bgp_pbime->path; extra = bgp_path_info_extra_get(path); - listnode_add_force(&extra->bgp_fs_pbr, bgp_pbime); + if (!extra->flowspec) { + extra->flowspec = + XCALLOC(MTYPE_BGP_ROUTE_EXTRA_FS, + sizeof(struct bgp_path_info_extra_fs)); + extra->flowspec->bgp_fs_iprule = NULL; + extra->flowspec->bgp_fs_pbr = NULL; + } + listnode_add_force(&extra->flowspec->bgp_fs_pbr, bgp_pbime); } break; case ZAPI_IPSET_ENTRY_FAIL_REMOVE: diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index a0f7819460..ed2d5e669d 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -10,9 +10,10 @@ /* Macro to update bgp_original based on bpg_path_info */ #define BGP_ORIGINAL_UPDATE(_bgp_orig, _mpinfo, _bgp) \ - ((_mpinfo->extra && _mpinfo->extra->bgp_orig \ - && _mpinfo->sub_type == BGP_ROUTE_IMPORTED) \ - ? (_bgp_orig = _mpinfo->extra->bgp_orig) \ + ((_mpinfo->extra && _mpinfo->extra->vrfleak && \ + _mpinfo->extra->vrfleak->bgp_orig && \ + _mpinfo->sub_type == BGP_ROUTE_IMPORTED) \ + ? (_bgp_orig = _mpinfo->extra->vrfleak->bgp_orig) \ : (_bgp_orig = _bgp)) /* Default weight for next hop, if doing weighted ECMP. */ diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 29698846c3..252b6d632a 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -420,15 +420,20 @@ void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p, vty_out(vty, " label=%u", decode_label(&bpi->extra->label[0])); - if (bpi->extra->num_sids) { - vty_out(vty, " sid=%pI6", &bpi->extra->sid[0].sid); - - if (bpi->extra->sid[0].loc_block_len != 0) { + if (bpi->attr->srv6_l3vpn || bpi->attr->srv6_vpn) { + struct in6_addr *sid_tmp = + bpi->attr->srv6_l3vpn + ? (&bpi->attr->srv6_l3vpn->sid) + : (&bpi->attr->srv6_vpn->sid); + vty_out(vty, " sid=%pI6", sid_tmp); + + if (bpi->attr->srv6_l3vpn && + bpi->attr->srv6_l3vpn->loc_block_len != 0) { vty_out(vty, " sid_structure=[%d,%d,%d,%d]", - bpi->extra->sid[0].loc_block_len, - bpi->extra->sid[0].loc_node_len, - bpi->extra->sid[0].func_len, - bpi->extra->sid[0].arg_len); + bpi->attr->srv6_l3vpn->loc_block_len, + bpi->attr->srv6_l3vpn->loc_node_len, + bpi->attr->srv6_l3vpn->func_len, + bpi->attr->srv6_l3vpn->arg_len); } } } -- 2.39.5