Skip to content

Commit 87d33a0

Browse files
authored
Merge pull request #20331 from krishna-samy/krishna/bgp-path-lookup
bgpd: Optimize BGP path lookup using typesafe hash for efficient lookup
2 parents 987eaab + b45c53b commit 87d33a0

File tree

5 files changed

+100
-7
lines changed

5 files changed

+100
-7
lines changed

bgpd/bgp_route.c

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "zclient.h"
3232
#include "frrdistance.h"
3333
#include "frregex_real.h"
34+
#include "jhash.h"
3435

3536
#include "bgpd/bgpd.h"
3637
#include "bgpd/bgp_nhc.h"
@@ -127,6 +128,52 @@ static const struct message bgp_pmsi_tnltype_str[] = {
127128
static int clear_batch_rib_helper(struct bgp_clearing_info *cinfo);
128129
static void bgp_gr_start_tier2_timer_if_required(struct bgp *bgp, afi_t afi, safi_t safi);
129130

131+
/*
132+
* Typesafe Hash Functions for bgp_path_info
133+
* hash key: prefix, peer, type, sub_type, addpath_rx_id
134+
*/
135+
int bgp_pi_hash_cmp(const struct bgp_path_info *p1, const struct bgp_path_info *p2)
136+
{
137+
int ret;
138+
139+
/* Get the prefix from pi->net and compare */
140+
const struct prefix *pfx1 = bgp_dest_get_prefix(p1->net);
141+
const struct prefix *pfx2 = bgp_dest_get_prefix(p2->net);
142+
143+
ret = prefix_cmp(pfx1, pfx2);
144+
if (ret != 0)
145+
return ret;
146+
147+
if (p1->peer != p2->peer)
148+
return (p1->peer < p2->peer) ? -1 : 1;
149+
150+
if (p1->type != p2->type)
151+
return (p1->type < p2->type) ? -1 : 1;
152+
153+
if (p1->sub_type != p2->sub_type)
154+
return (p1->sub_type < p2->sub_type) ? -1 : 1;
155+
156+
if (p1->addpath_rx_id != p2->addpath_rx_id)
157+
return (p1->addpath_rx_id < p2->addpath_rx_id) ? -1 : 1;
158+
159+
/* All fields are equal */
160+
return 0;
161+
}
162+
163+
uint32_t bgp_pi_hash_hashfn(const struct bgp_path_info *pi)
164+
{
165+
uint32_t h = 0;
166+
const struct prefix *pfx = bgp_dest_get_prefix(pi->net);
167+
168+
h = prefix_hash_key(pfx);
169+
h = jhash_1word((uint32_t)(uintptr_t)pi->peer, h);
170+
h = jhash_1word(pi->addpath_rx_id, h);
171+
h = jhash_1word((uint32_t)pi->type, h);
172+
h = jhash_1word((uint32_t)pi->sub_type, h);
173+
174+
return h;
175+
}
176+
130177
static inline char *bgp_route_dump_path_info_flags(struct bgp_path_info *pi,
131178
char *buf, size_t len)
132179
{
@@ -544,6 +591,7 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
544591
{
545592
frrtrace(3, frr_bgp, bgp_path_info_add, dest, pi, name);
546593
struct bgp_path_info *top;
594+
struct bgp_table *table;
547595

548596
top = bgp_dest_get_bgp_path_info(dest);
549597

@@ -553,6 +601,11 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
553601
top->prev = pi;
554602
bgp_dest_set_bgp_path_info(dest, pi);
555603

604+
/* Add this path info to global hash (per AFI/SAFI table) */
605+
table = bgp_dest_table(dest);
606+
if (table)
607+
bgp_pi_hash_add(&table->pi_hash, pi);
608+
556609
SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
557610
bgp_path_info_lock(pi);
558611
bgp_dest_lock_node(dest);
@@ -568,6 +621,8 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
568621
struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
569622
struct bgp_path_info *pi)
570623
{
624+
struct bgp_table *table;
625+
571626
if (pi->next)
572627
pi->next->prev = pi->prev;
573628
if (pi->prev)
@@ -578,6 +633,11 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
578633
pi->next = NULL;
579634
pi->prev = NULL;
580635

636+
/* Remove this path from global hash (per AFI/SAFI table) */
637+
table = bgp_dest_table(dest);
638+
if (table)
639+
bgp_pi_hash_del(&table->pi_hash, pi);
640+
581641
if (pi->peer)
582642
pi->peer->stat_pfx_loc_rib--;
583643
hook_call(bgp_snmp_update_stats, dest, pi, false);
@@ -589,9 +649,16 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
589649
static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest,
590650
struct bgp_path_info *pi)
591651
{
652+
struct bgp_table *table;
653+
592654
pi->next = NULL;
593655
pi->prev = NULL;
594656

657+
/* Remove this path from global hash (per AFI/SAFI table) */
658+
table = bgp_dest_table(dest);
659+
if (table)
660+
bgp_pi_hash_del(&table->pi_hash, pi);
661+
595662
if (pi->peer)
596663
pi->peer->stat_pfx_loc_rib--;
597664
hook_call(bgp_snmp_update_stats, dest, pi, false);
@@ -5547,6 +5614,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
55475614
{
55485615
int ret;
55495616
struct bgp_dest *dest;
5617+
struct bgp_table *rib_table;
55505618
struct bgp *bgp;
55515619
struct attr new_attr = {};
55525620
struct attr *attr_new;
@@ -5580,6 +5648,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
55805648

55815649
bgp = peer->bgp;
55825650
dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
5651+
rib_table = bgp_dest_table(dest);
55835652

55845653
if (num_labels &&
55855654
((afi == AFI_L2VPN && safi == SAFI_EVPN) || bgp_is_valid_label(&label[0]))) {
@@ -5606,12 +5675,14 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
56065675
bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels);
56075676
}
56085677

5609-
/* Check previously received route. */
5610-
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
5611-
if (pi->peer == peer && pi->type == type
5612-
&& pi->sub_type == sub_type
5613-
&& pi->addpath_rx_id == addpath_id)
5614-
break;
5678+
/* Check previously received route using pi_hash */
5679+
struct bgp_path_info pi_lookup = { .net = dest,
5680+
.peer = peer,
5681+
.type = type,
5682+
.sub_type = sub_type,
5683+
.addpath_rx_id = addpath_id };
5684+
5685+
pi = bgp_pi_hash_find(&rib_table->pi_hash, &pi_lookup);
56155686

56165687
/* AS path local-as loop check. */
56175688
if (peer->change_local_as) {

bgpd/bgp_route.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "hook.h"
1212
#include "queue.h"
1313
#include "nexthop.h"
14+
#include "typesafe.h"
1415
#include "bgp_table.h"
1516
#include "bgp_addpath_types.h"
1617
#include "bgp_rpki.h"
@@ -275,6 +276,9 @@ struct bgp_path_info {
275276
struct bgp_path_info *next;
276277
struct bgp_path_info *prev;
277278

279+
/* Hash linkage for pi_hash in bgp_table */
280+
struct bgp_pi_hash_item pi_hash_link;
281+
278282
/* For nexthop linked list */
279283
LIST_ENTRY(bgp_path_info) nh_thread;
280284

@@ -739,6 +743,11 @@ DECLARE_HOOK(bgp_route_update,
739743
struct bgp_path_info *old_route, struct bgp_path_info *new_route),
740744
(bgp, afi, safi, bn, old_route, new_route));
741745

746+
extern int bgp_pi_hash_cmp(const struct bgp_path_info *p1, const struct bgp_path_info *p2);
747+
extern uint32_t bgp_pi_hash_hashfn(const struct bgp_path_info *pi);
748+
749+
DECLARE_HASH(bgp_pi_hash, struct bgp_path_info, pi_hash_link, bgp_pi_hash_cmp, bgp_pi_hash_hashfn);
750+
742751
/* BGP show options */
743752
#define BGP_SHOW_OPT_JSON (1 << 0)
744753
#define BGP_SHOW_OPT_WIDE (1 << 1)

bgpd/bgp_table.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ void bgp_table_unlock(struct bgp_table *rt)
3333
return;
3434
}
3535

36+
/* Cleanup pi_hash in bgp_table */
37+
bgp_pi_hash_fini(&rt->pi_hash);
38+
3639
route_table_finish(rt->route_table);
3740
rt->route_table = NULL;
3841

@@ -84,6 +87,8 @@ inline struct bgp_dest *bgp_dest_unlock_node(struct bgp_dest *dest)
8487

8588
if (rn->lock == 1) {
8689
struct bgp_table *rt = bgp_dest_table(dest);
90+
91+
8792
if (rt->bgp) {
8893
bgp_addpath_free_node_data(&rt->bgp->tx_addpath,
8994
&dest->tx_addpath, rt->afi,
@@ -165,6 +170,7 @@ struct bgp_table *bgp_table_init(struct bgp *bgp, afi_t afi, safi_t safi)
165170
bgp_table_lock(rt);
166171
rt->afi = afi;
167172
rt->safi = safi;
173+
bgp_pi_hash_init(&rt->pi_hash);
168174

169175
return rt;
170176
}

bgpd/bgp_table.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010
#include "table.h"
1111
#include "queue.h"
1212
#include "linklist.h"
13+
#include "typesafe.h"
1314
#include "bgpd.h"
1415
#include "bgp_advertise.h"
1516
#include "bgp_attr_srv6.h"
1617

18+
/* Typesafe hash for bgp_path_info lookup */
19+
PREDECL_HASH(bgp_pi_hash);
20+
1721
struct bgp_table {
1822
/* table belongs to this instance */
1923
struct bgp *bgp;
@@ -24,6 +28,9 @@ struct bgp_table {
2428

2529
int lock;
2630

31+
/* Hash for bgp_path_info lookups across all prefixes in this table */
32+
struct bgp_pi_hash_head pi_hash;
33+
2734
/* soft_reconfig_table in progress */
2835
bool soft_reconfig_init;
2936
struct event *soft_reconfig_thread;

bgpd/rfapi/rfapi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
10081008
}
10091009
}
10101010

1011-
new = info_make(type, sub_type, 0, rfd->peer, new_attr, NULL);
1011+
new = info_make(type, sub_type, 0, rfd->peer, new_attr, bn);
10121012
SET_FLAG(new->flags, BGP_PATH_VALID);
10131013

10141014
/* save backref to rfapi handle */

0 commit comments

Comments
 (0)