]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: add ENHE support for "address-family ipv4 labeled-unicast"
authorDaniel Walton <dwalton@cumulusnetworks.com>
Wed, 10 May 2017 13:40:29 +0000 (09:40 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 10 May 2017 14:06:47 +0000 (10:06 -0400)
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
bgpd/bgp_attr.c
bgpd/bgp_open.c
bgpd/bgp_route.c
bgpd/bgp_updgrp_packet.c
bgpd/bgpd.h

index b2789cd47dcc4cfd542f8144994abc2fb9e4d3b3..9b9ad80d3585effaabe4448c4b0cdb65b0a7a732 100644 (file)
@@ -2890,10 +2890,15 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
 
          assert (attr->extra);
          bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
-         stream_putc (s, attre->mp_nexthop_len);
-         stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
-         if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+
+         if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+           stream_putc (s, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
+           stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
            stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
+          } else {
+           stream_putc (s, IPV6_MAX_BYTELEN);
+           stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
+          }
        }
        break;
       case SAFI_MPLS_VPN:
@@ -3137,14 +3142,14 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
   cp = stream_get_endp (s);
 
   if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) &&
-              !peer_cap_enhe(peer)))
+             !peer_cap_enhe(peer, afi, safi)))
     {
       size_t mpattrlen_pos = 0;
 
       mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi,
-                                    (peer_cap_enhe(peer) ? AFI_IP6 :
-                                     AFI_MAX), /* get from NH */
-                                    vecarr, attr);
+                                              (peer_cap_enhe(peer, afi, safi) ? AFI_IP6 :
+                                               AFI_MAX), /* get from NH */
+                                              vecarr, attr);
       bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag,
                                addpath_encode, addpath_tx_id, attr);
       bgp_packet_mpattr_end(s, mpattrlen_pos);
@@ -3220,7 +3225,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
       send_as4_path = 1; /* we'll do this later, at the correct place */
   
   /* Nexthop attribute. */
-  if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer))
+  if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer, afi, safi))
     {
       if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
         {
@@ -3230,7 +3235,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
           stream_putc (s, 4);
           stream_put_ipv4 (s, attr->nexthop.s_addr);
         }
-      else if (peer_cap_enhe(from))
+      else if (peer_cap_enhe(from, afi, safi))
         {
           /*
            * Likely this is the case when an IPv4 prefix was received with
index 83fc3fe97765b9949cf6c76c55eb9d8ed0b5c2bb..3ad6be1a3faaffab8016b43a1234716afb79a3b2 100644 (file)
@@ -594,11 +594,11 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr)
       /* RFC 5549 specifies use of this capability only for IPv4 AFI, with
        * the Nexthop AFI being IPv6. A future spec may introduce other
        * possibilities, so we ignore other values with a log. Also, only
-       * Unicast SAFI is currently supported (and expected).
+       * SAFI_UNICAST and SAFI_LABELED_UNICAST are currently supported (and expected).
        */
       nh_afi = afi_iana2int (pkt_nh_afi);
 
-      if (afi != AFI_IP || safi != SAFI_UNICAST || nh_afi != AFI_IP6)
+      if (afi != AFI_IP || nh_afi != AFI_IP6 || !(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
         {
           zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u "
                      "in Extended Next-hop capability, ignoring",
@@ -1288,32 +1288,34 @@ bgp_open_capability (struct stream *s, struct peer *peer)
             stream_putw (s, pkt_afi);
             stream_putc (s, 0);
             stream_putc (s, pkt_safi);
+
+            /* Extended nexthop capability - currently supporting RFC-5549 for
+             * Link-Local peering only
+             */
+            if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) &&
+                peer->su.sa.sa_family == AF_INET6 &&
+                IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr) &&
+                afi == AFI_IP &&
+                (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
+              {
+                /* RFC 5549 Extended Next Hop Encoding */
+                SET_FLAG (peer->cap, PEER_CAP_ENHE_ADV);
+                stream_putc (s, BGP_OPEN_OPT_CAP);
+                stream_putc (s, CAPABILITY_CODE_ENHE_LEN + 2);
+                stream_putc (s, CAPABILITY_CODE_ENHE);
+                stream_putc (s, CAPABILITY_CODE_ENHE_LEN);
+
+                SET_FLAG (peer->af_cap[AFI_IP][safi], PEER_CAP_ENHE_AF_ADV);
+                stream_putw (s, pkt_afi);
+                stream_putw (s, pkt_safi);
+                stream_putw (s, afi_int2iana(AFI_IP6));
+
+                if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV))
+                  SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO);
+              }
           }
       }
 
-  /* Extended nexthop capability - currently supporting RFC-5549 for
-   * Link-Local peering only
-   */
-  if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) &&
-      peer->su.sa.sa_family == AF_INET6 &&
-      IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
-    {
-      /* RFC 5549 Extended Next Hop Encoding */
-      SET_FLAG (peer->cap, PEER_CAP_ENHE_ADV);
-      stream_putc (s, BGP_OPEN_OPT_CAP);
-      stream_putc (s, CAPABILITY_CODE_ENHE_LEN + 2);
-      stream_putc (s, CAPABILITY_CODE_ENHE);
-      stream_putc (s, CAPABILITY_CODE_ENHE_LEN);
-      /* Currently supporting for SAFI_UNICAST only */
-      SET_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_ADV);
-      stream_putw (s, AFI_IP);
-      stream_putw (s, SAFI_UNICAST);
-      stream_putw (s, AFI_IP6);
-
-      if (CHECK_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_RCV))
-        SET_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_NEGO);
-    }
-
   /* Route refresh. */
   SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
   stream_putc (s, BGP_OPEN_OPT_CAP);
index f327e34f2ac42bd39c5530ada904ea65e4375f6a..ddb3679af9e8c0e1a8a747d39e5309fcfa18c6bc 100644 (file)
@@ -1456,7 +1456,7 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri,
 
 #define NEXTHOP_IS_V6 (\
     (safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN &&\
-     (p->family == AF_INET6 || peer_cap_enhe(peer))) || \
+     (p->family == AF_INET6 || peer_cap_enhe(peer, AFI_IP6, safi))) || \
     ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) &&\
      attr->extra->mp_nexthop_len >= IPV6_MAX_BYTELEN))
 
@@ -1558,7 +1558,7 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri,
           if (!reflect ||
               CHECK_FLAG (peer->af_flags[afi][safi],
                           PEER_FLAG_FORCE_NEXTHOP_SELF))
-            subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ?
+            subgroup_announce_reset_nhop ((peer_cap_enhe(peer, afi, safi) ?
                           AF_INET6 : p->family), attr);
         }
       else if (peer->sort == BGP_PEER_EBGP)
@@ -1573,14 +1573,14 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri,
                 break;
             }
           if (!paf)
-            subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ? AF_INET6 : p->family), attr);
+            subgroup_announce_reset_nhop ((peer_cap_enhe(peer, afi, safi) ? AF_INET6 : p->family), attr);
         }
       /* If IPv6/MP and nexthop does not have any override and happens to
        * be a link-local address, reset it so that we don't pass along the
        * source's link-local IPv6 address to recipients who may not be on
        * the same interface.
        */
-      if (p->family == AF_INET6 || peer_cap_enhe(peer))
+      if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))
         {
           if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
             subgroup_announce_reset_nhop (AF_INET6, attr);
index 9be1a50db750fdb2874b8bcc49745cca7663b019..459cf707d09df57e04973ed72f3485e66d6e95a6 100644 (file)
@@ -427,7 +427,7 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf)
       if (paf->afi == AFI_IP || paf->afi == AFI_IP6)
         {
           nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen);
-          if (peer_cap_enhe(peer))
+          if (peer_cap_enhe(peer, paf->afi, paf->safi))
             nhafi = AFI_IP6;
           if (paf->safi == SAFI_MPLS_VPN &&     /* if VPN && not global */
               nhlen != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
@@ -754,7 +754,7 @@ subgroup_update_packet (struct update_subgroup *subgrp)
        }
 
       if ((afi == AFI_IP && safi == SAFI_UNICAST) &&
-          !peer_cap_enhe(peer))
+          !peer_cap_enhe(peer, afi, safi))
        stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
       else
        {
@@ -769,9 +769,9 @@ subgroup_update_packet (struct update_subgroup *subgrp)
 
          if (stream_empty (snlri))
            mpattrlen_pos = bgp_packet_mpattr_start (snlri, afi, safi,
-                                         (peer_cap_enhe(peer) ? AFI_IP6 :
-                                          AFI_MAX), /* get from NH */
-                                         &vecarr, adv->baa->attr);
+                                                     (peer_cap_enhe(peer, afi, safi) ? AFI_IP6 :
+                                                      AFI_MAX), /* get from NH */
+                                                     &vecarr, adv->baa->attr);
 
           bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd,
                                     tag, addpath_encode, addpath_tx_id, adv->baa->attr);
@@ -923,7 +923,7 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp)
        first_time = 0;
 
       if (afi == AFI_IP && safi == SAFI_UNICAST &&
-          !peer_cap_enhe(peer))
+          !peer_cap_enhe(peer, afi, safi))
        stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
       else
        {
@@ -975,7 +975,7 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp)
   if (!stream_empty (s))
     {
       if (afi == AFI_IP && safi == SAFI_UNICAST &&
-          !peer_cap_enhe(peer))
+          !peer_cap_enhe(peer, afi, safi))
        {
          unfeasible_len
            = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
@@ -1072,7 +1072,7 @@ subgroup_default_update_packet (struct update_subgroup *subgrp,
 
   /* NLRI set. */
   if (p.family == AF_INET && safi == SAFI_UNICAST &&
-      !peer_cap_enhe(peer))
+      !peer_cap_enhe(peer, afi, safi))
     stream_put_prefix_addpath (s, &p, addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
 
   /* Set size. */
@@ -1133,7 +1133,7 @@ subgroup_default_withdraw_packet (struct update_subgroup *subgrp)
 
   /* Withdrawn Routes. */
   if (p.family == AF_INET && safi == SAFI_UNICAST &&
-      !peer_cap_enhe(peer))
+      !peer_cap_enhe(peer, afi, safi))
     {
       stream_put_prefix_addpath (s, &p, addpath_encode,
                                  BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
index ac09b97580f0a6d4ac36883719f500a977c95bd8..66ec8ccc84029856650e85693e966d1db2876ba5 100644 (file)
@@ -1514,16 +1514,10 @@ peer_dynamic_neighbor (struct peer *peer)
   return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0;
 }
 
-/*
- * Currently supporting RFC 5549 for AFI_IP/SAFI_UNICAST only.
- *
- * Note: When other RFC-5549 applicable SAFIs to be supported, that should
- * come as an argument to this routine.
- */
 static inline int
-peer_cap_enhe (struct peer *peer)
+peer_cap_enhe (struct peer *peer, afi_t afi, safi_t safi)
 {
-  return (CHECK_FLAG(peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_NEGO));
+  return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO));
 }
 
 /* Lookup VRF for BGP instance based on its type. */