summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2015-05-19 17:24:44 -0700
committerDonald Sharp <sharpd@cumulusnetworks.com>2015-05-19 17:24:44 -0700
commit431aa9f906144968a9ca6c127da292f46ffa242e (patch)
tree6df913ebd816eab27400538fb9a4e2846b152fa8
parentd291fcf1c9ea29d112fbd4e7daf90127efd48d5e (diff)
Enable support for BGP IPV6 multipath.
Signed-off-by: Ayan Banerjee <ayan@cumulusnetworks.com> Signed-off-by: Dinesh G Dutt <ddutt@cumulusnetworks.com> Reviewed-by: Scott Feldman <sfeldma@cumulusnetworks.com>
-rw-r--r--bgpd/bgp_main.c2
-rw-r--r--bgpd/bgp_vty.c6
-rw-r--r--bgpd/bgp_zebra.c130
-rw-r--r--bgpd/bgp_zebra.h2
4 files changed, 120 insertions, 20 deletions
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 5026b5eaa4..b0ba06fd6e 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -301,6 +301,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 a818fe7a86..22d5c64075 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -9175,12 +9175,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 f18d916f18..4e02eeb470 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
@@ -668,6 +669,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;
@@ -688,26 +690,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.flags = flags;
nexthop = &info->attr->nexthop;
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
@@ -722,7 +725,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);
@@ -756,16 +759,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. */
@@ -796,6 +829,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.flags = flags;
@@ -803,11 +892,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;
@@ -1100,4 +1189,5 @@ bgp_zebra_init (void)
if_init ();
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 80991930f3..466758ec3d 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);