]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Added Cisco and Quagga capability workaround option.
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 5 Mar 2009 10:52:47 +0000 (11:52 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 5 Mar 2009 10:52:47 +0000 (11:52 +0100)
doc/bird.sgml
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c

index c070be126b11c076d2035e71f70149d2c40a0c7c..5095b78051eff4ebf6f3ee1975d387ae118d7ee2 100644 (file)
@@ -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.
index b0ead9d3ca827fd80252f7da510cefb8a6848e95..bdad1a4ddb270495e70159e97ccc4ca3f2cfabd6 100644 (file)
@@ -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
index 73b584f1ca6e81537fb61e20e364b9f7c55ede9d..4b64ed5f03c8e7ce63a00d3de9295fadec1d2471 100644 (file)
@@ -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; }
  ;
 
index 4256489690dcbd1201f18a43cde221caea37b4d2..dc3748f0915355b8a8c286b7fdfcf63e5c9c106d 100644 (file)
@@ -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);