/* BGP adjacency out. */
struct bgp_adj_out {
- /* Lined list pointer. */
- struct bgp_adj_out *next;
- struct bgp_adj_out *prev;
+ /* RB Tree of adjacency entries */
+ RB_ENTRY(bgp_adj_out) adj_entry;
/* Advertised subgroup. */
struct update_subgroup *subgroup;
struct bgp_advertise *adv;
};
+RB_HEAD(bgp_adj_out_rb, bgp_adj_out);
+RB_PROTOTYPE(bgp_adj_out_rb, bgp_adj_out, adj_entry,
+ bgp_adj_out_compare);
+
/* BGP adjacency in. */
struct bgp_adj_in {
/* Linked list pointer. */
#define BGP_ADJ_IN_ADD(N, A) BGP_PATH_INFO_ADD(N, A, adj_in)
#define BGP_ADJ_IN_DEL(N, A) BGP_PATH_INFO_DEL(N, A, adj_in)
-#define BGP_ADJ_OUT_ADD(N, A) BGP_PATH_INFO_ADD(N, A, adj_out)
-#define BGP_ADJ_OUT_DEL(N, A) BGP_PATH_INFO_DEL(N, A, adj_out)
#define BGP_ADV_FIFO_ADD(F, N) \
do { \
/********************
* PRIVATE FUNCTIONS
********************/
+static int bgp_adj_out_compare(const struct bgp_adj_out *o1,
+ const struct bgp_adj_out *o2)
+{
+ if (o1->subgroup < o2->subgroup)
+ return -1;
+
+ if (o1->subgroup > o2->subgroup)
+ return 1;
+
+ return 0;
+}
+RB_GENERATE(bgp_adj_out_rb, bgp_adj_out, adj_entry, bgp_adj_out_compare);
static inline struct bgp_adj_out *adj_lookup(struct bgp_node *rn,
struct update_subgroup *subgrp,
uint32_t addpath_tx_id)
{
- struct bgp_adj_out *adj;
+ struct bgp_adj_out *adj, lookup;
struct peer *peer;
afi_t afi;
safi_t safi;
/* update-groups that do not support addpath will pass 0 for
* addpath_tx_id so do not both matching against it */
- for (adj = rn->adj_out; adj; adj = adj->next) {
- if (adj->subgroup == subgrp) {
- if (addpath_capable) {
- if (adj->addpath_tx_id == addpath_tx_id) {
- break;
- }
- } else {
- break;
- }
- }
+ lookup.subgroup = subgrp;
+ adj = RB_FIND(bgp_adj_out_rb, &rn->adj_out, &lookup);
+ if (adj) {
+ if (addpath_capable) {
+ if (adj->addpath_tx_id == addpath_tx_id)
+ return adj;
+ } else
+ return adj;
}
-
- return adj;
+ return NULL;
}
static void adj_free(struct bgp_adj_out *adj)
/* Look through all of the paths we have advertised for this rn and send
* a withdraw for the ones that are no longer present */
- for (adj = ctx->rn->adj_out; adj; adj = adj_next) {
- adj_next = adj->next;
+ RB_FOREACH_SAFE (adj, bgp_adj_out_rb, &ctx->rn->adj_out, adj_next) {
if (adj->subgroup == subgrp) {
for (pi = ctx->rn->info; pi; pi = pi->next) {
/* Find the addpath_tx_id of the path we
* had advertised and
* send a withdraw */
- for (adj = ctx->rn->adj_out; adj;
- adj = adj_next) {
- adj_next = adj->next;
-
+ RB_FOREACH_SAFE (adj, bgp_adj_out_rb,
+ &ctx->rn->adj_out,
+ adj_next) {
if (adj->subgroup == subgrp) {
subgroup_process_announce_selected(
subgrp, NULL,
output_count = 0;
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
- for (adj = rn->adj_out; adj; adj = adj->next)
+ RB_FOREACH (adj, bgp_adj_out_rb, &rn->adj_out)
if (adj->subgroup == subgrp) {
if (header1) {
vty_out(vty,
adj = XCALLOC(MTYPE_BGP_ADJ_OUT, sizeof(struct bgp_adj_out));
adj->subgroup = subgrp;
if (rn) {
- BGP_ADJ_OUT_ADD(rn, adj);
+ RB_INSERT(bgp_adj_out_rb, &rn->adj_out, adj);
bgp_lock_node(rn);
adj->rn = rn;
}
subgroup_trigger_write(subgrp);
} else {
/* Remove myself from adjacency. */
- BGP_ADJ_OUT_DEL(rn, adj);
+ RB_REMOVE(bgp_adj_out_rb, &rn->adj_out, adj);
/* Free allocated information. */
adj_free(adj);
if (adj->adv)
bgp_advertise_clean_subgroup(subgrp, adj);
- BGP_ADJ_OUT_DEL(rn, adj);
+ RB_REMOVE(bgp_adj_out_rb, &rn->adj_out, adj);
adj_free(adj);
}