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 */

Reply via email to