summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd/rde_rib.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2022-07-08 10:01:53 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2022-07-08 10:01:53 +0000
commit4f945bf16baaca018a2e846c86b6fdc432782e1a (patch)
tree3f7e554b422eacca6f5ebf2f0d45218f8a941fd4 /usr.sbin/bgpd/rde_rib.c
parente05789e91c8f2fd05bba844869c8728b6a6df2bf (diff)
Pass path_id_tx to the Adj-RIB-Out
Adjust prefix_adjout_update() to properly handle path_id_tx. Move the lookup of the prefix out of prefix_adjout_update() and to up_generate_updates(). While that code uses prefix_adjout_lookup() to find the current prefix in the Adj-RIB-Out and add-path aware function will use prefix_adjout_get(). In up_generate_default() just use 0 for path_id_tx since for this peer that is the only prefix installed into the Adj-RIB-Out. OK tb@
Diffstat (limited to 'usr.sbin/bgpd/rde_rib.c')
-rw-r--r--usr.sbin/bgpd/rde_rib.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c
index 69db4e83b4d..74da9508941 100644
--- a/usr.sbin/bgpd/rde_rib.c
+++ b/usr.sbin/bgpd/rde_rib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_rib.c,v 1.239 2022/07/08 08:11:25 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.240 2022/07/08 10:01:52 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -917,14 +917,14 @@ prefix_get(struct rib *rib, struct rde_peer *peer, uint32_t path_id,
* 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(&xp, 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, &peer->adj_rib_out, &xp);
}
@@ -1168,14 +1168,14 @@ prefix_add_eor(struct rde_peer *peer, uint8_t aid)
* 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 *peer, struct filterstate *state,
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, &peer->adj_rib_out, p) != NULL)
fatalx("%s: RB index invariant violated", __func__);
@@ -1194,7 +1194,14 @@ prefix_adjout_update(struct rde_peer *peer, struct filterstate *state,
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(&state->communities,
prefix_communities(p)) &&
@@ -1224,6 +1231,15 @@ prefix_adjout_update(struct rde_peer *peer, struct filterstate *state,
/* 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 re-insert p */
+ RB_REMOVE(prefix_index, &peer->adj_rib_out, p);
+ p->path_id_tx = path_id_tx;
+ if (RB_INSERT(prefix_index, &peer->adj_rib_out, p) != NULL)
+ fatalx("%s: RB index invariant violated", __func__);
+ }
+
if ((asp = path_lookup(&state->aspath)) == NULL) {
/* Path not available, create and link a new one. */
asp = path_copy(path_get(), &state->aspath);
@@ -1235,7 +1251,7 @@ prefix_adjout_update(struct rde_peer *peer, struct filterstate *state,
comm = communities_link(&state->communities);
}
- prefix_link(p, NULL, p->pt, peer, 0, /* XXX */ 0, asp, comm,
+ prefix_link(p, NULL, p->pt, peer, 0, p->path_id_tx, asp, comm,
state->nexthop, state->nhflags, vstate);
peer->prefix_out_cnt++;