This diff is assigning a local path_id to all prefixes. This path_id will
be used for sending out add-path updates. Since the RFC specifies that the
path_id has no meaning we assing the path_ids randomly. They just need to
be unique per rib entry. Now this code assigne the path_id in the
Adj-RIB-In and then inherits the number to all other ribs. Currently the
Adj-RIB-Out is excluded since that code is not yet ready for more than one
path. That is the next step.

-- 
:wq Claudio

Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.551
diff -u -p -r1.551 rde.c
--- rde.c       7 Jul 2022 13:55:52 -0000       1.551
+++ rde.c       7 Jul 2022 14:29:04 -0000
@@ -1600,6 +1600,46 @@ done:
        rde_filterstate_clean(&state);
 }
 
+/*
+ * Check if path_id is already in use.
+ */
+static int
+pathid_conflict(struct rib_entry *re, uint32_t pathid)
+{
+       struct prefix *p;
+
+       if (re == NULL)
+               return 0;
+
+       TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib)
+               if (p->path_id_tx == pathid)
+                       return 1;
+       return 0;
+}
+
+static uint32_t
+pathid_assign(struct rde_peer *peer, uint32_t path_id,
+    struct bgpd_addr *prefix, uint8_t prefixlen)
+{
+       struct rib_entry *re;
+       struct prefix *p = NULL;
+       uint32_t path_id_tx;
+
+       /* Assign a send side path_id to all paths */
+       re = rib_get(rib_byid(RIB_ADJ_IN), prefix, prefixlen);
+       if (re != NULL)
+               p = prefix_bypeer(re, peer, path_id);
+       if (p != NULL)
+               path_id_tx = p->path_id_tx;
+       else {
+               do {
+                       /* assign new local path_id */
+                       path_id_tx = arc4random();
+               } while (pathid_conflict(re, path_id_tx));
+       }
+       return path_id_tx;
+}
+
 int
 rde_update_update(struct rde_peer *peer, uint32_t path_id,
     struct filterstate *in, struct bgpd_addr *prefix, uint8_t prefixlen)
@@ -1608,15 +1648,18 @@ rde_update_update(struct rde_peer *peer,
        enum filter_actions      action;
        uint8_t                  vstate;
        uint16_t                 i;
+       uint32_t                 path_id_tx;
        const char              *wmsg = "filtered, withdraw";
 
        peer->prefix_rcvd_update++;
        vstate = rde_roa_validity(&rde_roa, prefix, prefixlen,
            aspath_origin(in->aspath.aspath));
 
+       path_id_tx = pathid_assign(peer, path_id, prefix, prefixlen);
+
        /* add original path to the Adj-RIB-In */
-       if (prefix_update(rib_byid(RIB_ADJ_IN), peer, path_id, in,
-           prefix, prefixlen, vstate) == 1)
+       if (prefix_update(rib_byid(RIB_ADJ_IN), peer, path_id, path_id_tx,
+           in, prefix, prefixlen, vstate) == 1)
                peer->prefix_cnt++;
 
        /* max prefix checker */
@@ -1644,8 +1687,8 @@ rde_update_update(struct rde_peer *peer,
                        rde_update_log("update", i, peer,
                            &state.nexthop->exit_nexthop, prefix,
                            prefixlen);
-                       prefix_update(rib, peer, path_id, &state, prefix,
-                           prefixlen, vstate);
+                       prefix_update(rib, peer, path_id, path_id_tx, &state,
+                           prefix, prefixlen, vstate);
                } else if (prefix_withdraw(rib, peer, path_id, prefix,
                    prefixlen)) {
                        rde_update_log(wmsg, i, peer,
@@ -3719,7 +3762,8 @@ rde_softreconfig_in(struct rib_entry *re
 
                        if (action == ACTION_ALLOW) {
                                /* update Local-RIB */
-                               prefix_update(rib, peer, p->path_id, &state,
+                               prefix_update(rib, peer, p->path_id,
+                                   p->path_id_tx, &state,
                                    &prefix, pt->prefixlen,
                                    p->validation_state);
                        } else if (action == ACTION_DENY) {
@@ -3858,7 +3902,8 @@ rde_roa_softreload(struct rib_entry *re,
 
                        if (action == ACTION_ALLOW) {
                                /* update Local-RIB */
-                               prefix_update(rib, peer, p->path_id, &state,
+                               prefix_update(rib, peer, p->path_id,
+                                   p->path_id_tx, &state,
                                    &prefix, pt->prefixlen,
                                    p->validation_state);
                        } else if (action == ACTION_DENY) {
@@ -4026,6 +4071,7 @@ network_add(struct network_config *nc, s
        struct in6_addr          prefix6;
        uint8_t                  vstate;
        uint16_t                 i;
+       uint32_t                 path_id_tx;
 
        if (nc->rd != 0) {
                SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry) {
@@ -4087,8 +4133,9 @@ network_add(struct network_config *nc, s
 
        vstate = rde_roa_validity(&rde_roa, &nc->prefix,
            nc->prefixlen, aspath_origin(state->aspath.aspath));
-       if (prefix_update(rib_byid(RIB_ADJ_IN), peerself, 0, state, &nc->prefix,
-           nc->prefixlen, vstate) == 1)
+       path_id_tx = pathid_assign(peerself, 0, &nc->prefix, nc->prefixlen);
+       if (prefix_update(rib_byid(RIB_ADJ_IN), peerself, 0, path_id_tx,
+           state, &nc->prefix, nc->prefixlen, vstate) == 1)
                peerself->prefix_cnt++;
        for (i = RIB_LOC_START; i < rib_size; i++) {
                struct rib *rib = rib_byid(i);
@@ -4097,7 +4144,7 @@ network_add(struct network_config *nc, s
                rde_update_log("announce", i, peerself,
                    state->nexthop ? &state->nexthop->exit_nexthop : NULL,
                    &nc->prefix, nc->prefixlen);
-               prefix_update(rib, peerself, 0, state, &nc->prefix,
+               prefix_update(rib, peerself, 0, path_id_tx, state, &nc->prefix,
                    nc->prefixlen, vstate);
        }
        filterset_free(&nc->attrset);
Index: rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.256
diff -u -p -r1.256 rde.h
--- rde.h       7 Jul 2022 12:16:04 -0000       1.256
+++ rde.h       7 Jul 2022 14:14:00 -0000
@@ -611,7 +611,8 @@ struct prefix       *prefix_adjout_lookup(stru
                     int);
 struct prefix  *prefix_adjout_next(struct rde_peer *, struct prefix *);
 int             prefix_update(struct rib *, struct rde_peer *, uint32_t,
-                    struct filterstate *, struct bgpd_addr *, int, uint8_t);
+                    uint32_t, struct filterstate *, struct bgpd_addr *,
+                    int, uint8_t);
 int             prefix_withdraw(struct rib *, struct rde_peer *, uint32_t,
                    struct bgpd_addr *, int);
 void            prefix_add_eor(struct rde_peer *, uint8_t);
Index: rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
retrieving revision 1.238
diff -u -p -r1.238 rde_rib.c
--- rde_rib.c   23 May 2022 13:40:12 -0000      1.238
+++ rde_rib.c   7 Jul 2022 14:21:53 -0000
@@ -842,7 +842,7 @@ path_put(struct rde_aspath *asp)
 /* prefix specific functions */
 
 static int     prefix_add(struct bgpd_addr *, int, struct rib *,
-                   struct rde_peer *, uint32_t, struct rde_aspath *,
+                   struct rde_peer *, uint32_t, uint32_t, struct rde_aspath *,
                    struct rde_community *, struct nexthop *,
                    uint8_t, uint8_t);
 static int     prefix_move(struct prefix *, struct rde_peer *,
@@ -850,7 +850,7 @@ static int  prefix_move(struct prefix *, 
                    struct nexthop *, uint8_t, uint8_t);
 
 static void    prefix_link(struct prefix *, struct rib_entry *,
-                    struct pt_entry *, struct rde_peer *, uint32_t,
+                    struct pt_entry *, struct rde_peer *, uint32_t, uint32_t,
                     struct rde_aspath *, struct rde_community *,
                     struct nexthop *, uint8_t, uint8_t);
 static void    prefix_unlink(struct prefix *);
@@ -1001,8 +1001,8 @@ prefix_adjout_match(struct rde_peer *pee
  */
 int
 prefix_update(struct rib *rib, struct rde_peer *peer, uint32_t path_id,
-    struct filterstate *state, struct bgpd_addr *prefix, int prefixlen,
-    uint8_t vstate)
+    uint32_t path_id_tx, struct filterstate *state, struct bgpd_addr *prefix,
+    int prefixlen, uint8_t vstate)
 {
        struct rde_aspath       *asp, *nasp = &state->aspath;
        struct rde_community    *comm, *ncomm = &state->communities;
@@ -1012,6 +1012,8 @@ prefix_update(struct rib *rib, struct rd
         * First try to find a prefix in the specified RIB.
         */
        if ((p = prefix_get(rib, peer, path_id, prefix, prefixlen)) != NULL) {
+               if (path_id_tx != p->path_id_tx)
+                       fatalx("path_id mismatch");
                if (prefix_nexthop(p) == state->nexthop &&
                    prefix_nhflags(p) == state->nhflags &&
                    communities_equal(ncomm, prefix_communities(p)) &&
@@ -1044,8 +1046,9 @@ prefix_update(struct rib *rib, struct rd
                return (prefix_move(p, peer, asp, comm, state->nexthop,
                    state->nhflags, vstate));
        else
-               return (prefix_add(prefix, prefixlen, rib, peer, path_id, asp,
-                   comm, state->nexthop, state->nhflags, vstate));
+               return (prefix_add(prefix, prefixlen, rib, peer, path_id,
+                   path_id_tx, asp, comm, state->nexthop, state->nhflags,
+                   vstate));
 }
 
 /*
@@ -1053,9 +1056,9 @@ prefix_update(struct rib *rib, struct rd
  */
 static int
 prefix_add(struct bgpd_addr *prefix, int prefixlen, struct rib *rib,
-    struct rde_peer *peer, uint32_t path_id, struct rde_aspath *asp,
-    struct rde_community *comm, struct nexthop *nexthop, uint8_t nhflags,
-    uint8_t vstate)
+    struct rde_peer *peer, uint32_t path_id, uint32_t path_id_tx,
+    struct rde_aspath *asp, struct rde_community *comm,
+    struct nexthop *nexthop, uint8_t nhflags, uint8_t vstate)
 {
        struct prefix           *p;
        struct rib_entry        *re;
@@ -1065,8 +1068,8 @@ prefix_add(struct bgpd_addr *prefix, int
                re = rib_add(rib, prefix, prefixlen);
 
        p = prefix_alloc();
-       prefix_link(p, re, re->prefix, peer, path_id, asp, comm, nexthop,
-           nhflags, vstate);
+       prefix_link(p, re, re->prefix, peer, path_id, path_id_tx, asp, comm,
+           nexthop, nhflags, vstate);
 
        /* add possible pftable reference form aspath */
        if (asp && asp->pftableid)
@@ -1094,8 +1097,8 @@ prefix_move(struct prefix *p, struct rde
 
        /* add new prefix node */
        np = prefix_alloc();
-       prefix_link(np, prefix_re(p), p->pt, peer, p->path_id, asp, comm,
-           nexthop, nhflags, vstate);
+       prefix_link(np, prefix_re(p), p->pt, peer, p->path_id, p->path_id_tx,
+           asp, comm, nexthop, nhflags, vstate);
 
        /* add possible pftable reference from new aspath */
        if (asp && asp->pftableid)
@@ -1232,8 +1235,8 @@ prefix_adjout_update(struct rde_peer *pe
                comm = communities_link(&state->communities);
        }
 
-       prefix_link(p, NULL, p->pt, peer, 0, asp, comm, state->nexthop,
-           state->nhflags, vstate);
+       prefix_link(p, NULL, p->pt, peer, 0, /* XXX */ 0, asp, comm,
+           state->nexthop, state->nhflags, vstate);
        peer->prefix_out_cnt++;
 
        if (p->flags & PREFIX_FLAG_MASK)
@@ -1549,9 +1552,9 @@ prefix_destroy(struct prefix *p)
  */
 static void
 prefix_link(struct prefix *p, struct rib_entry *re, struct pt_entry *pt,
-    struct rde_peer *peer, uint32_t path_id, struct rde_aspath *asp,
-    struct rde_community *comm, struct nexthop *nexthop, uint8_t nhflags,
-    uint8_t vstate)
+    struct rde_peer *peer, uint32_t path_id, uint32_t path_id_tx,
+    struct rde_aspath *asp, struct rde_community *comm,
+    struct nexthop *nexthop, uint8_t nhflags, uint8_t vstate)
 {
        if (re)
                p->entry.list.re = re;
@@ -1560,6 +1563,7 @@ prefix_link(struct prefix *p, struct rib
        p->peer = peer;
        p->pt = pt_ref(pt);
        p->path_id = path_id;
+       p->path_id_tx = path_id_tx;
        p->validation_state = vstate;
        p->nhflags = nhflags;
        p->nexthop = nexthop_ref(nexthop);

Reply via email to