Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd: adjust Adj-RIB-Out operations to support down peers
To:
tech@openbsd.org
Date:
Tue, 10 Dec 2024 17:03:23 +0100

Download raw body.

Thread
Both prefix_adjout_update() and prefix_adjout_withdraw() insert a RB tree
node into the update / withdraw tree structures. Those RB_INSERTs result
in the update to be sent out.

In preparation for caching the Adj-RIB-Out over a session restart add a
check in the two functions to only do this RB tree insert if the peer is
up. For prefix_adjout_update() nothing else needs to be done (the prefix
is still linked in the actual Adj-RIB-Out (called adj_rib_out) but on a
withdraw the prefix is already unlinked for the adj_rib_out and needs to
be destroyed. To make this work correctly mark the prefix as dead since
it is already unlinked and therefor dead.

Right now this is a no-op since  prefix_adjout_update() and
prefix_adjout_withdraw() are only called for peers that are up but this
diff is complex enough to send it out alone.

-- 
:wq Claudio

Index: rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
diff -u -p -r1.263 rde_rib.c
--- rde_rib.c	14 Aug 2024 19:09:51 -0000	1.263
+++ rde_rib.c	10 Dec 2024 15:42:04 -0000
@@ -1321,10 +1321,12 @@ 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[pte->aid], p) != NULL)
-		fatalx("%s: RB tree invariant violated", __func__);
-	peer->stats.pending_update++;
+	if (peer_is_up(peer)) {
+		p->flags |= PREFIX_FLAG_UPDATE;
+		if (RB_INSERT(prefix_tree, &peer->updates[pte->aid], p) != NULL)
+			fatalx("%s: RB tree invariant violated", __func__);
+		peer->stats.pending_update++;
+	}
 }
 
 /*
@@ -1360,10 +1362,17 @@ prefix_adjout_withdraw(struct prefix *p)
 	p->flags &= ~PREFIX_FLAG_MASK;
 	p->lastchange = getmonotime();
 
-	p->flags |= PREFIX_FLAG_WITHDRAW;
-	if (RB_INSERT(prefix_tree, &peer->withdraws[p->pt->aid], p) != NULL)
-		fatalx("%s: RB tree invariant violated", __func__);
-	peer->stats.pending_withdraw++;
+	if (peer_is_up(peer)) {
+		p->flags |= PREFIX_FLAG_WITHDRAW;
+		if (RB_INSERT(prefix_tree, &peer->withdraws[p->pt->aid],
+		    p) != NULL)
+			fatalx("%s: RB tree invariant violated", __func__);
+		peer->stats.pending_withdraw++;
+	} else {
+		/* mark prefix dead to skip unlink on destroy */
+		p->flags |= PREFIX_FLAG_DEAD;
+		prefix_adjout_destroy(p);
+	}
 }
 
 void