diff options
-rw-r--r-- | doc/bird.sgml | 9 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 24 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 2 | ||||
-rw-r--r-- | proto/bgp/config.Y | 1 |
4 files changed, 32 insertions, 4 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index c66e8c72..7cbb4de6 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1977,13 +1977,16 @@ using the following configuration parameters: immediately shut down. Note that this option cannot be used with multihop BGP. Default: disabled. - <tag><label id="bgp-bfd">bfd <M>switch</M></tag> + <tag><label id="bgp-bfd">bfd <M>switch</M>|graceful</tag> BGP could use BFD protocol as an advisory mechanism for neighbor liveness and failure detection. If enabled, BIRD setups a BFD session for the BGP neighbor and tracks its liveness by it. This has an advantage of an order of magnitude lower detection times in case of - failure. Note that BFD protocol also has to be configured, see - <ref id="bfd" name="BFD"> section for details. Default: disabled. + failure. When a neighbor failure is detected, the BGP session is + restarted. Optionally, it can be configured (by <cf/graceful/ argument) + to trigger graceful restart instead of regular restart. Note that BFD + protocol also has to be configured, see <ref id="bfd" name="BFD"> + section for details. Default: disabled. <tag><label id="bgp-ttl-security">ttl security <m/switch/</tag> Use GTSM (<rfc id="5082"> - the generalized TTL security mechanism). GTSM 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 |