summaryrefslogtreecommitdiff
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_main.c4
-rw-r--r--bgpd/bgp_route.c9
-rw-r--r--bgpd/bgp_zebra.c46
-rw-r--r--bgpd/bgp_zebra.h4
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,