Date: Thu, 9 Jan 2025 22:08:14 GMT From: Olivier Cochard <olivier@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: 4516e09a236b - main - net/bird3: Add new branch 3.x (multithreaded) Message-ID: <202501092208.509M8E3C053936@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by olivier: URL: https://cgit.FreeBSD.org/ports/commit/?id=4516e09a236bb31d6e852eadfb05f9576e4db7da commit 4516e09a236bb31d6e852eadfb05f9576e4db7da Author: Olivier Cochard <olivier@FreeBSD.org> AuthorDate: 2025-01-09 21:58:36 +0000 Commit: Olivier Cochard <olivier@FreeBSD.org> CommitDate: 2025-01-09 22:07:38 +0000 net/bird3: Add new branch 3.x (multithreaded) Warning: Consider version 3.0.0 to be unstable. PR: 283403 Sponsored by: Netflix --- net/Makefile | 1 + net/bird2/Makefile | 3 +- net/bird3/Makefile | 62 ++++ net/bird3/distinfo | 3 + net/bird3/files/bird.in | 30 ++ .../patch-00-kernel-Fix-crash-for-merge-paths | 38 ++ net/bird3/files/patch-01-Table-not-feeding-twice | 39 ++ .../files/patch-02-kernel-trace-the-final-result | 53 +++ net/bird3/files/patch-03-BGP-fix-locking-order | 176 +++++++++ .../files/patch-04-BFD-Fix-session-locking-order | 400 +++++++++++++++++++++ .../files/patch-05-mainloop-dropped-old-socket | 86 +++++ net/bird3/files/patch-06-cli-allocate-tx-buffers | 134 +++++++ net/bird3/files/patch-07-cli-flushing-tmp-linpool | 29 ++ net/bird3/files/patch-08-kernel-feed-only-once | 274 ++++++++++++++ net/bird3/files/patch-09-graceful-recovery | 311 ++++++++++++++++ net/bird3/files/patch-10-stonehenge | 116 ++++++ net/bird3/files/patch-11-route-attribute-storage | 80 +++++ net/bird3/files/patch-12-BGP-tx-bucket-storage | 84 +++++ .../files/patch-13-allocate-normalization-buckets | 100 ++++++ net/bird3/files/patch-14-BGP-fix-dislpay-name | 25 ++ .../patch-15-BGP-fixed-deterministic-med-crashes | 65 ++++ .../files/patch-16-Table-old-best-route-refeed-fix | 87 +++++ net/bird3/files/patch-Makefile.in | 11 + net/bird3/files/pkg-message.in | 11 + net/bird3/pkg-descr | 14 + net/bird3/pkg-plist | 4 + 26 files changed, 2234 insertions(+), 2 deletions(-) diff --git a/net/Makefile b/net/Makefile index 151a98fa8881..9093da9bdb0b 100644 --- a/net/Makefile +++ b/net/Makefile @@ -57,6 +57,7 @@ SUBDIR += bindtest SUBDIR += binkd SUBDIR += bird2 + SUBDIR += bird3 SUBDIR += bittwist SUBDIR += bmon SUBDIR += boinc-client diff --git a/net/bird2/Makefile b/net/bird2/Makefile index 7a6d87747d6f..3a5dc86df54a 100644 --- a/net/bird2/Makefile +++ b/net/bird2/Makefile @@ -15,8 +15,7 @@ rtsock_PKGNAMESUFFIX= 2-rtsock USES= bison cpe gmake ncurses readline -CONFLICTS= bird -CONFLICTS+= bird6 +CONFLICTS= bird3 CPE_VENDOR= nic diff --git a/net/bird3/Makefile b/net/bird3/Makefile new file mode 100644 index 000000000000..8c27bcafdc41 --- /dev/null +++ b/net/bird3/Makefile @@ -0,0 +1,62 @@ +PORTNAME= bird +DISTVERSION= 3.0.0 +CATEGORIES= net +MASTER_SITES= https://bird.network.cz/download/ +PKGNAMESUFFIX= 3 + +MAINTAINER= olivier@FreeBSD.org +COMMENT= Dynamic multithreaded IP routing daemon +WWW= https://bird.network.cz/ + +LICENSE= GPLv2 + +USES= bison cpe gmake ncurses readline + +CONFLICTS= bird2 + +CPE_VENDOR= nic + +USE_CSTD= gnu99 +GNU_CONFIGURE= yes +CONFIGURE_ARGS= --localstatedir=/var +USE_RC_SUBR= bird +SUB_FILES= pkg-message + +GROUPS= birdvty + +MAKE_JOBS_UNSAFE= yes + +OPTIONS_MULTI= RP +RP_DESC= Routing Protocols +OPTIONS_MULTI_RP= BFD BABEL BMP BGP MRT OSPF PIPE RADV RIP RPKI STATIC +OPTIONS_DEFAULT= BFD BABEL BGP MRT OSPF PIPE RADV RIP RPKI STATIC + +BFD_DESC= Bidirectional Forwarding Detection +BABEL_DESC= Babel routing protocol +BGP_DESC= Border Gateway Protocol +BMP_DESC= BGP Monitoring Protocol +MRT_DESC= Dumping Routing Information in MRT Format +OSPF_DESC= Open Short Path First +PIPE_DESC= PIPE routing +RADV_DESC= Router Advertisement +RIP_DESC= Routing Information Protocol +RPKI_DESC= Resource Public Key Infrastructure +STATIC_DESC= Static routing + +BFD_VARS= rt_prot+=bfd +BABEL_VARS= rt_prot+=babel +BGP_VARS= rt_prot+=bgp +BMP_VARS= rt_prot+=bmp +MRT_VARS= rt_prot+=mrt +OSPF_VARS= rt_prot+=ospf +PIPE_VARS= rt_prot+=pipe +RADV_VARS= rt_prot+=radv +RIP_VARS= rt_prot+=rip +RPKI_VARS= rt_prot+=rpki +STATIC_VARS= rt_prot+=static + +CONFIGURE_ARGS+=--with-protocols="${RT_PROT}" +CONFIGURE_ARGS+=--with-sysconfig=bsd-netlink +RPKI_LIB_DEPENDS= libssh.so:security/libssh + +.include <bsd.port.mk> diff --git a/net/bird3/distinfo b/net/bird3/distinfo new file mode 100644 index 000000000000..66fda3f7d35c --- /dev/null +++ b/net/bird3/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1734554961 +SHA256 (bird-3.0.0.tar.gz) = 8130440a2e273ba6456df2fb3acb43da7cb4d566f94a294a3a52a1b118f2512a +SIZE (bird-3.0.0.tar.gz) = 2641569 diff --git a/net/bird3/files/bird.in b/net/bird3/files/bird.in new file mode 100644 index 000000000000..de800bd69b81 --- /dev/null +++ b/net/bird3/files/bird.in @@ -0,0 +1,30 @@ +#!/bin/sh + +# PROVIDE: bird dynamicrouting +# REQUIRE: LOGIN +# KEYWORD: shutdown +# +# Add the following lines to /etc/rc.conf.local or /etc/rc.conf +# to enable this service: +# +# bird_enable (bool): Set to NO by default. +# Set it to YES to enable bird. +# bird_config (path): Set to %%PREFIX%%/etc/bird.conf +# by default. +# + +. /etc/rc.subr + +name="bird" +rcvar=bird_enable + +load_rc_config $name + +: ${bird_enable="NO"} +: ${bird_config="%%PREFIX%%/etc/bird.conf"} +: ${bird_group="birdvty"} + +command=%%PREFIX%%/sbin/${name} +command_args="-c $bird_config -g $bird_group" + +run_rc_command "$1" diff --git a/net/bird3/files/patch-00-kernel-Fix-crash-for-merge-paths b/net/bird3/files/patch-00-kernel-Fix-crash-for-merge-paths new file mode 100644 index 000000000000..d008d4cf070c --- /dev/null +++ b/net/bird3/files/patch-00-kernel-Fix-crash-for-merge-paths @@ -0,0 +1,38 @@ +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 +--- nest/rt-table.c ++++ 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 + diff --git a/net/bird3/files/patch-01-Table-not-feeding-twice b/net/bird3/files/patch-01-Table-not-feeding-twice new file mode 100644 index 000000000000..4fb40a644fb2 --- /dev/null +++ b/net/bird3/files/patch-01-Table-not-feeding-twice @@ -0,0 +1,39 @@ +From 0a2f92ad205d96d0be0945ecf2bb740b68d5a3c1 Mon Sep 17 00:00:00 2001 +From: Maria Matejka <mq@ucw.cz> +Date: Thu, 19 Dec 2024 11:54:05 +0100 +Subject: [PATCH] Table: not feeding twice, once is enough + +If there is no feed pending, the requested one should be +activated immediately, otherwise it is activated only after +the full run, effectively running first a full feed and +then the requested one. +--- + nest/rt-export.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/nest/rt-export.c b/nest/rt-export.c +index 7368447de..7d51e54cf 100644 +--- nest/rt-export.c ++++ nest/rt-export.c +@@ -357,8 +357,16 @@ rt_export_refeed_feeder(struct rt_export_feeder *f, struct rt_feeding_request *r + if (!rfr) + return; + +- rfr->next = f->feed_pending; +- f->feed_pending = rfr; ++ if (f->feeding) ++ { ++ rfr->next = f->feed_pending; ++ f->feed_pending = rfr; ++ } ++ else ++ { ++ rfr->next = NULL; ++ f->feeding = rfr; ++ } + } + + void rt_export_refeed_request(struct rt_export_request *rer, struct rt_feeding_request *rfr) +-- +GitLab + diff --git a/net/bird3/files/patch-02-kernel-trace-the-final-result b/net/bird3/files/patch-02-kernel-trace-the-final-result new file mode 100644 index 000000000000..a3c97320f30e --- /dev/null +++ b/net/bird3/files/patch-02-kernel-trace-the-final-result @@ -0,0 +1,53 @@ +From ab74652f96c301dd2d2d2a831dd1a159ae1d5e02 Mon Sep 17 00:00:00 2001 +From: Maria Matejka <mq@ucw.cz> +Date: Thu, 19 Dec 2024 12:28:27 +0100 +Subject: [PATCH] Kernel: when channel traces, we have to trace the final + result + +Otherwise it looks like we are sending too much traffic to netlink +every other while, which is not true. Now we can disambiguate between +in-kernel updates and ignored routes. +--- + sysdep/unix/krt.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c +index 2770b8be2..34882b88f 100644 +--- sysdep/unix/krt.c ++++ sysdep/unix/krt.c +@@ -672,7 +672,7 @@ krt_preexport(struct channel *C, rte *e) + } + + static void +-krt_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, ++krt_rt_notify(struct proto *P, struct channel *ch, const net_addr *net, + rte *new, const rte *old) + { + struct krt_proto *p = (struct krt_proto *) P; +@@ -688,13 +688,21 @@ krt_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, + case KPS_IDLE: + case KPS_PRUNING: + if (new && bmap_test(&p->seen_map, new->id)) +- /* Already installed and seen in the kernel dump */ +- return; ++ if (ch->debug & D_ROUTES) ++ { ++ /* Already installed and seen in the kernel dump */ ++ log(L_TRACE "%s.%s: %N already in kernel", ++ P->name, ch->name, net); ++ return; ++ } + + /* fall through */ + case KPS_SCANNING: + /* Actually replace the route */ + krt_replace_rte(p, net, new, old); ++ if (ch->debug & D_ROUTES) ++ log(L_TRACE "%s.%s: %N %s kernel", ++ P->name, ch->name, net, old ? "replaced in" : "added to"); + break; + + } +-- +GitLab + diff --git a/net/bird3/files/patch-03-BGP-fix-locking-order b/net/bird3/files/patch-03-BGP-fix-locking-order new file mode 100644 index 000000000000..51b73c26f8f8 --- /dev/null +++ b/net/bird3/files/patch-03-BGP-fix-locking-order @@ -0,0 +1,176 @@ +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 +--- nest/proto.c ++++ 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 +--- nest/protocol.h ++++ 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 +--- proto/bgp/bgp.c ++++ 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 + diff --git a/net/bird3/files/patch-04-BFD-Fix-session-locking-order b/net/bird3/files/patch-04-BFD-Fix-session-locking-order new file mode 100644 index 000000000000..3f5500500691 --- /dev/null +++ b/net/bird3/files/patch-04-BFD-Fix-session-locking-order @@ -0,0 +1,400 @@ +From 83495362789d961914c4bfaa590e31cb17370ed0 Mon Sep 17 00:00:00 2001 +From: Maria Matejka <mq@ucw.cz> +Date: Sat, 21 Dec 2024 19:02:22 +0100 +Subject: [PATCH] BFD: Fix session reconfiguration locking order + +The sessions have to be updated asynchronously to avoid +cross-locking between protocols. + +Testsuite: cf-ibgp-bfd-switch, cf-ibgp-multi-bfd-auth +Fixes: #139 + +Thanks to Daniel Suchy <danny@danysek.cz> for reporting: +https://trubka.network.cz/pipermail/bird-users/2024-December/017984.html +--- + nest/bfd.h | 7 ++- + proto/bfd/bfd.c | 144 +++++++++++++++++++++++--------------------- + proto/bfd/bfd.h | 21 +------ + proto/bfd/config.Y | 42 +++++-------- + proto/bfd/packets.c | 4 +- + 5 files changed, 98 insertions(+), 120 deletions(-) + +diff --git a/nest/bfd.h b/nest/bfd.h +index 5dacff5d7..c046152f8 100644 +--- nest/bfd.h ++++ nest/bfd.h +@@ -18,8 +18,11 @@ struct bfd_options { + u32 min_tx_int; + u32 idle_tx_int; + u8 multiplier; +- u8 passive; +- u8 passive_set; ++ PACKED enum bfd_opt_passive { ++ BFD_OPT_PASSIVE_UNKNOWN = 0, ++ BFD_OPT_PASSIVE, ++ BFD_OPT_NOT_PASSIVE, ++ } passive; + u8 mode; + u8 auth_type; /* Authentication type (BFD_AUTH_*) */ + list *passwords; /* Passwords for authentication */ +diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c +index 34f992b93..4997f803a 100644 +--- proto/bfd/bfd.c ++++ proto/bfd/bfd.c +@@ -172,17 +172,17 @@ static void bfd_free_iface(struct bfd_iface *ifa); + * BFD sessions + */ + +-static inline struct bfd_session_config +-bfd_merge_options(const struct bfd_iface_config *cf, const struct bfd_options *opts) ++static inline struct bfd_options ++bfd_merge_options(const struct bfd_options *bottom, const struct bfd_options *top) + { +- return (struct bfd_session_config) { +- .min_rx_int = opts->min_rx_int ?: cf->min_rx_int, +- .min_tx_int = opts->min_tx_int ?: cf->min_tx_int, +- .idle_tx_int = opts->idle_tx_int ?: cf->idle_tx_int, +- .multiplier = opts->multiplier ?: cf->multiplier, +- .passive = opts->passive_set ? opts->passive : cf->passive, +- .auth_type = opts->auth_type ?: cf->auth_type, +- .passwords = opts->passwords ?: cf->passwords, ++ return (struct bfd_options) { ++ .min_rx_int = top->min_rx_int ?: bottom->min_rx_int, ++ .min_tx_int = top->min_tx_int ?: bottom->min_tx_int, ++ .idle_tx_int = top->idle_tx_int ?: bottom->idle_tx_int, ++ .multiplier = top->multiplier ?: bottom->multiplier, ++ .passive = top->passive ?: bottom->passive, ++ .auth_type = top->auth_type ?: bottom->auth_type, ++ .passwords = top->passwords ?: bottom->passwords, + }; + } + +@@ -478,7 +478,7 @@ bfd_add_session(struct bfd_proto *p, ip_addr addr, ip_addr local, struct iface * + HASH_INSERT(p->session_hash_id, HASH_ID, s); + HASH_INSERT(p->session_hash_ip, HASH_IP, s); + +- s->cf = bfd_merge_options(ifa->cf, opts); ++ s->cf = bfd_merge_options(&ifa->cf->opts, opts); + + /* Initialization of state variables - see RFC 5880 6.8.1 */ + s->loc_state = BFD_STATE_DOWN; +@@ -561,26 +561,58 @@ bfd_remove_session(struct bfd_proto *p, struct bfd_session *s) + birdloop_leave(p->p.loop); + } + ++struct bfd_reconfigure_sessions_deferred_call { ++ struct deferred_call dc; ++ struct bfd_proto *p; ++ config_ref old_config; ++}; ++ + static void +-bfd_reconfigure_session(struct bfd_proto *p, struct bfd_session *s) ++bfd_reconfigure_sessions(struct deferred_call *dc) + { +- if (EMPTY_LIST(s->request_list)) +- return; ++ SKIP_BACK_DECLARE(struct bfd_reconfigure_sessions_deferred_call, ++ brsdc, dc, dc); + +- ASSERT_DIE(birdloop_inside(p->p.loop)); ++ struct bfd_proto *p = brsdc->p; ++ birdloop_enter(p->p.loop); + +- SKIP_BACK_DECLARE(struct bfd_request, req, n, HEAD(s->request_list)); +- s->cf = bfd_merge_options(s->ifa->cf, &req->opts); ++ HASH_WALK(p->session_hash_id, next_id, s) ++ { ++ if (!EMPTY_LIST(s->request_list)) ++ { ++ SKIP_BACK_DECLARE(struct bfd_request, req, n, HEAD(s->request_list)); ++ struct bfd_options opts = bfd_merge_options(&s->ifa->cf->opts, &req->opts); + +- u32 tx = (s->loc_state == BFD_STATE_UP) ? s->cf.min_tx_int : s->cf.idle_tx_int; +- bfd_session_set_min_tx(s, tx); +- bfd_session_set_min_rx(s, s->cf.min_rx_int); +- s->detect_mult = s->cf.multiplier; +- s->passive = s->cf.passive; ++#define CHK(x) (opts.x != s->cf.x) || ++ bool reload = MACRO_FOREACH(CHK, ++ min_rx_int, ++ min_tx_int, ++ idle_tx_int, ++ multiplier, ++ passive) false; /* terminating the || chain */ ++#undef CHK + +- bfd_session_control_tx_timer(s, 0); ++ s->cf = opts; ++ ++ if (reload) ++ { ++ u32 tx = (s->loc_state == BFD_STATE_UP) ? s->cf.min_tx_int : s->cf.idle_tx_int; ++ bfd_session_set_min_tx(s, tx); ++ bfd_session_set_min_rx(s, s->cf.min_rx_int); ++ s->detect_mult = s->cf.multiplier; ++ s->passive = s->cf.passive; ++ ++ bfd_session_control_tx_timer(s, 0); ++ ++ TRACE(D_EVENTS, "Session to %I reconfigured", s->addr); ++ } ++ } ++ } ++ HASH_WALK_END; ++ birdloop_leave(p->p.loop); + +- TRACE(D_EVENTS, "Session to %I reconfigured", s->addr); ++ /* Now the config is clean */ ++ OBSREF_CLEAR(brsdc->old_config); + } + + +@@ -589,10 +621,12 @@ bfd_reconfigure_session(struct bfd_proto *p, struct bfd_session *s) + */ + + static struct bfd_iface_config bfd_default_iface = { +- .min_rx_int = BFD_DEFAULT_MIN_RX_INT, +- .min_tx_int = BFD_DEFAULT_MIN_TX_INT, +- .idle_tx_int = BFD_DEFAULT_IDLE_TX_INT, +- .multiplier = BFD_DEFAULT_MULTIPLIER, ++ .opts = { ++ .min_rx_int = BFD_DEFAULT_MIN_RX_INT, ++ .min_tx_int = BFD_DEFAULT_MIN_TX_INT, ++ .idle_tx_int = BFD_DEFAULT_IDLE_TX_INT, ++ .multiplier = BFD_DEFAULT_MULTIPLIER, ++ }, + }; + + static inline struct bfd_iface_config * +@@ -650,24 +684,6 @@ bfd_free_iface(struct bfd_iface *ifa) + mb_free(ifa); + } + +-static void +-bfd_reconfigure_iface(struct bfd_proto *p UNUSED, struct bfd_iface *ifa, struct bfd_config *nc) +-{ +- struct bfd_iface_config *new = bfd_find_iface_config(nc, ifa->iface); +- struct bfd_iface_config *old = ifa->cf; +- +- /* Check options that are handled in bfd_reconfigure_session() */ +- ifa->changed = +- (new->min_rx_int != old->min_rx_int) || +- (new->min_tx_int != old->min_tx_int) || +- (new->idle_tx_int != old->idle_tx_int) || +- (new->multiplier != old->multiplier) || +- (new->passive != old->passive); +- +- /* This should be probably changed to not access ifa->cf from the BFD thread */ +- ifa->cf = new; +-} +- + + /* + * BFD requests +@@ -900,20 +916,7 @@ bfd_request_session(pool *p, ip_addr addr, ip_addr local, + void + bfd_update_request(struct bfd_request *req, const struct bfd_options *opts) + { +- struct bfd_session *s = req->session; +- +- if (!memcmp(opts, &req->opts, sizeof(const struct bfd_options))) +- return; +- + req->opts = *opts; +- +- if (s) +- { +- struct bfd_proto *p = s->ifa->bfd; +- birdloop_enter(p->p.loop); +- bfd_reconfigure_session(p, s); +- birdloop_leave(p->p.loop); +- } + } + + static void +@@ -1193,21 +1196,22 @@ bfd_reconfigure(struct proto *P, struct proto_config *c) + (new->zero_udp6_checksum_rx != old->zero_udp6_checksum_rx)) + return 0; + +- birdloop_mask_wakeups(p->p.loop); +- + WALK_LIST(ifa, p->iface_list) +- bfd_reconfigure_iface(p, ifa, new); +- +- HASH_WALK(p->session_hash_id, next_id, s) +- { +- if (s->ifa->changed) +- bfd_reconfigure_session(p, s); +- } +- HASH_WALK_END; ++ ifa->cf = bfd_find_iface_config(new, ifa->iface); + + bfd_reconfigure_neighbors(p, new); + +- birdloop_unmask_wakeups(p->p.loop); ++ /* Sessions get reconfigured after all the config is applied */ ++ struct bfd_reconfigure_sessions_deferred_call brsdc = { ++ .dc.hook = bfd_reconfigure_sessions, ++ .p = p, ++ }; ++ SKIP_BACK_DECLARE(struct bfd_reconfigure_sessions_deferred_call, ++ brsdcp, dc, defer_call(&brsdc.dc, sizeof brsdc)); ++ ++ /* We need to keep the old config alive until all the sessions get ++ * reconfigured */ ++ OBSREF_SET(brsdcp->old_config, P->cf->global); + + return 1; + } +diff --git a/proto/bfd/bfd.h b/proto/bfd/bfd.h +index 578ce8755..107829b72 100644 +--- proto/bfd/bfd.h ++++ proto/bfd/bfd.h +@@ -54,24 +54,7 @@ struct bfd_config + struct bfd_iface_config + { + struct iface_patt i; +- u32 min_rx_int; +- u32 min_tx_int; +- u32 idle_tx_int; +- u8 multiplier; +- u8 passive; +- u8 auth_type; /* Authentication type (BFD_AUTH_*) */ +- list *passwords; /* Passwords for authentication */ +-}; +- +-struct bfd_session_config +-{ +- u32 min_rx_int; +- u32 min_tx_int; +- u32 idle_tx_int; +- u8 multiplier; +- u8 passive; +- u8 auth_type; /* Authentication type (BFD_AUTH_*) */ +- list *passwords; /* Passwords for authentication */ ++ struct bfd_options opts; + }; + + struct bfd_neighbor +@@ -146,7 +129,7 @@ struct bfd_session + u32 loc_id; /* Local session ID (local discriminator) */ + u32 rem_id; /* Remote session ID (remote discriminator) */ + +- struct bfd_session_config cf; /* Static configuration parameters */ ++ struct bfd_options cf; /* Static configuration parameters */ + + u32 des_min_tx_int; /* Desired min rx interval, local option */ + u32 des_min_tx_new; /* Used for des_min_tx_int change */ +diff --git a/proto/bfd/config.Y b/proto/bfd/config.Y +index 9e9919c4e..56d1ffac4 100644 +--- proto/bfd/config.Y ++++ proto/bfd/config.Y +@@ -86,44 +86,37 @@ bfd_iface_start: + add_tail(&BFD_CFG->patt_list, NODE this_ipatt); + init_list(&this_ipatt->ipn_list); + +- BFD_IFACE->min_rx_int = BFD_DEFAULT_MIN_RX_INT; +- BFD_IFACE->min_tx_int = BFD_DEFAULT_MIN_TX_INT; +- BFD_IFACE->idle_tx_int = BFD_DEFAULT_IDLE_TX_INT; +- BFD_IFACE->multiplier = BFD_DEFAULT_MULTIPLIER; ++ this_bfd_opts = &BFD_IFACE->opts; ++ ++ this_bfd_opts->min_rx_int = BFD_DEFAULT_MIN_RX_INT; ++ this_bfd_opts->min_tx_int = BFD_DEFAULT_MIN_TX_INT; ++ this_bfd_opts->idle_tx_int = BFD_DEFAULT_IDLE_TX_INT; ++ this_bfd_opts->multiplier = BFD_DEFAULT_MULTIPLIER; + + reset_passwords(); + }; + + bfd_iface_finish: + { +- BFD_IFACE->passwords = get_passwords(); ++ this_bfd_opts->passwords = get_passwords(); + +- if (!BFD_IFACE->auth_type != !BFD_IFACE->passwords) ++ if (!this_bfd_opts->auth_type != !this_bfd_opts->passwords) + cf_warn("Authentication and password options should be used together"); + +- if (BFD_IFACE->passwords) ++ if (this_bfd_opts->passwords) + { + struct password_item *pass; +- WALK_LIST(pass, *BFD_IFACE->passwords) ++ WALK_LIST(pass, *this_bfd_opts->passwords) + { + if (pass->alg) + cf_error("Password algorithm option not available in BFD protocol"); + +- pass->alg = bfd_auth_type_to_hash_alg[BFD_IFACE->auth_type]; ++ pass->alg = bfd_auth_type_to_hash_alg[this_bfd_opts->auth_type]; + } + } +-}; + +-bfd_iface_item: +- INTERVAL expr_us { BFD_IFACE->min_rx_int = BFD_IFACE->min_tx_int = $2; } +- | MIN RX INTERVAL expr_us { BFD_IFACE->min_rx_int = $4; } +- | MIN TX INTERVAL expr_us { BFD_IFACE->min_tx_int = $4; } +- | IDLE TX INTERVAL expr_us { BFD_IFACE->idle_tx_int = $4; } +- | MULTIPLIER expr { BFD_IFACE->multiplier = $2; } +- | PASSIVE bool { BFD_IFACE->passive = $2; } +- | AUTHENTICATION bfd_auth_type { BFD_IFACE->auth_type = $2; } +- | password_list {} +- ; ++ this_bfd_opts = NULL; ++}; + + bfd_auth_type: + NONE { $$ = BFD_AUTH_NONE; } +@@ -134,14 +127,9 @@ bfd_auth_type: + | METICULOUS KEYED SHA1 { $$ = BFD_AUTH_METICULOUS_KEYED_SHA1; } + ; + +-bfd_iface_opts: +- /* empty */ +- | bfd_iface_opts bfd_iface_item ';' +- ; +- + bfd_iface_opt_list: + /* empty */ +- | '{' bfd_iface_opts '}' ++ | '{' bfd_items '}' + ; + + bfd_iface: +@@ -194,7 +182,7 @@ bfd_item: + | MIN TX INTERVAL expr_us { this_bfd_opts->min_tx_int = $4; } + | IDLE TX INTERVAL expr_us { this_bfd_opts->idle_tx_int = $4; } + | MULTIPLIER expr { this_bfd_opts->multiplier = $2; } +- | PASSIVE bool { this_bfd_opts->passive = $2; this_bfd_opts->passive_set = 1; } ++ | PASSIVE bool { this_bfd_opts->passive = $2 ? BFD_OPT_PASSIVE : BFD_OPT_NOT_PASSIVE; } + | GRACEFUL { this_bfd_opts->mode = BGP_BFD_GRACEFUL; } + | AUTHENTICATION bfd_auth_type { this_bfd_opts->auth_type = $2; } + | password_list {} +diff --git a/proto/bfd/packets.c b/proto/bfd/packets.c +index 1ceb470c1..f8bd63d73 100644 +--- proto/bfd/packets.c ++++ proto/bfd/packets.c +@@ -109,7 +109,7 @@ const u8 bfd_auth_type_to_hash_alg[] = { + static void + bfd_fill_authentication(struct bfd_proto *p, struct bfd_session *s, struct bfd_ctl_packet *pkt) + { +- struct bfd_session_config *cf = &s->cf; ++ struct bfd_options *cf = &s->cf; + struct password_item *pass = password_find(cf->passwords, 0); + uint meticulous = 0; + +@@ -179,7 +179,7 @@ bfd_fill_authentication(struct bfd_proto *p, struct bfd_session *s, struct bfd_c + static int + bfd_check_authentication(struct bfd_proto *p, struct bfd_session *s, struct bfd_ctl_packet *pkt) + { +- struct bfd_session_config *cf = &s->cf; ++ struct bfd_options *cf = &s->cf; + const char *err_dsc = NULL; + uint err_val = 0; + uint auth_type = 0; +-- +GitLab + diff --git a/net/bird3/files/patch-05-mainloop-dropped-old-socket b/net/bird3/files/patch-05-mainloop-dropped-old-socket new file mode 100644 index 000000000000..eea4d1d26af2 --- /dev/null +++ b/net/bird3/files/patch-05-mainloop-dropped-old-socket @@ -0,0 +1,86 @@ +From 3d1f19e335f55c8cfa3cb7ca9d7b88ca03173d8e Mon Sep 17 00:00:00 2001 +From: Maria Matejka <mq@ucw.cz> +Date: Sun, 22 Dec 2024 21:32:28 +0100 +Subject: [PATCH] Mainloop: Dropped old socket prioritization magic + +This is now done in worker threads and the mainloop needs to do other things, +most notably kernel and CLI, with less overhead of repeatedly checking poll. +--- + sysdep/unix/io-loop.c | 2 +- + sysdep/unix/io.c | 21 +++++++-------------- + 2 files changed, 8 insertions(+), 15 deletions(-) + +diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c +index f69189e06..a72c69a03 100644 +--- sysdep/unix/io-loop.c ++++ sysdep/unix/io-loop.c +@@ -1403,7 +1403,7 @@ bool task_still_in_limit(void) + { + static u64 main_counter = 0; + if (this_birdloop == &main_birdloop) +- return (++main_counter % 2048); /* This is a hack because of no accounting in mainloop */ ++ return (++main_counter % 512); /* This is a hack because of no accounting in mainloop */ + else + return ns_now() < account_last + this_thread->max_loop_time_ns; + } +diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c +index f9785c074..51395e1e9 100644 +--- sysdep/unix/io.c ++++ sysdep/unix/io.c +@@ -53,14 +53,15 @@ + + /* Maximum number of calls of tx handler for one socket in one + * poll iteration. Should be small enough to not monopolize CPU by +- * one protocol instance. ++ * one protocol instance. But as most of the problems are now offloaded ++ * to worker threads, too low values may actually bring problems with ++ * latency. + */ +-#define MAX_STEPS 4 ++#define MAX_STEPS 2048 + + /* Maximum number of calls of rx handler for all sockets in one poll +- iteration. RX callbacks are often much more costly so we limit +- this to gen small latencies */ +-#define MAX_RX_STEPS 4 ++ iteration. RX callbacks are often a little bit more costly. */ ++#define MAX_RX_STEPS 512 + + + /* +@@ -2581,8 +2582,6 @@ io_init(void) + srandom((uint) (now ^ (now >> 32))); + } + +-static int short_loops = 0; +-#define SHORT_LOOP_MAX 10 + #define WORK_EVENTS_MAX 10 + + sock *stored_sock; +@@ -2670,10 +2669,9 @@ io_loop(void) *** 1461 LINES SKIPPED ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202501092208.509M8E3C053936>