Re: bgpd: initial local path_id support for Adj-RIB-Out

2022-07-08 Thread Theo Buehler
On Fri, Jul 08, 2022 at 11:17:16AM +0200, Claudio Jeker wrote:
> This diff adds the required plumbing to support local path_ids in the
> output path. Mainly it extends prefix_adjout_update() to do the right
> thing. Since in normal mode of operation path_id_tx does not matter and
> only on prefix is in the Adj-RIB-Out the code uses prefix_adjout_lookup()
> to locate the prefix first and removes the lookup in
> prefix_adjout_update().
> 
> prefix_adjout_update() takes care if the passed in prefix switches
> path_id_tx and does the dance of unlinking the object from all RB trees
> before switching the path_id_tx.
> 
> In up_generate_default() just use 0 as the path_id_tx. There will only
> be the default route in this RIB so there is no conflict possible.

This all makes sense and reads perfectly fine.

ok tb



bgpd: initial local path_id support for Adj-RIB-Out

2022-07-08 Thread Claudio Jeker
This diff adds the required plumbing to support local path_ids in the
output path. Mainly it extends prefix_adjout_update() to do the right
thing. Since in normal mode of operation path_id_tx does not matter and
only on prefix is in the Adj-RIB-Out the code uses prefix_adjout_lookup()
to locate the prefix first and removes the lookup in
prefix_adjout_update().

prefix_adjout_update() takes care if the passed in prefix switches
path_id_tx and does the dance of unlinking the object from all RB trees
before switching the path_id_tx.

In up_generate_default() just use 0 as the path_id_tx. There will only
be the default route in this RIB so there is no conflict possible.

-- 
:wq Claudio

Index: rde.h
===
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.257
diff -u -p -r1.257 rde.h
--- rde.h   8 Jul 2022 08:11:25 -   1.257
+++ rde.h   8 Jul 2022 08:56:09 -
@@ -616,8 +616,9 @@ int  prefix_update(struct rib *, struct
 int prefix_withdraw(struct rib *, struct rde_peer *, uint32_t,
struct bgpd_addr *, int);
 voidprefix_add_eor(struct rde_peer *, uint8_t);
-voidprefix_adjout_update(struct rde_peer *, struct filterstate *,
-   struct bgpd_addr *, int, uint8_t);
+voidprefix_adjout_update(struct prefix *, struct rde_peer *,
+   struct filterstate *, struct bgpd_addr *, int,
+   uint32_t, uint8_t);
 voidprefix_adjout_withdraw(struct prefix *);
 voidprefix_adjout_destroy(struct prefix *);
 voidprefix_adjout_dump(struct rde_peer *, void *,
Index: rde_rib.c
===
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
retrieving revision 1.239
diff -u -p -r1.239 rde_rib.c
--- rde_rib.c   8 Jul 2022 08:11:25 -   1.239
+++ rde_rib.c   8 Jul 2022 09:01:20 -
@@ -917,14 +917,14 @@ prefix_get(struct rib *rib, struct rde_p
  * Returns NULL if not found.
  */
 struct prefix *
-prefix_adjout_get(struct rde_peer *peer, uint32_t path_id,
+prefix_adjout_get(struct rde_peer *peer, uint32_t path_id_tx,
 struct bgpd_addr *prefix, int prefixlen)
 {
struct prefix xp;
 
memset(, 0, sizeof(xp));
xp.pt = pt_fill(prefix, prefixlen);
-   xp.path_id_tx = path_id;
+   xp.path_id_tx = path_id_tx;
 
return RB_FIND(prefix_index, >adj_rib_out, );
 }
@@ -1168,14 +1168,14 @@ prefix_add_eor(struct rde_peer *peer, ui
  * Put a prefix from the Adj-RIB-Out onto the update queue.
  */
 void
-prefix_adjout_update(struct rde_peer *peer, struct filterstate *state,
-struct bgpd_addr *prefix, int prefixlen, uint8_t vstate)
+prefix_adjout_update(struct prefix *p, struct rde_peer *peer,
+struct filterstate *state, struct bgpd_addr *prefix, int prefixlen,
+uint32_t path_id_tx, uint8_t vstate)
 {
struct rde_aspath *asp;
struct rde_community *comm;
-   struct prefix *p;
 
-   if ((p = prefix_adjout_get(peer, 0, prefix, prefixlen)) == NULL) {
+   if (p == NULL) {
p = prefix_alloc();
/* initally mark DEAD so code below is skipped */
p->flags |= PREFIX_FLAG_ADJOUT | PREFIX_FLAG_DEAD;
@@ -1185,7 +1185,7 @@ prefix_adjout_update(struct rde_peer *pe
p->pt = pt_add(prefix, prefixlen);
pt_ref(p->pt);
p->peer = peer;
-   p->path_id_tx = 0 /* XXX force this for now */;
+   p->path_id_tx = path_id_tx;
 
if (RB_INSERT(prefix_index, >adj_rib_out, p) != NULL)
fatalx("%s: RB index invariant violated", __func__);
@@ -1194,7 +1194,14 @@ prefix_adjout_update(struct rde_peer *pe
if ((p->flags & PREFIX_FLAG_ADJOUT) == 0)
fatalx("%s: prefix without PREFIX_FLAG_ADJOUT hit", __func__);
if ((p->flags & (PREFIX_FLAG_WITHDRAW | PREFIX_FLAG_DEAD)) == 0) {
-   if (prefix_nhflags(p) == state->nhflags &&
+   /*
+* XXX for now treat a different path_id_tx like different
+* attributes and force out an update. It is unclear how
+* common it is to have equivalent updates from alternative
+* paths.
+*/
+   if (p->path_id_tx == path_id_tx &&
+   prefix_nhflags(p) == state->nhflags &&
prefix_nexthop(p) == state->nexthop &&
communities_equal(>communities,
prefix_communities(p)) &&
@@ -1224,6 +1231,15 @@ prefix_adjout_update(struct rde_peer *pe
/* nothing needs to be done for PREFIX_FLAG_DEAD and STALE */
p->flags &= ~PREFIX_FLAG_MASK;
 
+   /* update path_id_tx now that the prefix is unlinked */
+   if (p->path_id_tx != path_id_tx) {
+   /* path_id_tx is part of the index so remove and