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

BGP: Promiscuous ASN mode

Allow to specify just 'internal' or 'external' for remote neighbor
instead of specific ASN. In the second case that means BGP peers with
any non-local ASNs are accepted.
parent a22c3e59
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -2195,12 +2195,15 @@ using the following configuration parameters:
	<cf/local 10.0.0.1; local as 65000;/ are valid). This parameter is
	mandatory.

	<tag><label id="bgp-neighbor">neighbor [<m/ip/] [port <m/number/] [as <m/number/]</tag>
	<tag><label id="bgp-neighbor">neighbor [<m/ip/] [port <m/number/] [as <m/number/] [internal|external]</tag>
	Define neighboring router this instance will be talking to and what AS
	it is located in. In case the neighbor is in the same AS as we are, we
	automatically switch to iBGP. Optionally, the remote port may also be
	specified. Like <cf/local/ parameter, this parameter may also be used
	multiple times with different sub-options. This parameter is mandatory.
	automatically switch to IBGP. Alternatively, it is possible to specify
	just <cf/internal/ or </cf/external/ instead of AS number, in that case
	either local AS number, or any external AS number is accepted.
	Optionally, the remote port may also be specified. Like <cf/local/
	parameter, this parameter may also be used multiple times with different
	sub-options. This parameter is mandatory.

	<tag><label id="bgp-iface">interface <m/string/</tag>
	Define interface we should use for link-local BGP IPv6 sessions.
+20 −5
Original line number Diff line number Diff line
@@ -507,6 +507,10 @@ bgp_conn_enter_established_state(struct bgp_conn *conn)
  if (ipa_zero(p->local_ip))
    p->local_ip = conn->sk->saddr;

  /* For promiscuous sessions */
  if (!p->remote_as)
    p->remote_as = conn->received_as;

  /* In case of LLv6 is not valid during BGP start */
  if (ipa_zero(p->link_addr) && p->neigh && p->neigh->iface && p->neigh->iface->llv6)
    p->link_addr = p->neigh->iface->llv6->ip;
@@ -1754,14 +1758,19 @@ void
bgp_postconfig(struct proto_config *CF)
{
  struct bgp_config *cf = (void *) CF;
  int internal = (cf->local_as == cf->remote_as);
  int interior = internal || cf->confederation_member;

  /* Do not check templates at all */
  if (cf->c.class == SYM_TEMPLATE)
    return;


  /* Handle undefined remote_as, zero should mean unspecified external */
  if (!cf->remote_as && (cf->peer_type == BGP_PT_INTERNAL))
    cf->remote_as = cf->local_as;

  int internal = (cf->local_as == cf->remote_as);
  int interior = internal || cf->confederation_member;

  /* EBGP direct by default, IBGP multihop by default */
  if (cf->multihop < 0)
    cf->multihop = internal ? 64 : 0;
@@ -1781,8 +1790,14 @@ bgp_postconfig(struct proto_config *CF)
  if (ipa_zero(cf->remote_ip))
    cf_error("Neighbor must be configured");

  if (!cf->remote_as)
    cf_error("Remote AS number must be set");
  if (!cf->remote_as && !cf->peer_type)
    cf_error("Remote AS number (or peer type) must be set");

  if ((cf->peer_type == BGP_PT_INTERNAL) && !internal)
    cf_error("IBGP cannot have different ASNs");

  if ((cf->peer_type == BGP_PT_EXTERNAL) &&  internal)
    cf_error("EBGP cannot have the same ASNs");

  if (!cf->iface && (ipa_is_link_local(cf->local_ip) ||
		     ipa_is_link_local(cf->remote_ip)))
@@ -2242,7 +2257,7 @@ bgp_show_proto_info(struct proto *P)

  cli_msg(-1006, "  BGP state:          %s", bgp_state_dsc(p));
  cli_msg(-1006, "    Neighbor address: %I%J", p->cf->remote_ip, p->cf->iface);
  cli_msg(-1006, "    Neighbor AS:      %u", p->cf->remote_as);
  cli_msg(-1006, "    Neighbor AS:      %u", p->cf->remote_as ?: p->remote_as);

  if (p->gr_active_num)
    cli_msg(-1006, "    Neighbor graceful restart active");
+5 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ struct bgp_config {
  struct iface *iface;			/* Interface for link-local addresses */
  u16 local_port;			/* Local listening port */
  u16 remote_port; 			/* Neighbor destination port */
  int peer_type;			/* Internal or external BGP (BGP_PT_*, optional) */
  int multihop;				/* Number of hops if multihop */
  int strict_bind;			/* Bind listening socket to local address */
  int ttl_security;			/* Enable TTL security [RFC 5082] */
@@ -152,6 +153,9 @@ struct bgp_channel_config {
  struct rtable_config *igp_table_ip6;	/* Table for recursive IPv6 next hop lookups */
};

#define BGP_PT_INTERNAL		1
#define BGP_PT_EXTERNAL		2

#define NH_NO			0
#define NH_ALL			1
#define NH_IBGP			2
@@ -237,6 +241,7 @@ struct bgp_conn {
  u8 state;				/* State of connection state machine */
  u8 as4_session;			/* Session uses 4B AS numbers in AS_PATH (both sides support it) */
  u8 ext_messages;			/* Session uses extended message length */
  u32 received_as;			/* ASN received in OPEN message */

  struct bgp_caps *local_caps;
  struct bgp_caps *remote_caps;
+3 −1
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
	SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX,
	GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY,
	STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6, LONG,
	LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY)
	LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY, INTERNAL, EXTERNAL)

%type <i> bgp_nh
%type <i32> bgp_afi
@@ -82,6 +82,8 @@ bgp_nbr_opts:
   /* empty */
 | bgp_nbr_opts PORT expr { BGP_CFG->remote_port = $3; if (($3<1) || ($3>65535)) cf_error("Invalid port number"); }
 | bgp_nbr_opts AS expr { BGP_CFG->remote_as = $3; }
 | bgp_nbr_opts INTERNAL { BGP_CFG->peer_type = BGP_PT_INTERNAL; }
 | bgp_nbr_opts EXTERNAL { BGP_CFG->peer_type = BGP_PT_EXTERNAL; }
 ;

bgp_cease_mask:
+7 −2
Original line number Diff line number Diff line
@@ -732,13 +732,18 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
    if ((as4 != asn) && (asn != AS_TRANS))
      log(L_WARN "%s: Peer advertised inconsistent AS numbers", p->p.name);

    if (as4 != p->remote_as)
    /* When remote ASN is unspecified, it must be external one */
    if (p->remote_as ? (as4 != p->remote_as) : (as4 == p->local_as))
    { as4 = htonl(as4); bgp_error(conn, 2, 2, (byte *) &as4, 4); return; }

    conn->received_as = as4;
  }
  else
  {
    if (asn != p->remote_as)
    if (p->remote_as ? (asn != p->remote_as) : (asn == p->local_as))
    { bgp_error(conn, 2, 2, pkt+20, 2); return; }

    conn->received_as = asn;
  }

  /* Check the other connection */