#include "memory.h"
#include "lib/json.h"
#include "lib/bfd.h"
+#include "filter.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_mpath.h"
#include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_nht.h"
+#include "bgpd/bgp_bfd.h"
+#if ENABLE_BGP_VNC
+# include "bgpd/rfapi/rfapi_backend.h"
+# include "bgpd/rfapi/vnc_export_bgp.h"
+#endif
/* All information about zebra. */
struct zclient *zclient = NULL;
return 1;
}
+int zclient_num_connects;
+
/* Router-id update message from zebra. */
static int
bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
vrf_id_t vrf_id)
{
struct prefix router_id;
- struct listnode *node, *nnode;
- struct bgp *bgp;
zebra_router_id_update_read(zclient->ibuf,&router_id);
zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf);
}
- if (vrf_id == VRF_DEFAULT)
- {
- /* Router-id change for default VRF has to also update all views. */
- for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
- {
- if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
- continue;
-
- bgp->router_id_zebra = router_id.u.prefix4;
-
- if (!bgp->router_id_static.s_addr)
- bgp_router_id_set (bgp, &router_id.u.prefix4);
- }
- }
- else
- {
- bgp = bgp_lookup_by_vrf_id (vrf_id);
- if (bgp)
- {
- bgp->router_id_zebra = router_id.u.prefix4;
-
- if (!bgp->router_id_static.s_addr)
- bgp_router_id_set (bgp, &router_id.u.prefix4);
- }
- }
-
+ bgp_router_id_zebra_bump (vrf_id, &router_id);
return 0;
}
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
{
+#if defined(HAVE_CUMULUS)
+ /* Take down directly connected EBGP peers as well as 1-hop BFD
+ * tracked (directly connected) IBGP peers.
+ */
+ if ((peer->ttl != 1) && (peer->gtsm_hops != 1) &&
+ (!peer->bfd_info || bgp_bfd_is_peer_multihop(peer)))
+#else
+ /* Take down directly connected EBGP peers */
if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
+#endif
continue;
if (ifp == peer->nexthop.ifp)
/* Type, flags, message. */
api.type = stream_getc (s);
api.instance = stream_getw (s);
- api.flags = stream_getc (s);
+ api.flags = stream_getl (s);
api.message = stream_getc (s);
/* IPv4 prefix. */
memset (&p, 0, sizeof (struct prefix_ipv4));
p.family = AF_INET;
- p.prefixlen = stream_getc (s);
+ p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (s));
stream_get (&p.prefix, s, PSIZE (p.prefixlen));
/* Nexthop, ifindex, distance, metric. */
api.metric = 0;
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
- api.tag = stream_getw (s);
+ api.tag = stream_getl (s);
else
api.tag = 0;
if (bgp_debug_zebra((struct prefix *)&p))
{
char buf[2][INET_ADDRSTRLEN];
- zlog_debug("Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %d",
+ zlog_debug("Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %"ROUTE_TAG_PRI,
vrf_id,
zebra_route_string(api.type), api.instance,
inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
{
char buf[2][INET_ADDRSTRLEN];
zlog_debug("Rx IPv4 route delete VRF %u %s[%d] %s/%d "
- "nexthop %s metric %u tag %d",
+ "nexthop %s metric %u tag %"ROUTE_TAG_PRI,
vrf_id,
zebra_route_string(api.type), api.instance,
inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
/* Type, flags, message. */
api.type = stream_getc (s);
api.instance = stream_getw (s);
- api.flags = stream_getc (s);
+ api.flags = stream_getl (s);
api.message = stream_getc (s);
/* IPv6 prefix. */
memset (&p, 0, sizeof (struct prefix_ipv6));
p.family = AF_INET6;
- p.prefixlen = stream_getc (s);
+ p.prefixlen = MIN(IPV6_MAX_PREFIXLEN, stream_getc (s));
stream_get (&p.prefix, s, PSIZE (p.prefixlen));
/* Nexthop, ifindex, distance, metric. */
api.metric = 0;
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG))
- api.tag = stream_getw (s);
+ api.tag = stream_getl (s);
else
api.tag = 0;
if (bgp_debug_zebra((struct prefix *)&p))
{
char buf[2][INET6_ADDRSTRLEN];
- zlog_debug("Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %d",
+ zlog_debug("Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %"ROUTE_TAG_PRI,
vrf_id,
zebra_route_string(api.type), api.instance,
inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
{
char buf[2][INET6_ADDRSTRLEN];
zlog_debug("Rx IPv6 route delete VRF %u %s[%d] %s/%d "
- "nexthop %s metric %u tag %d",
+ "nexthop %s metric %u tag %"ROUTE_TAG_PRI,
vrf_id,
zebra_route_string(api.type), api.instance,
inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
#ifdef HAVE_IPV6
struct interface *
-if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id)
+if_lookup_by_ipv6 (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id)
{
struct listnode *ifnode;
struct listnode *cnode;
if (cp->family == AF_INET6)
if (prefix_match (cp, (struct prefix *)&p))
{
- if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6.s6_addr32[0]))
+ if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6))
{
if (ifindex == ifp->ifindex)
return ifp;
}
struct interface *
-if_lookup_by_ipv6_exact (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id)
+if_lookup_by_ipv6_exact (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id)
{
struct listnode *ifnode;
struct listnode *cnode;
/* If both global and link-local address present. */
if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
{
- /* Workaround for Cisco's nexthop bug. */
- if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
- && info->peer->su_remote->sa.sa_family == AF_INET6)
- nexthop = &info->peer->su_remote->sin6.sin6_addr;
+ /* Check if route-map is set to prefer global over link-local */
+ if (info->attr->extra->mp_nexthop_prefer_global)
+ nexthop = &info->attr->extra->mp_nexthop_global;
else
- nexthop = &info->attr->extra->mp_nexthop_local;
+ {
+ /* Workaround for Cisco's nexthop bug. */
+ if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
+ && info->peer->su_remote->sa.sa_family == AF_INET6)
+ nexthop = &info->peer->su_remote->sin6.sin6_addr;
+ else
+ nexthop = &info->attr->extra->mp_nexthop_local;
+ }
}
return nexthop;
bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
afi_t afi, safi_t safi)
{
- int flags;
+ u_int32_t flags;
u_char distance;
struct peer *peer;
struct bgp_info *mpinfo;
u_int32_t nhcount, metric;
struct bgp_info local_info;
struct bgp_info *info_cp = &local_info;
- u_short tag;
+ route_tag_t tag;
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
* know of this instance.
api.tag = tag;
}
- distance = bgp_distance_apply (p, info, bgp);
-
+ distance = bgp_distance_apply (p, info, afi, safi, bgp);
if (distance)
{
SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
if (bgp_debug_zebra(p))
{
int i;
- zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %d"
+ zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI
" count %d", (valid_nh_count ? "add":"delete"),
bgp->vrf_id,
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
if (p->family == AF_INET6 ||
(p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)))
{
- unsigned int ifindex;
+ ifindex_t ifindex;
struct in6_addr *nexthop;
struct zapi_ipv6 api;
int valid_nh_count = 0;
if (!ifindex)
{
if (info->peer->conf_if || info->peer->ifname)
- ifindex = if_nametoindex (info->peer->conf_if ? info->peer->conf_if : info->peer->ifname);
+ ifindex = ifname2ifindex_vrf (info->peer->conf_if ? info->peer->conf_if :
+ info->peer->ifname, bgp->vrf_id);
else if (info->peer->nexthop.ifp)
ifindex = info->peer->nexthop.ifp->ifindex;
}
if (!ifindex)
{
if (mpinfo->peer->conf_if || mpinfo->peer->ifname)
- ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname);
+ ifindex = ifname2ifindex_vrf (mpinfo->peer->conf_if ? mpinfo->peer->conf_if :
+ mpinfo->peer->ifname, bgp->vrf_id);
else if (mpinfo->peer->nexthop.ifp)
ifindex = mpinfo->peer->nexthop.ifp->ifindex;
}
api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
api.ifindex_num = valid_nh_count;
- api.ifindex = (unsigned int *)STREAM_DATA (bgp_ifindices_buf);
+ api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = metric;
api.tag = 0;
api.tag = tag;
}
+ distance = bgp_distance_apply (p, info, afi, safi, bgp);
+ if (distance)
+ {
+ SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
+ api.distance = distance;
+ }
+
if (p->family == AF_INET)
{
if (bgp_debug_zebra(p))
{
int i;
- zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %d",
+ zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI,
valid_nh_count ? "add" : "delete", bgp->vrf_id,
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag);
if (bgp_debug_zebra(p))
{
int i;
- zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %d",
+ zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI,
valid_nh_count ? "add" : "delete", bgp->vrf_id,
inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag);
void
bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
{
- int flags;
+ u_int32_t flags;
struct peer *peer;
peer = info->peer;
if (bgp_debug_zebra(p))
{
char buf[2][INET_ADDRSTRLEN];
- zlog_debug("Tx IPv4 route delete VRF %u %s/%d metric %u tag %d",
+ zlog_debug("Tx IPv4 route delete VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI,
peer->bgp->vrf_id,
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag);
if (bgp_debug_zebra(p))
{
char buf[2][INET6_ADDRSTRLEN];
- zlog_debug("Tx IPv6 route delete VRF %u %s/%d metric %u tag %d",
+ zlog_debug("Tx IPv6 route delete VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI,
peer->bgp->vrf_id,
inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag);
if (red)
{
listnode_delete(bgp->redist[afi][type], red);
+ XFREE (MTYPE_BGP_REDIST, red);
if (!bgp->redist[afi][type]->count)
{
list_free(bgp->redist[afi][type]);
if (vrf_bitmap_check (zclient->redist[afi][type], bgp->vrf_id))
return CMD_WARNING;
+#if ENABLE_BGP_VNC
+ if (bgp->vrf_id == VRF_DEFAULT &&
+ type == ZEBRA_ROUTE_VNC_DIRECT) {
+ vnc_export_bgp_enable(bgp, afi); /* only enables if mode bits cfg'd */
+ }
+#endif
+
vrf_bitmap_set (zclient->redist[afi][type], bgp->vrf_id);
}
red->redist_metric_flag = 1;
red->redist_metric = metric;
- for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) {
- for (ri = rn->info; ri; ri = ri->next) {
- if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE && ri->type == type &&
- ri->instance == red->instance) {
- ri->attr->med = red->redist_metric;
- bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
- bgp_process(bgp, rn, afi, SAFI_UNICAST);
- }
+ for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn))
+ {
+ for (ri = rn->info; ri; ri = ri->next)
+ {
+ if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE &&
+ ri->type == type &&
+ ri->instance == red->instance)
+ {
+ struct attr *old_attr;
+ struct attr new_attr;
+ struct attr_extra new_extra;
+
+ new_attr.extra = &new_extra;
+ bgp_attr_dup (&new_attr, ri->attr);
+ new_attr.med = red->redist_metric;
+ old_attr = ri->attr;
+ ri->attr = bgp_attr_intern (&new_attr);
+ bgp_attr_unintern (&old_attr);
+
+ bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
+ bgp_process(bgp, rn, afi, SAFI_UNICAST);
+ }
+ }
}
- }
return 1;
}
vrf_bitmap_unset (zclient->redist[afi][type], bgp->vrf_id);
}
+#if ENABLE_BGP_VNC
+ if (bgp->vrf_id == VRF_DEFAULT &&
+ type == ZEBRA_ROUTE_VNC_DIRECT) {
+ vnc_export_bgp_disable(bgp, afi);
+ }
+#endif
+
if (bgp_install_info_to_zebra (bgp))
{
/* Send distribute delete message to zebra. */
return CMD_SUCCESS;
}
+/* Update redistribute vrf bitmap during triggers like
+ restart networking or delete/add VRFs */
+void
+bgp_update_redist_vrf_bitmaps (struct bgp *bgp, vrf_id_t old_vrf_id)
+{
+ int i;
+ afi_t afi;
+
+ for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ if (vrf_bitmap_check (zclient->redist[afi][i], old_vrf_id))
+ {
+ vrf_bitmap_unset (zclient->redist[afi][i], old_vrf_id);
+ vrf_bitmap_set (zclient->redist[afi][i], bgp->vrf_id);
+ }
+ return;
+}
+
void
bgp_zclient_reset (void)
{
{
struct bgp *bgp;
+ zclient_num_connects++; /* increment even if not responding */
+
/* At this point, we may or may not have BGP instances configured, but
* we're only interested in the default VRF (others wouldn't have learnt
* the VRF from Zebra yet.)
void
bgp_zebra_init (struct thread_master *master)
{
+ zclient_num_connects = 0;
+
/* Set default values. */
zclient = zclient_new (master);
zclient_init (zclient, ZEBRA_ROUTE_BGP, 0);
zclient->interface_nbr_address_add = bgp_interface_nbr_address_add;
zclient->interface_nbr_address_delete = bgp_interface_nbr_address_delete;
zclient->interface_vrf_update = bgp_interface_vrf_update;
- zclient->ipv4_route_add = zebra_read_ipv4;
- zclient->ipv4_route_delete = zebra_read_ipv4;
zclient->redistribute_route_ipv4_add = zebra_read_ipv4;
zclient->redistribute_route_ipv4_del = zebra_read_ipv4;
zclient->interface_up = bgp_interface_up;
zclient->interface_down = bgp_interface_down;
- zclient->ipv6_route_add = zebra_read_ipv6;
- zclient->ipv6_route_delete = zebra_read_ipv6;
zclient->redistribute_route_ipv6_add = zebra_read_ipv6;
zclient->redistribute_route_ipv6_del = zebra_read_ipv6;
zclient->nexthop_update = bgp_read_nexthop_update;
zclient_free(zclient);
zclient = NULL;
}
+
+int
+bgp_zebra_num_connects(void)
+{
+ return zclient_num_connects;
+}