Link state support in BGP.

Configurable fast shutdown of a BGP session when an interface loses link.
This commit is contained in:
Ondrej Zajicek 2015-02-21 11:46:14 +01:00
parent 7730553b7e
commit 523f020b5f
4 changed files with 83 additions and 47 deletions

View file

@ -316,20 +316,20 @@ protocol rip {
<sect>Global options
<p><descrip>
<tag>include "<m/filename/"</tag>
<tag>include "<m/filename/"</tag>
This statement causes inclusion of a new file. <m/Filename/ could also
be a wildcard. The maximal depth is 8. Note that this statement could be
used anywhere in the config file, not just as a top-level option.
<tag><label id="dsc-log">log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag>
<tag><label id="dsc-log">log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag>
Set logging of messages having the given class (either <cf/all/ or
<cf/{ error, trace }/ etc.) into selected destination (a file specified
as a filename string, syslog with optional name argument, or the stderr
output). Classes are:
<cf/info/, <cf/warning/, <cf/error/ and <cf/fatal/ for messages about local problems,
<cf/debug/ for debugging messages,
<cf/trace/ when you want to know what happens in the network,
<cf/remote/ for messages about misbehavior of remote machines,
<cf/debug/ for debugging messages,
<cf/trace/ when you want to know what happens in the network,
<cf/remote/ for messages about misbehavior of remote machines,
<cf/auth/ about authentication failures,
<cf/bug/ for internal BIRD bugs.
You may specify more than one <cf/log/ line to establish logging to
@ -358,7 +358,7 @@ protocol rip {
<tag>function <m/name/ (<m/parameters/) <m/local variables/ { <m/commands/ }</tag>
Define a function. You can learn more about functions in the following chapter.
<tag>protocol rip|ospf|bgp|... [<m/name/ [from <m/name2/]] { <m>protocol options</m> }</tag>
Define a protocol instance called <cf><m/name/</cf> (or with a name like
"rip5" generated automatically if you don't specify any
@ -508,7 +508,7 @@ agreement").
This option can be used to override global router id for a given
protocol. Default: uses global router id.
<tag>import all | none | filter <m/name/ | filter { <m/filter commands/ } | where <m/filter expression/</tag>
<tag>import all | none | filter <m/name/ | filter { <m/filter commands/ } | where <m/filter expression/</tag>
Specify a filter to be used for filtering routes coming from the
protocol to the routing table. <cf/all/ is shorthand for <cf/where true/
and <cf/none/ is shorthand for <cf/where false/. Default: <cf/all/.
@ -586,7 +586,7 @@ agreement").
An interface option can be used more times with different interface-specific
options, in that case for given interface the first matching interface
option is used.
This option is allowed in BFD, Direct, OSPF, RAdv and RIP protocols, but
in OSPF protocol it is used in the <cf/area/ subsection.
@ -599,7 +599,7 @@ agreement").
<cf>interface "eth1", "eth4", "eth5" { type ptp; };</cf> - start the
protocol on enumerated interfaces with <cf>type ptp</cf> option.
<cf>interface -192.168.1.0/24, 192.168.0.0/16;</cf> - start the protocol
on all interfaces that have address from 192.168.0.0/16, but not from
192.168.1.0/24.
@ -632,7 +632,7 @@ agreement").
used. Specifying passwords does not mean that authentication is enabled,
authentication can be enabled by separate, protocol-dependent
<cf/authentication/ option.
This option is allowed in OSPF and RIP protocols. BGP has also
<cf/password/ option, but it is slightly different and described
separately.
@ -1085,7 +1085,7 @@ foot).
is true, but <cf>1.0.0.0/16 &tilde; [ 1.0.0.0/8- ]</cf> is false.
Cisco-style patterns like <cf>10.0.0.0/8 ge 16 le 24</cf> can be expressed
in BIRD as <cf>10.0.0.0/8{16,24}</cf>, <cf>192.168.0.0/16 le 24</cf> as
in BIRD as <cf>10.0.0.0/8{16,24}</cf>, <cf>192.168.0.0/16 le 24</cf> as
<cf>192.168.0.0/16{16,24}</cf> and <cf>192.168.0.0/16 ge 24</cf> as
<cf>192.168.0.0/16{24,32}</cf>.
@ -1129,7 +1129,7 @@ foot).
&tilde; [= 2 3 5 * =]</cf> syntax). The masks resemble wildcard patterns
as used by UNIX shells. Autonomous system numbers match themselves,
<cf/*/ matches any (even empty) sequence of arbitrary AS numbers and
<cf/?/ matches one arbitrary AS number. For example, if <cf>bgp_path</cf>
<cf/?/ matches one arbitrary AS number. For example, if <cf>bgp_path</cf>
is 4 3 2 1, then: <tt>bgp_path &tilde; [= * 4 3 * =]</tt> is true,
but <tt>bgp_path &tilde; [= * 4 5 * =]</tt> is false. BGP mask
expressions can also contain integer expressions enclosed in parenthesis
@ -1206,7 +1206,7 @@ prefix and an ASN as arguments.
<sect>Control structures
<p>Filters support two control structures: conditions and case switches.
<p>Filters support two control structures: conditions and case switches.
<p>Syntax of a condition is: <cf>if <M>boolean expression</M> then <m/command1/;
else <m/command2/;</cf> and you can use <cf>{ <m/command_1/; <m/command_2/;
@ -1232,9 +1232,9 @@ case arg1 {
else: print "something else";
}
if 1234 = i then printn "."; else {
print "not 1234";
print "You need {} around multiple commands";
if 1234 = i then printn "."; else {
print "not 1234";
print "You need {} around multiple commands";
}
</code>
@ -1267,7 +1267,7 @@ clist for most purposes.
<tag><m/ip/ from</tag>
The router which the route has originated from.
<tag><m/ip/ gw</tag>
Next hop packets routed using this route should be forwarded to.
@ -1448,7 +1448,7 @@ protocol bfd [&lt;name&gt;] {
BFD sessions are usually created on demand as requested by other
protocols (like OSPF or BGP). This option allows to explicitly add
a BFD session to the specified neighbor regardless of such requests.
The session is identified by the IP address of the neighbor, with
optional specification of used interface and local IP. By default
the neighbor must be directly connected, unless the the session is
@ -1559,13 +1559,13 @@ MD5 password authentication
(RFC 2385<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt">),
extended communities
(RFC 4360<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4360.txt">),
route reflectors
route reflectors
(RFC 4456<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4456.txt">),
graceful restart
(RFC 4724<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4724.txt">),
multiprotocol extensions
(RFC 4760<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4760.txt">),
4B AS numbers
4B AS numbers
(RFC 4893<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4893.txt">),
and 4B AS numbers in extended communities
(RFC 5668<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5668.txt">).
@ -1691,6 +1691,13 @@ using the following configuration parameters:
Specifies a table that is used as an IGP routing table. Default: the
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>
BGP could use BFD protocol as an advisory mechanism for neighbor
liveness and failure detection. If enabled, BIRD setups a BFD session
@ -1709,7 +1716,7 @@ using the following configuration parameters:
(IPv4), 2.6.35+ (IPv6), BSD: since long ago, IPv4 only. Note that full
(ICMP protection, for example) RFC 5082 support is provided by Linux
only. Default: disabled.
<tag>password <m/string/</tag>
Use this password for MD5 authentication of BGP sessions. Default: no
authentication. Password has to be set by external utility
@ -1732,7 +1739,7 @@ using the following configuration parameters:
id. Clients in a cluster need not know their cluster id and this option
is not allowed for them. Default: the same as router id.
<tag>rs client</tag>
<tag>rs client</tag>
Be a route server and treat the neighbor as a route server client.
A route server is used as a replacement for full mesh EBGP routing in
Internet exchange points in a similar way to route reflectors used in
@ -1760,7 +1767,7 @@ using the following configuration parameters:
TX direction. When active, all available routes accepted by the export
filter are advertised to the neighbor. Default: off.
<tag>allow local as [<m/number/]</tag>
<tag>allow local as [<m/number/]</tag>
BGP prevents routing loops by rejecting received routes with the local
AS number in the AS path. This option allows to loose or disable the
check. Optional <cf/number/ argument can be used to specify the maximum

View file

@ -366,7 +366,7 @@ void
bgp_conn_enter_established_state(struct bgp_conn *conn)
{
struct bgp_proto *p = conn->bgp;
BGP_TRACE(D_EVENTS, "BGP session established");
DBG("BGP: UP!!!\n");
@ -828,7 +828,7 @@ bgp_start_neighbor(struct bgp_proto *p)
/* Called only for single-hop BGP sessions */
if (ipa_zero(p->source_addr))
p->source_addr = p->neigh->ifa->ip;
p->source_addr = p->neigh->ifa->ip;
#ifdef IPV6
{
@ -855,25 +855,43 @@ static void
bgp_neigh_notify(neighbor *n)
{
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;
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))
{
BGP_TRACE(D_EVENTS, "Neighbor found");
bgp_start_neighbor(p);
if (!prepare)
{
BGP_TRACE(D_EVENTS, "Neighbor lost");
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
{
if ((p->p.proto_state == PS_START) || (p->p.proto_state == PS_UP))
if (prepare)
{
BGP_TRACE(D_EVENTS, "Neighbor lost");
bgp_store_error(p, NULL, BE_MISC, BEM_NEIGHBOR_LOST);
bgp_stop(p, 0);
BGP_TRACE(D_EVENTS, "Neighbor ready");
bgp_start_neighbor(p);
}
}
}
@ -952,8 +970,8 @@ bgp_start_locked(struct object_lock *lock)
return;
}
p->neigh = neigh_find2(&p->p, &cf->remote_ip, cf->iface, NEF_STICKY);
if (!p->neigh || (p->neigh->scope == SCOPE_HOST))
neighbor *n = neigh_find2(&p->p, &cf->remote_ip, cf->iface, NEF_STICKY);
if (!n)
{
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 */
@ -962,11 +980,15 @@ bgp_start_locked(struct object_lock *lock)
proto_notify_state(&p->p, PS_DOWN);
return;
}
if (p->neigh->scope > 0)
bgp_start_neighbor(p);
else
p->neigh = n;
if (n->scope <= 0)
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
@ -1173,6 +1195,9 @@ bgp_check_config(struct bgp_config *c)
ipa_is_link_local(c->source_addr)))
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))
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_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 const char *
@ -1396,7 +1421,7 @@ bgp_show_proto_info(struct proto *P)
tm_remains(c->keepalive_timer), c->keepalive_time);
}
if ((p->last_error_class != BE_NONE) &&
if ((p->last_error_class != BE_NONE) &&
(p->last_error_class != BE_MAN_DOWN))
{
const char *err1 = bgp_err_classes[p->last_error_class];

View file

@ -62,6 +62,7 @@ struct bgp_config {
char *password; /* Password used for MD5 authentication */
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 */
};
@ -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_MD5 3 /* MD5 authentication kernel request failed (possibly not supported) */
#define BEM_NO_SOCKET 4
#define BEM_BFD_DOWN 5
#define BEM_GRACEFUL_RESTART 6
#define BEM_LINK_DOWN 5
#define BEM_BFD_DOWN 6
#define BEM_GRACEFUL_RESTART 7
/* Automatic shutdown error codes */

View file

@ -26,7 +26,8 @@ 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, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE)
SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
CHECK, LINK)
CF_GRAMMAR
@ -97,7 +98,7 @@ bgp_proto:
| bgp_proto DEFAULT BGP_LOCAL_PREF expr ';' { BGP_CFG->default_local_pref = $4; }
| bgp_proto SOURCE ADDRESS ipa ';' { BGP_CFG->source_addr = $4; }
| bgp_proto START DELAY TIME expr ';' { BGP_CFG->start_delay_time = $5; }
| bgp_proto ERROR FORGET TIME expr ';' { BGP_CFG->error_amnesia_time = $5; }
| bgp_proto ERROR FORGET TIME expr ';' { BGP_CFG->error_amnesia_time = $5; }
| bgp_proto ERROR WAIT TIME expr ',' expr ';' { BGP_CFG->error_delay_time_min = $5; BGP_CFG->error_delay_time_max = $7; }
| bgp_proto DISABLE AFTER ERROR bool ';' { BGP_CFG->disable_after_error = $5; }
| bgp_proto ENABLE ROUTE REFRESH bool ';' { BGP_CFG->enable_refresh = $5; }
@ -123,6 +124,7 @@ bgp_proto:
| bgp_proto GRACEFUL RESTART TIME expr ';' { BGP_CFG->gr_time = $5; }
| bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $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); }
;