summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
Diffstat (limited to 'proto')
-rw-r--r--proto/bgp/bgp.c24
-rw-r--r--proto/bgp/bgp.h2
-rw-r--r--proto/bgp/config.Y1
3 files changed, 26 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
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 53194fb6..7703fb6e 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -102,6 +102,8 @@ struct bgp_config {
#define BGP_GRS_LLGR_1 2 /* Long-lived GR phase 1 (restart time) */
#define BGP_GRS_LLGR_2 3 /* Long-lived GR phase 2 (stale time) */
+#define BGP_BFD_GRACEFUL 2 /* BFD down triggers graceful restart */
+
struct bgp_conn {
struct bgp_proto *bgp;
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 2ed1944d..95ceccb5 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -172,6 +172,7 @@ bgp_proto:
| bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
| bgp_proto CHECK LINK bool ';' { BGP_CFG->check_link = $4; }
| bgp_proto BFD bool ';' { BGP_CFG->bfd = $3; cf_check_bfd($3); }
+ | bgp_proto BFD GRACEFUL ';' { BGP_CFG->bfd = BGP_BFD_GRACEFUL; cf_check_bfd(1); }
;
CF_ADDTO(dynamic_attr, BGP_ORIGIN