mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 01:15:12 +00:00
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>
This commit is contained in:
parent
d291fcf1c9
commit
431aa9f906
@ -301,6 +301,8 @@ bgp_exit (int status)
|
|||||||
zclient_free (zlookup);
|
zclient_free (zlookup);
|
||||||
if (bgp_nexthop_buf)
|
if (bgp_nexthop_buf)
|
||||||
stream_free (bgp_nexthop_buf);
|
stream_free (bgp_nexthop_buf);
|
||||||
|
if (bgp_ifindices_buf)
|
||||||
|
stream_free (bgp_ifindices_buf);
|
||||||
|
|
||||||
/* reverse bgp_master_init */
|
/* reverse bgp_master_init */
|
||||||
if (master)
|
if (master)
|
||||||
|
@ -9175,12 +9175,18 @@ bgp_vty_init (void)
|
|||||||
install_element (BGP_IPV4_NODE, &bgp_maxpaths_cmd);
|
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_cmd);
|
||||||
install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_arg_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, &bgp_maxpaths_ibgp_cmd);
|
||||||
install_element (BGP_NODE, &no_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_NODE, &no_bgp_maxpaths_ibgp_arg_cmd);
|
||||||
install_element (BGP_IPV4_NODE, &bgp_maxpaths_ibgp_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_cmd);
|
||||||
install_element (BGP_IPV4_NODE, &no_bgp_maxpaths_ibgp_arg_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. */
|
/* "timers bgp" commands. */
|
||||||
install_element (BGP_NODE, &bgp_timers_cmd);
|
install_element (BGP_NODE, &bgp_timers_cmd);
|
||||||
|
128
bgpd/bgp_zebra.c
128
bgpd/bgp_zebra.c
@ -45,6 +45,7 @@ struct in_addr router_id_zebra;
|
|||||||
|
|
||||||
/* Growable buffer for nexthops sent to zebra */
|
/* Growable buffer for nexthops sent to zebra */
|
||||||
struct stream *bgp_nexthop_buf = NULL;
|
struct stream *bgp_nexthop_buf = NULL;
|
||||||
|
struct stream *bgp_ifindices_buf = NULL;
|
||||||
|
|
||||||
/* Router-id update message from zebra. */
|
/* Router-id update message from zebra. */
|
||||||
static int
|
static int
|
||||||
@ -668,6 +669,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
|
|||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
struct bgp_info *mpinfo;
|
struct bgp_info *mpinfo;
|
||||||
size_t oldsize, newsize;
|
size_t oldsize, newsize;
|
||||||
|
u_int32_t nhcount;
|
||||||
|
|
||||||
if (zclient->sock < 0)
|
if (zclient->sock < 0)
|
||||||
return;
|
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))
|
|| CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
|
||||||
SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
|
SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
|
||||||
|
|
||||||
/* resize nexthop buffer size if necessary */
|
nhcount = 1 + bgp_info_mpath_count (info);
|
||||||
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)
|
if (p->family == AF_INET)
|
||||||
{
|
{
|
||||||
struct zapi_ipv4 api;
|
struct zapi_ipv4 api;
|
||||||
struct in_addr *nexthop;
|
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;
|
api.flags = flags;
|
||||||
nexthop = &info->attr->nexthop;
|
nexthop = &info->attr->nexthop;
|
||||||
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
|
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.message = 0;
|
||||||
api.safi = safi;
|
api.safi = safi;
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
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.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
|
||||||
api.ifindex_num = 0;
|
api.ifindex_num = 0;
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
|
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
|
||||||
@ -756,12 +759,42 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
|
|||||||
(struct prefix_ipv4 *) p, &api);
|
(struct prefix_ipv4 *) p, &api);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|
||||||
/* We have to think about a IPv6 link-local address curse. */
|
/* We have to think about a IPv6 link-local address curse. */
|
||||||
if (p->family == AF_INET6)
|
if (p->family == AF_INET6)
|
||||||
{
|
{
|
||||||
unsigned int ifindex;
|
unsigned int ifindex;
|
||||||
struct in6_addr *nexthop;
|
struct in6_addr *nexthop;
|
||||||
struct zapi_ipv6 api;
|
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;
|
ifindex = 0;
|
||||||
nexthop = NULL;
|
nexthop = NULL;
|
||||||
@ -796,6 +829,62 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
|
|||||||
else if (info->peer->nexthop.ifp)
|
else if (info->peer->nexthop.ifp)
|
||||||
ifindex = info->peer->nexthop.ifp->ifindex;
|
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. */
|
/* Make Zebra API structure. */
|
||||||
api.flags = flags;
|
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.message = 0;
|
||||||
api.safi = safi;
|
api.safi = safi;
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = 1;
|
api.nexthop_num = valid_nh_count;
|
||||||
api.nexthop = &nexthop;
|
api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
|
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
|
||||||
api.ifindex_num = 1;
|
api.ifindex_num = valid_nh_count;
|
||||||
api.ifindex = &ifindex;
|
api.ifindex = (unsigned int *)STREAM_DATA (bgp_ifindices_buf);
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
|
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
|
||||||
api.metric = info->attr->med;
|
api.metric = info->attr->med;
|
||||||
|
|
||||||
@ -1100,4 +1189,5 @@ bgp_zebra_init (void)
|
|||||||
if_init ();
|
if_init ();
|
||||||
|
|
||||||
bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
|
bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
|
||||||
|
bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,10 @@ Boston, MA 02111-1307, USA. */
|
|||||||
#define _QUAGGA_BGP_ZEBRA_H
|
#define _QUAGGA_BGP_ZEBRA_H
|
||||||
|
|
||||||
#define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *))
|
#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_nexthop_buf;
|
||||||
|
extern struct stream *bgp_ifindices_buf;
|
||||||
|
|
||||||
extern void bgp_zebra_init (void);
|
extern void bgp_zebra_init (void);
|
||||||
extern int bgp_if_update_all (void);
|
extern int bgp_if_update_all (void);
|
||||||
|
Loading…
Reference in New Issue
Block a user