diff options
Diffstat (limited to 'proto')
-rw-r--r-- | proto/bgp/bgp.c | 24 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 2 | ||||
-rw-r--r-- | proto/bgp/config.Y | 1 |
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 |