diff options
author | Maria Matejka <mq@ucw.cz> | 2023-04-05 21:59:01 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2023-04-06 12:48:02 +0200 |
commit | 22a0900ec22511b6ce872f126e9766ccb4e5a824 (patch) | |
tree | f1b15ebdebb05ef6d6d232bc06043da75d8f74e9 /proto/bgp | |
parent | 4a69a64745e44066abfa4f6a17a7bb7a2fde9834 (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.c | 7 |
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; } |