]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Modify the BGP to zebra route announcement to support multipath
authorJosh Bailey <joshb@google.com>
Thu, 21 Jul 2011 03:47:07 +0000 (20:47 -0700)
committerJosh Bailey <joshb@google.com>
Thu, 21 Jul 2011 03:47:07 +0000 (20:47 -0700)
routes. Use a growable buffer (bgp_nexthop_buf) to collect nexthops
that are included in the announcement. Use the BGP_INFO_MULTIPATH_CHG
flag to trigger zebra announcement so zebra will be updated if the
multipath set changes. Display all multipath nexthops in
'debug bgp zebra' output.

* bgpd/bgp_main.c
  * bgp_exit(): Free bgp_nexthop_buf when exiting
* bgpd/bgp_route.c
  * bgp_process_rsclient(): Clear BGP_INFO_MULTIPATH_CHG after processing
  * bgp_process_main(): Check BGP_INFO_MULTIPATH_CHG to trigger zebra
    announcement and clear aftr processing
* bgpd/bgp_zebra.c
  * bgp_nexthop_buf: Growable buffer used to collect nexthops for zebra
    announcement
  * bgp_zebra_announce(): Grow bgp_nexthop_buf if needed. Include
    multipath count in zebra announcement and add all nexthops to
    bgp_nexthop_buf. Pass bgp_nexthop_buf data to zebra announcement.
    Added nexthops to debug output.
  * bgp_zebra_init(): Initialize bgp_nexthop_buf at startup
* bgpd/bgp_zebra.h
  * BGP_NEXTHOP_BUF_SIZE: Default initial bgp_nexthop_buf size has room
    for 8 nexthops

bgpd/bgp_main.c
bgpd/bgp_route.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h

index 1a460c6bbecd7d6814e27c91851df6967de354e3..e5fa79d60e9cafe9a7c2820869a14bc23ab55c2d 100644 (file)
@@ -35,6 +35,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "routemap.h"
 #include "filter.h"
 #include "plist.h"
+#include "stream.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_attr.h"
@@ -47,6 +48,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "bgpd/bgp_clist.h"
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_filter.h"
+#include "bgpd/bgp_zebra.h"
 
 /* bgpd options, we use GNU getopt library. */
 static const struct option longopts[] = 
@@ -293,6 +295,8 @@ bgp_exit (int status)
     zclient_free (zclient);
   if (zlookup)
     zclient_free (zlookup);
+  if (bgp_nexthop_buf)
+    stream_free (bgp_nexthop_buf);
 
   /* reverse bgp_master_init */
   if (master)
index ec17dc61296b29ab22087c7a8aec66c3aec4835a..f3e46221caf0b57a856f10de80bd48bdec731d0b 100644 (file)
@@ -1487,7 +1487,8 @@ bgp_process_rsclient (struct work_queue *wq, void *data)
               {
                 bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
                 bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
-              }
+               UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
+             }
 
             bgp_process_announce_selected (rsclient, new_select, rn,
                                            afi, safi);
@@ -1501,6 +1502,7 @@ bgp_process_rsclient (struct work_queue *wq, void *data)
        {
          bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
          bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
+         UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
        }
       bgp_process_announce_selected (rsclient, new_select, rn, afi, safi);
     }
@@ -1537,9 +1539,11 @@ bgp_process_main (struct work_queue *wq, void *data)
     {
       if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
         {
-          if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED))
+          if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) ||
+             CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG))
             bgp_zebra_announce (p, old_select, bgp);
           
+         UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
           UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
           return WQ_SUCCESS;
         }
@@ -1551,6 +1555,7 @@ bgp_process_main (struct work_queue *wq, void *data)
     {
       bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
       bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
+      UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
     }
 
 
index f3baeee0e6dd19fbe6600083c11f06477db70940..6c21230a041a1a1a2d8d86943a647df089a21b51 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)
@@ -645,6 +649,8 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
   int flags;
   u_char distance;
   struct peer *peer;
+  struct bgp_info *mpinfo;
+  size_t oldsize, newsize;
 
   if (zclient->sock < 0)
     return;
@@ -665,6 +671,21 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
       || 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;
@@ -672,12 +693,19 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
 
       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;
       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;
@@ -692,12 +720,18 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
 
       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, 
@@ -1043,4 +1077,6 @@ bgp_zebra_init (void)
 
   /* Interface related init. */
   if_init ();
+
+  bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
 }
index 5172cb8a5a98e7701b579fa8e31951a8ebc2d190..461255e3935f7c4adbf4f50182075ed0f9488b17 100644 (file)
@@ -21,6 +21,10 @@ Boston, MA 02111-1307, USA.  */
 #ifndef _QUAGGA_BGP_ZEBRA_H
 #define _QUAGGA_BGP_ZEBRA_H
 
+#define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *))
+
+extern struct stream *bgp_nexthop_buf;
+
 extern void bgp_zebra_init (void);
 extern int bgp_if_update_all (void);
 extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,