From: Ayan Banerjee <[email protected]>

Signed-off-by: Ayan Banerjee <[email protected]>
Signed-off-by: Dinesh G Dutt <[email protected]>
Reviewed-by: Scott Feldman <[email protected]>
---
 bgpd/bgp_main.c  |    2 +
 bgpd/bgp_vty.c   |    6 +++
 bgpd/bgp_zebra.c |  130 +++++++++++++++++++++++++++++++++++++++++++++---------
 bgpd/bgp_zebra.h |    2 +
 4 files changed, 120 insertions(+), 20 deletions(-)

diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 7c2988c..13e0dea 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -300,6 +300,8 @@ bgp_exit (int status)
     zclient_free (zlookup);
   if (bgp_nexthop_buf)
     stream_free (bgp_nexthop_buf);
+  if (bgp_ifindices_buf)
+    stream_free (bgp_ifindices_buf);
 
   /* reverse bgp_master_init */
   if (master)
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 4fd255f..3f2c49a 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -9179,12 +9179,18 @@ bgp_vty_init (void)
   install_element (BGP_IPV4_NODE, &bgp_maxpaths_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_arg_cmd);
+  install_element (BGP_IPV6_NODE, &bgp_maxpaths_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_arg_cmd);
   install_element (BGP_NODE, &bgp_maxpaths_ibgp_cmd);
   install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_cmd);
   install_element (BGP_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
   install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_cmd);
   install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
+  install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd);
+  install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
 
   /* "timers bgp" commands. */
   install_element (BGP_NODE, &bgp_timers_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 2616351..5e25da9 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -45,6 +45,7 @@ struct in_addr router_id_zebra;
 
 /* Growable buffer for nexthops sent to zebra */
 struct stream *bgp_nexthop_buf = NULL;
+struct stream *bgp_ifindices_buf = NULL;
 
 /* Router-id update message from zebra. */
 static int
@@ -674,6 +675,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info 
*info, struct bgp *bgp, sa
   struct peer *peer;
   struct bgp_info *mpinfo;
   size_t oldsize, newsize;
+  u_int32_t nhcount;
 
   if (zclient->sock < 0)
     return;
@@ -694,26 +696,27 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info 
*info, struct bgp *bgp, sa
       || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
     SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
 
-  /* resize nexthop buffer size if necessary */
-  if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
-      (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1)))
-    {
-      newsize = (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 
1));
-      newsize = stream_resize (bgp_nexthop_buf, newsize);
-      if (newsize == oldsize)
-       {
-         zlog_err ("can't resize nexthop buffer");
-         return;
-       }
-    }
-
-  stream_reset (bgp_nexthop_buf);
+  nhcount = 1 + bgp_info_mpath_count (info);
 
   if (p->family == AF_INET)
     {
       struct zapi_ipv4 api;
       struct in_addr *nexthop;
 
+      /* resize nexthop buffer size if necessary */
+      if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
+          (sizeof (struct in_addr *) * nhcount))
+        {
+          newsize = (sizeof (struct in_addr *) * nhcount);
+          newsize = stream_resize (bgp_nexthop_buf, newsize);
+          if (newsize == oldsize)
+            {
+                 zlog_err ("can't resize nexthop buffer");
+                 return;
+            }
+        }
+      stream_reset (bgp_nexthop_buf);
+
       api.vrf_id = VRF_DEFAULT;
       api.flags = flags;
       nexthop = &info->attr->nexthop;
@@ -729,7 +732,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info 
*info, struct bgp *bgp, sa
       api.message = 0;
       api.safi = safi;
       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
-      api.nexthop_num = 1 + bgp_info_mpath_count (info);
+      api.nexthop_num = nhcount;
       api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
       api.ifindex_num = 0;
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
@@ -763,16 +766,46 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info 
*info, struct bgp *bgp, sa
                        (struct prefix_ipv4 *) p, &api);
     }
 #ifdef HAVE_IPV6
+
   /* We have to think about a IPv6 link-local address curse. */
   if (p->family == AF_INET6)
     {
       unsigned int ifindex;
       struct in6_addr *nexthop;
       struct zapi_ipv6 api;
+      int valid_nh_count = 0;
+
+      /* resize nexthop buffer size if necessary */
+      if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
+          (sizeof (struct in6_addr *) * nhcount))
+        {
+          newsize = (sizeof (struct in6_addr *) * nhcount);
+          newsize = stream_resize (bgp_nexthop_buf, newsize);
+          if (newsize == oldsize)
+            {
+              zlog_err ("can't resize nexthop buffer");
+              return;
+            }
+        }
+      stream_reset (bgp_nexthop_buf);
+
+      /* resize ifindices buffer size if necessary */
+      if ((oldsize = stream_get_size (bgp_ifindices_buf)) <
+          (sizeof (unsigned int) * nhcount))
+        {
+          newsize = (sizeof (unsigned int) * nhcount);
+          newsize = stream_resize (bgp_ifindices_buf, newsize);
+          if (newsize == oldsize)
+            {
+              zlog_err ("can't resize nexthop buffer");
+              return;
+            }
+        }
+      stream_reset (bgp_ifindices_buf);
 
       ifindex = 0;
       nexthop = NULL;
-      
+
       assert (info->attr->extra);
       
       /* Only global address nexthop exists. */
@@ -803,6 +836,62 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info 
*info, struct bgp *bgp, sa
          else if (info->peer->nexthop.ifp)
            ifindex = info->peer->nexthop.ifp->ifindex;
        }
+      stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
+      stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
+      valid_nh_count++;
+
+      for (mpinfo = bgp_info_mpath_first (info); mpinfo;
+           mpinfo = bgp_info_mpath_next (mpinfo))
+       {
+          /* Only global address nexthop exists. */
+          if (mpinfo->attr->extra->mp_nexthop_len == 16)
+            {
+              nexthop = &mpinfo->attr->extra->mp_nexthop_global;
+            }
+          /* If both global and link-local address present. */
+                 if (mpinfo->attr->extra->mp_nexthop_len == 32)
+            {
+              /* Workaround for Cisco's nexthop bug.  */
+              if (IN6_IS_ADDR_UNSPECIFIED 
(&mpinfo->attr->extra->mp_nexthop_global)
+                  && mpinfo->peer->su_remote->sa.sa_family == AF_INET6)
+                {
+                   nexthop = &mpinfo->peer->su_remote->sin6.sin6_addr;
+                }
+              else
+                {
+                  nexthop = &mpinfo->attr->extra->mp_nexthop_local;
+               }
+
+              if (mpinfo->peer->nexthop.ifp)
+                {
+                  ifindex = mpinfo->peer->nexthop.ifp->ifindex;
+                }
+            }
+             if (nexthop == NULL)
+               {
+                 continue;
+               }
+
+          if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex)
+               {
+                 if (mpinfo->peer->ifname)
+                {
+                   ifindex = if_nametoindex (mpinfo->peer->ifname);
+               }
+                 else if (mpinfo->peer->nexthop.ifp)
+                       {
+                          ifindex = mpinfo->peer->nexthop.ifp->ifindex;
+                       }
+                }
+             if (ifindex == 0)
+               {
+                 continue;
+               }
+
+          stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
+          stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
+          valid_nh_count++;
+       }
 
       /* Make Zebra API structure. */
       api.vrf_id = VRF_DEFAULT;
@@ -811,11 +900,11 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info 
*info, struct bgp *bgp, sa
       api.message = 0;
       api.safi = safi;
       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
-      api.nexthop_num = 1;
-      api.nexthop = &nexthop;
+      api.nexthop_num = valid_nh_count;
+      api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
       SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
-      api.ifindex_num = 1;
-      api.ifindex = &ifindex;
+      api.ifindex_num = valid_nh_count;
+      api.ifindex = (unsigned int *)STREAM_DATA (bgp_ifindices_buf);
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = info->attr->med;
 
@@ -1115,4 +1204,5 @@ bgp_zebra_init (void)
 #endif /* HAVE_IPV6 */
 
   bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
+  bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
 }
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 8099193..466758e 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -22,8 +22,10 @@ Boston, MA 02111-1307, USA.  */
 #define _QUAGGA_BGP_ZEBRA_H
 
 #define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *))
+#define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int))
 
 extern struct stream *bgp_nexthop_buf;
+extern struct stream *bgp_ifindices_buf;
 
 extern void bgp_zebra_init (void);
 extern int bgp_if_update_all (void);
-- 
1.7.10.4


_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to