The lookup functions for the Adj-RIB-Out trees (prefix_adjout_{get,lookup})
work mainly with a pt_entry so lets change them.
Now prefix_adjout_lookup() which returns the first path (in case of
add-path) is also used by bgpctl code-paths and there we want to keep
using bgpd_addr.
This diff changes prefix_adjout_get() to use struct pt_entry, introduces a
new prefix_adjout_first() which works together with prefix_adjout_next()
and also passes the pt_entry to prefix_adjout_update() so the allocation
can be skipped there.
With this most conversions from and to bgpd_addr in the Adj-RIB-Out are
gone. The last remaining bit is rde_filter() but there I think the use of
bgpd_addr will remain. For flowspec the conversion to a struct bgpd_addr
will just return the destination prefix which is the right thing for
rde_filter.
With this the Adj-RIB-Out should be able to handle flowspec.
--
:wq Claudio
Index: rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.288
diff -u -p -r1.288 rde.h
--- rde.h 28 Mar 2023 15:17:34 -0000 1.288
+++ rde.h 28 Mar 2023 16:50:39 -0000
@@ -580,19 +580,20 @@ void path_put(struct rde_aspath *);
struct prefix *prefix_get(struct rib *, struct rde_peer *, uint32_t,
struct bgpd_addr *, int);
struct prefix *prefix_adjout_get(struct rde_peer *, uint32_t,
- struct bgpd_addr *, int);
-struct prefix *prefix_match(struct rde_peer *, struct bgpd_addr *);
-struct prefix *prefix_adjout_match(struct rde_peer *, struct bgpd_addr *);
+ struct pt_entry *);
+struct prefix *prefix_adjout_first(struct rde_peer *, struct pt_entry *);
+struct prefix *prefix_adjout_next(struct rde_peer *, struct prefix *);
struct prefix *prefix_adjout_lookup(struct rde_peer *, struct bgpd_addr *,
int);
-struct prefix *prefix_adjout_next(struct rde_peer *, struct prefix *);
+struct prefix *prefix_adjout_match(struct rde_peer *, struct bgpd_addr *);
+struct prefix *prefix_match(struct rde_peer *, struct bgpd_addr *);
int prefix_update(struct rib *, struct rde_peer *, uint32_t,
uint32_t, struct filterstate *, struct bgpd_addr *, int);
int prefix_withdraw(struct rib *, struct rde_peer *, uint32_t,
struct bgpd_addr *, int);
void prefix_add_eor(struct rde_peer *, uint8_t);
void prefix_adjout_update(struct prefix *, struct rde_peer *,
- struct filterstate *, struct bgpd_addr *, int, uint32_t);
+ struct filterstate *, struct pt_entry *, uint32_t);
void prefix_adjout_withdraw(struct prefix *);
void prefix_adjout_destroy(struct prefix *);
void prefix_adjout_dump(struct rde_peer *, void *,
Index: rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
retrieving revision 1.256
diff -u -p -r1.256 rde_rib.c
--- rde_rib.c 28 Mar 2023 15:17:34 -0000 1.256
+++ rde_rib.c 28 Mar 2023 15:57:25 -0000
@@ -873,12 +873,12 @@ prefix_get(struct rib *rib, struct rde_p
*/
struct prefix *
prefix_adjout_get(struct rde_peer *peer, uint32_t path_id_tx,
- struct bgpd_addr *prefix, int prefixlen)
+ struct pt_entry *pte)
{
struct prefix xp;
memset(&xp, 0, sizeof(xp));
- xp.pt = pt_fill(prefix, prefixlen);
+ xp.pt = pte;
xp.path_id_tx = path_id_tx;
return RB_FIND(prefix_index, &peer->adj_rib_out, &xp);
@@ -889,13 +889,12 @@ prefix_adjout_get(struct rde_peer *peer,
* Returns NULL if not found.
*/
struct prefix *
-prefix_adjout_lookup(struct rde_peer *peer, struct bgpd_addr *prefix,
- int prefixlen)
+prefix_adjout_first(struct rde_peer *peer, struct pt_entry *pte)
{
struct prefix xp, *np;
memset(&xp, 0, sizeof(xp));
- xp.pt = pt_fill(prefix, prefixlen);
+ xp.pt = pte;
np = RB_NFIND(prefix_index, &peer->adj_rib_out, &xp);
if (np == NULL || pt_prefix_cmp(np->pt, xp.pt) != 0)
@@ -918,6 +917,16 @@ prefix_adjout_next(struct rde_peer *peer
}
/*
+ * Lookup addr/prefixlen in the peer prefix_index. Returns first match.
+ * Returns NULL if not found.
+ */
+struct prefix *
+prefix_adjout_lookup(struct rde_peer *peer, struct bgpd_addr *addr, int plen)
+{
+ return prefix_adjout_first(peer, pt_fill(addr, plen));
+}
+
+/*
* Lookup addr in the peer prefix_index. Returns first match.
* Returns NULL if not found.
*/
@@ -1124,8 +1133,7 @@ prefix_add_eor(struct rde_peer *peer, ui
*/
void
prefix_adjout_update(struct prefix *p, struct rde_peer *peer,
- struct filterstate *state, struct bgpd_addr *prefix, int prefixlen,
- uint32_t path_id_tx)
+ struct filterstate *state, struct pt_entry *pte, uint32_t path_id_tx)
{
struct rde_aspath *asp;
struct rde_community *comm;
@@ -1135,10 +1143,7 @@ prefix_adjout_update(struct prefix *p, s
/* initially mark DEAD so code below is skipped */
p->flags |= PREFIX_FLAG_ADJOUT | PREFIX_FLAG_DEAD;
- p->pt = pt_get(prefix, prefixlen);
- if (p->pt == NULL)
- p->pt = pt_add(prefix, prefixlen);
- pt_ref(p->pt);
+ p->pt = pt_ref(pte);
p->peer = peer;
p->path_id_tx = path_id_tx;
@@ -1170,7 +1175,7 @@ prefix_adjout_update(struct prefix *p, s
/* if pending update unhook it before it is unlinked */
if (p->flags & PREFIX_FLAG_UPDATE) {
- RB_REMOVE(prefix_tree, &peer->updates[prefix->aid], p);
+ RB_REMOVE(prefix_tree, &peer->updates[pte->aid], p);
peer->stats.pending_update--;
}
@@ -1179,7 +1184,7 @@ prefix_adjout_update(struct prefix *p, s
peer->stats.prefix_out_cnt--;
}
if (p->flags & PREFIX_FLAG_WITHDRAW) {
- RB_REMOVE(prefix_tree, &peer->withdraws[prefix->aid], p);
+ RB_REMOVE(prefix_tree, &peer->withdraws[pte->aid], p);
peer->stats.pending_withdraw--;
}
@@ -1213,7 +1218,7 @@ prefix_adjout_update(struct prefix *p, s
if (p->flags & PREFIX_FLAG_MASK)
fatalx("%s: bad flags %x", __func__, p->flags);
p->flags |= PREFIX_FLAG_UPDATE;
- if (RB_INSERT(prefix_tree, &peer->updates[prefix->aid], p) != NULL)
+ if (RB_INSERT(prefix_tree, &peer->updates[pte->aid], p) != NULL)
fatalx("%s: RB tree invariant violated", __func__);
peer->stats.pending_update++;
}
Index: rde_update.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v
retrieving revision 1.160
diff -u -p -r1.160 rde_update.c
--- rde_update.c 28 Mar 2023 15:17:34 -0000 1.160
+++ rde_update.c 29 Mar 2023 07:41:00 -0000
@@ -150,10 +150,10 @@ up_enforce_open_policy(struct rde_peer *
* - UP_EXCLUDED if prefix was excluded because of up_test_update()
*/
static enum up_state
-up_process_prefix(struct rde_peer *peer, struct prefix *new, struct prefix *p,
- struct bgpd_addr *addr, uint8_t plen)
+up_process_prefix(struct rde_peer *peer, struct prefix *new, struct prefix *p)
{
struct filterstate state;
+ struct bgpd_addr addr;
int excluded = 0;
/*
@@ -166,14 +166,15 @@ up_process_prefix(struct rde_peer *peer,
excluded = 1;
rde_filterstate_prep(&state, new);
- if (rde_filter(peer->out_rules, peer, prefix_peer(new), addr, plen,
- &state) == ACTION_DENY) {
+ pt_getaddr(new->pt, &addr);
+ if (rde_filter(peer->out_rules, peer, prefix_peer(new), &addr,
+ new->pt->prefixlen, &state) == ACTION_DENY) {
rde_filterstate_clean(&state);
return UP_FILTERED;
}
/* Open Policy Check: acts like an output filter */
- if (up_enforce_open_policy(peer, &state, addr->aid)) {
+ if (up_enforce_open_policy(peer, &state, new->pt->aid)) {
rde_filterstate_clean(&state);
return UP_FILTERED;
}
@@ -185,10 +186,10 @@ up_process_prefix(struct rde_peer *peer,
/* from here on we know this is an update */
if (p == (void *)-1)
- p = prefix_adjout_get(peer, new->path_id_tx, addr, plen);
+ p = prefix_adjout_get(peer, new->path_id_tx, new->pt);
- up_prep_adjout(peer, &state, addr->aid);
- prefix_adjout_update(p, peer, &state, addr, plen, new->path_id_tx);
+ up_prep_adjout(peer, &state, new->pt->aid);
+ prefix_adjout_update(p, peer, &state, new->pt, new->path_id_tx);
rde_filterstate_clean(&state);
/* max prefix checker outbound */
@@ -208,18 +209,13 @@ up_process_prefix(struct rde_peer *peer,
void
up_generate_updates(struct rde_peer *peer, struct rib_entry *re)
{
- struct bgpd_addr addr;
struct prefix *new, *p;
- uint8_t prefixlen;
- pt_getaddr(re->prefix, &addr);
- prefixlen = re->prefix->prefixlen;
-
- p = prefix_adjout_lookup(peer, &addr, prefixlen);
+ p = prefix_adjout_first(peer, re->prefix);
new = prefix_best(re);
while (new != NULL) {
- switch (up_process_prefix(peer, new, p, &addr, prefixlen)) {
+ switch (up_process_prefix(peer, new, p)) {
case UP_OK:
case UP_ERR_LIMIT:
return;
@@ -251,16 +247,11 @@ done:
void
up_generate_addpath(struct rde_peer *peer, struct rib_entry *re)
{
- struct bgpd_addr addr;
struct prefix *head, *new, *p;
- uint8_t prefixlen;
int maxpaths = 0, extrapaths = 0, extra;
int checkmode = 1;
- pt_getaddr(re->prefix, &addr);
- prefixlen = re->prefix->prefixlen;
-
- head = prefix_adjout_lookup(peer, &addr, prefixlen);
+ head = prefix_adjout_first(peer, re->prefix);
/* mark all paths as stale */
for (p = head; p != NULL; p = prefix_adjout_next(peer, p))
@@ -310,8 +301,7 @@ up_generate_addpath(struct rde_peer *pee
}
}
- switch (up_process_prefix(peer, new, (void *)-1, &addr,
- prefixlen)) {
+ switch (up_process_prefix(peer, new, (void *)-1)) {
case UP_OK:
maxpaths++;
extrapaths += extra;
@@ -345,21 +335,16 @@ void
up_generate_addpath_all(struct rde_peer *peer, struct rib_entry *re,
struct prefix *new, struct prefix *old)
{
- struct bgpd_addr addr;
struct prefix *p, *head = NULL;
- uint8_t prefixlen;
int all = 0;
- pt_getaddr(re->prefix, &addr);
- prefixlen = re->prefix->prefixlen;
-
/*
* if old and new are NULL then insert all prefixes from best,
* clearing old routes in the process
*/
if (old == NULL && new == NULL) {
/* mark all paths as stale */
- head = prefix_adjout_lookup(peer, &addr, prefixlen);
+ head = prefix_adjout_first(peer, re->prefix);
for (p = head; p != NULL; p = prefix_adjout_next(peer, p))
p->flags |= PREFIX_FLAG_STALE;
@@ -369,15 +354,14 @@ up_generate_addpath_all(struct rde_peer
if (old != NULL) {
/* withdraw stale paths */
- p = prefix_adjout_get(peer, old->path_id_tx, &addr, prefixlen);
+ p = prefix_adjout_get(peer, old->path_id_tx, old->pt);
if (p != NULL)
prefix_adjout_withdraw(p);
}
/* add new path (or multiple if all is set) */
while (new != NULL) {
- switch (up_process_prefix(peer, new, (void *)-1, &addr,
- prefixlen)) {
+ switch (up_process_prefix(peer, new, (void *)-1)) {
case UP_OK:
case UP_FILTERED:
case UP_EXCLUDED:
@@ -405,10 +389,6 @@ up_generate_addpath_all(struct rde_peer
}
}
-struct rib_entry *rib_add(struct rib *, struct bgpd_addr *, int);
-void rib_remove(struct rib_entry *);
-int rib_empty(struct rib_entry *);
-
/* send a default route to the specified peer */
void
up_generate_default(struct rde_peer *peer, uint8_t aid)
@@ -417,6 +397,7 @@ up_generate_default(struct rde_peer *pee
struct filterstate state;
struct rde_aspath *asp;
struct prefix *p;
+ struct pt_entry *pte;
struct bgpd_addr addr;
if (peer->capa.mp[aid] == 0)
@@ -447,7 +428,11 @@ up_generate_default(struct rde_peer *pee
}
up_prep_adjout(peer, &state, addr.aid);
- prefix_adjout_update(p, peer, &state, &addr, 0, 0);
+ /* can't use pt_fill here since prefix_adjout_update keeps a ref */
+ pte = pt_get(&addr, 0);
+ if (pte == NULL)
+ pte = pt_add(&addr, 0);
+ prefix_adjout_update(p, peer, &state, pte, 0);
rde_filterstate_clean(&state);
/* max prefix checker outbound */