]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Partial support for IPv4 routes with IPv6 next hop (RFC 5549)
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 24 Jan 2017 01:00:35 +0000 (02:00 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 24 Jan 2017 01:00:35 +0000 (02:00 +0100)
Mostly capability signalling

proto/bgp/attrs.c
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c

index 35aecdb038ed644fa0ddc3fe3f6483285d1dc03d..c557403b39f86dd21f51c42f920aef8dbb2676c7 100644 (file)
@@ -1285,6 +1285,8 @@ bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li
   if (src == NULL)
     return 0;
 
+  // XXXX: Check next hop AF
+
   /* IBGP route reflection, RFC 4456 */
   if (p->is_internal && src->is_internal && (p->local_as == src->local_as))
   {
index 83c1688948da169d92402ecd0c0476b7dbab3850..61d24f42be0c91c566f6ea7941d3ea46cf86eb36 100644 (file)
@@ -521,6 +521,7 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
     if (peer->gr_aware)
       c->load_state = BFS_LOADING;
 
+    c->ext_next_hop = c->cf->ext_next_hop && (bgp_channel_is_ipv6(c) || rem->ext_next_hop);
     c->add_path_rx = (loc->add_path & BGP_ADD_PATH_RX) && (rem->add_path & BGP_ADD_PATH_TX);
     c->add_path_tx = (loc->add_path & BGP_ADD_PATH_TX) && (rem->add_path & BGP_ADD_PATH_RX);
 
@@ -1788,6 +1789,7 @@ bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps)
   uint any_mp_bgp = 0;
   uint any_gr_able = 0;
   uint any_add_path = 0;
+  uint any_ext_next_hop = 0;
   u32 *afl1 = alloca(caps->af_count * sizeof(u32));
   u32 *afl2 = alloca(caps->af_count * sizeof(u32));
   uint afn1, afn2;
@@ -1797,6 +1799,7 @@ bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps)
     any_mp_bgp |= ac->ready;
     any_gr_able |= ac->gr_able;
     any_add_path |= ac->add_path;
+    any_ext_next_hop |= ac->ext_next_hop;
   }
 
   if (any_mp_bgp)
@@ -1814,6 +1817,18 @@ bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps)
   if (caps->route_refresh)
     cli_msg(-1006, "      Route refresh");
 
+  if (any_ext_next_hop)
+  {
+    cli_msg(-1006, "      Extended next hop");
+
+    afn1 = 0;
+    WALK_AF_CAPS(caps, ac)
+      if (ac->ext_next_hop)
+       afl1[afn1++] = ac->afi;
+
+    bgp_show_afis(-1006, "        IPv6 nexthop:", afl1, afn1);
+  }
+
   if (caps->ext_messages)
     cli_msg(-1006, "      Extended message");
 
index 7f5be4ea6cf449f5d7e44d03922b071efc73a360..e5d860755c1f9b52a7e6b099affaaf32b2e98ab0 100644 (file)
@@ -123,6 +123,7 @@ struct bgp_channel_config {
   u8 gw_mode;                          /* How we compute route gateway from next_hop attr, see GW_* */
   u8 secondary;                                /* Accept also non-best routes (i.e. RA_ACCEPTED) */
   u8 gr_able;                          /* Allow full graceful restart for the channel */
+  u8 ext_next_hop;                     /* Allow both IPv4 and IPv6 next hops */
   u8 add_path;                         /* Use ADD-PATH extension [RFC 7911] */
 
   struct rtable_config *igp_table;     /* Table used for recursive next hop lookups */
@@ -154,6 +155,7 @@ struct bgp_af_caps {
   u8 ready;                            /* Multiprotocol capability, RFC 4760 */
   u8 gr_able;                          /* Graceful restart support, RFC 4724 */
   u8 gr_af_flags;                      /* Graceful restart per-AF flags */
+  u8 ext_next_hop;                     /* Extended IPv6 next hop,   RFC 5549 */
   u8 add_path;                         /* Multiple paths support,   RFC 7911 */
 };
 
@@ -274,6 +276,8 @@ struct bgp_channel {
   u8 gr_ready;                         /* Neighbor could do GR on this AF */
   u8 gr_active;                                /* Neighbor is doing GR and keeping fwd state */
 
+  u8 ext_next_hop;                     /* Session allows both IPv4 and IPv6 next hops */
+
   u8 add_path_rx;                      /* Session expects receive of ADD-PATH extended NLRI */
   u8 add_path_tx;                      /* Session expects transmit of ADD-PATH extended NLRI */
 
index 7c89fd50dbd80664a76df0e68399b3d35688639f..8c63b331d32c236590bc01dcfcd391d7bde5f6b5 100644 (file)
@@ -169,6 +169,7 @@ bgp_channel_item:
  | GATEWAY RECURSIVE { BGP_CC->gw_mode = GW_RECURSIVE; }
  | SECONDARY bool { BGP_CC->secondary = $2; }
  | GRACEFUL RESTART bool { BGP_CC->gr_able = $3; }
+ | EXTENDED NEXT HOP bool { BGP_CC->ext_next_hop = $4; }
  | ADD PATHS RX { BGP_CC->add_path = BGP_ADD_PATH_RX; }
  | ADD PATHS TX { BGP_CC->add_path = BGP_ADD_PATH_TX; }
  | ADD PATHS bool { BGP_CC->add_path = $3 ? BGP_ADD_PATH_FULL : 0; }
index a7df1c6373ca848ccd4d003b7d711b058783cded..dbc5fe12b2651ac727b1746be06c424529ed5194 100644 (file)
@@ -228,6 +228,7 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
   struct bgp_channel *c;
   struct bgp_caps *caps;
   struct bgp_af_caps *ac;
+  uint any_ext_next_hop = 0;
   uint any_add_path = 0;
   byte *data;
 
@@ -259,6 +260,9 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
     ac->afi = c->afi;
     ac->ready = 1;
 
+    ac->ext_next_hop = bgp_channel_is_ipv4(c) && c->cf->ext_next_hop;
+    any_ext_next_hop |= ac->ext_next_hop;
+
     ac->add_path = c->cf->add_path;
     any_add_path |= ac->add_path;
 
@@ -298,6 +302,23 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
     *buf++ = 0;                        /* Capability data length */
   }
 
+  if (any_ext_next_hop)
+  {
+    *buf++ = 5;                        /* Capability 5: Support for extended next hop */
+    *buf++ = 0;                        /* Capability data length, will be fixed later */
+    data = buf;
+
+    WALK_AF_CAPS(caps, ac)
+      if (ac->ext_next_hop)
+      {
+       put_af4(buf, ac->afi);
+       put_u16(buf+4, BGP_AFI_IPV6);
+       buf += 6;
+      }
+
+    data[-1] = buf - data;
+  }
+
   if (caps->ext_messages)
   {
     *buf++ = 6;                        /* Capability 6: Support for extended messages */
@@ -394,6 +415,23 @@ bgp_read_capabilities(struct bgp_conn *conn, struct bgp_caps *caps, byte *pos, i
       caps->route_refresh = 1;
       break;
 
+    case  5: /* Extended next hop encoding capability, RFC 5549 */
+      if (cl % 6)
+       goto err;
+
+      for (i = 0; i < cl; i += 6)
+      {
+       /* Specified only for IPv4 prefixes with IPv6 next hops */
+       if ((get_u16(pos+2+i+0) != BGP_AFI_IPV4) ||
+           (get_u16(pos+2+i+4) != BGP_AFI_IPV6))
+         continue;
+
+       af = get_af4(pos+2+i);
+       ac = bgp_get_af_caps(caps, af);
+       ac->ext_next_hop = 1;
+      }
+      break;
+
     case  6: /* Extended message length capability, RFC draft */
       if (cl != 0)
        goto err;