forked from Mirror/frr
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
This commit is contained in:
parent
de8d5dff15
commit
8196f13d2a
|
@ -35,6 +35,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
#include "routemap.h"
|
#include "routemap.h"
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
#include "plist.h"
|
#include "plist.h"
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
#include "bgpd/bgpd.h"
|
#include "bgpd/bgpd.h"
|
||||||
#include "bgpd/bgp_attr.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_clist.h"
|
||||||
#include "bgpd/bgp_debug.h"
|
#include "bgpd/bgp_debug.h"
|
||||||
#include "bgpd/bgp_filter.h"
|
#include "bgpd/bgp_filter.h"
|
||||||
|
#include "bgpd/bgp_zebra.h"
|
||||||
|
|
||||||
/* bgpd options, we use GNU getopt library. */
|
/* bgpd options, we use GNU getopt library. */
|
||||||
static const struct option longopts[] =
|
static const struct option longopts[] =
|
||||||
|
@ -293,6 +295,8 @@ bgp_exit (int status)
|
||||||
zclient_free (zclient);
|
zclient_free (zclient);
|
||||||
if (zlookup)
|
if (zlookup)
|
||||||
zclient_free (zlookup);
|
zclient_free (zlookup);
|
||||||
|
if (bgp_nexthop_buf)
|
||||||
|
stream_free (bgp_nexthop_buf);
|
||||||
|
|
||||||
/* reverse bgp_master_init */
|
/* reverse bgp_master_init */
|
||||||
if (master)
|
if (master)
|
||||||
|
|
|
@ -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_set_flag (rn, new_select, BGP_INFO_SELECTED);
|
||||||
bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
|
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,
|
bgp_process_announce_selected (rsclient, new_select, rn,
|
||||||
afi, safi);
|
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_set_flag (rn, new_select, BGP_INFO_SELECTED);
|
||||||
bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
|
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);
|
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_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);
|
bgp_zebra_announce (p, old_select, bgp);
|
||||||
|
|
||||||
|
UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
|
||||||
UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
|
UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
|
||||||
return WQ_SUCCESS;
|
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_set_flag (rn, new_select, BGP_INFO_SELECTED);
|
||||||
bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
|
bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
|
||||||
|
UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,15 @@ Boston, MA 02111-1307, USA. */
|
||||||
#include "bgpd/bgp_zebra.h"
|
#include "bgpd/bgp_zebra.h"
|
||||||
#include "bgpd/bgp_fsm.h"
|
#include "bgpd/bgp_fsm.h"
|
||||||
#include "bgpd/bgp_debug.h"
|
#include "bgpd/bgp_debug.h"
|
||||||
|
#include "bgpd/bgp_mpath.h"
|
||||||
|
|
||||||
/* All information about zebra. */
|
/* All information about zebra. */
|
||||||
struct zclient *zclient = NULL;
|
struct zclient *zclient = NULL;
|
||||||
struct in_addr router_id_zebra;
|
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. */
|
/* Router-id update message from zebra. */
|
||||||
static int
|
static int
|
||||||
bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length)
|
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;
|
int flags;
|
||||||
u_char distance;
|
u_char distance;
|
||||||
struct peer *peer;
|
struct peer *peer;
|
||||||
|
struct bgp_info *mpinfo;
|
||||||
|
size_t oldsize, newsize;
|
||||||
|
|
||||||
if (zclient->sock < 0)
|
if (zclient->sock < 0)
|
||||||
return;
|
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))
|
|| 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 */
|
||||||
|
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;
|
||||||
|
@ -672,12 +693,19 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp)
|
||||||
|
|
||||||
api.flags = flags;
|
api.flags = flags;
|
||||||
nexthop = &info->attr->nexthop;
|
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.type = ZEBRA_ROUTE_BGP;
|
||||||
api.message = 0;
|
api.message = 0;
|
||||||
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||||
api.nexthop_num = 1;
|
api.nexthop_num = 1 + bgp_info_mpath_count (info);
|
||||||
api.nexthop = &nexthop;
|
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);
|
||||||
api.metric = info->attr->med;
|
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))
|
if (BGP_DEBUG(zebra, ZEBRA))
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
char buf[2][INET_ADDRSTRLEN];
|
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])),
|
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
|
||||||
p->prefixlen,
|
p->prefixlen,
|
||||||
inet_ntop(AF_INET, nexthop, buf[1], sizeof(buf[1])),
|
inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])),
|
||||||
api.metric);
|
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,
|
zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient,
|
||||||
|
@ -1043,4 +1077,6 @@ bgp_zebra_init (void)
|
||||||
|
|
||||||
/* Interface related init. */
|
/* Interface related init. */
|
||||||
if_init ();
|
if_init ();
|
||||||
|
|
||||||
|
bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,10 @@ Boston, MA 02111-1307, USA. */
|
||||||
#ifndef _QUAGGA_BGP_ZEBRA_H
|
#ifndef _QUAGGA_BGP_ZEBRA_H
|
||||||
#define _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 void bgp_zebra_init (void);
|
||||||
extern int bgp_if_update_all (void);
|
extern int bgp_if_update_all (void);
|
||||||
extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
|
extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
|
||||||
|
|
Loading…
Reference in a new issue