summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2023-04-05 21:59:01 +0200
committerMaria Matejka <mq@ucw.cz>2023-04-06 12:48:02 +0200
commit22a0900ec22511b6ce872f126e9766ccb4e5a824 (patch)
treef1b15ebdebb05ef6d6d232bc06043da75d8f74e9 /proto/bgp
parent4a69a64745e44066abfa4f6a17a7bb7a2fde9834 (diff)
BFD: fixed a request pickup race condition
When several BGPs requested a BFD session in short time, chances were that the second BGP would file a request while the pickup routine was still running and it would get enqueued into the waiting list instead of being picked up. Fixed this by enforcing pickup loop restart when new requests got added, and also by atomically moving the unpicked requests to a temporary list to announce admin down before actually being added into the wait list.
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/bgp.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 41df59bb..fffa8cec 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1524,15 +1524,22 @@ static void
bgp_update_bfd(struct bgp_proto *p, const struct bfd_options *bfd)
{
if (bfd && p->bfd_req)
+ {
+ BGP_TRACE(D_EVENTS, "Updating existing BFD request");
bfd_update_request(p->bfd_req, bfd);
+ }
if (bfd && !p->bfd_req && !bgp_is_dynamic(p))
+ {
p->bfd_req = bfd_request_session(p->p.pool, p->remote_ip, p->local_ip,
p->cf->multihop ? NULL : p->neigh->iface,
p->p.vrf, bgp_bfd_notify, p, p->p.loop, bfd);
+ BGP_TRACE(D_EVENTS, "Requesting a new BFD session");
+ }
if (!bfd && p->bfd_req)
{
+ BGP_TRACE(D_EVENTS, "Retracting the BFD request");
rfree(p->bfd_req);
p->bfd_req = NULL;
}