(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">).
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
}
}
- p->start_state = BSS_CONNECT;
+ p->start_state = p->cf->capabilities ? BSS_CONNECT : BSS_CONNECT_NOCAP;
return 0;
}
{
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");
}
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 */
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
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;
}
;
| 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; }
;
#ifdef IPV6
cap = bgp_put_cap_ipv6(conn, cap);
#endif
+
if (conn->want_as4_support)
cap = bgp_put_cap_as4(conn, cap);
static int
bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
{
+ struct bgp_proto *p = conn->bgp;
int ol;
while (len > 0)
switch (opt[0])
{
case 2:
- bgp_parse_capabilities(conn, opt + 2, ol);
+ if (conn->start_state == BSS_CONNECT_NOCAP)
+ BGP_TRACE(D_PACKETS, "Ignoring received capabilities");
+ else
+ bgp_parse_capabilities(conn, opt + 2, ol);
break;
default:
struct bgp_proto *p = conn->bgp;
struct bgp_config *cf = p->cf;
unsigned hold;
+ u16 base_as;
u32 id;
/* Check state */
{ 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);
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;
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;
}