Link state support in BGP.
Configurable fast shutdown of a BGP session when an interface loses link.
This commit is contained in:
parent
7730553b7e
commit
523f020b5f
4 changed files with 83 additions and 47 deletions
|
@ -1691,6 +1691,13 @@ using the following configuration parameters:
|
||||||
Specifies a table that is used as an IGP routing table. Default: the
|
Specifies a table that is used as an IGP routing table. Default: the
|
||||||
same as the table BGP is connected to.
|
same as the table BGP is connected to.
|
||||||
|
|
||||||
|
<tag>check link <M>switch</M></tag>
|
||||||
|
BGP could use hardware link state into consideration. If enabled,
|
||||||
|
BIRD tracks the link state of the associated interface and when link
|
||||||
|
disappears (e.g. an ethernet cable is unplugged), the BGP session is
|
||||||
|
immediately shut down. Note that this option cannot be used with
|
||||||
|
multihop BGP. Default: disabled.
|
||||||
|
|
||||||
<tag>bfd <M>switch</M></tag>
|
<tag>bfd <M>switch</M></tag>
|
||||||
BGP could use BFD protocol as an advisory mechanism for neighbor
|
BGP could use BFD protocol as an advisory mechanism for neighbor
|
||||||
liveness and failure detection. If enabled, BIRD setups a BFD session
|
liveness and failure detection. If enabled, BIRD setups a BFD session
|
||||||
|
|
|
@ -855,25 +855,43 @@ static void
|
||||||
bgp_neigh_notify(neighbor *n)
|
bgp_neigh_notify(neighbor *n)
|
||||||
{
|
{
|
||||||
struct bgp_proto *p = (struct bgp_proto *) n->proto;
|
struct bgp_proto *p = (struct bgp_proto *) n->proto;
|
||||||
|
int ps = p->p.proto_state;
|
||||||
|
|
||||||
if (! (n->flags & NEF_STICKY))
|
if (n != p->neigh)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (n->scope > 0)
|
if ((ps == PS_DOWN) || (ps == PS_STOP))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int prepare = (ps == PS_START) && (p->start_state == BSS_PREPARE);
|
||||||
|
|
||||||
|
if (n->scope <= 0)
|
||||||
{
|
{
|
||||||
if ((p->p.proto_state == PS_START) && (p->start_state == BSS_PREPARE))
|
if (!prepare)
|
||||||
{
|
{
|
||||||
BGP_TRACE(D_EVENTS, "Neighbor found");
|
BGP_TRACE(D_EVENTS, "Neighbor lost");
|
||||||
bgp_start_neighbor(p);
|
bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
|
||||||
|
/* Perhaps also run bgp_update_startup_delay(p)? */
|
||||||
|
bgp_stop(p, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))
|
||||||
|
{
|
||||||
|
if (!prepare)
|
||||||
|
{
|
||||||
|
BGP_TRACE(D_EVENTS, "Link down");
|
||||||
|
bgp_store_error(p, NULL, BE_MISC, BEM_LINK_DOWN);
|
||||||
|
if (ps == PS_UP)
|
||||||
|
bgp_update_startup_delay(p);
|
||||||
|
bgp_stop(p, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((p->p.proto_state == PS_START) || (p->p.proto_state == PS_UP))
|
if (prepare)
|
||||||
{
|
{
|
||||||
BGP_TRACE(D_EVENTS, "Neighbor lost");
|
BGP_TRACE(D_EVENTS, "Neighbor ready");
|
||||||
bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
|
bgp_start_neighbor(p);
|
||||||
bgp_stop(p, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -952,8 +970,8 @@ bgp_start_locked(struct object_lock *lock)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->neigh = neigh_find2(&p->p, &cf->remote_ip, cf->iface, NEF_STICKY);
|
neighbor *n = neigh_find2(&p->p, &cf->remote_ip, cf->iface, NEF_STICKY);
|
||||||
if (!p->neigh || (p->neigh->scope == SCOPE_HOST))
|
if (!n)
|
||||||
{
|
{
|
||||||
log(L_ERR "%s: Invalid remote address %I%J", p->p.name, cf->remote_ip, cf->iface);
|
log(L_ERR "%s: Invalid remote address %I%J", p->p.name, cf->remote_ip, cf->iface);
|
||||||
/* As we do not start yet, we can just disable protocol */
|
/* As we do not start yet, we can just disable protocol */
|
||||||
|
@ -963,10 +981,14 @@ bgp_start_locked(struct object_lock *lock)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->neigh->scope > 0)
|
p->neigh = n;
|
||||||
bgp_start_neighbor(p);
|
|
||||||
else
|
if (n->scope <= 0)
|
||||||
BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", cf->remote_ip, cf->iface);
|
BGP_TRACE(D_EVENTS, "Waiting for %I%J to become my neighbor", cf->remote_ip, cf->iface);
|
||||||
|
else if (p->cf->check_link && !(n->iface->flags & IF_LINK_UP))
|
||||||
|
BGP_TRACE(D_EVENTS, "Waiting for link on %s", n->iface->name);
|
||||||
|
else
|
||||||
|
bgp_start_neighbor(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1173,6 +1195,9 @@ bgp_check_config(struct bgp_config *c)
|
||||||
ipa_is_link_local(c->source_addr)))
|
ipa_is_link_local(c->source_addr)))
|
||||||
cf_error("Multihop BGP cannot be used with link-local addresses");
|
cf_error("Multihop BGP cannot be used with link-local addresses");
|
||||||
|
|
||||||
|
if (c->multihop && c->check_link)
|
||||||
|
cf_error("Multihop BGP cannot depend on link state");
|
||||||
|
|
||||||
if (c->multihop && c->bfd && ipa_zero(c->source_addr))
|
if (c->multihop && c->bfd && ipa_zero(c->source_addr))
|
||||||
cf_error("Multihop BGP with BFD requires specified source address");
|
cf_error("Multihop BGP with BFD requires specified source address");
|
||||||
|
|
||||||
|
@ -1288,7 +1313,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_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" };
|
||||||
static char *bgp_err_classes[] = { "", "Error: ", "Socket: ", "Received: ", "BGP Error: ", "Automatic shutdown: ", ""};
|
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", "BFD session down", "Graceful restart"};
|
static char *bgp_misc_errors[] = { "", "Neighbor lost", "Invalid next hop", "Kernel MD5 auth failed", "No listening socket", "Link down", "BFD session down", "Graceful restart"};
|
||||||
static char *bgp_auto_errors[] = { "", "Route limit exceeded"};
|
static char *bgp_auto_errors[] = { "", "Route limit exceeded"};
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
|
|
@ -62,6 +62,7 @@ struct bgp_config {
|
||||||
|
|
||||||
char *password; /* Password used for MD5 authentication */
|
char *password; /* Password used for MD5 authentication */
|
||||||
struct rtable_config *igp_table; /* Table used for recursive next hop lookups */
|
struct rtable_config *igp_table; /* Table used for recursive next hop lookups */
|
||||||
|
int check_link; /* Use iface link state for liveness detection */
|
||||||
int bfd; /* Use BFD for liveness detection */
|
int bfd; /* Use BFD for liveness detection */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -335,8 +336,9 @@ void bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsi
|
||||||
#define BEM_INVALID_NEXT_HOP 2
|
#define BEM_INVALID_NEXT_HOP 2
|
||||||
#define BEM_INVALID_MD5 3 /* MD5 authentication kernel request failed (possibly not supported) */
|
#define BEM_INVALID_MD5 3 /* MD5 authentication kernel request failed (possibly not supported) */
|
||||||
#define BEM_NO_SOCKET 4
|
#define BEM_NO_SOCKET 4
|
||||||
#define BEM_BFD_DOWN 5
|
#define BEM_LINK_DOWN 5
|
||||||
#define BEM_GRACEFUL_RESTART 6
|
#define BEM_BFD_DOWN 6
|
||||||
|
#define BEM_GRACEFUL_RESTART 7
|
||||||
|
|
||||||
/* Automatic shutdown error codes */
|
/* Automatic shutdown error codes */
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,8 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
|
||||||
PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
|
PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
|
||||||
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
|
INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
|
||||||
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
|
TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
|
||||||
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE)
|
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
|
||||||
|
CHECK, LINK)
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
|
@ -123,6 +124,7 @@ bgp_proto:
|
||||||
| bgp_proto GRACEFUL RESTART TIME expr ';' { BGP_CFG->gr_time = $5; }
|
| bgp_proto GRACEFUL RESTART TIME expr ';' { BGP_CFG->gr_time = $5; }
|
||||||
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
|
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
|
||||||
| bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
|
| 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 bool ';' { BGP_CFG->bfd = $3; cf_check_bfd($3); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue