summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/bird.sgml9
-rw-r--r--proto/bgp/bgp.c24
-rw-r--r--proto/bgp/bgp.h2
-rw-r--r--proto/bgp/config.Y1
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