BGP: Mandatory option for channels

Allow to mark channel to be mandatory, and do not allow BGP sessions if
no common AFI/SAFI is established.
This commit is contained in:
Ondrej Zajicek (work) 2019-03-19 17:44:50 +01:00
parent 7e5f769d91
commit 3c3605818f
4 changed files with 52 additions and 1 deletions

View file

@ -2565,6 +2565,15 @@ be used in explicit configuration.
<p>BGP channels have additional config options (together with the common ones): <p>BGP channels have additional config options (together with the common ones):
<descrip> <descrip>
<tag><label id="bgp-mandatory">mandatory <m/switch/</tag>
When local and neighbor sets of configured AFI/SAFI pairs differ,
capability negotiation ensures that a common subset is used. For
mandatory channels their associated AFI/SAFI must be negotiated
(i.e., also announced by the neighbor), otherwise BGP session
negotiation fails with <it/'Required capability missing'/ error.
Regardless, at least one AFI/SAFI must be negotiated in order to BGP
session be successfully established. Default: off.
<tag><label id="bgp-next-hop-keep">next hop keep <m/switch/|ibgp|ebgp</tag> <tag><label id="bgp-next-hop-keep">next hop keep <m/switch/|ibgp|ebgp</tag>
Do not modify the Next Hop attribute and advertise the current one Do not modify the Next Hop attribute and advertise the current one
unchanged even in cases where our own local address should be used unchanged even in cases where our own local address should be used

View file

@ -136,6 +136,7 @@ struct bgp_channel_config {
ip_addr next_hop_addr; /* Local address for NEXT_HOP attribute */ ip_addr next_hop_addr; /* Local address for NEXT_HOP attribute */
u8 next_hop_self; /* Always set next hop to local IP address (NH_*) */ u8 next_hop_self; /* Always set next hop to local IP address (NH_*) */
u8 next_hop_keep; /* Do not modify next hop attribute (NH_*) */ u8 next_hop_keep; /* Do not modify next hop attribute (NH_*) */
u8 mandatory; /* Channel is mandatory in capability negotiation */
u8 missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */ u8 missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */
u8 gw_mode; /* How we compute route gateway from next_hop attr, see GW_* */ u8 gw_mode; /* How we compute route gateway from next_hop attr, see GW_* */
u8 secondary; /* Accept also non-best routes (i.e. RA_ACCEPTED) */ u8 secondary; /* Accept also non-best routes (i.e. RA_ACCEPTED) */

View file

@ -29,7 +29,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX,
GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY,
STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG, STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG,
LIVED, STALE, IMPORT, IBGP, EBGP) LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY)
%type <i> bgp_nh %type <i> bgp_nh
%type <i32> bgp_afi %type <i32> bgp_afi
@ -223,6 +223,7 @@ bgp_channel_item:
| NEXT HOP ADDRESS ipa { BGP_CC->next_hop_addr = $4; } | NEXT HOP ADDRESS ipa { BGP_CC->next_hop_addr = $4; }
| NEXT HOP SELF bgp_nh { BGP_CC->next_hop_self = $4; } | NEXT HOP SELF bgp_nh { BGP_CC->next_hop_self = $4; }
| NEXT HOP KEEP bgp_nh { BGP_CC->next_hop_keep = $4; } | NEXT HOP KEEP bgp_nh { BGP_CC->next_hop_keep = $4; }
| MANDATORY bool { BGP_CC->mandatory = $2; }
| MISSING LLADDR SELF { BGP_CC->missing_lladdr = MLL_SELF; } | MISSING LLADDR SELF { BGP_CC->missing_lladdr = MLL_SELF; }
| MISSING LLADDR DROP { BGP_CC->missing_lladdr = MLL_DROP; } | MISSING LLADDR DROP { BGP_CC->missing_lladdr = MLL_DROP; }
| MISSING LLADDR IGNORE { BGP_CC->missing_lladdr = MLL_IGNORE; } | MISSING LLADDR IGNORE { BGP_CC->missing_lladdr = MLL_IGNORE; }

View file

@ -573,6 +573,42 @@ err:
return; return;
} }
static int
bgp_check_capabilities(struct bgp_conn *conn)
{
struct bgp_proto *p = conn->bgp;
struct bgp_caps *local = conn->local_caps;
struct bgp_caps *remote = conn->remote_caps;
struct bgp_channel *c;
int count = 0;
/* This is partially overlapping with bgp_conn_enter_established_state(),
but we need to run this just after we receive OPEN message */
WALK_LIST(c, p->p.channels)
{
const struct bgp_af_caps *loc = bgp_find_af_caps(local, c->afi);
const struct bgp_af_caps *rem = bgp_find_af_caps(remote, c->afi);
/* Find out whether this channel will be active */
int active = loc && loc->ready &&
((rem && rem->ready) || (!remote->length && (c->afi == BGP_AF_IPV4)));
/* Mandatory must be active */
if (c->cf->mandatory && !active)
return 0;
if (active)
count++;
}
/* We need at least one channel active */
if (!count)
return 0;
return 1;
}
static int static int
bgp_read_options(struct bgp_conn *conn, byte *pos, int len) bgp_read_options(struct bgp_conn *conn, byte *pos, int len)
{ {
@ -683,6 +719,10 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
if (!id || (p->is_internal && id == p->local_id)) if (!id || (p->is_internal && id == p->local_id))
{ bgp_error(conn, 2, 3, pkt+24, -4); return; } { bgp_error(conn, 2, 3, pkt+24, -4); return; }
/* RFC 5492 4 - check for required capabilities */
if (p->cf->capabilities && !bgp_check_capabilities(conn))
{ bgp_error(conn, 2, 7, NULL, 0); return; }
struct bgp_caps *caps = conn->remote_caps; struct bgp_caps *caps = conn->remote_caps;
if (caps->as4_support) if (caps->as4_support)