summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2009-03-05 11:52:47 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2009-03-05 11:52:47 +0100
commite3299ab14877de6ce688050e550c44cd4e85b212 (patch)
tree7c54570a3b010051e2e957667bfb7121af346447
parent82a79586e5810af2f0338cb4c5982e085b5c5292 (diff)
downloadbird-e3299ab14877de6ce688050e550c44cd4e85b212.tar
bird-e3299ab14877de6ce688050e550c44cd4e85b212.zip
Added Cisco and Quagga capability workaround option.
-rw-r--r--doc/bird.sgml10
-rw-r--r--proto/bgp/bgp.h2
-rw-r--r--proto/bgp/config.Y3
-rw-r--r--proto/bgp/packets.c26
4 files changed, 37 insertions, 4 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml
index c070be1..5095b78 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -762,6 +762,16 @@ 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>disable after error <m/switch/</tag> When an error is encountered (either
locally or by the other side), disable the instance automatically
and wait for an administrator to fix the problem manually. Default: off.
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index b0ead9d..bdad1a4 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -29,6 +29,7 @@ struct bgp_config {
u32 rr_cluster_id; /* Route reflector cluster ID, if different from local ID */
int rr_client; /* Whether neighbor is RR client of me */
int rs_client; /* Whether neighbor is RS client of me */
+ int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */
unsigned connect_retry_time;
unsigned hold_time, initial_hold_time;
unsigned keepalive_time;
@@ -259,6 +260,7 @@ void bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subco
/* Address families */
+#define BGP_AF_IPV4 1
#define BGP_AF_IPV6 2
#endif
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index 73b584f..4b64ed5 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -21,7 +21,7 @@ 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)
+ PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4)
CF_GRAMMAR
@@ -71,6 +71,7 @@ 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 PASSWORD TEXT ';' { BGP_CFG->password = $3; }
;
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 4256489..dc3748f 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -47,6 +47,20 @@ bgp_put_cap_ipv6(struct bgp_conn *conn UNUSED, byte *buf)
*buf++ = 1; /* and SAFI 1 */
return buf;
}
+
+#else
+
+static byte *
+bgp_put_cap_ipv4(struct bgp_conn *conn UNUSED, byte *buf)
+{
+ *buf++ = 1; /* Capability 1: Multiprotocol extensions */
+ *buf++ = 4; /* Capability data length */
+ *buf++ = 0; /* We support AF IPv4 */
+ *buf++ = BGP_AF_IPV4;
+ *buf++ = 0; /* RFU */
+ *buf++ = 1; /* and SAFI 1 */
+ return buf;
+}
#endif
static byte *
@@ -82,6 +96,11 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
/* Skipped 3 B for length field and Capabilities parameter header */
cap = buf + 12;
+#ifndef IPV6
+ if (p->cf->advertise_ipv4)
+ cap = bgp_put_cap_ipv4(conn, cap);
+#endif
+
#ifdef IPV6
cap = bgp_put_cap_ipv6(conn, cap);
#endif
@@ -940,6 +959,9 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
unsigned subcode = pkt[20];
int delay = 1;
+ bgp_log_error(conn->bgp, "Received error notification", code, subcode, pkt+21, len-21);
+ bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode);
+
#ifndef IPV6
if ((code == 2) && ((subcode == 4) || (subcode == 7)))
{
@@ -948,14 +970,12 @@ bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
* 7 - Peer request some capability. Strange unless it is IPv6 only peer.
* We try connect without capabilities
*/
- BGP_TRACE(D_EVENTS, "Capability related error received, capabilities disabled");
+ log(L_WARN "%s: Capability related error received, capabilities disabled", p->p.name);
conn->bgp->start_state = BSS_CONNECT_NOCAP;
delay = 0;
}
#endif
- bgp_log_error(conn->bgp, "Received error notification", code, subcode, pkt+21, len-21);
- bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode);
if (delay) bgp_update_startup_delay(conn->bgp, conn, code, subcode);
bgp_conn_enter_close_state(conn);
bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE);