Update capability handshake options
Add 'capabilities' option, change default behavior to advertise ipv4, add some checks and ignore incoming capabilities when capabilities are disabled.
This commit is contained in:
parent
e3299ab148
commit
e8ba557c7f
5 changed files with 54 additions and 24 deletions
|
@ -669,6 +669,8 @@ MD5 password authentication
|
|||
(RFC 2385<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt">),
|
||||
route reflectors
|
||||
(RFC 4456<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4456.txt">),
|
||||
multiprotocol extensions
|
||||
(RFC 4760<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4760.txt">),
|
||||
and 4B AS numbers
|
||||
(RFC 4893<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4893.txt">).
|
||||
|
||||
|
@ -762,15 +764,19 @@ for each neighbor using the following configuration parameters:
|
|||
Even when disabled (off), BIRD behaves internally as AS4-aware BGP router.
|
||||
Default: on.
|
||||
|
||||
<tag>advertise ipv4</tag> Advertise IPv4 multiprotocol capability.
|
||||
This is not correct behavior but it is required by some BGP
|
||||
implementations (Cisco and Quagga). Without this option,
|
||||
the session establishment with these implementations takes
|
||||
more time, session is degraded (no optional capabilities)
|
||||
and the problem is logged. When the option is used, there might
|
||||
be compatibility issues with other BGP implementations.
|
||||
This option is relevant to IPv4 mode only.
|
||||
Default: disabled.
|
||||
<tag>capabilities <m/switch/</tag> Use capability advertisement
|
||||
to advertise optional capabilities. This is standard behavior
|
||||
for newer BGP implementations, but there might be some older
|
||||
BGP implementations that reject such connection attempts.
|
||||
When disabled (off), features that request it (4B AS support)
|
||||
are also disabled. Default: on, with automatic fallback to
|
||||
off when received capability-related error.
|
||||
|
||||
<tag>advertise ipv4 <m/switch/</tag> Advertise IPv4 multiprotocol capability.
|
||||
This is not a correct behavior according to the strict interpretation
|
||||
of RFC 4760, but it is widespread and required by some BGP
|
||||
implementations (Cisco and Quagga). This option is relevant
|
||||
to IPv4 mode with enabled capability advertisement only. Default: on.
|
||||
|
||||
<tag>disable after error <m/switch/</tag> When an error is encountered (either
|
||||
locally or by the other side), disable the instance automatically
|
||||
|
|
|
@ -113,7 +113,7 @@ bgp_open(struct bgp_proto *p)
|
|||
}
|
||||
}
|
||||
|
||||
p->start_state = BSS_CONNECT;
|
||||
p->start_state = p->cf->capabilities ? BSS_CONNECT : BSS_CONNECT_NOCAP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -823,16 +823,22 @@ bgp_check(struct bgp_config *c)
|
|||
{
|
||||
if (!c->local_as)
|
||||
cf_error("Local AS number must be set");
|
||||
|
||||
if (!c->remote_as)
|
||||
cf_error("Neighbor must be configured");
|
||||
|
||||
if (!bgp_as4_support && c->enable_as4)
|
||||
cf_error("AS4 support disabled globally");
|
||||
if (!c->enable_as4 && (c->local_as > 0xFFFF))
|
||||
|
||||
if (!bgp_as4_support && (c->local_as > 0xFFFF))
|
||||
cf_error("Local AS number out of range");
|
||||
if (!c->enable_as4 && (c->remote_as > 0xFFFF))
|
||||
cf_error("Neighbor AS number out of range");
|
||||
|
||||
if (!(c->capabilities && c->enable_as4) && (c->remote_as > 0xFFFF))
|
||||
cf_error("Neighbor AS number out of range (AS4 not available)");
|
||||
|
||||
if ((c->local_as != c->remote_as) && (c->rr_client))
|
||||
cf_error("Only internal neighbor can be RR client");
|
||||
|
||||
if ((c->local_as == c->remote_as) && (c->rs_client))
|
||||
cf_error("Only external neighbor can be RS client");
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ struct bgp_config {
|
|||
int compare_path_lengths; /* Use path lengths when selecting best route */
|
||||
u32 default_local_pref; /* Default value for LOCAL_PREF attribute */
|
||||
u32 default_med; /* Default value for MULTI_EXIT_DISC attribute */
|
||||
int capabilities; /* Enable capability handshake [RFC3392] */
|
||||
int enable_as4; /* Enable local support for 4B AS numbers [RFC4893] */
|
||||
u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */
|
||||
int rr_client; /* Whether neighbor is RR client of me */
|
||||
|
|
|
@ -21,7 +21,8 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
|
|||
ERROR, START, DELAY, FORGET, WAIT, ENABLE, DISABLE, AFTER,
|
||||
BGP_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN, BGP_NEXT_HOP,
|
||||
BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS,
|
||||
PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4)
|
||||
PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4,
|
||||
CAPABILITIES)
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
|
@ -40,6 +41,8 @@ bgp_proto_start: proto_start BGP {
|
|||
BGP_CFG->error_delay_time_min = 60;
|
||||
BGP_CFG->error_delay_time_max = 300;
|
||||
BGP_CFG->enable_as4 = bgp_as4_support;
|
||||
BGP_CFG->capabilities = 2;
|
||||
BGP_CFG->advertise_ipv4 = 1;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -71,7 +74,8 @@ bgp_proto:
|
|||
| 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 AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
|
||||
| bgp_proto ADVERTISE IPV4 ';' { BGP_CFG->advertise_ipv4 = 1; }
|
||||
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
|
||||
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
|
||||
| bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; }
|
||||
;
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
|
|||
#ifdef IPV6
|
||||
cap = bgp_put_cap_ipv6(conn, cap);
|
||||
#endif
|
||||
|
||||
if (conn->want_as4_support)
|
||||
cap = bgp_put_cap_as4(conn, cap);
|
||||
|
||||
|
@ -504,6 +505,7 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
|
|||
static int
|
||||
bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
|
||||
{
|
||||
struct bgp_proto *p = conn->bgp;
|
||||
int ol;
|
||||
|
||||
while (len > 0)
|
||||
|
@ -524,6 +526,9 @@ bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
|
|||
switch (opt[0])
|
||||
{
|
||||
case 2:
|
||||
if (conn->start_state == BSS_CONNECT_NOCAP)
|
||||
BGP_TRACE(D_PACKETS, "Ignoring received capabilities");
|
||||
else
|
||||
bgp_parse_capabilities(conn, opt + 2, ol);
|
||||
break;
|
||||
|
||||
|
@ -550,6 +555,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
|
|||
struct bgp_proto *p = conn->bgp;
|
||||
struct bgp_config *cf = p->cf;
|
||||
unsigned hold;
|
||||
u16 base_as;
|
||||
u32 id;
|
||||
|
||||
/* Check state */
|
||||
|
@ -561,7 +567,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
|
|||
{ bgp_error(conn, 1, 2, pkt+16, 2); return; }
|
||||
if (pkt[19] != BGP_VERSION)
|
||||
{ bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */
|
||||
conn->advertised_as = get_u16(pkt+20);
|
||||
conn->advertised_as = base_as = get_u16(pkt+20);
|
||||
hold = get_u16(pkt+22);
|
||||
id = get_u32(pkt+24);
|
||||
BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", conn->advertised_as, hold, id);
|
||||
|
@ -575,10 +581,11 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
|
|||
if (!id || id == 0xffffffff || id == p->local_id)
|
||||
{ bgp_error(conn, 2, 3, pkt+24, -4); return; }
|
||||
|
||||
if ((conn->advertised_as != base_as) && (base_as != AS_TRANS))
|
||||
log(L_WARN "%s: Peer advertised inconsistent AS numbers", p->p.name);
|
||||
|
||||
if (conn->advertised_as != p->remote_as)
|
||||
{
|
||||
bgp_error(conn, 2, 2, (byte *) &(conn->advertised_as), -4); return;
|
||||
}
|
||||
{ bgp_error(conn, 2, 2, (byte *) &(conn->advertised_as), -4); return; }
|
||||
|
||||
/* Check the other connection */
|
||||
other = (conn == &p->outgoing_conn) ? &p->incoming_conn : &p->outgoing_conn;
|
||||
|
@ -963,14 +970,20 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
|
|||
bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode);
|
||||
|
||||
#ifndef IPV6
|
||||
if ((code == 2) && ((subcode == 4) || (subcode == 7)))
|
||||
{
|
||||
if ((code == 2) && ((subcode == 4) || (subcode == 7))
|
||||
/* Error related to capability:
|
||||
* 4 - Peer does not support capabilities at all.
|
||||
* 7 - Peer request some capability. Strange unless it is IPv6 only peer.
|
||||
* We try connect without capabilities
|
||||
*/
|
||||
log(L_WARN "%s: Capability related error received, capabilities disabled", p->p.name);
|
||||
&& (p->cf->capabilities == 2)
|
||||
/* Capabilities are not explicitly enabled or disabled, therefore heuristic is used */
|
||||
&& (conn->start_state == BSS_CONNECT)
|
||||
/* Failed connection attempt have used capabilities */
|
||||
&& (p->cf->remote_as <= 0xFFFF))
|
||||
/* Not possible with disabled capabilities */
|
||||
{
|
||||
/* We try connect without capabilities */
|
||||
log(L_WARN "%s: Capability related error received, retry with capabilities disabled", p->p.name);
|
||||
conn->bgp->start_state = BSS_CONNECT_NOCAP;
|
||||
delay = 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue