From e3299ab14877de6ce688050e550c44cd4e85b212 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 5 Mar 2009 11:52:47 +0100 Subject: [PATCH] Added Cisco and Quagga capability workaround option. --- doc/bird.sgml | 10 ++++++++++ proto/bgp/bgp.h | 2 ++ proto/bgp/config.Y | 3 ++- proto/bgp/packets.c | 26 +++++++++++++++++++++++--- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/doc/bird.sgml b/doc/bird.sgml index c070be12..5095b780 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. + advertise ipv4 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. + disable after error 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 b0ead9d3..bdad1a4d 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 73b584f1..4b64ed5f 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 42564896..dc3748f0 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);