Commit d8022d26 authored by Ondrej Zajicek (work)'s avatar Ondrej Zajicek (work)
Browse files

BGP: Partial support for IPv4 routes with IPv6 next hop (RFC 5549)

Mostly capability signalling
parent 5509e17d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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))
  {
+15 −0
Original line number Diff line number Diff line
@@ -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");

+4 −0
Original line number Diff line number Diff line
@@ -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 */

+1 −0
Original line number Diff line number Diff line
@@ -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; }
+38 −0
Original line number Diff line number Diff line
@@ -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;