]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_zebra.c
Merge branch 'quagga' into google-bgp-multipath
[mirror_frr.git] / bgpd / bgp_zebra.c
index 20feba0f49830119b671a4183eac8f7308864328..5c0dbb8871798747ab8d20f3cee883b30a96549c 100644 (file)
@@ -37,11 +37,15 @@ Boston, MA 02111-1307, USA.  */
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_fsm.h"
 #include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_mpath.h"
 \f
 /* All information about zebra. */
 struct zclient *zclient = NULL;
 struct in_addr router_id_zebra;
 
+/* Growable buffer for nexthops sent to zebra */
+struct stream *bgp_nexthop_buf = NULL;
+
 /* Router-id update message from zebra. */
 static int
 bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length)
@@ -648,6 +652,8 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
   int flags;
   u_char distance;
   struct peer *peer;
+  struct bgp_info *mpinfo;
+  size_t oldsize, newsize;
 
   if (zclient->sock < 0)
     return;
@@ -668,6 +674,21 @@ 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);
+
   if (p->family == AF_INET)
     {
       struct zapi_ipv4 api;
@@ -675,13 +696,20 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
 
       api.flags = flags;
       nexthop = &info->attr->nexthop;
+      stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
+      for (mpinfo = bgp_info_mpath_first (info); mpinfo;
+          mpinfo = bgp_info_mpath_next (mpinfo))
+       {
+         nexthop = &mpinfo->attr->nexthop;
+         stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
+       }
 
       api.type = ZEBRA_ROUTE_BGP;
       api.message = 0;
       api.safi = safi;
       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
-      api.nexthop_num = 1;
-      api.nexthop = &nexthop;
+      api.nexthop_num = 1 + bgp_info_mpath_count (info);
+      api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
       api.ifindex_num = 0;
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = info->attr->med;
@@ -696,12 +724,18 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
 
       if (BGP_DEBUG(zebra, ZEBRA))
        {
+         int i;
          char buf[2][INET_ADDRSTRLEN];
-         zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u",
+         zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u"
+                    " count %d",
                     inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
                     p->prefixlen,
-                    inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
-                    api.metric);
+                    inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])),
+                    api.metric, api.nexthop_num);
+         for (i = 1; i < api.nexthop_num; i++)
+           zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s",
+                      i, inet_ntop(AF_INET, api.nexthop[i], buf[1],
+                                   sizeof(buf[1])));
        }
 
       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, 
@@ -1050,4 +1084,6 @@ bgp_zebra_init (void)
 
   /* Interface related init. */
   if_init ();
+
+  bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
 }