summaryrefslogtreecommitdiff
path: root/proto/bgp
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp')
-rw-r--r--proto/bgp/bgp.c48
-rw-r--r--proto/bgp/bgp.h5
-rw-r--r--proto/bgp/config.Y3
3 files changed, 53 insertions, 3 deletions
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 7cad75df..07ad31f3 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -59,8 +59,9 @@
#include "nest/iface.h"
#include "nest/protocol.h"
#include "nest/route.h"
-#include "nest/locks.h"
+#include "nest/bfd.h"
#include "nest/cli.h"
+#include "nest/locks.h"
#include "conf/conf.h"
#include "lib/socket.h"
#include "lib/resource.h"
@@ -76,6 +77,7 @@ static void bgp_close(struct bgp_proto *p, int apply_md5);
static void bgp_connect(struct bgp_proto *p);
static void bgp_active(struct bgp_proto *p);
static sock *bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags);
+static void bgp_update_bfd(struct bgp_proto *p, int use_bfd);
/**
@@ -153,8 +155,12 @@ bgp_initiate(struct bgp_proto *p)
if (rv < 0)
return;
+ if (p->cf->bfd)
+ bgp_update_bfd(p, p->cf->bfd);
+
if (p->startup_delay)
{
+ p->start_state = BSS_DELAY;
BGP_TRACE(D_EVENTS, "Startup delayed by %d seconds", p->startup_delay);
bgp_start_timer(p->startup_timer, p->startup_delay);
}
@@ -765,6 +771,37 @@ bgp_neigh_notify(neighbor *n)
}
}
+static void
+bgp_bfd_notify(struct bfd_request *req)
+{
+ struct bgp_proto *p = req->data;
+ int ps = p->p.proto_state;
+
+ if (req->down && ((ps == PS_START) || (ps == PS_UP)))
+ {
+ BGP_TRACE(D_EVENTS, "BFD 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);
+ }
+}
+
+static void
+bgp_update_bfd(struct bgp_proto *p, int use_bfd)
+{
+ if (use_bfd && !p->bfd_req)
+ p->bfd_req = bfd_request_session(p->p.pool, p->cf->remote_ip, p->source_addr,
+ p->cf->multihop ? NULL : p->neigh->iface,
+ bgp_bfd_notify, p);
+
+ if (!use_bfd && p->bfd_req)
+ {
+ rfree(p->bfd_req);
+ p->bfd_req = NULL;
+ }
+}
+
static int
bgp_reload_routes(struct proto *P)
{
@@ -825,6 +862,7 @@ bgp_start(struct proto *P)
p->outgoing_conn.state = BS_IDLE;
p->incoming_conn.state = BS_IDLE;
p->neigh = NULL;
+ p->bfd_req = NULL;
rt_lock_table(p->igp_table);
@@ -992,6 +1030,9 @@ bgp_check_config(struct bgp_config *c)
ipa_has_link_scope(c->source_addr)))
cf_error("Multihop BGP cannot be used with link-local addresses");
+ if (c->multihop && c->bfd && ipa_zero(c->source_addr))
+ cf_error("Multihop BGP with BFD requires specified source address");
+
/* Different default based on rs_client */
if (!c->missing_lladdr)
@@ -1034,6 +1075,9 @@ bgp_reconfigure(struct proto *P, struct proto_config *C)
|| (old->password && new->password && !strcmp(old->password, new->password)))
&& (get_igp_table(old) == get_igp_table(new));
+ if (same && (p->start_state > BSS_PREPARE))
+ bgp_update_bfd(p, new->bfd);
+
/* We should update our copy of configuration ptr as old configuration will be freed */
if (same)
p->cf = new;
@@ -1115,7 +1159,7 @@ bgp_store_error(struct bgp_proto *p, struct bgp_conn *c, u8 class, u32 code)
static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""};
-static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket" };
+static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket", "BFD session down" };
static char *bgp_auto_errors[] = { "", "Route limit exceeded"};
static const char *
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index bcbdf2cc..d2a96bbb 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -14,6 +14,7 @@
struct linpool;
struct eattr;
+struct bfd_request;
struct bgp_config {
struct proto_config c;
@@ -53,8 +54,10 @@ struct bgp_config {
unsigned error_delay_time_min; /* Time to wait after an error is detected */
unsigned error_delay_time_max;
unsigned disable_after_error; /* Disable the protocol when error is detected */
+
char *password; /* Password used for MD5 authentication */
struct rtable_config *igp_table; /* Table used for recursive next hop lookups */
+ int bfd; /* Use BFD for liveness detection */
};
#define MLL_SELF 1
@@ -100,6 +103,7 @@ struct bgp_proto {
struct bgp_conn incoming_conn; /* Incoming connection we have neither accepted nor rejected yet */
struct object_lock *lock; /* Lock for neighbor connection */
struct neighbor *neigh; /* Neighbor entry corresponding to remote ip, NULL if multihop */
+ struct bfd_request *bfd_req; /* BFD request, if BFD is used */
ip_addr source_addr; /* Local address used as an advertised next hop */
rtable *igp_table; /* Table used for recursive next hop lookups */
struct event *event; /* Event for respawning and shutting process */
@@ -288,6 +292,7 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
#define BEM_INVALID_NEXT_HOP 2
#define BEM_INVALID_MD5 3 /* MD5 authentication kernel request failed (possibly not supported) */
#define BEM_NO_SOCKET 4
+#define BEM_BFD_DOWN 5
/* Automatic shutdown error codes */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index f4b2c5fe..185b1bda 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -26,7 +26,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
- SECONDARY, ALLOW)
+ SECONDARY, ALLOW, BFD)
CF_GRAMMAR
@@ -112,6 +112,7 @@ bgp_proto:
| bgp_proto ALLOW LOCAL AS expr ';' { BGP_CFG->allow_local_as = $5; }
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
| bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
+ | bgp_proto BFD bool ';' { BGP_CFG->bfd = $3; cf_check_bfd($3); }
;
CF_ADDTO(dynamic_attr, BGP_ORIGIN