Skip to content

Commit 1eea2e3

Browse files
bgpd: optimize attribute interning in route leak updates
This patch modifies `leak_update()` to accept a non-interned static attribute rather than requiring an already-interned one. Previously, callers such as `vpn_leak_to_vrf_update_onevrf()` and `_vpn_leak_from_vrf_update_leak_attr()` would intern the attribute prior to calling `leak_update()`. If `leak_update()` determined that the route was unchanged, it would simply unintern the attribute and continue, resulting in unnecessary memory allocation and hash table overhead. With this change, the caller passes a pointer to the static attribute, and `leak_update()` now defers calling `bgp_attr_intern()` until it actually needs to update an existing path or allocate a new one. The callers handle flushing the static attribute when done. Additionally, this commit fixes a minor issue during new path creation: if the new leaked path is determined to have a valid nexthop, the `BGP_ATTR_NH_VALID` flag is now correctly set on the newly interned attribute's `nh_flags`. Signed-off-by: Francois Dumontet <[email protected]>
1 parent dd5baf1 commit 1eea2e3

File tree

1 file changed

+27
-29
lines changed

1 file changed

+27
-29
lines changed

bgpd/bgp_mplsvpn.c

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,17 +1220,18 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
12201220
/*
12211221
* returns pointer to new bgp_path_info upon success
12221222
*/
1223-
static struct bgp_path_info *
1224-
leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
1225-
struct attr *new_attr, /* already interned */
1226-
afi_t afi, safi_t safi, struct bgp_path_info *source_bpi,
1227-
mpls_label_t *label, uint8_t num_labels, struct bgp *bgp_orig,
1228-
struct prefix *nexthop_orig, int nexthop_self_flag, int debug)
1223+
static struct bgp_path_info *leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
1224+
struct attr *static_attr, /* not already interned */
1225+
afi_t afi, safi_t safi, struct bgp_path_info *source_bpi,
1226+
mpls_label_t *label, uint8_t num_labels,
1227+
struct bgp *bgp_orig, struct prefix *nexthop_orig,
1228+
int nexthop_self_flag, int debug)
12291229
{
12301230
const struct prefix *p = bgp_dest_get_prefix(bn);
12311231
struct bgp_path_info *bpi;
12321232
struct bgp_path_info *new;
12331233
struct bgp_path_info_extra *extra;
1234+
struct attr *new_attr;
12341235
struct bgp_labels bgp_labels = {};
12351236
struct bgp *bgp_nexthop;
12361237
bool labelssame;
@@ -1267,11 +1268,11 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
12671268
if (!bpi->extra || !bpi->extra->vrfleak ||
12681269
bpi->extra->vrfleak->parent != source_bpi)
12691270
continue;
1270-
if (new_attr->srv6_l3service && !bpi->attr->srv6_l3service &&
1271+
if (static_attr->srv6_l3service && !bpi->attr->srv6_l3service &&
12711272
!bgp_labels_is_implicit_null(bpi))
12721273
/* SRv6 path can not overwrite MPLS path */
12731274
continue;
1274-
if ((!new_attr->srv6_l3service && num_labels == 1 &&
1275+
if ((!static_attr->srv6_l3service && num_labels == 1 &&
12751276
decode_label(&label[0]) != MPLS_LABEL_NONE) &&
12761277
bpi->attr->srv6_l3service)
12771278
/* MPLS path can not overwrite Srv6 path */
@@ -1312,11 +1313,10 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
13121313
}
13131314

13141315
if (labelssame && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) &&
1315-
attrhash_cmp(bpi->attr, new_attr) &&
1316-
leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi, source_bpi, bpi,
1316+
attrhash_cmp(bpi->attr, static_attr) &&
1317+
leak_update_nexthop_valid(to_bgp, bn, static_attr, afi, safi, source_bpi, bpi,
13171318
bgp_orig, p,
13181319
debug) == !!CHECK_FLAG(bpi->flags, BGP_PATH_VALID)) {
1319-
bgp_attr_unintern(&new_attr);
13201320
if (debug)
13211321
zlog_debug(
13221322
"%s: ->%s: %pBD: Found route, no change",
@@ -1332,10 +1332,9 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
13321332
* set extcommunity rt none
13331333
*/
13341334
if (bgp_attr_exists(bpi->attr, BGP_ATTR_EXT_COMMUNITIES) &&
1335-
bgp_attr_exists(new_attr, BGP_ATTR_EXT_COMMUNITIES)) {
1336-
if (!ecommunity_cmp(
1337-
bgp_attr_get_ecommunity(bpi->attr),
1338-
bgp_attr_get_ecommunity(new_attr))) {
1335+
bgp_attr_exists(static_attr, BGP_ATTR_EXT_COMMUNITIES)) {
1336+
if (!ecommunity_cmp(bgp_attr_get_ecommunity(bpi->attr),
1337+
bgp_attr_get_ecommunity(static_attr))) {
13391338
vpn_leak_to_vrf_withdraw(bpi);
13401339
bgp_aggregate_decrement(to_bgp, p, bpi, afi,
13411340
safi);
@@ -1352,6 +1351,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
13521351
else
13531352
bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
13541353
bgp_attr_unintern(&bpi->attr);
1354+
new_attr = bgp_attr_intern(static_attr);
13551355
bpi->attr = new_attr;
13561356
bpi->uptime = monotime(NULL);
13571357

@@ -1408,8 +1408,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
14081408
return NULL;
14091409
}
14101410

1411-
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
1412-
to_bgp->peer_self, new_attr, bn);
1411+
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0, to_bgp->peer_self, static_attr, bn);
14131412

14141413
bgp_path_info_extra_get(new);
14151414
if (!new->extra->vrfleak)
@@ -1438,13 +1437,14 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
14381437

14391438
if (nexthop_orig)
14401439
new->extra->vrfleak->nexthop_orig = *nexthop_orig;
1441-
1442-
if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,
1443-
source_bpi, new, bgp_orig, p, debug)) {
1440+
1441+
if (leak_update_nexthop_valid(to_bgp, bn, static_attr, afi, safi, source_bpi, new,
1442+
bgp_orig, p, debug)) {
14441443
bgp_path_info_set_flag(bn, new, BGP_PATH_VALID);
14451444
SET_FLAG(new->attr->nh_flags, BGP_ATTR_NH_VALID);
14461445
} else
14471446
bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID);
1447+
new->attr = bgp_attr_intern(static_attr);
14481448

14491449
bgp_path_info_add(bn, new);
14501450
bgp_aggregate_increment(to_bgp, p, new, afi, safi);
@@ -1838,16 +1838,14 @@ static void _vpn_leak_from_vrf_update_leak_attr(struct attr *static_attr, struct
18381838
int nexthop_self_flag, int debug,
18391839
mpls_label_t *label)
18401840
{
1841-
struct attr *new_attr;
18421841
struct bgp_dest *bn;
18431842
const struct prefix *p = bgp_dest_get_prefix(path_vrf->net);
18441843
struct bgp_path_info *new_info;
18451844

1846-
new_attr = bgp_attr_intern(static_attr); /* hashed refcounted everything */
18471845
bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p,
18481846
&(from_bgp->vpn_policy[afi].tovpn_rd));
1849-
new_info = leak_update(to_bgp, bn, new_attr, afi, safi, path_vrf, label, 1, from_bgp, NULL,
1850-
nexthop_self_flag, debug);
1847+
new_info = leak_update(to_bgp, bn, static_attr, afi, safi, path_vrf, label, 1, from_bgp,
1848+
NULL, nexthop_self_flag, debug);
18511849
/*
18521850
* Routes actually installed in the vpn RIB must also be
18531851
* offered to all vrfs (because now they originate from
@@ -2331,7 +2329,6 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
23312329
afi_t afi = family2afi(p->family);
23322330

23332331
struct attr static_attr = {0};
2334-
struct attr *new_attr = NULL;
23352332
struct bgp_dest *bn;
23362333
safi_t safi = SAFI_UNICAST;
23372334
const char *debugmsg;
@@ -2612,9 +2609,10 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
26122609
static_attr.aspath = new_aspath;
26132610
}
26142611

2612+
/*
26152613
new_attr = bgp_attr_intern(&static_attr);
26162614
bgp_attr_flush(&static_attr);
2617-
2615+
*/
26182616
/*
26192617
* ensure labels are copied
26202618
*
@@ -2650,10 +2648,10 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
26502648
zlog_debug("%s: pfx %pBD: num_labels %d", __func__,
26512649
path_vpn->net, num_labels);
26522650

2653-
if (!leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, label_pnt,
2654-
num_labels, src_vrf, &nexthop_orig, nexthop_self_flag,
2655-
debug))
2651+
if (!leak_update(to_bgp, bn, &static_attr, afi, safi, path_vpn, label_pnt, num_labels,
2652+
src_vrf, &nexthop_orig, nexthop_self_flag, debug))
26562653
bgp_dest_unlock_node(bn);
2654+
bgp_attr_flush(&static_attr);
26572655
}
26582656

26592657
bool vpn_leak_to_vrf_no_retain_filter_check(struct bgp *from_bgp,

0 commit comments

Comments
 (0)