]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Extended messages support
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 18 Jul 2015 11:38:21 +0000 (13:38 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 18 Jul 2015 11:38:21 +0000 (13:38 +0200)
Implements draft-ietf-idr-bgp-extended-messages-10, for now
undocumented and with temporary private capability number.

doc/bird.sgml
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c

index 752465b9793ea0d1cc8e029df33c254e31d6528d..2ae9f64988ca803531cfab73434e110481ae5c86 100644 (file)
@@ -1571,7 +1571,7 @@ RFC 4271<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4271.txt">
 It also supports the community attributes
 (RFC 1997<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc1997.txt">),
 capability negotiation
-(RFC 3392<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc3392.txt">),
+(RFC 5492<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc5492.txt">),
 MD5 password authentication
 (RFC 2385<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc2385.txt">),
 extended communities
index 9e28b27874424090563859639b72bfcbd98f775b..f549b0ed9aafadf9d39de68bbc341494c91a5ff7 100644 (file)
@@ -569,6 +569,7 @@ bgp_send_open(struct bgp_conn *conn)
   conn->peer_gr_time = 0;
   conn->peer_gr_flags = 0;
   conn->peer_gr_aflags = 0;
+  conn->peer_ext_messages_support = 0;
 
   DBG("BGP: Sending open\n");
   conn->sk->rx_hook = bgp_rx;
@@ -733,8 +734,8 @@ bgp_connect(struct bgp_proto *p)    /* Enter Connect state and start establishing c
   s->dport = p->cf->remote_port;
   s->iface = p->neigh ? p->neigh->iface : NULL;
   s->ttl = p->cf->ttl_security ? 255 : hops;
-  s->rbsize = BGP_RX_BUFFER_SIZE;
-  s->tbsize = BGP_TX_BUFFER_SIZE;
+  s->rbsize = p->cf->enable_extended_messages ? BGP_RX_BUFFER_EXT_SIZE : BGP_RX_BUFFER_SIZE;
+  s->tbsize = p->cf->enable_extended_messages ? BGP_TX_BUFFER_EXT_SIZE : BGP_TX_BUFFER_SIZE;
   s->tos = IP_PREC_INTERNET_CONTROL;
   s->password = p->cf->password;
   s->tx_hook = bgp_connected;
@@ -843,6 +844,13 @@ bgp_incoming_connection(sock *sk, int dummy UNUSED)
     if (sk_set_min_ttl(sk, 256 - hops) < 0)
       goto err;
 
+  if (p->cf->enable_extended_messages)
+    {
+      sk->rbsize = BGP_RX_BUFFER_EXT_SIZE;
+      sk->tbsize = BGP_TX_BUFFER_EXT_SIZE;
+      sk_reallocate(sk);
+    }
+
   bgp_setup_conn(p, &p->incoming_conn);
   bgp_setup_sk(&p->incoming_conn, sk);
   bgp_send_open(&p->incoming_conn);
@@ -1518,21 +1526,23 @@ bgp_show_proto_info(struct proto *P)
   else if (P->proto_state == PS_UP)
     {
       cli_msg(-1006, "    Neighbor ID:      %R", p->remote_id);
-      cli_msg(-1006, "    Neighbor caps:   %s%s%s%s%s%s",
+      cli_msg(-1006, "    Neighbor caps:   %s%s%s%s%s%s%s",
              c->peer_refresh_support ? " refresh" : "",
              c->peer_enhanced_refresh_support ? " enhanced-refresh" : "",
              c->peer_gr_able ? " restart-able" : (c->peer_gr_aware ? " restart-aware" : ""),
              c->peer_as4_support ? " AS4" : "",
              (c->peer_add_path & ADD_PATH_RX) ? " add-path-rx" : "",
-             (c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "");
-      cli_msg(-1006, "    Session:          %s%s%s%s%s%s%s",
+             (c->peer_add_path & ADD_PATH_TX) ? " add-path-tx" : "",
+             c->peer_ext_messages_support ? " ext-messages" : "");
+      cli_msg(-1006, "    Session:          %s%s%s%s%s%s%s%s",
              p->is_internal ? "internal" : "external",
              p->cf->multihop ? " multihop" : "",
              p->rr_client ? " route-reflector" : "",
              p->rs_client ? " route-server" : "",
              p->as4_session ? " AS4" : "",
              p->add_path_rx ? " add-path-rx" : "",
-             p->add_path_tx ? " add-path-tx" : "");
+             p->add_path_tx ? " add-path-tx" : "",
+             p->ext_messages ? " ext-messages" : "");
       cli_msg(-1006, "    Source address:   %I", p->source_addr);
       if (P->cf->in_limit)
        cli_msg(-1006, "    Route limit:      %d/%d",
index b6e80fe5ab7203513efd27b3ba7b3381f3909fa9..274794f136c8e2e208911165a59b531ba0acceea 100644 (file)
@@ -40,6 +40,7 @@ struct bgp_config {
   int capabilities;                    /* Enable capability handshake [RFC3392] */
   int enable_refresh;                  /* Enable local support for route refresh [RFC2918] */
   int enable_as4;                      /* Enable local support for 4B AS numbers [RFC4893] */
+  int enable_extended_messages;                /* Enable local support for extended messages [draft] */
   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 */
@@ -109,6 +110,7 @@ struct bgp_conn {
   u16 peer_gr_time;
   u8 peer_gr_flags;
   u8 peer_gr_aflags;
+  u8 peer_ext_messages_support;                /* Peer supports extended message length [draft] */
   unsigned hold_time, keepalive_time;  /* Times calculated from my and neighbor's requirements */
 };
 
@@ -121,6 +123,7 @@ struct bgp_proto {
   u8 as4_session;                      /* Session uses 4B AS numbers in AS_PATH (both sides support it) */
   u8 add_path_rx;                      /* Session expects receive of ADD-PATH extended NLRI */
   u8 add_path_tx;                      /* Session expects transmit of ADD-PATH extended NLRI */
+  u8 ext_messages;                     /* Session allows to use extended messages (both sides support it) */
   u32 local_id;                                /* BGP identifier of this router */
   u32 remote_id;                       /* BGP identifier of the neighbor */
   u32 rr_cluster_id;                   /* Route reflector cluster ID */
@@ -180,9 +183,15 @@ struct bgp_bucket {
 #define BGP_PORT               179
 #define BGP_VERSION            4
 #define BGP_HEADER_LENGTH      19
-#define BGP_MAX_PACKET_LENGTH  4096
+#define BGP_MAX_MESSAGE_LENGTH 4096
+#define BGP_MAX_EXT_MSG_LENGTH 65535
 #define BGP_RX_BUFFER_SIZE     4096
-#define BGP_TX_BUFFER_SIZE     BGP_MAX_PACKET_LENGTH
+#define BGP_TX_BUFFER_SIZE     4096
+#define BGP_RX_BUFFER_EXT_SIZE 65535
+#define BGP_TX_BUFFER_EXT_SIZE 65535
+
+static inline int bgp_max_packet_length(struct bgp_proto *p)
+{ return p->ext_messages ? BGP_MAX_EXT_MSG_LENGTH : BGP_MAX_MESSAGE_LENGTH; }
 
 extern struct linpool *bgp_linpool;
 
index 49afe5ae13cca66ad1713949bc6f246ae5364277..85b93a6b9e5f8dc6de62a11bb9236354b5f857a8 100644 (file)
@@ -27,7 +27,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
        INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
        TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
        SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
-       CHECK, LINK, PORT)
+       CHECK, LINK, PORT, EXTENDED, MESSAGES)
 
 CF_GRAMMAR
 
@@ -108,6 +108,7 @@ bgp_proto:
  | bgp_proto DISABLE AFTER ERROR bool ';' { BGP_CFG->disable_after_error = $5; }
  | bgp_proto ENABLE ROUTE REFRESH bool ';' { BGP_CFG->enable_refresh = $5; }
  | bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
+ | bgp_proto ENABLE EXTENDED MESSAGES bool ';' { BGP_CFG->enable_extended_messages = $5; }
  | 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; }
index 378f5ab1a986321d8fdeb967d05947d07f565f6f..ed99f6236d7fe3777f8d13c1469b9b47f7a47be4 100644 (file)
@@ -84,7 +84,7 @@ mrt_put_bgp4_hdr(byte *buf, struct bgp_conn *conn, int as4)
 static void
 mrt_dump_bgp_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
 {
-  byte buf[BGP_MAX_PACKET_LENGTH + 128];
+  byte *buf = alloca(128+len); /* 128 is enough for MRT headers */
   byte *bp = buf + MRTDUMP_HDR_LENGTH;
   int as4 = conn->bgp->as4_session;
 
@@ -223,6 +223,14 @@ bgp_put_cap_err(struct bgp_proto *p UNUSED, byte *buf)
   return buf;
 }
 
+static byte *
+bgp_put_cap_ext_msg(struct bgp_proto *p UNUSED, byte *buf)
+{
+  *buf++ = 230;                /* Capability TBD: Support for extended messages */
+  *buf++ = 0;          /* Capability data length */
+  return buf;
+}
+
 
 static byte *
 bgp_create_open(struct bgp_conn *conn, byte *buf)
@@ -274,6 +282,9 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
   if (p->cf->enable_refresh)
     cap = bgp_put_cap_err(p, cap);
 
+  if (p->cf->enable_extended_messages)
+    cap = bgp_put_cap_ext_msg(p, cap);
+
   cap_len = cap - buf - 12;
   if (cap_len > 0)
     {
@@ -342,7 +353,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
 {
   struct bgp_proto *p = conn->bgp;
   struct bgp_bucket *buck;
-  int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4;
+  int remains = bgp_max_packet_length(p) - BGP_HEADER_LENGTH - 4;
   byte *w;
   int wd_size = 0;
   int r_size = 0;
@@ -428,7 +439,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf)
   struct bgp_proto *p = conn->bgp;
   struct bgp_bucket *buck;
   int size, second, rem_stored;
-  int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4;
+  int remains = bgp_max_packet_length(p) - BGP_HEADER_LENGTH - 4;
   byte *w, *w_stored, *tmp, *tstart;
   ip_addr *ipp, ip, ip_ll;
   ea_list *ea;
@@ -856,6 +867,12 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
          conn->peer_enhanced_refresh_support = 1;
          break;
 
+       case 230: /* Extended message length capability, draft, cap number TBD */
+         if (cl != 0)
+           goto err;
+         conn->peer_ext_messages_support = 1;
+         break;
+
          /* We can safely ignore all other capabilities */
        }
       len -= 2 + cl;
@@ -1019,6 +1036,7 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
   p->add_path_rx = (p->cf->add_path & ADD_PATH_RX) && (conn->peer_add_path & ADD_PATH_TX);
   p->add_path_tx = (p->cf->add_path & ADD_PATH_TX) && (conn->peer_add_path & ADD_PATH_RX);
   p->gr_ready = p->cf->gr_mode && conn->peer_gr_able;
+  p->ext_messages = p->cf->enable_extended_messages && conn->peer_ext_messages_support;
 
   if (p->add_path_tx)
     p->p.accept_ra_types = RA_ANY;
@@ -1418,7 +1436,7 @@ static struct {
   { 2, 4, "Unsupported optional parameter" },
   { 2, 5, "Authentication failure" },
   { 2, 6, "Unacceptable hold time" },
-  { 2, 7, "Required capability missing" }, /* [RFC3392] */
+  { 2, 7, "Required capability missing" }, /* [RFC5492] */
   { 2, 8, "No supported AFI/SAFI" }, /* This error msg is nonstandard */
   { 3, 0, "Invalid UPDATE message" },
   { 3, 1, "Malformed attribute list" },
@@ -1666,6 +1684,7 @@ int
 bgp_rx(sock *sk, int size)
 {
   struct bgp_conn *conn = sk->data;
+  struct bgp_proto *p = conn->bgp;
   byte *pkt_start = sk->rbuf;
   byte *end = pkt_start + size;
   unsigned i, len;
@@ -1682,7 +1701,7 @@ bgp_rx(sock *sk, int size)
            break;
          }
       len = get_u16(pkt_start+16);
-      if (len < BGP_HEADER_LENGTH || len > BGP_MAX_PACKET_LENGTH)
+      if (len < BGP_HEADER_LENGTH || len > bgp_max_packet_length(p))
        {
          bgp_error(conn, 1, 2, pkt_start+16, 2);
          break;