net-misc/bird: Apply the whole v3.0.0...thread-next

Signed-off-by: Alarig Le Lay <alarig@swordarmor.fr>
This commit is contained in:
Alarig Le Lay 2025-01-08 14:16:28 +01:00
parent 55c7e2755c
commit 2f8e55449b
Signed by: alarig
GPG key ID: 7AFE62C6DF8BCDEC
6 changed files with 1759 additions and 370 deletions

View file

@ -37,10 +37,7 @@ FILECAPS=(
) )
PATCHES=( PATCHES=(
"${FILESDIR}"/${P}-proto-lock.patch "${FILESDIR}"/${P}_p20250107.patch
"${FILESDIR}"/${P}-nest-rt-table.c.patch
"${FILESDIR}"/${P}-rt-table.c.patch
"${FILESDIR}"/${P}-bgp-med.patch
) )
src_prepare() { src_prepare() {

View file

@ -1,65 +0,0 @@
From c5b07695ce810e4345ed1811eadfce935c83b324 Mon Sep 17 00:00:00 2001
From: Maria Matejka <mq@ucw.cz>
Date: Tue, 7 Jan 2025 11:08:04 +0100
Subject: [PATCH] BGP: fixed deterministic med crashes
There were several places of forgotten NULL checks.
Thanks to Alarig Le Lay <alarig@swordarmor.fr> for reporting:
https://trubka.network.cz/pipermail/bird-users/2024-December/017990.html
---
nest/rt-table.c | 14 ++++++++++++--
proto/bgp/attrs.c | 8 ++++----
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 05191d743..fc6d0d4e0 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -2024,12 +2024,22 @@ rte_recalculate(struct rtable_private *table, struct rt_import_hook *c, struct n
do_recalculate:
/* Add the new route to the list right behind the old one */
if (new_stored)
+ {
+ /* There is the same piece of code several lines farther. Needs refactoring.
+ * The old_stored check is needed because of the possible jump from deterministic med */
+ if (old_stored)
{
atomic_store_explicit(&new_stored->next, atomic_load_explicit(&old_stored->next, memory_order_relaxed), memory_order_release);
atomic_store_explicit(&old_stored->next, new_stored, memory_order_release);
-
- table->rt_count++;
}
+ else
+ {
+ atomic_store_explicit(&new_stored->next, NULL, memory_order_release);
+ atomic_store_explicit(last_ptr, new_stored, memory_order_release);
+ }
+
+ table->rt_count++;
+ }
/* Find a new optimal route (if there is any) */
struct rte_storage * _Atomic *bp = &local_sentinel.next;
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 5dc06be51..db6542343 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -2689,10 +2689,10 @@ bgp_rte_recalculate(struct rtable_private *table, net *net,
struct rte_storage *new_stored, struct rte_storage *old_stored, struct rte_storage *old_best_stored)
{
struct rte_storage *key_stored = new_stored ? new_stored : old_stored;
- const struct rte *new = &new_stored->rte,
- *old = &old_stored->rte,
- *old_best = &old_best_stored->rte,
- *key = &key_stored->rte;
+ const struct rte *new = RTE_OR_NULL(new_stored),
+ *old = RTE_OR_NULL(old_stored),
+ *old_best = RTE_OR_NULL(old_best_stored),
+ *key = RTE_OR_NULL(key_stored);
u32 lpref = rt_get_preference(key);
u32 lasn = bgp_get_neighbor(key);
--
GitLab

View file

@ -1,38 +0,0 @@
From b6caccfd45fb639b6dd3a8d140d3c5ba4cc79311 Mon Sep 17 00:00:00 2001
From: Maria Matejka <mq@ucw.cz>
Date: Thu, 19 Dec 2024 11:00:15 +0100
Subject: [PATCH] Kernel: Fix crash for merge paths on if no route is in BIRD
There was a missing check for a NULL return value.
Also fixed an indenting error.
Thanks to Radu Anghel for reporting it:
https://bird.network.cz/pipermail/bird-users/2024-December/017977.html
---
nest/rt-table.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/nest/rt-table.c b/nest/rt-table.c
index fd8bb50dd..05191d743 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -5265,14 +5265,14 @@ krt_export_net(struct channel *c, const net_addr *a, linpool *lp)
if (c->ra_mode == RA_MERGED)
{
struct rt_export_feed *feed = rt_net_feed(c->table, a, NULL);
- if (!feed->count_routes)
+ if (!feed || !feed->count_routes)
return NULL;
if (!bmap_test(&c->export_accepted_map, feed->block[0].id))
return NULL;
return rt_export_merged(c, feed, lp, 1);
- }
+ }
static _Thread_local rte best;
best = rt_net_best(c->table, a);
--
GitLab

View file

@ -1,176 +0,0 @@
From 6779e5da698feb9b9e02411859ad81885ba46c01 Mon Sep 17 00:00:00 2001
From: Maria Matejka <mq@ucw.cz>
Date: Fri, 20 Dec 2024 11:28:00 +0100
Subject: [PATCH] BGP: fix locking order error on dynamic protocol spawn
We missed that the protocol spawner violates the prescribed
locking order. When the rtable level is locked, no new protocol can be
started, thus we need to:
* create the protocol from a clean mainloop context
* in protocol start hook, take the socket
Testsuite: cf-bgp-autopeer
Fixes: #136
Thanks to Job Snijders <job@fastly.com> for reporting:
https://trubka.network.cz/pipermail/bird-users/2024-December/017980.html
---
nest/proto.c | 19 +++++++++++++++++++
nest/protocol.h | 2 ++
proto/bgp/bgp.c | 46 +++++++++++++++++++++++++++++++++++-----------
3 files changed, 56 insertions(+), 11 deletions(-)
diff --git a/nest/proto.c b/nest/proto.c
index dded84f51..678697d69 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -1867,6 +1867,25 @@ proto_spawn(struct proto_config *cf, uint disabled)
return p;
}
+bool
+proto_disable(struct proto *p)
+{
+ ASSERT_DIE(birdloop_inside(&main_birdloop));
+ bool changed = !p->disabled;
+ p->disabled = 1;
+ proto_rethink_goal(p);
+ return changed;
+}
+
+bool
+proto_enable(struct proto *p)
+{
+ ASSERT_DIE(birdloop_inside(&main_birdloop));
+ bool changed = p->disabled;
+ p->disabled = 0;
+ proto_rethink_goal(p);
+ return changed;
+}
/**
* DOC: Graceful restart recovery
diff --git a/nest/protocol.h b/nest/protocol.h
index 25ed6f553..cf7ecb898 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -78,6 +78,8 @@ void proto_build(struct protocol *); /* Called from protocol to register itself
void protos_preconfig(struct config *);
void protos_commit(struct config *new, struct config *old, int type);
struct proto * proto_spawn(struct proto_config *cf, uint disabled);
+bool proto_disable(struct proto *p);
+bool proto_enable(struct proto *p);
void protos_dump_all(struct dump_request *);
#define GA_UNKNOWN 0 /* Attribute not recognized */
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 5fc2b5fff..3170e3a42 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -378,8 +378,6 @@ bgp_startup(struct bgp_proto *p)
if (p->postponed_sk)
{
/* Apply postponed incoming connection */
- sk_reloop(p->postponed_sk, p->p.loop);
-
bgp_setup_conn(p, &p->incoming_conn);
bgp_setup_sk(&p->incoming_conn, p->postponed_sk);
bgp_send_open(&p->incoming_conn);
@@ -583,6 +581,9 @@ bgp_graceful_close_conn(struct bgp_conn *conn, int subcode, byte *data, uint len
static void
bgp_down(struct bgp_proto *p)
{
+ /* Check that the dynamic BGP socket has been picked up */
+ ASSERT_DIE(p->postponed_sk == NULL);
+
if (bgp_start_state(p) > BSS_PREPARE)
{
bgp_setup_auth(p, 0);
@@ -617,8 +618,8 @@ bgp_decision(void *vp)
bgp_down(p);
}
-static struct bgp_proto *
-bgp_spawn(struct bgp_proto *pp, ip_addr remote_ip)
+static void
+bgp_spawn(struct bgp_proto *pp, struct birdsock *sk)
{
struct symbol *sym;
char fmt[SYM_MAX_LEN];
@@ -635,9 +636,16 @@ bgp_spawn(struct bgp_proto *pp, ip_addr remote_ip)
cfg_mem = NULL;
/* Just pass remote_ip to bgp_init() */
- ((struct bgp_config *) sym->proto)->remote_ip = remote_ip;
+ ((struct bgp_config *) sym->proto)->remote_ip = sk->daddr;
+
+ /* Create the protocol disabled initially */
+ SKIP_BACK_DECLARE(struct bgp_proto, p, p, proto_spawn(sym->proto, 1));
- return (void *) proto_spawn(sym->proto, 0);
+ /* Pass the socket */
+ p->postponed_sk = sk;
+
+ /* And enable the protocol */
+ proto_enable(&p->p);
}
void
@@ -1489,10 +1497,15 @@ bgp_incoming_connection(sock *sk, uint dummy UNUSED)
/* For dynamic BGP, spawn new instance and postpone the socket */
if (bgp_is_dynamic(p))
{
- p = bgp_spawn(p, sk->daddr);
- p->postponed_sk = sk;
- rmove(sk, p->p.pool);
- goto leave;
+ UNLOCK_DOMAIN(rtable, bgp_listen_domain);
+
+ /* The dynamic protocol must be in the START state */
+ ASSERT_DIE(p->p.proto_state == PS_START);
+ birdloop_leave(p->p.loop);
+
+ /* Now we have a clean mainloop */
+ bgp_spawn(p, sk);
+ return 0;
}
rmove(sk, p->p.pool);
@@ -1806,7 +1819,6 @@ bgp_start(struct proto *P)
p->incoming_conn.state = BS_IDLE;
p->neigh = NULL;
p->bfd_req = NULL;
- p->postponed_sk = NULL;
p->gr_ready = 0;
p->gr_active_num = 0;
@@ -1848,6 +1860,16 @@ bgp_start(struct proto *P)
channel_graceful_restart_lock(&c->c);
}
+ /* Now it's the last chance to move the postponed socket to this BGP,
+ * as bgp_start is the only hook running from main loop. */
+ if (p->postponed_sk)
+ {
+ LOCK_DOMAIN(rtable, bgp_listen_domain);
+ rmove(p->postponed_sk, p->p.pool);
+ sk_reloop(p->postponed_sk, p->p.loop);
+ UNLOCK_DOMAIN(rtable, bgp_listen_domain);
+ }
+
/*
* Before attempting to create the connection, we need to lock the port,
* so that we are the only instance attempting to talk with that neighbor.
@@ -1999,6 +2021,8 @@ bgp_init(struct proto_config *CF)
p->remote_ip = cf->remote_ip;
p->remote_as = cf->remote_as;
+ p->postponed_sk = NULL;
+
/* Hack: We use cf->remote_ip just to pass remote_ip from bgp_spawn() */
if (cf->c.parent)
cf->remote_ip = IPA_NONE;
--
GitLab

View file

@ -1,87 +0,0 @@
From 2e14832d36c83b2ab5b7fb28b701de554fa5fdd9 Mon Sep 17 00:00:00 2001
From: Maria Matejka <mq@ucw.cz>
Date: Tue, 7 Jan 2025 12:13:57 +0100
Subject: [PATCH] Table: old best route refeed fix
When refeeding with RA_OPTIMAL, the old best routes weren't announced,
leading to weird behavior of protocols, mostly kernel. Fixed.
---
nest/rt-table.c | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/nest/rt-table.c b/nest/rt-table.c
index fc6d0d4e0..18a445a62 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -1485,11 +1485,18 @@ channel_notify_basic(void *_channel)
rte *new = &u->feed->block[i];
rte *old = NULL;
for (uint o = oldpos; o < u->feed->count_routes; o++)
- if (new->src == u->feed->block[o].src)
+ if ((c->ra_mode == RA_ANY) && (new->src == u->feed->block[o].src))
{
old = &u->feed->block[o];
break;
}
+ else if ((c->ra_mode == RA_OPTIMAL) && (
+ bmap_test(&c->export_accepted_map, u->feed->block[o].id) ||
+ bmap_test(&c->export_rejected_map, u->feed->block[o].id)))
+ {
+ ASSERT_DIE(!old);
+ old = &u->feed->block[o];
+ }
rt_notify_basic(c, new, old);
@@ -2542,10 +2549,14 @@ rt_feed_net_best(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, bool
last_in_net = atomic_load_explicit(&n->best.last, memory_order_acquire);
first = rt_net_feed_validate_first(tr, first_in_net, last_in_net, first);
- uint ecnt = 0;
+ uint ecnt = 0, ocnt = 0;
for (const struct rt_pending_export *rpe = first; rpe;
rpe = atomic_load_explicit(&rpe->next, memory_order_acquire))
+ {
ecnt++;
+ if (rpe->it.old)
+ ocnt++;
+ }
if (ecnt) {
const net_addr *a = (first->it.new ?: first->it.old)->net;
@@ -2558,10 +2569,11 @@ rt_feed_net_best(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, bool
if (!ecnt && (!best || prefilter && !prefilter(f, best->rte.net)))
return NULL;
- struct rt_export_feed *feed = rt_alloc_feed(!!best, ecnt);
+ struct rt_export_feed *feed = rt_alloc_feed(!!best + ocnt, ecnt);
+ uint bpos = 0;
if (best)
{
- feed->block[0] = best->rte;
+ feed->block[bpos++] = best->rte;
feed->ni = NET_TO_INDEX(best->rte.net);
}
else
@@ -2575,8 +2587,18 @@ rt_feed_net_best(struct rt_exporter *e, struct rcu_unwinder *u, u32 index, bool
if (e >= ecnt)
RT_READ_RETRY(tr);
else
+ {
feed->exports[e++] = rpe->it.seq;
+ if (rpe->it.old)
+ {
+ ASSERT_DIE(bpos < !!best + ocnt);
+ feed->block[bpos] = *rpe->it.old;
+ feed->block[bpos].flags |= REF_OBSOLETE;
+ bpos++;
+ }
+ }
+ ASSERT_DIE(bpos == !!best + ocnt);
ASSERT_DIE(e == ecnt);
}
--
GitLab

File diff suppressed because it is too large Load diff