summaryrefslogtreecommitdiff
path: root/bgpd/bgp_zebra.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_zebra.c')
-rw-r--r--bgpd/bgp_zebra.c262
1 files changed, 67 insertions, 195 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 66c18c8e57..71a4d4317a 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1222,12 +1222,11 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
u_char distance;
struct peer *peer;
struct bgp_info *mpinfo;
- size_t oldsize, newsize;
- u_int32_t nhcount, metric;
+ u_int32_t metric;
struct bgp_info local_info;
struct bgp_info *info_cp = &local_info;
route_tag_t tag;
- u_int32_t label;
+ mpls_label_t label;
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
* know of this instance.
@@ -1270,87 +1269,26 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
SET_FLAG (flags, ZEBRA_FLAG_INTERNAL);
- nhcount = 1 + bgp_info_mpath_count (info);
-
if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(info->attr))
{
struct zapi_ipv4 api;
struct in_addr *nexthop;
char buf[2][INET_ADDRSTRLEN];
int valid_nh_count = 0;
+ int has_valid_label = 0;
/* 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);
nexthop = NULL;
- /* For labeled unicast, each nexthop has a label too. Resize label
- * buffer, if required.
- */
- if (safi == SAFI_LABELED_UNICAST)
- {
- if ((oldsize = stream_get_size (bgp_label_buf)) <
- (sizeof (unsigned int) * nhcount))
- {
- newsize = (sizeof (unsigned int) * nhcount);
- newsize = stream_resize (bgp_label_buf, newsize);
- if (newsize == oldsize)
- {
- zlog_err ("can't resize label buffer");
- return;
- }
- }
- stream_reset (bgp_label_buf);
- }
-
- /* Metric is currently based on the best-path only. */
- metric = info->attr->med;
+ stream_reset (bgp_label_buf);
if (bgp->table_map[afi][safi].name)
- {
- BGP_INFO_ATTR_BUF_INIT();
-
- /* Copy info and attributes, so the route-map apply doesn't modify the
- BGP route info. */
- BGP_INFO_ATTR_BUF_COPY(info, info_cp);
- if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
- {
- metric = info_cp->attr->med;
- nexthop = &info_cp->attr->nexthop;
-
- if (info_cp->attr->extra)
- tag = info_cp->attr->extra->tag;
- }
- BGP_INFO_ATTR_BUF_FREE(info_cp);
- }
- else
- {
- nexthop = &info->attr->nexthop;
- }
+ BGP_INFO_ATTR_BUF_INIT();
- if (nexthop)
- {
- stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
- valid_nh_count++;
- if (safi == SAFI_LABELED_UNICAST)
- {
- label = label_pton(info->extra->tag);
- stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
- }
- }
-
- for (mpinfo = bgp_info_mpath_first (info); mpinfo;
- mpinfo = bgp_info_mpath_next (mpinfo))
+ /* Metric is currently based on the best-path only */
+ metric = info->attr->med;
+ for (mpinfo = info ; mpinfo; mpinfo = bgp_info_mpath_next (mpinfo))
{
nexthop = NULL;
@@ -1360,22 +1298,29 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
BGP route info. */
BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
- nexthop = &info_cp->attr->nexthop;
+ {
+ if (mpinfo == info)
+ {
+ /* Metric is currently based on the best-path only */
+ metric = info_cp->attr->med;
+ tag = info_cp->attr->extra->tag;
+ }
+ nexthop = &info_cp->attr->nexthop;
+ }
BGP_INFO_ATTR_BUF_FREE(info_cp);
}
else
- {
- nexthop = &mpinfo->attr->nexthop;
- }
+ nexthop = &mpinfo->attr->nexthop;
if (nexthop == NULL)
continue;
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
- if (safi == SAFI_LABELED_UNICAST)
+ if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label))
{
- label = label_pton(mpinfo->extra->tag);
- stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
+ has_valid_label = 1;
+ label = label_pton(&mpinfo->extra->label);
+ stream_put (bgp_label_buf, &label, sizeof (mpls_label_t));
}
valid_nh_count++;
}
@@ -1385,9 +1330,10 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
api.type = ZEBRA_ROUTE_BGP;
api.instance = 0;
api.message = 0;
- api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
+ api.safi = safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- if (safi == SAFI_LABELED_UNICAST)
+
+ if (has_valid_label)
SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
/* Note that this currently only applies to Null0 routes for aggregates.
@@ -1401,7 +1347,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
api.nexthop_num = valid_nh_count;
api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
- if (safi == SAFI_LABELED_UNICAST)
+ if (has_valid_label)
{
api.label_num = valid_nh_count;
api.label = (unsigned int *)STREAM_DATA (bgp_label_buf);
@@ -1441,7 +1387,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
for (i = 0; i < api.nexthop_num; i++)
{
label_buf[0] = '\0';
- if (safi == SAFI_LABELED_UNICAST)
+ if (has_valid_label)
sprintf(label_buf, "label %u", api.label[i]);
zlog_debug(" nhop [%d]: %s %s",
i+1,
@@ -1463,109 +1409,22 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
struct zapi_ipv6 api;
int valid_nh_count = 0;
char buf[2][INET6_ADDRSTRLEN];
+ int has_valid_label = 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);
-
- /* For labeled unicast, each nexthop has a label too. Resize label
- * buffer, if required.
- */
- if (safi == SAFI_LABELED_UNICAST)
- {
- if ((oldsize = stream_get_size (bgp_label_buf)) <
- (sizeof (unsigned int) * nhcount))
- {
- newsize = (sizeof (unsigned int) * nhcount);
- newsize = stream_resize (bgp_label_buf, newsize);
- if (newsize == oldsize)
- {
- zlog_err ("can't resize label buffer");
- return;
- }
- }
- stream_reset (bgp_label_buf);
- }
+ stream_reset (bgp_label_buf);
ifindex = 0;
nexthop = NULL;
assert (info->attr->extra);
- /* Metric is currently based on the best-path only. */
- metric = info->attr->med;
-
if (bgp->table_map[afi][safi].name)
- {
- BGP_INFO_ATTR_BUF_INIT();
-
- /* Copy info and attributes, so the route-map apply doesn't modify the
- BGP route info. */
- BGP_INFO_ATTR_BUF_COPY(info, info_cp);
- if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
- {
- metric = info_cp->attr->med;
- nexthop = bgp_info_to_ipv6_nexthop(info_cp);
-
- if (info_cp->attr->extra)
- tag = info_cp->attr->extra->tag;
- }
- BGP_INFO_ATTR_BUF_FREE(info_cp);
- }
- else
- {
- nexthop = bgp_info_to_ipv6_nexthop(info);
- }
-
- if (nexthop)
- {
- if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
- if (info->peer->nexthop.ifp)
- ifindex = info->peer->nexthop.ifp->ifindex;
-
- if (!ifindex)
- {
- if (info->peer->conf_if || info->peer->ifname)
- ifindex = if_nametoindex (info->peer->conf_if ? info->peer->conf_if : info->peer->ifname);
- 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));
- if (safi == SAFI_LABELED_UNICAST)
- {
- label = label_pton(info->extra->tag);
- stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
- }
- valid_nh_count++;
- }
+ BGP_INFO_ATTR_BUF_INIT();
- for (mpinfo = bgp_info_mpath_first (info); mpinfo;
- mpinfo = bgp_info_mpath_next (mpinfo))
+ metric = info->attr->med;
+ for (mpinfo = info ; mpinfo; mpinfo = bgp_info_mpath_next (mpinfo))
{
ifindex = 0;
nexthop = NULL;
@@ -1576,18 +1435,24 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
BGP route info. */
BGP_INFO_ATTR_BUF_COPY(mpinfo, info_cp);
if (bgp_table_map_apply(bgp->table_map[afi][safi].map, p, info_cp))
- nexthop = bgp_info_to_ipv6_nexthop(info_cp);
+ {
+ if (mpinfo == info)
+ {
+ metric = info_cp->attr->med;
+ tag = info_cp->attr->extra->tag;
+ }
+ nexthop = bgp_info_to_ipv6_nexthop(info_cp);
+ }
BGP_INFO_ATTR_BUF_FREE(info_cp);
}
else
- {
- nexthop = bgp_info_to_ipv6_nexthop(mpinfo);
- }
+ nexthop = bgp_info_to_ipv6_nexthop(mpinfo);
if (nexthop == NULL)
continue;
- if (mpinfo->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+ if ((mpinfo == info) &&
+ mpinfo->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
if (mpinfo->peer->nexthop.ifp)
ifindex = mpinfo->peer->nexthop.ifp->ifindex;
@@ -1603,10 +1468,12 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
- if (safi == SAFI_LABELED_UNICAST)
+
+ if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label))
{
- label = label_pton(mpinfo->extra->tag);
- stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
+ has_valid_label = 1;
+ label = label_pton(&mpinfo->extra->label);
+ stream_put (bgp_label_buf, &label, sizeof (mpls_label_t));
}
valid_nh_count++;
}
@@ -1617,9 +1484,10 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
api.type = ZEBRA_ROUTE_BGP;
api.instance = 0;
api.message = 0;
- api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
+ api.safi = safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- if (safi == SAFI_LABELED_UNICAST)
+
+ if (has_valid_label)
SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
/* Note that this currently only applies to Null0 routes for aggregates.
@@ -1636,7 +1504,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
api.ifindex_num = valid_nh_count;
api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
- if (safi == SAFI_LABELED_UNICAST)
+ if (has_valid_label)
{
api.label_num = valid_nh_count;
api.label = (unsigned int *)STREAM_DATA (bgp_label_buf);
@@ -1676,7 +1544,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
for (i = 0; i < api.nexthop_num; i++)
{
label_buf[0] = '\0';
- if (safi == SAFI_LABELED_UNICAST)
+ if (has_valid_label)
sprintf(label_buf, "label %u", api.label[i]);
zlog_debug(" nhop [%d]: %s if %s %s",
i+1,
@@ -1707,7 +1575,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
for (i = 0; i < api.nexthop_num; i++)
{
label_buf[0] = '\0';
- if (safi == SAFI_LABELED_UNICAST)
+ if (has_valid_label)
sprintf(label_buf, "label %u", api.label[i]);
zlog_debug(" nhop [%d]: %s if %s %s",
i+1,
@@ -1793,10 +1661,8 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
api.type = ZEBRA_ROUTE_BGP;
api.instance = 0;
api.message = 0;
- api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
+ api.safi = safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- if (safi == SAFI_LABELED_UNICAST)
- SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
api.nexthop_num = 0;
api.nexthop = NULL;
api.label_num = 0;
@@ -1836,10 +1702,8 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
api.type = ZEBRA_ROUTE_BGP;
api.instance = 0;
api.message = 0;
- api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
+ api.safi = safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- if (safi == SAFI_LABELED_UNICAST)
- SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
api.nexthop_num = 0;
api.nexthop = NULL;
api.ifindex_num = 0;
@@ -2270,14 +2134,22 @@ bgp_zebra_init (struct thread_master *master)
zclient->import_check_update = bgp_read_import_check_update;
zclient->fec_update = bgp_read_fec_update;
- bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
- bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
- bgp_label_buf = stream_new(BGP_LABEL_BUF_SIZE);
+ bgp_nexthop_buf = stream_new(multipath_num * sizeof (struct in6_addr));
+ bgp_ifindices_buf = stream_new(multipath_num * sizeof (unsigned int));
+ bgp_label_buf = stream_new(multipath_num * sizeof (unsigned int));
}
void
bgp_zebra_destroy(void)
{
+
+ if (bgp_nexthop_buf)
+ stream_free (bgp_nexthop_buf);
+ if (bgp_ifindices_buf)
+ stream_free (bgp_ifindices_buf);
+ if (bgp_label_buf)
+ stream_free (bgp_label_buf);
+
if (zclient == NULL)
return;
zclient_stop(zclient);