]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: general MP/SAFI improvements
authorLou Berger <lberger@labn.net>
Tue, 12 Jan 2016 18:41:59 +0000 (13:41 -0500)
committervivek <vivek@cumulusnetworks.com>
Fri, 10 Jun 2016 01:20:42 +0000 (18:20 -0700)
This fixes some minor mixups particularly in MPLS-related SAFIs, as well
as doing some stylistic changes & adding comments.

Signed-off-by: Lou Berger <lberger@labn.net>
Reviewed-by: David Lamparter <equinox@opensourcerouting.org>
(cherry picked from commit 050defe816e4bd4cac7b028f69e45cb1974ca96d)

Conflicts:
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_route.h

bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
bgpd/bgp_routemap.c
bgpd/bgp_updgrp_packet.c

index ad8c7641e44842e90b1ba5f5e8032839597c9d94..2ffe464f0a8d7314a3d0bff0b1a600b49b2caea0 100644 (file)
@@ -2208,8 +2208,9 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
   stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
   sizep = stream_get_endp (s);
   stream_putw (s, 0);  /* Marker: Attribute length. */
-  stream_putw (s, afi);        /* AFI */
-  stream_putc (s, safi);       /* SAFI */
+
+  stream_putw (s, afi);
+  stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
 
   /* Nexthop */
   switch (nh_afi)
@@ -2217,7 +2218,6 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
     case AFI_IP:
       switch (safi)
        {
-       case SAFI_UNICAST:
        case SAFI_MULTICAST:
          bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
          stream_putc (s, 4);
@@ -2226,10 +2226,11 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
        case SAFI_MPLS_VPN:
          bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
          stream_putc (s, 12);
-         stream_putl (s, 0);
+         stream_putl (s, 0);   /* RD = 0, per RFC */
          stream_putl (s, 0);
          stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
          break;
+       case SAFI_UNICAST:      /* invalid for IPv4 */
        default:
          break;
        }
@@ -2250,6 +2251,28 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
          if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
            stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
        }
+       break;
+      case SAFI_MPLS_VPN:
+       {
+         struct attr_extra *attre = attr->extra;
+
+         assert (attr->extra);
+          if (attre->mp_nexthop_len == 16) {
+            stream_putc (s, 24);
+            stream_putl (s, 0);   /* RD = 0, per RFC */
+            stream_putl (s, 0);
+            stream_put (s, &attre->mp_nexthop_global, 16);
+          } else if (attre->mp_nexthop_len == 32) {
+            stream_putc (s, 48);
+            stream_putl (s, 0);   /* RD = 0, per RFC */
+            stream_putl (s, 0);
+            stream_put (s, &attre->mp_nexthop_global, 16);
+            stream_putl (s, 0);   /* RD = 0, per RFC */
+            stream_putl (s, 0);
+            stream_put (s, &attre->mp_nexthop_local, 16);
+          }
+        }
+       break;
       default:
        break;
       }
@@ -2270,24 +2293,27 @@ bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
                           u_char *tag, int addpath_encode,
                           u_int32_t addpath_tx_id)
 {
-  switch (safi)
+  if (safi == SAFI_MPLS_VPN)
     {
-    case SAFI_MPLS_VPN:
-      /* addpath TX ID */
       if (addpath_encode)
         stream_putl(s, addpath_tx_id);
-
       /* Tag, RD, Prefix write. */
       stream_putc (s, p->prefixlen + 88);
       stream_put (s, tag, 3);
       stream_put (s, prd->val, 8);
       stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
-      break;
-    default:
-      /* Prefix write. */
-      stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
-      break;
     }
+  else
+    stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
+}
+
+size_t
+bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p)
+{
+  int size = PSIZE (p->prefixlen);
+  if (safi == SAFI_MPLS_VPN)
+      size += 88;
+  return size;
 }
 
 void
@@ -2314,7 +2340,6 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
   int send_as4_path = 0;
   int send_as4_aggregator = 0;
   int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
-  size_t mpattrlen_pos = 0;
 
   if (! bgp)
     bgp = peer->bgp;
@@ -2325,6 +2350,8 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
   if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) &&
               !peer_cap_enhe(peer)))
     {
+      size_t mpattrlen_pos = 0;
+
       mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi,
                                     (peer_cap_enhe(peer) ? AFI_IP6 : afi),
                                     vecarr, attr);
@@ -2403,7 +2430,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 && !peer_cap_enhe(peer))
+  if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer))
     {
       if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
         {
@@ -2689,8 +2716,7 @@ bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
   stream_putw (s, 0);          /* Length of this attribute. */
 
   stream_putw (s, afi);
-  safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi;
-  stream_putc (s, safi);
+  stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
   return attrlen_pnt;
 }
 
@@ -2718,12 +2744,7 @@ bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
 void
 bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
 {
-  bgp_size_t size;
-
-  /* Set MP attribute length. Don't count the (2) bytes used to encode
-     the attr length */
-  size = stream_get_endp (s) - attrlen_pnt - 2;
-  stream_putw_at (s, attrlen_pnt, size);
+  bgp_packet_mpattr_end (s, attrlen_pnt);
 }
 
 /* Initialization of attribute. */
index da9bfec497523747dd5c90400ea5027d1a8cfdcb..5cd6b8544a336cf69d7049ca5a346ac46c6520ec 100644 (file)
@@ -239,6 +239,8 @@ extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
                                     struct prefix *p, struct prefix_rd *prd,
                                     u_char *tag, int addpath_encode,
                                      u_int32_t addpath_tx_id);
+extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
+                                            struct prefix *p);
 extern void bgp_packet_mpattr_end(struct stream *s, size_t sizep);
 
 extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi,
index 9f27c9addb6d38e5d934095848bc43c681c6a62d..00f8221bcbc9c73f77daeba6f886d525cdbed0e1 100644 (file)
@@ -206,13 +206,10 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
           decode_rd_ip (pnt + 5, &rd_ip);
           break;
 
-        case RD_TYPE_EOI:
-          break;
-
-        default:
-          zlog_err ("Invalid RD type %d", type);
-          return -1;
-        }
+       default:
+         zlog_err ("Unknown RD type %d", type);
+          break;  /* just report */
+      }
 
       p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8;
       memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, 
@@ -348,14 +345,6 @@ prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size)
       snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
       return buf;
     }
-  else if (type == RD_TYPE_EOI)
-    {
-      snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x",
-               pnt[1], /* LHI */
-               pnt[2], pnt[3], pnt[4], pnt[5], pnt[6], pnt[7]); /* MAC */
-      return buf;
-    }
-
   return NULL;
 }
 
index 4e9b317b71bdcfe412c83a9d860bea32bf2c28d4..3299b9cb9a0474cd6e48d735e1cd4de9e9305325 100644 (file)
@@ -24,7 +24,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #define RD_TYPE_AS      0
 #define RD_TYPE_IP      1
 #define RD_TYPE_AS4     2
-#define RD_TYPE_EOI    0xff00
 
 #define RD_ADDRSTRLEN  28
 
index 11b6919bf2718b84301b1a8e29a74e703976772e..3018d074fc5b67eac24fa61cf380d937f09877cc 100644 (file)
@@ -2369,6 +2369,7 @@ route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
     
       /* Set next hop value. */ 
       (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address;
+      (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4;
     }
 
   return RMAP_OKAY;
index 9577d1b19e20f4d2ddcd873ff2c1e0bc0e0580e4..63f88e932e02009138e5c799387af2b7023ee7bb 100644 (file)
@@ -666,7 +666,8 @@ subgroup_update_packet (struct update_subgroup *subgrp)
 
       space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
                         BGP_MAX_PACKET_SIZE_OVERFLOW;
-      space_needed = BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen);
+      space_needed = BGP_NLRI_LENGTH +
+                     bgp_packet_mpattr_prefix_size (afi, safi, &rn->p);
 
       /* When remaining space can't include NLRI and it's length.  */
       if (space_remaining < space_needed)
@@ -675,10 +676,18 @@ subgroup_update_packet (struct update_subgroup *subgrp)
       /* If packet is empty, set attribute. */
       if (stream_empty (s))
        {
+         struct prefix_rd *prd = NULL;
+         u_char *tag = NULL;
          struct peer *from = NULL;
 
+         if (rn->prn)
+           prd = (struct prefix_rd *) &rn->prn->p;
          if (binfo)
-           from = binfo->peer;
+            {
+              from = binfo->peer;
+              if (binfo->extra)
+                tag = binfo->extra->tag;
+            }
 
          /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
           * one byte message type.
@@ -701,8 +710,8 @@ subgroup_update_packet (struct update_subgroup *subgrp)
          /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
          total_attr_len = bgp_packet_attribute (NULL, peer, s,
                                                 adv->baa->attr, &vecarr,
-                                                NULL, afi, safi,
-                                                from, NULL, NULL, 0, 0);
+                                                &rn->p, afi, safi,
+                                                from, prd, tag, 0, 0);
 
           space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
                             BGP_MAX_PACKET_SIZE_OVERFLOW;