The dynamic BGP postponed socket handling was moved from bgp_init() to bgp_start_locked() to ensure both domains are properly locked during the rmove() operation.
In bgp_init(), the protocol birdloop does not exist yet, but in bgp_start_locked() it is possible to safely enter both the socket original birdloop and the protocol birdloop to satisfy dual-lock requirement and avoid DG_IS_LOCKED failed assertions. Signed-off-by: Matteo Perin <[email protected]> --- proto/bgp/bgp.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index d3d61eaf..ad6dd334 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -2648,6 +2648,22 @@ bgp_start_locked(void *_p) DBG("BGP: Got lock\n"); + /* Move postponed socket to protocol's birdloop if present */ + if (p->postponed_sk) + { + sock *sk = p->postponed_sk; + struct birdloop *sk_loop = sk->loop; + + if (sk_loop && (sk_loop != p->p.loop)) + birdloop_enter(sk_loop); + + rmove(sk, p->p.pool); + sk_reloop(sk, p->p.loop); + + if (sk_loop && (sk_loop != p->p.loop)) + birdloop_leave(sk_loop); + } + if (cf->multihop || bgp_is_dynamic(p)) { /* Multi-hop sessions do not use neighbor entries */ @@ -2770,15 +2786,6 @@ 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) - BGP_LISTEN_LOCKED(bl) - { - rmove(p->postponed_sk, p->p.pool); - sk_reloop(p->postponed_sk, p->p.loop); - } - /* * 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. -- 2.43.0
