diff options
author | Josh Bailey <joshb@google.com> | 2011-07-20 20:47:07 -0700 |
---|---|---|
committer | Josh Bailey <joshb@google.com> | 2011-07-20 20:47:07 -0700 |
commit | 8196f13d2ab7f3b09150c00328228f90391acb7c (patch) | |
tree | 18c0dcfac4f07cc4cf532cd134a41cfd1d03bc55 | |
parent | de8d5dff1523bb9fe47d54f31c9e5322bd805b44 (diff) |
bgpd: Modify the BGP to zebra route announcement to support multipath
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
-rw-r--r-- | bgpd/bgp_main.c | 4 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 9 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 46 | ||||
-rw-r--r-- | bgpd/bgp_zebra.h | 4 |
4 files changed, 56 insertions, 7 deletions
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 1a460c6b..e5fa79d6 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -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) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ec17dc61..f3e46221 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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); } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index f3baeee0..6c21230a 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -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" /* 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); } diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 5172cb8a..461255e3 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -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, |