]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Mandatory option for channels
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 19 Mar 2019 16:44:50 +0000 (17:44 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 19 Mar 2019 16:44:50 +0000 (17:44 +0100)
Allow to mark channel to be mandatory, and do not allow BGP sessions if
no common AFI/SAFI is established.

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

index e531da404080fb7c6bdaada4c9a66f1be16159ec..8d93f8ac32504c7dcb55a9916d6b00996fb9f2f2 100644 (file)
@@ -2565,6 +2565,15 @@ be used in explicit configuration.
 <p>BGP channels have additional config options (together with the common ones):
 
 <descrip>
+       <tag><label id="bgp-mandatory">mandatory <m/switch/</tag>
+       When local and neighbor sets of configured AFI/SAFI pairs differ,
+       capability negotiation ensures that a common subset is used. For
+       mandatory channels their associated AFI/SAFI must be negotiated
+       (i.e., also announced by the neighbor), otherwise BGP session
+       negotiation fails with <it/'Required capability missing'/ error.
+       Regardless, at least one AFI/SAFI must be negotiated in order to BGP
+       session be successfully established. Default: off.
+
        <tag><label id="bgp-next-hop-keep">next hop keep <m/switch/|ibgp|ebgp</tag>
        Do not modify the Next Hop attribute and advertise the current one
        unchanged even in cases where our own local address should be used
index 56dbf4854c12a79a54b008fa05a88092fec29da9..8c7d57b9bdef2d585862fb7dfa61ab270e3488c8 100644 (file)
@@ -136,6 +136,7 @@ struct bgp_channel_config {
   ip_addr next_hop_addr;               /* Local address for NEXT_HOP attribute */
   u8 next_hop_self;                    /* Always set next hop to local IP address (NH_*) */
   u8 next_hop_keep;                    /* Do not modify next hop attribute (NH_*) */
+  u8 mandatory;                                /* Channel is mandatory in capability negotiation */
   u8 missing_lladdr;                   /* What we will do when we don' know link-local addr, see MLL_* */
   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) */
index ac8d024aaa2d182d7e501ad6c1b86bb626d681aa..9dea78ca2c8f661a5060ea9daf616b5d5ffd124d 100644 (file)
@@ -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)
+       LIVED, STALE, IMPORT, IBGP, EBGP, MANDATORY)
 
 %type <i> bgp_nh
 %type <i32> bgp_afi
@@ -223,6 +223,7 @@ bgp_channel_item:
  | NEXT HOP ADDRESS ipa { BGP_CC->next_hop_addr = $4; }
  | NEXT HOP SELF bgp_nh { BGP_CC->next_hop_self = $4; }
  | NEXT HOP KEEP bgp_nh { BGP_CC->next_hop_keep = $4; }
+ | MANDATORY bool { BGP_CC->mandatory = $2; }
  | MISSING LLADDR SELF { BGP_CC->missing_lladdr = MLL_SELF; }
  | MISSING LLADDR DROP { BGP_CC->missing_lladdr = MLL_DROP; }
  | MISSING LLADDR IGNORE { BGP_CC->missing_lladdr = MLL_IGNORE; }
index 4ae6c5cf6f191f77844742a98ac33a9c6a80cd03..c09e9859e7b110841bebd5f4a868b7c8d686b8f2 100644 (file)
@@ -573,6 +573,42 @@ err:
   return;
 }
 
+static int
+bgp_check_capabilities(struct bgp_conn *conn)
+{
+  struct bgp_proto *p = conn->bgp;
+  struct bgp_caps *local = conn->local_caps;
+  struct bgp_caps *remote = conn->remote_caps;
+  struct bgp_channel *c;
+  int count = 0;
+
+  /* This is partially overlapping with bgp_conn_enter_established_state(),
+     but we need to run this just after we receive OPEN message */
+
+  WALK_LIST(c, p->p.channels)
+  {
+    const struct bgp_af_caps *loc = bgp_find_af_caps(local,  c->afi);
+    const struct bgp_af_caps *rem = bgp_find_af_caps(remote, c->afi);
+
+    /* Find out whether this channel will be active */
+    int active = loc && loc->ready &&
+      ((rem && rem->ready) || (!remote->length && (c->afi == BGP_AF_IPV4)));
+
+    /* Mandatory must be active */
+    if (c->cf->mandatory && !active)
+      return 0;
+
+    if (active)
+      count++;
+  }
+
+  /* We need at least one channel active */
+  if (!count)
+    return 0;
+
+  return 1;
+}
+
 static int
 bgp_read_options(struct bgp_conn *conn, byte *pos, int len)
 {
@@ -683,6 +719,10 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
   if (!id || (p->is_internal && id == p->local_id))
   { bgp_error(conn, 2, 3, pkt+24, -4); return; }
 
+  /* RFC 5492 4 - check for required capabilities */
+  if (p->cf->capabilities && !bgp_check_capabilities(conn))
+  { bgp_error(conn, 2, 7, NULL, 0); return; }
+
   struct bgp_caps *caps = conn->remote_caps;
 
   if (caps->as4_support)