summaryrefslogtreecommitdiff
path: root/proto/bgp/bgp.c
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2018-07-04 16:42:42 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2018-07-17 13:16:35 +0200
commitaa2ec912f5a557f340a633e95b9fbf2ad7937edd (patch)
treece2c7f1173793c16355f2bcab57dd1e22da6d52b /proto/bgp/bgp.c
parenta9d869c484f899f2ef509659a8d928804d020461 (diff)
BGP: Long-lived graceful restart enhancements
When use of LLGR is negotiated, handle hold timeout by LLGR instead of by hard restart. Allow to configure whether BFD session down event should be handled by GR/LLGR or by hard restart.
Diffstat (limited to 'proto/bgp/bgp.c')
-rw-r--r--proto/bgp/bgp.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 0932051a..369d78f5 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -704,6 +704,12 @@ bgp_hold_timeout(timer *t)
if (sk_rx_ready(conn->sk) > 0)
bgp_start_timer(conn->hold_timer, 10);
+ else if ((conn->state == BS_ESTABLISHED) && p->gr_ready && conn->peer_llgr_able)
+ {
+ BGP_TRACE(D_EVENTS, "Hold timer expired");
+ bgp_handle_graceful_restart(p);
+ bgp_conn_enter_idle_state(conn);
+ }
else
bgp_error(conn, 4, 0, NULL, 0);
}
@@ -1046,13 +1052,29 @@ bgp_bfd_notify(struct bfd_request *req)
int ps = p->p.proto_state;
if (req->down && ((ps == PS_START) || (ps == PS_UP)))
+ {
+ BGP_TRACE(D_EVENTS, "BFD session down");
+
+ /* Ignore if already in GR */
+ if (p->gr_active && (p->cf->bfd == BGP_BFD_GRACEFUL))
+ return;
+
+ if (p->conn && (p->conn->state == BS_ESTABLISHED) &&
+ p->gr_ready && (p->cf->bfd == BGP_BFD_GRACEFUL))
+ {
+ /* Trigger graceful restart */
+ bgp_handle_graceful_restart(p);
+ bgp_conn_enter_idle_state(p->conn);
+ }
+ else
{
- BGP_TRACE(D_EVENTS, "BFD session down");
+ /* Trigger session down */
bgp_store_error(p, NULL, BE_MISC, BEM_BFD_DOWN);
if (ps == PS_UP)
bgp_update_startup_delay(p);
bgp_stop(p, 0, NULL, 0);
}
+ }
}
static void