summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfdd/bfd.c41
-rw-r--r--bfdd/bfd.h20
-rw-r--r--bfdd/bfd_packet.c49
-rw-r--r--bfdd/bsd.c64
-rw-r--r--bfdd/linux.c58
-rw-r--r--bfdd/ptm_adapter.c49
-rw-r--r--bgpd/bgp_attr.c2
-rw-r--r--bgpd/bgp_attr.h8
-rw-r--r--bgpd/bgp_attr_evpn.c4
-rw-r--r--bgpd/bgp_clist.c113
-rw-r--r--bgpd/bgp_clist.h15
-rw-r--r--bgpd/bgp_flowspec_util.c25
-rw-r--r--bgpd/bgp_flowspec_util.h4
-rw-r--r--bgpd/bgp_keepalives.c6
-rw-r--r--bgpd/bgp_mac.c354
-rw-r--r--bgpd/bgp_mac.h41
-rw-r--r--bgpd/bgp_mplsvpn.c5
-rw-r--r--bgpd/bgp_nht.c11
-rw-r--r--bgpd/bgp_pbr.c2
-rw-r--r--bgpd/bgp_pbr.h3
-rw-r--r--bgpd/bgp_route.c18
-rw-r--r--bgpd/bgp_routemap.c65
-rw-r--r--bgpd/bgp_vty.c28
-rw-r--r--bgpd/bgp_zebra.c9
-rw-r--r--bgpd/bgpd.c3
-rw-r--r--bgpd/bgpd.h3
-rw-r--r--bgpd/subdir.am2
-rw-r--r--doc/developer/building-frr-for-freebsd10.rst4
-rw-r--r--doc/developer/building-frr-for-freebsd11.rst4
-rw-r--r--doc/user/bgp.rst7
-rw-r--r--eigrpd/eigrp_zebra.c2
-rw-r--r--isisd/isis_zebra.c4
-rw-r--r--lib/frr_pthread.c30
-rw-r--r--lib/frr_pthread.h9
-rw-r--r--lib/lib_errors.c8
-rw-r--r--lib/northbound.c11
-rw-r--r--lib/northbound_cli.c2
-rw-r--r--lib/prefix.c20
-rw-r--r--lib/prefix.h32
-rw-r--r--lib/table.c2
-rw-r--r--lib/thread.c7
-rw-r--r--lib/zclient.c68
-rw-r--r--lib/zclient.h7
-rw-r--r--ospf6d/ospf6_zebra.c3
-rw-r--r--ospfd/ospf_flood.c5
-rw-r--r--ospfd/ospf_zebra.c12
-rw-r--r--sharpd/sharp_vty.c36
-rw-r--r--sharpd/sharp_zebra.c41
-rw-r--r--staticd/static_nht.c83
-rw-r--r--zebra/connected.c8
-rw-r--r--zebra/connected.h8
-rw-r--r--zebra/main.c5
-rw-r--r--zebra/redistribute.c38
-rw-r--r--zebra/rib.h10
-rw-r--r--zebra/zapi_msg.c5
-rw-r--r--zebra/zebra_dplane.c56
-rw-r--r--zebra/zebra_dplane.h56
-rw-r--r--zebra/zebra_netns_notify.c19
-rw-r--r--zebra/zebra_ns.c6
-rw-r--r--zebra/zebra_ns.h2
-rw-r--r--zebra/zebra_rib.c247
-rw-r--r--zebra/zebra_router.c21
-rw-r--r--zebra/zebra_router.h2
-rw-r--r--zebra/zebra_vrf.c16
-rw-r--r--zebra/zebra_vty.c16
-rw-r--r--zebra/zebra_vxlan.c29
-rw-r--r--zebra/zserv.c10
-rw-r--r--zebra/zserv.h2
68 files changed, 1345 insertions, 610 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 814366f320..df263a91c9 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -540,6 +540,7 @@ static void bfd_session_free(struct bfd_session *bs)
struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
{
struct bfd_session *bfd, *l_bfd;
+ struct interface *ifp = NULL;
int psock;
/* check to see if this needs a new session */
@@ -553,6 +554,24 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
}
/*
+ * No session found, we have to allocate a new one.
+ *
+ * First a few critical checks:
+ *
+ * * Check that the specified interface exists.
+ * * Attempt to create the UDP socket (might fail if we exceed
+ * our limits).
+ */
+ if (bpc->bpc_has_localif) {
+ ifp = if_lookup_by_name(bpc->bpc_localif, VRF_DEFAULT);
+ if (ifp == NULL) {
+ log_error(
+ "session-new: specified interface doesn't exists.");
+ return NULL;
+ }
+ }
+
+ /*
* Get socket for transmitting control packets. Note that if we
* could use the destination port (3784) for the source
* port we wouldn't need a socket per session.
@@ -574,19 +593,21 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
return NULL;
}
- if (bpc->bpc_has_localif && !bpc->bpc_mhop) {
- bfd->ifindex = ptm_bfd_fetch_ifindex(bpc->bpc_localif);
- ptm_bfd_fetch_local_mac(bpc->bpc_localif, bfd->local_mac);
- }
+ if (bpc->bpc_has_localif && !bpc->bpc_mhop)
+ bfd->ifp = ifp;
if (bpc->bpc_ipv4 == false) {
BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6);
/* Set the IPv6 scope id for link-local addresses. */
if (IN6_IS_ADDR_LINKLOCAL(&bpc->bpc_local.sa_sin6.sin6_addr))
- bpc->bpc_local.sa_sin6.sin6_scope_id = bfd->ifindex;
+ bpc->bpc_local.sa_sin6.sin6_scope_id =
+ bfd->ifp != NULL ? bfd->ifp->ifindex
+ : IFINDEX_INTERNAL;
if (IN6_IS_ADDR_LINKLOCAL(&bpc->bpc_peer.sa_sin6.sin6_addr))
- bpc->bpc_peer.sa_sin6.sin6_scope_id = bfd->ifindex;
+ bpc->bpc_peer.sa_sin6.sin6_scope_id =
+ bfd->ifp != NULL ? bfd->ifp->ifindex
+ : IFINDEX_INTERNAL;
}
/* Initialize the session */
@@ -770,10 +791,10 @@ void integer2timestr(uint64_t time, char *buf, size_t buflen)
int rv;
#define MINUTES (60)
-#define HOURS (24 * MINUTES)
-#define DAYS (30 * HOURS)
-#define MONTHS (12 * DAYS)
-#define YEARS (MONTHS)
+#define HOURS (60 * MINUTES)
+#define DAYS (24 * HOURS)
+#define MONTHS (30 * DAYS)
+#define YEARS (12 * MONTHS)
if (time >= YEARS) {
year = time / YEARS;
time -= year * YEARS;
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 3a58a8d53c..a3e5ad1447 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -31,6 +31,7 @@
#include "lib/libfrr.h"
#include "lib/qobj.h"
#include "lib/queue.h"
+#include "lib/vrf.h"
#include "bfdctl.h"
@@ -237,7 +238,7 @@ struct bfd_session {
struct sockaddr_any local_address;
struct sockaddr_any local_ip;
- int ifindex;
+ struct interface *ifp;
uint8_t local_mac[ETHERNET_ADDRESS_LENGTH];
uint8_t peer_mac[ETHERNET_ADDRESS_LENGTH];
@@ -512,7 +513,6 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc);
int ptm_bfd_ses_del(struct bfd_peer_cfg *bpc);
void ptm_bfd_ses_dn(struct bfd_session *bfd, uint8_t diag);
void ptm_bfd_ses_up(struct bfd_session *bfd);
-void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen);
void ptm_bfd_echo_stop(struct bfd_session *bfd, int polling);
void ptm_bfd_echo_start(struct bfd_session *bfd);
void ptm_bfd_xmt_TO(struct bfd_session *bfd, int fbit);
@@ -584,20 +584,4 @@ void bfdd_zclient_stop(void);
int ptm_bfd_notify(struct bfd_session *bs);
-
-/*
- * OS compatibility functions.
- */
-#if defined(BFD_LINUX) || defined(BFD_BSD)
-int ptm_bfd_fetch_ifindex(const char *ifname);
-void ptm_bfd_fetch_local_mac(const char *ifname, uint8_t *mac);
-void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen);
-#endif /* BFD_LINUX || BFD_BSD */
-
-#ifdef BFD_BSD
-ssize_t bsd_echo_sock_read(int sd, uint8_t *buf, ssize_t *buflen,
- struct sockaddr_storage *ss, socklen_t *sslen,
- uint8_t *ttl, uint32_t *id);
-#endif /* BFD_BSD */
-
#endif /* _BFD_H_ */
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 606f739b46..9cfd7e866f 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -241,6 +241,7 @@ ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
size_t vrfnamelen, struct sockaddr_any *local,
struct sockaddr_any *peer)
{
+ struct interface *ifp;
struct cmsghdr *cm;
int ifindex;
ssize_t mlen;
@@ -307,8 +308,14 @@ ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
local->sa_sin.sin_len = sizeof(local->sa_sin);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- fetch_portname_from_ifindex(pi->ipi_ifindex, port,
- portlen);
+
+ ifp = if_lookup_by_index(pi->ipi_ifindex, VRF_DEFAULT);
+ if (ifp == NULL)
+ break;
+
+ if (strlcpy(port, ifp->name, portlen) >= portlen)
+ log_debug(
+ "ipv4-recv: interface name truncated");
break;
}
#endif /* BFD_LINUX */
@@ -345,8 +352,15 @@ ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
/* OS agnostic way of getting interface name. */
if (port[0] == 0) {
ifindex = getsockopt_ifindex(AF_INET, &msghdr);
- if (ifindex > 0)
- fetch_portname_from_ifindex(ifindex, port, portlen);
+ if (ifindex <= 0)
+ return mlen;
+
+ ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+ if (ifp == NULL)
+ return mlen;
+
+ if (strlcpy(port, ifp->name, portlen) >= portlen)
+ log_debug("ipv4-recv: interface name truncated");
}
return mlen;
@@ -357,6 +371,7 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
size_t vrfnamelen, struct sockaddr_any *local,
struct sockaddr_any *peer)
{
+ struct interface *ifp;
struct cmsghdr *cm;
struct in6_pktinfo *pi6 = NULL;
int ifindex = 0;
@@ -413,9 +428,16 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
local->sa_sin6.sin6_len = sizeof(local->sa_sin6);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- fetch_portname_from_ifindex(pi6->ipi6_ifindex,
- port, portlen);
+
ifindex = pi6->ipi6_ifindex;
+ ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+ if (ifp == NULL)
+ break;
+
+ if (strlcpy(port, ifp->name, portlen)
+ >= portlen)
+ log_debug(
+ "ipv6-recv: interface name truncated");
}
}
}
@@ -610,8 +632,8 @@ int bfd_recv_cb(struct thread *t)
* If no interface was detected, save the interface where the
* packet came in.
*/
- if (bfd->ifindex == 0)
- bfd->ifindex = ptm_bfd_fetch_ifindex(port);
+ if (bfd->ifp == NULL)
+ bfd->ifp = if_lookup_by_name(port, VRF_DEFAULT);
/* Log remote discriminator changes. */
if ((bfd->discrs.remote_discr != 0)
@@ -1046,7 +1068,8 @@ int bp_peer_socket(struct bfd_peer_cfg *bpc)
int bp_peer_socketv6(struct bfd_peer_cfg *bpc)
{
- int sd, pcount, ifindex;
+ struct interface *ifp;
+ int sd, pcount;
struct sockaddr_in6 sin6;
static int srcPort = BFD_SRCPORTINIT;
@@ -1076,9 +1099,11 @@ int bp_peer_socketv6(struct bfd_peer_cfg *bpc)
sin6.sin6_len = sizeof(sin6);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
sin6 = bpc->bpc_local.sa_sin6;
- ifindex = ptm_bfd_fetch_ifindex(bpc->bpc_localif);
- if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
- sin6.sin6_scope_id = ifindex;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) {
+ ifp = if_lookup_by_name(bpc->bpc_localif, VRF_DEFAULT);
+ sin6.sin6_scope_id =
+ (ifp != NULL) ? ifp->ifindex : IFINDEX_INTERNAL;
+ }
if (bpc->bpc_has_localif) {
if (bp_bind_dev(sd, bpc->bpc_localif) != 0) {
diff --git a/bfdd/bsd.c b/bfdd/bsd.c
index e0fb340e30..923fbd909e 100644
--- a/bfdd/bsd.c
+++ b/bfdd/bsd.c
@@ -35,70 +35,6 @@
/*
* Definitions.
*/
-int ptm_bfd_fetch_ifindex(const char *ifname)
-{
- return if_nametoindex(ifname);
-}
-
-void ptm_bfd_fetch_local_mac(const char *ifname, uint8_t *mac)
-{
- struct ifaddrs *ifap, *ifa;
- struct if_data *ifi;
- struct sockaddr_dl *sdl;
- size_t maclen;
-
- /* Always clean the target, zeroed macs mean failure. */
- memset(mac, 0, ETHERNET_ADDRESS_LENGTH);
-
- if (getifaddrs(&ifap) != 0)
- return;
-
- for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
- /* Find interface with that name. */
- if (strcmp(ifa->ifa_name, ifname) != 0)
- continue;
- /* Skip non link addresses. We want the MAC address. */
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
-
- sdl = (struct sockaddr_dl *)ifa->ifa_addr;
- ifi = (struct if_data *)ifa->ifa_data;
- /* Skip non ethernet related data. */
- if (ifi->ifi_type != IFT_ETHER)
- continue;
-
- if (sdl->sdl_alen != ETHERNET_ADDRESS_LENGTH)
- log_warning("%s:%d mac address length %d (expected %d)",
- __func__, __LINE__, sdl->sdl_alen,
- ETHERNET_ADDRESS_LENGTH);
-
- maclen = (sdl->sdl_alen > ETHERNET_ADDRESS_LENGTH)
- ? ETHERNET_ADDRESS_LENGTH
- : sdl->sdl_alen;
- memcpy(mac, LLADDR(sdl), maclen);
- break;
- }
-
- freeifaddrs(ifap);
-}
-
-
-/* Was _fetch_portname_from_ifindex() */
-void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen)
-{
- char ifname_tmp[IF_NAMESIZE];
-
- /* Set ifname to empty to signalize failures. */
- memset(ifname, 0, ifnamelen);
-
- if (if_indextoname(ifindex, ifname_tmp) == NULL)
- return;
-
- if (strlcpy(ifname, ifname_tmp, ifnamelen) > ifnamelen)
- log_warning("%s:%d interface name truncated", __func__,
- __LINE__);
-}
-
int bp_bind_dev(int sd, const char *dev)
{
/*
diff --git a/bfdd/linux.c b/bfdd/linux.c
index e260851ddb..3a76b459d7 100644
--- a/bfdd/linux.c
+++ b/bfdd/linux.c
@@ -29,64 +29,6 @@
/*
* Definitions.
*/
-int ptm_bfd_fetch_ifindex(const char *ifname)
-{
- struct ifreq ifr;
-
- if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name))
- > sizeof(ifr.ifr_name))
- log_error("interface-to-index: name truncated ('%s' -> '%s')",
- ifr.ifr_name, ifname);
-
- if (ioctl(bglobal.bg_shop, SIOCGIFINDEX, &ifr) == -1) {
- log_error("interface-to-index: %s translation failed: %s",
- ifname, strerror(errno));
- return -1;
- }
-
- return ifr.ifr_ifindex;
-}
-
-void ptm_bfd_fetch_local_mac(const char *ifname, uint8_t *mac)
-{
- struct ifreq ifr;
-
- if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name))
- > sizeof(ifr.ifr_name))
- log_error("interface-mac: name truncated ('%s' -> '%s')",
- ifr.ifr_name, ifname);
-
- if (ioctl(bglobal.bg_shop, SIOCGIFHWADDR, &ifr) == -1) {
- log_error("interface-mac: %s MAC retrieval failed: %s", ifname,
- strerror(errno));
- return;
- }
-
- memcpy(mac, ifr.ifr_hwaddr.sa_data, ETHERNET_ADDRESS_LENGTH);
-}
-
-
-/* Was _fetch_portname_from_ifindex() */
-void fetch_portname_from_ifindex(int ifindex, char *ifname, size_t ifnamelen)
-{
- struct ifreq ifr;
-
- ifname[0] = 0;
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_ifindex = ifindex;
-
- if (ioctl(bglobal.bg_shop, SIOCGIFNAME, &ifr) == -1) {
- log_error("index-to-interface: index %d failure: %s", ifindex,
- strerror(errno));
- return;
- }
-
- if (strlcpy(ifname, ifr.ifr_name, ifnamelen) >= ifnamelen)
- log_debug("index-to-interface: name truncated '%s' -> '%s'",
- ifr.ifr_name, ifname);
-}
-
int bp_bind_dev(int sd __attribute__((__unused__)),
const char *dev __attribute__((__unused__)))
{
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index f9c7c16fb1..a57167376a 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -189,7 +189,10 @@ int ptm_bfd_notify(struct bfd_session *bs)
stream_putl(msg, ZEBRA_INTERFACE_BFD_DEST_UPDATE);
/* NOTE: Interface is a shortcut to avoid comparing source address. */
- stream_putl(msg, bs->ifindex);
+ if (bs->ifp != NULL)
+ stream_putl(msg, bs->ifp->ifindex);
+ else
+ stream_putl(msg, IFINDEX_INTERNAL);
/* BFD destination prefix information. */
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
@@ -287,6 +290,7 @@ stream_failure:
static int _ptm_msg_read(struct stream *msg, int command,
struct bfd_peer_cfg *bpc, struct ptm_client **pc)
{
+ struct interface *ifp;
uint32_t pid;
uint8_t ttl __attribute__((unused));
size_t ifnamelen;
@@ -393,9 +397,19 @@ static int _ptm_msg_read(struct stream *msg, int command,
*/
if (bpc->bpc_ipv4 == false
&& IN6_IS_ADDR_LINKLOCAL(
- &bpc->bpc_peer.sa_sin6.sin6_addr))
+ &bpc->bpc_peer.sa_sin6.sin6_addr)) {
+ ifp = if_lookup_by_name_all_vrf(
+ bpc->bpc_localif);
+ if (ifp == NULL) {
+ log_error(
+ "ptm-read: interface %s doesn't exists",
+ bpc->bpc_localif);
+ return -1;
+ }
+
bpc->bpc_peer.sa_sin6.sin6_scope_id =
- ptm_bfd_fetch_ifindex(bpc->bpc_localif);
+ ifp->ifindex;
+ }
}
}
@@ -576,9 +590,34 @@ static void bfdd_zebra_connected(struct zclient *zc)
stream_putl(msg, ZEBRA_BFD_DEST_REPLAY);
stream_putw_at(msg, 0, stream_get_endp(msg));
+ /* Ask for interfaces information. */
+ zclient_create_header(msg, ZEBRA_INTERFACE_ADD, VRF_DEFAULT);
+
+ /* Send requests. */
zclient_send_message(zclient);
}
+static int bfdd_interface_update(int cmd, struct zclient *zc, uint16_t len,
+ vrf_id_t vrfid)
+{
+ /*
+ * `zebra_interface_add_read` will handle the interface creation
+ * on `lib/if.c`. We'll use that data structure instead of
+ * rolling our own.
+ */
+ if (cmd == ZEBRA_INTERFACE_ADD) {
+ zebra_interface_add_read(zc->ibuf, vrfid);
+ return 0;
+ }
+
+ /* Update interface information. */
+ zebra_interface_state_read(zc->ibuf, vrfid);
+
+ /* TODO: stop all sessions using this interface. */
+
+ return 0;
+}
+
void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
{
zclient = zclient_new(master, &zclient_options_default);
@@ -594,6 +633,10 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
/* Send replay request on zebra connect. */
zclient->zebra_connected = bfdd_zebra_connected;
+
+ /* Learn interfaces from zebra instead of the OS. */
+ zclient->interface_add = bfdd_interface_update;
+ zclient->interface_delete = bfdd_interface_update;
}
void bfdd_zclient_stop(void)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index b990e99bda..03f31eddfc 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -392,7 +392,7 @@ static bool overlay_index_same(const struct attr *a1, const struct attr *a2)
if (!a1 && !a2)
return true;
return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay),
- sizeof(struct overlay_index));
+ sizeof(struct bgp_route_evpn));
}
/* Unknown transit attribute. */
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 47a4182fee..6d5c647b21 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -92,12 +92,6 @@ struct bgp_tea_options {
#endif
-/* Overlay Index Info */
-struct overlay_index {
- struct eth_segment_id eth_s_id;
- union gw_addr gw_ip;
-};
-
enum pta_type {
PMSI_TNLTYPE_NO_INFO = 0,
PMSI_TNLTYPE_RSVP_TE_P2MP,
@@ -204,7 +198,7 @@ struct attr {
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
#endif
/* EVPN */
- struct overlay_index evpn_overlay;
+ struct bgp_route_evpn evpn_overlay;
/* EVPN MAC Mobility sequence number, if any. */
uint32_t mm_seqnum;
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index 88e520fdc5..3e9d05ad97 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -267,13 +267,13 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4,
&src->u.prefix4,
sizeof(struct in_addr));
- dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
+ dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
} else {
SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip);
memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6,
&src->u.prefix6,
sizeof(struct in6_addr));
- dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
+ dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
}
} else
return -1;
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index c4a20ca233..84a00488c1 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -26,6 +26,7 @@
#include "queue.h"
#include "filter.h"
#include "stream.h"
+#include "jhash.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_community.h"
@@ -35,6 +36,31 @@
#include "bgpd/bgp_regex.h"
#include "bgpd/bgp_clist.h"
+static uint32_t bgp_clist_hash_key_community_list(void *data)
+{
+ struct community_list *cl = data;
+
+ if (cl->name_hash)
+ return cl->name_hash;
+
+ cl->name_hash = bgp_clist_hash_key(cl->name);
+ return cl->name_hash;
+}
+
+static bool bgp_clist_hash_cmp_community_list(const void *a1, const void *a2)
+{
+ const struct community_list *cl1 = a1;
+ const struct community_list *cl2 = a2;
+
+ if (cl1->name_hash != cl2->name_hash)
+ return false;
+
+ if (strcmp(cl1->name, cl2->name) == 0)
+ return true;
+
+ return false;
+}
+
/* Lookup master structure for community-list or
extcommunity-list. */
struct community_list_master *
@@ -125,6 +151,10 @@ community_list_insert(struct community_list_handler *ch, const char *name,
/* Allocate new community_list and copy given name. */
new = community_list_new();
new->name = XSTRDUP(MTYPE_COMMUNITY_LIST_NAME, name);
+ new->name_hash = bgp_clist_hash_key_community_list(new);
+
+ /* Save for later */
+ hash_get(cm->hash, new, hash_alloc_intern);
/* If name is made by all digit character. We treat it as
number. */
@@ -194,9 +224,11 @@ community_list_insert(struct community_list_handler *ch, const char *name,
}
struct community_list *community_list_lookup(struct community_list_handler *ch,
- const char *name, int master)
+ const char *name,
+ uint32_t name_hash,
+ int master)
{
- struct community_list *list;
+ struct community_list lookup;
struct community_list_master *cm;
if (!name)
@@ -206,14 +238,9 @@ struct community_list *community_list_lookup(struct community_list_handler *ch,
if (!cm)
return NULL;
- for (list = cm->num.head; list; list = list->next)
- if (strcmp(list->name, name) == 0)
- return list;
- for (list = cm->str.head; list; list = list->next)
- if (strcmp(list->name, name) == 0)
- return list;
-
- return NULL;
+ lookup.name = (char *)name;
+ lookup.name_hash = name_hash;
+ return hash_get(cm->hash, &lookup, NULL);
}
static struct community_list *
@@ -222,13 +249,14 @@ community_list_get(struct community_list_handler *ch, const char *name,
{
struct community_list *list;
- list = community_list_lookup(ch, name, master);
+ list = community_list_lookup(ch, name, 0, master);
if (!list)
list = community_list_insert(ch, name, master);
return list;
}
-static void community_list_delete(struct community_list *list)
+static void community_list_delete(struct community_list_master *cm,
+ struct community_list *list)
{
struct community_list_list *clist;
struct community_entry *entry, *next;
@@ -250,6 +278,7 @@ static void community_list_delete(struct community_list *list)
else
clist->head = list->next;
+ hash_release(cm->hash, list);
community_list_free(list);
}
@@ -273,7 +302,8 @@ static void community_list_entry_add(struct community_list *list,
}
/* Delete community-list entry from the list. */
-static void community_list_entry_delete(struct community_list *list,
+static void community_list_entry_delete(struct community_list_master *cm,
+ struct community_list *list,
struct community_entry *entry)
{
if (entry->next)
@@ -289,7 +319,7 @@ static void community_list_entry_delete(struct community_list *list,
community_entry_free(entry);
if (community_list_empty_p(list))
- community_list_delete(list);
+ community_list_delete(cm, list);
}
/* Lookup community-list entry from the list. */
@@ -882,18 +912,20 @@ int community_list_set(struct community_list_handler *ch, const char *name,
int community_list_unset(struct community_list_handler *ch, const char *name,
const char *str, int direct, int style)
{
+ struct community_list_master *cm = NULL;
struct community_entry *entry = NULL;
struct community_list *list;
struct community *com = NULL;
/* Lookup community list. */
- list = community_list_lookup(ch, name, COMMUNITY_LIST_MASTER);
+ list = community_list_lookup(ch, name, 0, COMMUNITY_LIST_MASTER);
if (list == NULL)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ cm = community_list_master_lookup(ch, COMMUNITY_LIST_MASTER);
/* Delete all of entry belongs to this community-list. */
if (!str) {
- community_list_delete(list);
+ community_list_delete(cm, list);
route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
return 0;
}
@@ -910,7 +942,7 @@ int community_list_unset(struct community_list_handler *ch, const char *name,
if (!entry)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
- community_list_entry_delete(list, entry);
+ community_list_entry_delete(cm, list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
return 0;
@@ -1031,19 +1063,21 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name,
int lcommunity_list_unset(struct community_list_handler *ch, const char *name,
const char *str, int direct, int style)
{
+ struct community_list_master *cm = NULL;
struct community_entry *entry = NULL;
struct community_list *list;
struct lcommunity *lcom = NULL;
regex_t *regex = NULL;
/* Lookup community list. */
- list = community_list_lookup(ch, name, LARGE_COMMUNITY_LIST_MASTER);
+ list = community_list_lookup(ch, name, 0, LARGE_COMMUNITY_LIST_MASTER);
if (list == NULL)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ cm = community_list_master_lookup(ch, LARGE_COMMUNITY_LIST_MASTER);
/* Delete all of entry belongs to this community-list. */
if (!str) {
- community_list_delete(list);
+ community_list_delete(cm, list);
return 0;
}
@@ -1068,7 +1102,7 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name,
if (!entry)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
- community_list_entry_delete(list, entry);
+ community_list_entry_delete(cm, list, entry);
return 0;
}
@@ -1147,18 +1181,20 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name,
int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
const char *str, int direct, int style)
{
+ struct community_list_master *cm = NULL;
struct community_entry *entry = NULL;
struct community_list *list;
struct ecommunity *ecom = NULL;
/* Lookup extcommunity list. */
- list = community_list_lookup(ch, name, EXTCOMMUNITY_LIST_MASTER);
+ list = community_list_lookup(ch, name, 0, EXTCOMMUNITY_LIST_MASTER);
if (list == NULL)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ cm = community_list_master_lookup(ch, EXTCOMMUNITY_LIST_MASTER);
/* Delete all of entry belongs to this extcommunity-list. */
if (!str) {
- community_list_delete(list);
+ community_list_delete(cm, list);
route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
return 0;
}
@@ -1175,7 +1211,7 @@ int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
if (!entry)
return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
- community_list_entry_delete(list, entry);
+ community_list_entry_delete(cm, list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
return 0;
@@ -1187,6 +1223,22 @@ struct community_list_handler *community_list_init(void)
struct community_list_handler *ch;
ch = XCALLOC(MTYPE_COMMUNITY_LIST_HANDLER,
sizeof(struct community_list_handler));
+
+ ch->community_list.hash =
+ hash_create_size(4, bgp_clist_hash_key_community_list,
+ bgp_clist_hash_cmp_community_list,
+ "Community List Number Quick Lookup");
+
+ ch->extcommunity_list.hash =
+ hash_create_size(4, bgp_clist_hash_key_community_list,
+ bgp_clist_hash_cmp_community_list,
+ "Extended Community List Quick Lookup");
+
+ ch->lcommunity_list.hash =
+ hash_create_size(4, bgp_clist_hash_key_community_list,
+ bgp_clist_hash_cmp_community_list,
+ "Large Community List Quick Lookup");
+
return ch;
}
@@ -1198,21 +1250,24 @@ void community_list_terminate(struct community_list_handler *ch)
cm = &ch->community_list;
while ((list = cm->num.head) != NULL)
- community_list_delete(list);
+ community_list_delete(cm, list);
while ((list = cm->str.head) != NULL)
- community_list_delete(list);
+ community_list_delete(cm, list);
+ hash_free(cm->hash);
cm = &ch->lcommunity_list;
while ((list = cm->num.head) != NULL)
- community_list_delete(list);
+ community_list_delete(cm, list);
while ((list = cm->str.head) != NULL)
- community_list_delete(list);
+ community_list_delete(cm, list);
+ hash_free(cm->hash);
cm = &ch->extcommunity_list;
while ((list = cm->num.head) != NULL)
- community_list_delete(list);
+ community_list_delete(cm, list);
while ((list = cm->str.head) != NULL)
- community_list_delete(list);
+ community_list_delete(cm, list);
+ hash_free(cm->hash);
XFREE(MTYPE_COMMUNITY_LIST_HANDLER, ch);
}
diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h
index 9efb34d7b9..9cf8a14a6a 100644
--- a/bgpd/bgp_clist.h
+++ b/bgpd/bgp_clist.h
@@ -21,6 +21,8 @@
#ifndef _QUAGGA_BGP_CLIST_H
#define _QUAGGA_BGP_CLIST_H
+#include "jhash.h"
+
/* Master Community-list. */
#define COMMUNITY_LIST_MASTER 0
#define EXTCOMMUNITY_LIST_MASTER 1
@@ -47,6 +49,9 @@ struct community_list {
/* Name of the community-list. */
char *name;
+ /* Stored hash value of name, to further speed up hash operations */
+ uint32_t name_hash;
+
/* String or number. */
int sort;
@@ -100,6 +105,7 @@ struct community_list_list {
struct community_list_master {
struct community_list_list num;
struct community_list_list str;
+ struct hash *hash;
};
/* Community-list handler. community_list_init() returns this
@@ -151,7 +157,8 @@ extern struct community_list_master *
community_list_master_lookup(struct community_list_handler *, int);
extern struct community_list *
-community_list_lookup(struct community_list_handler *, const char *, int);
+community_list_lookup(struct community_list_handler *c, const char *name,
+ uint32_t name_hash, int master);
extern int community_list_match(struct community *, struct community_list *);
extern int ecommunity_list_match(struct ecommunity *, struct community_list *);
@@ -163,4 +170,10 @@ extern struct community *community_list_match_delete(struct community *,
extern struct lcommunity *
lcommunity_list_match_delete(struct lcommunity *lcom,
struct community_list *list);
+
+static inline uint32_t bgp_clist_hash_key(char *name)
+{
+ return jhash(name, sizeof(name), 0xdeadbeaf);
+}
+
#endif /* _QUAGGA_BGP_CLIST_H */
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index c6386dcdb5..cd5bec6267 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -23,6 +23,7 @@
#include "prefix.h"
#include "lib_errors.h"
+#include "bgp_route.h"
#include "bgp_table.h"
#include "bgp_flowspec_util.h"
#include "bgp_flowspec_private.h"
@@ -581,3 +582,27 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
}
return error;
}
+
+/* return 1 if FS entry invalid or no NH IP */
+int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
+ struct prefix *p)
+{
+ struct bgp_pbr_entry_main api;
+ int i;
+ struct bgp_node *rn = pi->net;
+ struct bgp_pbr_entry_action *api_action;
+
+ memset(&api, 0, sizeof(struct bgp_pbr_entry_main));
+ if (bgp_pbr_build_and_validate_entry(&rn->p, pi, &api) < 0)
+ return 1;
+ for (i = 0; i < api.action_num; i++) {
+ api_action = &api.actions[i];
+ if (api_action->action != ACTION_REDIRECT_IP)
+ continue;
+ p->family = AF_INET;
+ p->prefixlen = IPV4_MAX_BITLEN;
+ p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
+ return 0;
+ }
+ return 1;
+}
diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h
index 9bf05847d3..2ce911da4e 100644
--- a/bgpd/bgp_flowspec_util.h
+++ b/bgpd/bgp_flowspec_util.h
@@ -54,4 +54,8 @@ extern bool bgp_flowspec_contains_prefix(struct prefix *pfs,
struct prefix *input,
int prefix_check);
+extern int bgp_flowspec_get_first_nh(struct bgp *bgp,
+ struct bgp_path_info *pi,
+ struct prefix *nh);
+
#endif /* _FRR_BGP_FLOWSPEC_UTIL_H */
diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c
index 50aad70ddc..87e3ff2495 100644
--- a/bgpd/bgp_keepalives.c
+++ b/bgpd/bgp_keepalives.c
@@ -181,7 +181,11 @@ void *bgp_keepalives_start(void *arg)
pthread_cond_init(peerhash_cond, &attrs);
pthread_condattr_destroy(&attrs);
- frr_pthread_set_name(fpt, NULL, "bgpd_ka");
+ /*
+ * We are not using normal FRR pthread mechanics and are
+ * not using fpt_run
+ */
+ frr_pthread_set_name(fpt);
/* initialize peer hashtable */
peerhash = hash_create_size(2048, peer_hash_key, peer_hash_cmp, NULL);
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
new file mode 100644
index 0000000000..24f93e4373
--- /dev/null
+++ b/bgpd/bgp_mac.c
@@ -0,0 +1,354 @@
+/*
+ * BGPd - Mac hash code
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include <jhash.h>
+#include <hash.h>
+#include <prefix.h>
+#include <memory.h>
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_mac.h"
+#include "bgpd/bgp_memory.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_evpn_private.h"
+
+DEFINE_MTYPE_STATIC(BGPD, BSM, "Mac Hash Entry");
+DEFINE_MTYPE_STATIC(BGPD, BSM_STRING, "Mac Hash Entry Interface String");
+
+struct bgp_self_mac {
+ struct ethaddr macaddr;
+ struct list *ifp_list;
+};
+
+static unsigned int bgp_mac_hash_key_make(void *data)
+{
+ struct bgp_self_mac *bsm = data;
+
+ return jhash(&bsm->macaddr, ETH_ALEN, 0xa5a5dead);
+}
+
+static bool bgp_mac_hash_cmp(const void *d1, const void *d2)
+{
+ const struct bgp_self_mac *bsm1 = d1;
+ const struct bgp_self_mac *bsm2 = d2;
+
+ if (memcmp(&bsm1->macaddr, &bsm2->macaddr, ETH_ALEN) == 0)
+ return true;
+
+ return false;
+}
+
+void bgp_mac_init(void)
+{
+ bm->self_mac_hash = hash_create(bgp_mac_hash_key_make, bgp_mac_hash_cmp,
+ "BGP MAC Hash");
+}
+
+static void bgp_mac_hash_free(void *data)
+{
+ struct bgp_self_mac *bsm = data;
+
+ if (bsm->ifp_list)
+ list_delete(&bsm->ifp_list);
+
+ XFREE(MTYPE_BSM, bsm);
+}
+
+void bgp_mac_finish(void)
+{
+ hash_clean(bm->self_mac_hash, bgp_mac_hash_free);
+ hash_free(bm->self_mac_hash);
+}
+
+static void bgp_mac_hash_interface_string_del(void *val)
+{
+ char *data = val;
+
+ XFREE(MTYPE_BSM_STRING, data);
+}
+
+static void *bgp_mac_hash_alloc(void *p)
+{
+ const struct bgp_self_mac *orig = p;
+ struct bgp_self_mac *bsm;
+
+ bsm = XCALLOC(MTYPE_BSM, sizeof(struct bgp_self_mac));
+ memcpy(&bsm->macaddr, &orig->macaddr, ETH_ALEN);
+
+ bsm->ifp_list = list_new();
+ bsm->ifp_list->del = bgp_mac_hash_interface_string_del;
+
+ return bsm;
+}
+
+struct bgp_mac_find_internal {
+ struct bgp_self_mac *bsm;
+ const char *ifname;
+};
+
+static void bgp_mac_find_ifp_internal(struct hash_backet *backet, void *arg)
+{
+ struct bgp_mac_find_internal *bmfi = arg;
+ struct bgp_self_mac *bsm = backet->data;
+ struct listnode *node;
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) {
+ if (strcmp(name, bmfi->ifname) == 0) {
+ bmfi->bsm = bsm;
+ return;
+ }
+ }
+}
+
+static struct bgp_self_mac *bgp_mac_find_interface_name(const char *ifname)
+{
+ struct bgp_mac_find_internal bmfi;
+
+ bmfi.bsm = NULL;
+ bmfi.ifname = ifname;
+ hash_iterate(bm->self_mac_hash, bgp_mac_find_ifp_internal, &bmfi);
+
+ return bmfi.bsm;
+}
+
+static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
+ struct bgp_table *table)
+{
+ struct bgp_node *prn, *rn;
+ struct bgp_path_info *pi;
+ uint32_t count = 0;
+
+ for (prn = bgp_table_top(table); prn; prn = bgp_route_next(prn)) {
+ struct bgp_table *sub = prn->info;
+
+ if (!sub)
+ continue;
+
+ for (rn = bgp_table_top(sub); rn; rn = bgp_route_next(rn)) {
+ struct prefix_rd prd;
+ uint32_t num_labels = 0;
+ mpls_label_t *label_pnt = NULL;
+ struct bgp_route_evpn evpn;
+
+ count++;
+ for (pi = rn->info; pi; pi = pi->next) {
+ if (pi->peer == peer)
+ break;
+ }
+
+ if (!pi)
+ continue;
+
+ if (pi->extra)
+ num_labels = pi->extra->num_labels;
+ if (num_labels)
+ label_pnt = &pi->extra->label[0];
+
+ prd.family = AF_UNSPEC;
+ prd.prefixlen = 64;
+ memcpy(&prd.val, &prn->p.u.val, 8);
+
+ memcpy(&evpn, &pi->attr->evpn_overlay, sizeof(evpn));
+ int32_t ret = bgp_update(peer, &rn->p,
+ pi->addpath_rx_id,
+ pi->attr, AFI_L2VPN, SAFI_EVPN,
+ ZEBRA_ROUTE_BGP,
+ BGP_ROUTE_NORMAL, &prd,
+ label_pnt, num_labels,
+ 1, &evpn);
+
+ if (ret < 0)
+ bgp_unlock_node(rn);
+ }
+ }
+}
+
+static void bgp_mac_rescan_evpn_table(struct bgp *bgp)
+{
+ struct listnode *node;
+ struct peer *peer;
+ safi_t safi;
+ afi_t afi;
+
+ afi = AFI_L2VPN;
+ safi = SAFI_EVPN;
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
+ continue;
+
+ if (peer->status != Established)
+ continue;
+
+ if (CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_SOFT_RECONFIG)) {
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("Processing EVPN MAC interface change on peer %s (inbound, soft-reconfig)",
+ peer->host);
+
+ bgp_soft_reconfig_in(peer, afi, safi);
+ } else {
+ struct bgp_table *table = bgp->rib[afi][safi];
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("Processing EVPN MAC interface change on peer %s",
+ peer->host);
+ bgp_process_mac_rescan_table(bgp, peer, table);
+ }
+ }
+}
+
+static void bgp_mac_rescan_all_evpn_tables(void)
+{
+ struct listnode *node;
+ struct bgp *bgp;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+ struct bgp_table *table = bgp->rib[AFI_L2VPN][SAFI_EVPN];
+
+ if (table)
+ bgp_mac_rescan_evpn_table(bgp);
+ }
+}
+
+static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname)
+{
+ struct listnode *node = NULL;
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) {
+ if (strcmp(name, ifname) == 0)
+ break;
+ }
+
+ if (node) {
+ list_delete_node(bsm->ifp_list, node);
+ XFREE(MTYPE_BSM_STRING, name);
+ }
+
+ if (bsm->ifp_list->count == 0) {
+ hash_release(bm->self_mac_hash, bsm);
+ list_delete(&bsm->ifp_list);
+ XFREE(MTYPE_BSM, bsm);
+
+ bgp_mac_rescan_all_evpn_tables();
+ }
+}
+
+void bgp_mac_add_mac_entry(struct interface *ifp)
+{
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+ struct bgp_self_mac *old_bsm;
+ char *ifname;
+
+ memcpy(&lookup.macaddr, &ifp->hw_addr, ETH_ALEN);
+ bsm = hash_get(bm->self_mac_hash, &lookup, bgp_mac_hash_alloc);
+
+ /*
+ * Does this happen to be a move
+ */
+ old_bsm = bgp_mac_find_interface_name(ifp->name);
+ ifname = XSTRDUP(MTYPE_BSM_STRING, ifp->name);
+
+ if (bsm->ifp_list->count == 0) {
+
+ listnode_add(bsm->ifp_list, ifname);
+ if (old_bsm)
+ bgp_mac_remove_ifp_internal(old_bsm, ifname);
+ } else {
+ /*
+ * If old mac address is the same as the new,
+ * then there is nothing to do here
+ */
+ if (old_bsm == bsm)
+ return;
+
+ if (old_bsm)
+ bgp_mac_remove_ifp_internal(old_bsm, ifp->name);
+
+ listnode_add(bsm->ifp_list, ifname);
+ }
+
+ bgp_mac_rescan_all_evpn_tables();
+}
+
+void bgp_mac_del_mac_entry(struct interface *ifp)
+{
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+
+ memcpy(&lookup.macaddr, &ifp->hw_addr, ETH_ALEN);
+ bsm = hash_lookup(bm->self_mac_hash, &lookup);
+ if (!bsm)
+ return;
+
+ /*
+ * Write code to allow old mac address to no-longer
+ * win if we happen to have received it from a peer.
+ */
+ bgp_mac_remove_ifp_internal(bsm, ifp->name);
+}
+
+bool bgp_mac_entry_exists(struct prefix *p)
+{
+ struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+
+ if (pevpn->family != AF_EVPN)
+ return false;
+
+ if (pevpn->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
+ return false;
+
+ memcpy(&lookup.macaddr, &p->u.prefix_evpn.macip_addr.mac, ETH_ALEN);
+ bsm = hash_lookup(bm->self_mac_hash, &lookup);
+ if (!bsm)
+ return false;
+
+ return true;
+}
+
+static void bgp_mac_show_mac_entry(struct hash_backet *backet, void *arg)
+{
+ struct vty *vty = arg;
+ struct bgp_self_mac *bsm = backet->data;
+ struct listnode *node;
+ char *name;
+ char buf_mac[ETHER_ADDR_STRLEN];
+
+ vty_out(vty, "Mac Address: %s ",
+ prefix_mac2str(&bsm->macaddr, buf_mac, sizeof(buf_mac)));
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name))
+ vty_out(vty, "%s ", name);
+
+ vty_out(vty, "\n");
+}
+
+void bgp_mac_dump_table(struct vty *vty)
+{
+ hash_iterate(bm->self_mac_hash, bgp_mac_show_mac_entry, vty);
+}
diff --git a/bgpd/bgp_mac.h b/bgpd/bgp_mac.h
new file mode 100644
index 0000000000..1dd987ef12
--- /dev/null
+++ b/bgpd/bgp_mac.h
@@ -0,0 +1,41 @@
+/*
+ * BGPd - Mac hash header
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __BGP_MAC_H__
+#define __BGP_MAC_H__
+
+void bgp_mac_init(void);
+void bgp_mac_finish(void);
+
+/*
+ * Functions to add/delete the mac entry from the appropriate
+ * bgp hash's. Additionally to do some additional processing
+ * to allow the win/loss to be processed.
+ */
+void bgp_mac_add_mac_entry(struct interface *ifp);
+void bgp_mac_del_mac_entry(struct interface *ifp);
+
+void bgp_mac_dump_table(struct vty *vty);
+
+/*
+ * Function to lookup the prefix and see if we have a matching mac
+ */
+bool bgp_mac_entry_exists(struct prefix *p);
+
+#endif
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index cf91faf964..d0ccdcedfb 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -289,6 +289,8 @@ void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi)
bgp->vrf_id);
}
+ if (label == BGP_PREVENT_VRF_2_VRF_LEAK)
+ label = MPLS_LABEL_NONE;
zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP);
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
}
@@ -316,6 +318,9 @@ void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi)
bgp->name_pretty, bgp->vrf_id);
}
+ if (label == BGP_PREVENT_VRF_2_VRF_LEAK)
+ label = MPLS_LABEL_NONE;
+
zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP);
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
}
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index b6ef5a55c5..2b4ad22b93 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -42,6 +42,7 @@
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_flowspec_util.h"
extern struct zclient *zclient;
@@ -533,7 +534,15 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
&& (pi->sub_type == BGP_ROUTE_STATIC))
? 1
: 0;
-
+ struct bgp_node *net = pi->net;
+ struct prefix *p_orig = &net->p;
+
+ if (p_orig->family == AF_FLOWSPEC) {
+ if (!pi->peer)
+ return -1;
+ return bgp_flowspec_get_first_nh(pi->peer->bgp,
+ pi, p);
+ }
memset(p, 0, sizeof(struct prefix));
switch (afi) {
case AFI_IP:
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index f0a0e615e6..f002154701 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -626,7 +626,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
}
/* return -1 if build or validation failed */
-static int bgp_pbr_build_and_validate_entry(struct prefix *p,
+int bgp_pbr_build_and_validate_entry(struct prefix *p,
struct bgp_path_info *path,
struct bgp_pbr_entry_main *api)
{
diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h
index 84095f9ab9..45c3c9ea13 100644
--- a/bgpd/bgp_pbr.h
+++ b/bgpd/bgp_pbr.h
@@ -290,4 +290,7 @@ extern void bgp_pbr_reset(struct bgp *bgp, afi_t afi);
extern struct bgp_pbr_interface *bgp_pbr_interface_lookup(const char *name,
struct bgp_pbr_interface_head *head);
+extern int bgp_pbr_build_and_validate_entry(struct prefix *p,
+ struct bgp_path_info *path,
+ struct bgp_pbr_entry_main *api);
#endif /* __BGP_PBR_H__ */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 31cd3d1f05..6bce7261ae 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -66,6 +66,7 @@
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_label.h"
#include "bgpd/bgp_addpath.h"
+#include "bgpd/bgp_mac.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@@ -3057,6 +3058,11 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
goto filtered;
}
+ if (bgp_mac_entry_exists(p)) {
+ reason = "self mac;";
+ goto filtered;
+ }
+
attr_new = bgp_attr_intern(&new_attr);
/* If the update is implicit withdraw. */
@@ -3778,16 +3784,22 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
bgp_node_get_bgp_path_info(rn);
uint32_t num_labels = 0;
mpls_label_t *label_pnt = NULL;
+ struct bgp_route_evpn evpn;
if (pi && pi->extra)
num_labels = pi->extra->num_labels;
if (num_labels)
label_pnt = &pi->extra->label[0];
+ if (pi)
+ memcpy(&evpn, &pi->attr->evpn_overlay,
+ sizeof(evpn));
+ else
+ memset(&evpn, 0, sizeof(evpn));
ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, prd, label_pnt,
- num_labels, 1, NULL);
+ num_labels, 1, &evpn);
if (ret < 0) {
bgp_unlock_node(rn);
@@ -9266,7 +9278,7 @@ static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
{
struct community_list *list;
- list = community_list_lookup(bgp_clist, lcom,
+ list = community_list_lookup(bgp_clist, lcom, 0,
LARGE_COMMUNITY_LIST_MASTER);
if (list == NULL) {
vty_out(vty, "%% %s is not a valid large-community-list name\n",
@@ -9787,7 +9799,7 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
{
struct community_list *list;
- list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER);
+ list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
if (list == NULL) {
vty_out(vty, "%% %s is not a valid community-list name\n", com);
return CMD_WARNING;
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 30159f9023..d7ee2aa19f 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1037,6 +1037,7 @@ struct route_map_rule_cmd route_match_aspath_cmd = {
/* `match community COMMUNIY' */
struct rmap_community {
char *name;
+ uint32_t name_hash;
int exact;
};
@@ -1048,13 +1049,14 @@ static route_map_result_t route_match_community(void *rule,
{
struct community_list *list;
struct bgp_path_info *path;
- struct rmap_community *rcom;
+ struct rmap_community *rcom = rule;
if (type == RMAP_BGP) {
path = object;
rcom = rule;
list = community_list_lookup(bgp_clist, rcom->name,
+ rcom->name_hash,
COMMUNITY_LIST_MASTER);
if (!list)
return RMAP_NOMATCH;
@@ -1090,6 +1092,8 @@ static void *route_match_community_compile(const char *arg)
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
rcom->exact = 0;
}
+
+ rcom->name_hash = bgp_clist_hash_key(rcom->name);
return rcom;
}
@@ -1115,13 +1119,13 @@ static route_map_result_t route_match_lcommunity(void *rule,
{
struct community_list *list;
struct bgp_path_info *path;
- struct rmap_community *rcom;
+ struct rmap_community *rcom = rule;
if (type == RMAP_BGP) {
path = object;
- rcom = rule;
list = community_list_lookup(bgp_clist, rcom->name,
+ rcom->name_hash,
LARGE_COMMUNITY_LIST_MASTER);
if (!list)
return RMAP_NOMATCH;
@@ -1150,6 +1154,8 @@ static void *route_match_lcommunity_compile(const char *arg)
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
rcom->exact = 0;
}
+
+ rcom->name_hash = bgp_clist_hash_key(rcom->name);
return rcom;
}
@@ -1176,11 +1182,13 @@ static route_map_result_t route_match_ecommunity(void *rule,
{
struct community_list *list;
struct bgp_path_info *path;
+ struct rmap_community *rcom = rule;
if (type == RMAP_BGP) {
path = object;
- list = community_list_lookup(bgp_clist, (char *)rule,
+ list = community_list_lookup(bgp_clist, rcom->name,
+ rcom->name_hash,
EXTCOMMUNITY_LIST_MASTER);
if (!list)
return RMAP_NOMATCH;
@@ -1194,13 +1202,22 @@ static route_map_result_t route_match_ecommunity(void *rule,
/* Compile function for extcommunity match. */
static void *route_match_ecommunity_compile(const char *arg)
{
- return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+ struct rmap_community *rcom;
+
+ rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+ rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+ rcom->name_hash = bgp_clist_hash_key(rcom->name);
+
+ return rcom;
}
/* Compile function for extcommunity match. */
static void route_match_ecommunity_free(void *rule)
{
- XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+ struct rmap_community *rcom = rule;
+
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
}
/* Route map commands for community matching. */
@@ -1932,13 +1949,15 @@ static route_map_result_t route_set_lcommunity_delete(void *rule,
struct lcommunity *new;
struct lcommunity *old;
struct bgp_path_info *path;
+ struct rmap_community *rcom = rule;
if (type == RMAP_BGP) {
- if (!rule)
+ if (!rcom)
return RMAP_OKAY;
path = object;
- list = community_list_lookup(bgp_clist, rule,
+ list = community_list_lookup(bgp_clist, rcom->name,
+ rcom->name_hash,
LARGE_COMMUNITY_LIST_MASTER);
old = path->attr->lcommunity;
@@ -1975,10 +1994,13 @@ static route_map_result_t route_set_lcommunity_delete(void *rule,
/* Compile function for set lcommunity. */
static void *route_set_lcommunity_delete_compile(const char *arg)
{
+ struct rmap_community *rcom;
char *p;
char *str;
int len;
+ rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+
p = strchr(arg, ' ');
if (p) {
len = p - arg;
@@ -1987,13 +2009,18 @@ static void *route_set_lcommunity_delete_compile(const char *arg)
} else
str = NULL;
- return str;
+ rcom->name = str;
+ rcom->name_hash = bgp_clist_hash_key(rcom->name);
+ return rcom;
}
/* Free function for set lcommunity. */
static void route_set_lcommunity_delete_free(void *rule)
{
- XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+ struct rmap_community *rcom = rule;
+
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
}
/* Set lcommunity rule structure. */
@@ -2017,13 +2044,15 @@ static route_map_result_t route_set_community_delete(
struct community *new;
struct community *old;
struct bgp_path_info *path;
+ struct rmap_community *rcom = rule;
if (type == RMAP_BGP) {
- if (!rule)
+ if (!rcom)
return RMAP_OKAY;
path = object;
- list = community_list_lookup(bgp_clist, rule,
+ list = community_list_lookup(bgp_clist, rcom->name,
+ rcom->name_hash,
COMMUNITY_LIST_MASTER);
old = path->attr->community;
@@ -2060,10 +2089,13 @@ static route_map_result_t route_set_community_delete(
/* Compile function for set community. */
static void *route_set_community_delete_compile(const char *arg)
{
+ struct rmap_community *rcom;
char *p;
char *str;
int len;
+ rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
+
p = strchr(arg, ' ');
if (p) {
len = p - arg;
@@ -2072,13 +2104,18 @@ static void *route_set_community_delete_compile(const char *arg)
} else
str = NULL;
- return str;
+ rcom->name = str;
+ rcom->name_hash = bgp_clist_hash_key(rcom->name);
+ return rcom;
}
/* Free function for set community. */
static void route_set_community_delete_free(void *rule)
{
- XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+ struct rmap_community *rcom = rule;
+
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
}
/* Set community rule structure. */
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 2a4421aa54..c6e48cc160 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -37,6 +37,7 @@
#include "frrstr.h"
#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_aspath.h"
@@ -62,6 +63,7 @@
#include "bgpd/bgp_io.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_addpath.h"
+#include "bgpd/bgp_mac.h"
static struct peer_group *listen_range_exists(struct bgp *bgp,
struct prefix *range, int exact);
@@ -7244,13 +7246,15 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
/* one clear bgp command to rule them all */
DEFUN (clear_ip_bgp_all,
clear_ip_bgp_all_cmd,
- "clear [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
+ "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
CLEAR_STR
IP_STR
BGP_STR
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
+ "Address Family\n"
BGP_SAFI_WITH_LABEL_HELP_STR
+ "Address Family modifier\n"
"Clear all peers\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
@@ -7574,6 +7578,18 @@ DEFUN (show_bgp_vrfs,
return CMD_SUCCESS;
}
+DEFUN (show_bgp_mac_hash,
+ show_bgp_mac_hash_cmd,
+ "show bgp mac hash",
+ SHOW_STR
+ BGP_STR
+ "Mac Address\n"
+ "Mac Address database\n")
+{
+ bgp_mac_dump_table(vty);
+
+ return CMD_SUCCESS;
+}
static void show_tip_entry(struct hash_backet *backet, void *args)
{
@@ -12999,6 +13015,8 @@ void bgp_vty_init(void)
&neighbor_soft_reconfiguration_cmd);
install_element(BGP_FLOWSPECV6_NODE,
&no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_soft_reconfiguration_cmd);
/* "neighbor attribute-unchanged" commands. */
install_element(BGP_NODE, &neighbor_attr_unchanged_hidden_cmd);
@@ -13832,6 +13850,8 @@ void bgp_vty_init(void)
/* "show bgp martian next-hop" */
install_element(VIEW_NODE, &show_bgp_martian_nexthop_db_cmd);
+ install_element(VIEW_NODE, &show_bgp_mac_hash_cmd);
+
/* "show [ip] bgp views" commands. */
install_element(VIEW_NODE, &show_bgp_views_cmd);
@@ -14309,7 +14329,7 @@ DEFUN (show_community_list_arg,
vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n");
zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used");
}
- list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg,
+ list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0,
COMMUNITY_LIST_MASTER);
if (!list) {
vty_out(vty, "%% Can't find community-list\n");
@@ -14834,7 +14854,7 @@ DEFUN (show_lcommunity_list_arg,
zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used");
}
- list = community_list_lookup(bgp_clist, argv[3]->arg,
+ list = community_list_lookup(bgp_clist, argv[3]->arg, 0,
LARGE_COMMUNITY_LIST_MASTER);
if (!list) {
vty_out(vty, "%% Can't find extcommunity-list\n");
@@ -15235,7 +15255,7 @@ DEFUN (show_extcommunity_list_arg,
vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n");
zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used");
}
- list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg,
+ list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0,
EXTCOMMUNITY_LIST_MASTER);
if (!list) {
vty_out(vty, "%% Can't find extcommunity-list\n");
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 66d3333739..3c4b219466 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -59,6 +59,7 @@
#include "bgpd/bgp_labelpool.h"
#include "bgpd/bgp_pbr.h"
#include "bgpd/bgp_evpn_private.h"
+#include "bgpd/bgp_mac.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
@@ -221,6 +222,8 @@ static int bgp_interface_add(int command, struct zclient *zclient,
if (!bgp)
return 0;
+ bgp_mac_add_mac_entry(ifp);
+
bgp_update_interface_nbrs(bgp, ifp, ifp);
return 0;
}
@@ -245,6 +248,8 @@ static int bgp_interface_delete(int command, struct zclient *zclient,
if (bgp)
bgp_update_interface_nbrs(bgp, ifp, NULL);
+ bgp_mac_del_mac_entry(ifp);
+
if_set_index(ifp, IFINDEX_INTERNAL);
return 0;
}
@@ -267,6 +272,8 @@ static int bgp_interface_up(int command, struct zclient *zclient,
if (!ifp)
return 0;
+ bgp_mac_add_mac_entry(ifp);
+
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name);
@@ -300,6 +307,8 @@ static int bgp_interface_down(int command, struct zclient *zclient,
if (!ifp)
return 0;
+ bgp_mac_del_mac_entry(ifp);
+
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 7a3afbd18d..5b8ceb0541 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -87,6 +87,7 @@
#include "bgpd/bgp_pbr.h"
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_evpn_private.h"
+#include "bgpd/bgp_mac.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information");
@@ -7775,6 +7776,7 @@ void bgp_master_init(struct thread_master *master)
bgp_process_queue_init();
+ bgp_mac_init();
/* init the rd id space.
assign 0th index in the bitfield,
so that we start with id 1
@@ -7964,4 +7966,5 @@ void bgp_terminate(void)
if (bm->t_rmap_update)
BGP_TIMER_OFF(bm->t_rmap_update);
+ bgp_mac_finish();
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index f28ca9fa0b..484fc105e8 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -122,6 +122,9 @@ struct bgp_master {
/* Listener address */
char *address;
+ /* The Mac table */
+ struct hash *self_mac_hash;
+
/* BGP start time. */
time_t start_time;
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index 7d7d3ca189..7dd1d73f69 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -72,6 +72,7 @@ bgpd_libbgp_a_SOURCES = \
bgpd/bgp_label.c \
bgpd/bgp_labelpool.c \
bgpd/bgp_lcommunity.c \
+ bgpd/bgp_mac.c \
bgpd/bgp_memory.c \
bgpd/bgp_mpath.c \
bgpd/bgp_mplsvpn.c \
@@ -145,6 +146,7 @@ noinst_HEADERS += \
bgpd/bgp_label.h \
bgpd/bgp_labelpool.h \
bgpd/bgp_lcommunity.h \
+ bgpd/bgp_mac.h \
bgpd/bgp_memory.h \
bgpd/bgp_mpath.h \
bgpd/bgp_mplsvpn.h \
diff --git a/doc/developer/building-frr-for-freebsd10.rst b/doc/developer/building-frr-for-freebsd10.rst
index 5dde915f6a..a6539309a2 100644
--- a/doc/developer/building-frr-for-freebsd10.rst
+++ b/doc/developer/building-frr-for-freebsd10.rst
@@ -17,12 +17,14 @@ is first package install and asked)
::
pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
- bison flex py27-pytest c-ares python3 py-sphinx libyang
+ bison flex py27-pytest c-ares python3 py-sphinx
Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin): (FreeBSD frequently provides a older flex
as part of the base OS which takes preference in path)
+.. include:: building-libyang.rst
+
::
rm -f /usr/bin/flex
diff --git a/doc/developer/building-frr-for-freebsd11.rst b/doc/developer/building-frr-for-freebsd11.rst
index 9bef1fbfde..16d06e0a66 100644
--- a/doc/developer/building-frr-for-freebsd11.rst
+++ b/doc/developer/building-frr-for-freebsd11.rst
@@ -17,12 +17,14 @@ is first package install and asked)
.. code-block:: shell
pkg install git autoconf automake libtool gmake gawk json-c pkgconf \
- bison flex py27-pytest c-ares python3 py36-sphinx texinfo libyang
+ bison flex py27-pytest c-ares python3 py36-sphinx texinfo
Make sure there is no /usr/bin/flex preinstalled (and use the newly
installed in /usr/local/bin): (FreeBSD frequently provides a older flex
as part of the base OS which takes preference in path)
+.. include:: building-libyang.rst
+
.. code-block:: shell
rm -f /usr/bin/flex
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index a27243ea77..5b453e75c3 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -968,6 +968,13 @@ Configuring Peers
and will not be displayed as part of a `show run`. The no form
of the command turns off this ability.
+.. index:: [no] bgp default ipv4-unicast
+.. clicmd:: [no] bgp default ipv4-unicast
+
+ This command allows the user to specify that v4 peering is turned
+ on by default or not. This command defaults to on and is not displayed.
+ The `no bgp default ipv4-unicast` form of the command is displayed.
+
.. _bgp-peer-filtering:
Peer Filtering
diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c
index 29bd23b514..a810e01468 100644
--- a/eigrpd/eigrp_zebra.c
+++ b/eigrpd/eigrp_zebra.c
@@ -425,7 +425,7 @@ void eigrp_zebra_route_delete(struct prefix *p)
int eigrp_is_type_redistributed(int type)
{
return ((DEFAULT_ROUTE_TYPE(type))
- ? vrf_bitmap_check(zclient->default_information,
+ ? vrf_bitmap_check(zclient->default_information[AFI_IP],
VRF_DEFAULT)
: vrf_bitmap_check(zclient->redist[AFI_IP][type],
VRF_DEFAULT));
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 101bd57cc9..958f8c2281 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -390,7 +390,7 @@ void isis_zebra_redistribute_set(afi_t afi, int type)
{
if (type == DEFAULT_ROUTE)
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
- zclient, VRF_DEFAULT);
+ zclient, afi, VRF_DEFAULT);
else
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
0, VRF_DEFAULT);
@@ -400,7 +400,7 @@ void isis_zebra_redistribute_unset(afi_t afi, int type)
{
if (type == DEFAULT_ROUTE)
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
- zclient, VRF_DEFAULT);
+ zclient, afi, VRF_DEFAULT);
else
zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
type, 0, VRF_DEFAULT);
diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c
index a0223730b8..d5a2007c4d 100644
--- a/lib/frr_pthread.c
+++ b/lib/frr_pthread.c
@@ -84,6 +84,8 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr,
fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name);
if (os_name)
snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name);
+ else
+ snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", name);
/* initialize startup synchronization primitives */
fpt->running_cond_mtx = XCALLOC(
MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t));
@@ -115,36 +117,19 @@ void frr_pthread_destroy(struct frr_pthread *fpt)
XFREE(MTYPE_FRR_PTHREAD, fpt);
}
-int frr_pthread_set_name(struct frr_pthread *fpt, const char *name,
- const char *os_name)
+int frr_pthread_set_name(struct frr_pthread *fpt)
{
int ret = 0;
- if (name) {
- pthread_mutex_lock(&fpt->mtx);
- {
- if (fpt->name)
- XFREE(MTYPE_FRR_PTHREAD, fpt->name);
- fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name);
- }
- pthread_mutex_unlock(&fpt->mtx);
- thread_master_set_name(fpt->master, name);
- }
-
- if (os_name) {
- pthread_mutex_lock(&fpt->mtx);
- snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name);
- pthread_mutex_unlock(&fpt->mtx);
#ifdef HAVE_PTHREAD_SETNAME_NP
# ifdef GNU_LINUX
- ret = pthread_setname_np(fpt->thread, fpt->os_name);
+ ret = pthread_setname_np(fpt->thread, fpt->os_name);
# else /* NetBSD */
- ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL);
+ ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL);
# endif
#elif defined(HAVE_PTHREAD_SET_NAME_NP)
- pthread_set_name_np(fpt->thread, fpt->os_name);
+ pthread_set_name_np(fpt->thread, fpt->os_name);
#endif
- }
return ret;
}
@@ -273,8 +258,7 @@ static void *fpt_run(void *arg)
fpt->master->handle_signals = false;
- if (fpt->os_name[0])
- frr_pthread_set_name(fpt, NULL, fpt->os_name);
+ frr_pthread_set_name(fpt);
frr_pthread_notify_running(fpt);
diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h
index b9e60511d5..e6b3f031b3 100644
--- a/lib/frr_pthread.h
+++ b/lib/frr_pthread.h
@@ -133,16 +133,13 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr,
const char *name, const char *os_name);
/*
- * Changes the name of the frr_pthread.
+ * Changes the name of the frr_pthread as reported by the operating
+ * system.
*
* @param fpt - the frr_pthread to operate on
- * @param name - Human-readable name
- * @param os_name - 16 characters thread name , including the null
- * terminator ('\0') to set in os.
* @return - on success returns 0 otherwise nonzero error number.
*/
-int frr_pthread_set_name(struct frr_pthread *fpt, const char *name,
- const char *os_name);
+int frr_pthread_set_name(struct frr_pthread *fpt);
/*
* Destroys an frr_pthread.
diff --git a/lib/lib_errors.c b/lib/lib_errors.c
index 7e428f135c..5f6c25b770 100644
--- a/lib/lib_errors.c
+++ b/lib/lib_errors.c
@@ -102,7 +102,7 @@ static struct log_ref ferr_lib_warn[] = {
.code = EC_LIB_NB_CB_UNNEEDED,
.title = "Unneeded northbound callback",
.description = "The northbound subsystem, during initialization, has detected a callback that doesn't need to be implemented",
- .suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries",
+ .suggestion = "This is a bug; please report it"
},
{
.code = EC_LIB_NB_CB_CONFIG_VALIDATE,
@@ -270,19 +270,19 @@ static struct log_ref ferr_lib_err[] = {
.code = EC_LIB_NB_CB_MISSING,
.title = "Missing northbound callback",
.description = "The northbound subsystem, during initialization, has detected a missing callback for one node of the loaded YANG modules",
- .suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries",
+ .suggestion = "This is a bug; please report it"
},
{
.code = EC_LIB_NB_CB_INVALID_PRIO,
.title = "Norhtbound callback has an invalid priority",
.description = "The northbound subsystem, during initialization, has detected a callback whose priority is invalid",
- .suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries",
+ .suggestion = "This is a bug; please report it"
},
{
.code = EC_LIB_NB_CBS_VALIDATION,
.title = "Failure to validate the northbound callbacks",
.description = "The northbound subsystem, during initialization, has detected one or more errors while loading the northbound callbacks",
- .suggestion = "Check if the installed FRR YANG modules are in sync with the FRR binaries",
+ .suggestion = "This is a bug; please report it"
},
{
.code = EC_LIB_LIBYANG,
diff --git a/lib/northbound.c b/lib/northbound.c
index a7f9c8620e..6fe612d72a 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -719,7 +719,6 @@ static int nb_configuration_callback(const enum nb_event event,
const struct lyd_node *dnode = change->cb.dnode;
union nb_resource *resource;
int ret = NB_ERR;
- enum lib_log_refs ref;
if (debug_northbound) {
const char *value = "(none)";
@@ -753,6 +752,8 @@ static int nb_configuration_callback(const enum nb_event event,
}
if (ret != NB_OK) {
+ enum lib_log_refs ref = 0;
+
switch (event) {
case NB_EV_VALIDATE:
ref = EC_LIB_NB_CB_CONFIG_VALIDATE;
@@ -1277,8 +1278,12 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
n++;
}
list_keys.num = n;
- assert(list_keys.num
- == ((struct lys_node_list *)dn->schema)->keys_size);
+ if (list_keys.num
+ != ((struct lys_node_list *)dn->schema)->keys_size) {
+ list_delete(&list_dnodes);
+ yang_dnode_free(dnode);
+ return NB_ERR_NOT_FOUND;
+ }
/* Find the list entry pointer. */
nn = dn->schema->priv;
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 2b024ace93..33035de31b 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -261,7 +261,7 @@ static int nb_cli_confirmed_commit_timeout(struct thread *thread)
static int nb_cli_commit(struct vty *vty, bool force,
unsigned int confirmed_timeout, char *comment)
{
- uint32_t transaction_id;
+ uint32_t transaction_id = 0;
int ret;
/* Check if there's a pending confirmed commit. */
diff --git a/lib/prefix.c b/lib/prefix.c
index 858f860ee8..0203301562 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -451,7 +451,7 @@ int is_zero_mac(struct ethaddr *mac)
return 1;
}
-unsigned int prefix_bit(const uint8_t *prefix, const uint8_t prefixlen)
+unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen)
{
unsigned int offset = prefixlen / 8;
unsigned int shift = 7 - (prefixlen % 8);
@@ -459,7 +459,7 @@ unsigned int prefix_bit(const uint8_t *prefix, const uint8_t prefixlen)
return (prefix[offset] >> shift) & 1;
}
-unsigned int prefix6_bit(const struct in6_addr *prefix, const uint8_t prefixlen)
+unsigned int prefix6_bit(const struct in6_addr *prefix, const uint16_t prefixlen)
{
return prefix_bit((const uint8_t *)&prefix->s6_addr, prefixlen);
}
@@ -966,18 +966,16 @@ void masklen2ip(const int masklen, struct in_addr *netmask)
}
/* Convert IP address's netmask into integer. We assume netmask is
- sequential one. Argument netmask should be network byte order. */
+ * sequential one. Argument netmask should be network byte order. */
uint8_t ip_masklen(struct in_addr netmask)
{
uint32_t tmp = ~ntohl(netmask.s_addr);
- if (tmp)
- /* clz: count leading zeroes. sadly, the behaviour of this
- * builtin
- * is undefined for a 0 argument, even though most CPUs give 32
- */
- return __builtin_clz(tmp);
- else
- return 32;
+
+ /*
+ * clz: count leading zeroes. sadly, the behaviour of this builtin is
+ * undefined for a 0 argument, even though most CPUs give 32
+ */
+ return tmp ? __builtin_clz(tmp) : 32;
}
/* Apply mask to IPv4 prefix (network byte order). */
diff --git a/lib/prefix.h b/lib/prefix.h
index 4247569137..aaffb1e0c5 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -151,7 +151,7 @@ struct flowspec_prefix {
/* FRR generic prefix structure. */
struct prefix {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
union {
uint8_t prefix;
struct in_addr prefix4;
@@ -162,6 +162,7 @@ struct prefix {
} lp;
struct ethaddr prefix_eth; /* AF_ETHERNET */
uint8_t val[16];
+ uint32_t val32[4];
uintptr_t ptr;
struct evpn_addr prefix_evpn; /* AF_EVPN */
struct flowspec_prefix prefix_flowspec; /* AF_FLOWSPEC */
@@ -171,20 +172,20 @@ struct prefix {
/* IPv4 prefix structure. */
struct prefix_ipv4 {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
struct in_addr prefix __attribute__((aligned(8)));
};
/* IPv6 prefix structure. */
struct prefix_ipv6 {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
struct in6_addr prefix __attribute__((aligned(8)));
};
struct prefix_ls {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
struct in_addr id __attribute__((aligned(8)));
struct in_addr adv_router;
};
@@ -192,21 +193,21 @@ struct prefix_ls {
/* Prefix for routing distinguisher. */
struct prefix_rd {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
uint8_t val[8] __attribute__((aligned(8)));
};
/* Prefix for ethernet. */
struct prefix_eth {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
struct ethaddr eth_addr __attribute__((aligned(8))); /* AF_ETHERNET */
};
/* EVPN prefix structure. */
struct prefix_evpn {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
struct evpn_addr prefix __attribute__((aligned(8)));
};
@@ -252,20 +253,20 @@ static inline int is_evpn_prefix_ipaddr_v6(const struct prefix_evpn *evp)
/* Prefix for a generic pointer */
struct prefix_ptr {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
uintptr_t prefix __attribute__((aligned(8)));
};
/* Prefix for a Flowspec entry */
struct prefix_fs {
uint8_t family;
- uint8_t prefixlen; /* unused */
+ uint16_t prefixlen; /* unused */
struct flowspec_prefix prefix __attribute__((aligned(8)));
};
struct prefix_sg {
uint8_t family;
- uint8_t prefixlen;
+ uint16_t prefixlen;
struct in_addr src __attribute__((aligned(8)));
struct in_addr grp;
};
@@ -296,15 +297,16 @@ union prefixconstptr {
#endif /* INET_ADDRSTRLEN */
#ifndef INET6_ADDRSTRLEN
+/* dead:beef:dead:beef:dead:beef:dead:beef + \0 */
#define INET6_ADDRSTRLEN 46
#endif /* INET6_ADDRSTRLEN */
#ifndef INET6_BUFSIZ
-#define INET6_BUFSIZ 51
+#define INET6_BUFSIZ 53
#endif /* INET6_BUFSIZ */
-/* Maximum prefix string length (IPv6) */
-#define PREFIX_STRLEN 51
+/* Maximum string length of the result of prefix2str */
+#define PREFIX_STRLEN 80
/* Max bit/byte length of IPv4 address. */
#define IPV4_MAX_BYTELEN 4
@@ -367,9 +369,9 @@ extern const char *safi2str(safi_t safi);
extern const char *afi2str(afi_t afi);
/* Check bit of the prefix. */
-extern unsigned int prefix_bit(const uint8_t *prefix, const uint8_t prefixlen);
+extern unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen);
extern unsigned int prefix6_bit(const struct in6_addr *prefix,
- const uint8_t prefixlen);
+ const uint16_t prefixlen);
extern struct prefix *prefix_new(void);
extern void prefix_free(struct prefix *);
diff --git a/lib/table.c b/lib/table.c
index 0026b7692b..edba7f1932 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -283,7 +283,7 @@ struct route_node *route_node_get(struct route_table *const table,
struct route_node *node;
struct route_node *match;
struct route_node *inserted;
- uint8_t prefixlen = p->prefixlen;
+ uint16_t prefixlen = p->prefixlen;
const uint8_t *prefix = &p->u.prefix;
apply_mask((struct prefix *)p);
diff --git a/lib/thread.c b/lib/thread.c
index 44c9e2b2f1..867ca2dc60 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -1572,8 +1572,13 @@ void thread_set_yield_time(struct thread *thread, unsigned long yield_time)
void thread_getrusage(RUSAGE_T *r)
{
+#if defined RUSAGE_THREAD
+#define FRR_RUSAGE RUSAGE_THREAD
+#else
+#define FRR_RUSAGE RUSAGE_SELF
+#endif
monotime(&r->real);
- getrusage(RUSAGE_SELF, &(r->cpu));
+ getrusage(FRR_RUSAGE, &(r->cpu));
}
/*
diff --git a/lib/zclient.c b/lib/zclient.c
index 1c40750db0..cc936d47d7 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -173,10 +173,10 @@ void zclient_stop(struct zclient *zclient)
redist_del_instance(
&zclient->mi_redist[afi][zclient->redist_default],
zclient->instance);
- }
- vrf_bitmap_free(zclient->default_information);
- zclient->default_information = VRF_BITMAP_NULL;
+ vrf_bitmap_free(zclient->default_information[afi]);
+ zclient->default_information[afi] = VRF_BITMAP_NULL;
+ }
}
void zclient_reset(struct zclient *zclient)
@@ -447,7 +447,7 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
}
/* Resend all redistribute request. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
if (i != zclient->redist_default
&& vrf_bitmap_check(zclient->redist[afi][i],
@@ -456,10 +456,13 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
zclient, afi, i, 0,
vrf_id);
- /* If default information is needed. */
- if (vrf_bitmap_check(zclient->default_information, VRF_DEFAULT))
- zebra_message_send(zclient, ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
- vrf_id);
+ /* If default information is needed. */
+ if (vrf_bitmap_check(zclient->default_information[afi],
+ VRF_DEFAULT))
+ zebra_redistribute_default_send(
+ ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, afi,
+ vrf_id);
+ }
}
/* Send unregister requests to zebra daemon for the information in a VRF. */
@@ -512,7 +515,7 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
}
/* Flush all redistribute request. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
if (i != zclient->redist_default
&& vrf_bitmap_check(zclient->redist[afi][i],
@@ -521,10 +524,13 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id)
ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
i, 0, vrf_id);
- /* If default information is needed. */
- if (vrf_bitmap_check(zclient->default_information, VRF_DEFAULT))
- zebra_message_send(zclient, ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
- vrf_id);
+ /* If default information is needed. */
+ if (vrf_bitmap_check(zclient->default_information[afi],
+ VRF_DEFAULT))
+ zebra_redistribute_default_send(
+ ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, afi,
+ vrf_id);
+ }
}
/* Send request to zebra daemon to start or stop RA. */
@@ -620,12 +626,13 @@ void zclient_init(struct zclient *zclient, int redist_default,
zclient->redist_default = redist_default;
zclient->instance = instance;
/* Pending: make afi(s) an arg. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
redist_add_instance(&zclient->mi_redist[afi][redist_default],
instance);
- /* Set default-information redistribute to zero. */
- zclient->default_information = vrf_bitmap_init();
+ /* Set default-information redistribute to zero. */
+ zclient->default_information[afi] = vrf_bitmap_init();
+ }
if (zclient_debug)
zlog_debug("zclient_start is called");
@@ -1280,6 +1287,22 @@ int zebra_redistribute_send(int command, struct zclient *zclient, afi_t afi,
return zclient_send_message(zclient);
}
+int zebra_redistribute_default_send(int command, struct zclient *zclient,
+ afi_t afi, vrf_id_t vrf_id)
+{
+ struct stream *s;
+
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, command, vrf_id);
+ stream_putc(s, afi);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zclient_send_message(zclient);
+}
+
/* Get prefix in ZServ format; family should be filled in on prefix */
static void zclient_stream_get_prefix(struct stream *s, struct prefix *p)
{
@@ -2709,21 +2732,22 @@ void zclient_redistribute(int command, struct zclient *zclient, afi_t afi,
void zclient_redistribute_default(int command, struct zclient *zclient,
- vrf_id_t vrf_id)
+ afi_t afi, vrf_id_t vrf_id)
{
if (command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) {
- if (vrf_bitmap_check(zclient->default_information, vrf_id))
+ if (vrf_bitmap_check(zclient->default_information[afi], vrf_id))
return;
- vrf_bitmap_set(zclient->default_information, vrf_id);
+ vrf_bitmap_set(zclient->default_information[afi], vrf_id);
} else {
- if (!vrf_bitmap_check(zclient->default_information, vrf_id))
+ if (!vrf_bitmap_check(zclient->default_information[afi],
+ vrf_id))
return;
- vrf_bitmap_unset(zclient->default_information, vrf_id);
+ vrf_bitmap_unset(zclient->default_information[afi], vrf_id);
}
if (zclient->sock > 0)
- zebra_message_send(zclient, command, vrf_id);
+ zebra_redistribute_default_send(command, zclient, afi, vrf_id);
}
static void zclient_event(enum event event, struct zclient *zclient)
diff --git a/lib/zclient.h b/lib/zclient.h
index 831cccfb7e..401d6c400a 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -216,7 +216,7 @@ struct zclient {
vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX];
/* Redistribute defauilt. */
- vrf_bitmap_t default_information;
+ vrf_bitmap_t default_information[AFI_MAX];
/* Pointer to the callback functions. */
void (*zebra_connected)(struct zclient *);
@@ -479,13 +479,16 @@ extern int zebra_redistribute_send(int command, struct zclient *, afi_t,
int type, unsigned short instance,
vrf_id_t vrf_id);
+extern int zebra_redistribute_default_send(int command, struct zclient *zclient,
+ afi_t afi, vrf_id_t vrf_id);
+
/* If state has changed, update state and call zebra_redistribute_send. */
extern void zclient_redistribute(int command, struct zclient *, afi_t, int type,
unsigned short instance, vrf_id_t vrf_id);
/* If state has changed, update state and send the command to zebra. */
extern void zclient_redistribute_default(int command, struct zclient *,
- vrf_id_t vrf_id);
+ afi_t, vrf_id_t vrf_id);
/* Send the message in zclient->obuf to the zebra daemon (or enqueue it).
Returns 0 for success or -1 on an I/O error. */
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 5db9b529ef..54f1735e7a 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -269,7 +269,8 @@ DEFUN (show_zebra,
vty_out(vty, "Zebra Infomation\n");
vty_out(vty, " fail: %d\n", zclient->fail);
vty_out(vty, " redistribute default: %d\n",
- vrf_bitmap_check(zclient->default_information, VRF_DEFAULT));
+ vrf_bitmap_check(zclient->default_information[AFI_IP6],
+ VRF_DEFAULT));
vty_out(vty, " redistribute:");
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT))
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 714c47b4e6..6d1e44996e 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -96,8 +96,9 @@ struct external_info *ospf_external_info_check(struct ospf *ospf,
redist_on =
is_prefix_default(&p)
- ? vrf_bitmap_check(zclient->default_information,
- ospf->vrf_id)
+ ? vrf_bitmap_check(
+ zclient->default_information[AFI_IP],
+ ospf->vrf_id)
: (zclient->mi_redist[AFI_IP][type].enabled
|| vrf_bitmap_check(
zclient->redist[AFI_IP][type],
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index c7bde55cd9..79ddb192c1 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -655,7 +655,7 @@ int ospf_is_type_redistributed(struct ospf *ospf, int type,
unsigned short instance)
{
return (DEFAULT_ROUTE_TYPE(type)
- ? vrf_bitmap_check(zclient->default_information,
+ ? vrf_bitmap_check(zclient->default_information[AFI_IP],
ospf->vrf_id)
: ((instance
&& redist_check_instance(
@@ -793,8 +793,8 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
* existance.
*/
zclient_redistribute_default(
- ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
- zclient, ospf->vrf_id);
+ ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, AFI_IP,
+ ospf->vrf_id);
}
ospf_asbr_status_update(ospf, ++ospf->redistribute);
@@ -820,7 +820,7 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
zclient_redistribute_default(
ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
- zclient, ospf->vrf_id);
+ zclient, AFI_IP, ospf->vrf_id);
/* here , ex-info should be added since ex-info might
* have not updated earlier if def route is not exist.
* If ex-iinfo ex-info already exist , it will return
@@ -845,7 +845,7 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
zclient_redistribute_default(
ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
- zclient, ospf->vrf_id);
+ zclient, AFI_IP, ospf->vrf_id);
}
}
@@ -857,7 +857,7 @@ int ospf_redistribute_default_unset(struct ospf *ospf)
if (!ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0))
return CMD_SUCCESS;
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
- zclient, ospf->vrf_id);
+ zclient, AFI_IP, ospf->vrf_id);
}
ospf->default_originate = DEFAULT_ORIGINATE_NONE;
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index d0a34c0f93..86c8bfe1c2 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -90,11 +90,12 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
DEFPY (install_routes,
install_routes_cmd,
- "sharp install routes A.B.C.D$start <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
+ "sharp install routes <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n"
"install some routes\n"
"Routes to install\n"
- "Address to start /32 generation at\n"
+ "v4 Address to start /32 generation at\n"
+ "v6 Address to start /32 generation at\n"
"Nexthop to use(Can be an IPv4 or IPv6 address)\n"
"V4 Nexthop address to use\n"
"V6 Nexthop address to use\n"
@@ -119,9 +120,15 @@ DEFPY (install_routes,
memset(&nhop, 0, sizeof(nhop));
memset(&nhop_group, 0, sizeof(nhop_group));
- prefix.family = AF_INET;
- prefix.prefixlen = 32;
- prefix.u.prefix4 = start;
+ if (start4.s_addr != 0) {
+ prefix.family = AF_INET;
+ prefix.prefixlen = 32;
+ prefix.u.prefix4 = start4;
+ } else {
+ prefix.family = AF_INET6;
+ prefix.prefixlen = 128;
+ prefix.u.prefix6 = start6;
+ }
orig_prefix = prefix;
if (nexthop_group) {
@@ -185,12 +192,13 @@ DEFPY(vrf_label, vrf_label_cmd,
DEFPY (remove_routes,
remove_routes_cmd,
- "sharp remove routes A.B.C.D$start (1-1000000)$routes [instance (0-255)$instance]",
+ "sharp remove routes <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
"Sharp Routing Protocol\n"
"Remove some routes\n"
"Routes to remove\n"
- "Starting spot\n"
- "Routes to uniinstall\n"
+ "v4 Starting spot\n"
+ "v6 Starting spot\n"
+ "Routes to uninstall\n"
"instance to use\n"
"Value of instance\n")
{
@@ -199,9 +207,15 @@ DEFPY (remove_routes,
memset(&prefix, 0, sizeof(prefix));
- prefix.family = AF_INET;
- prefix.prefixlen = 32;
- prefix.u.prefix4 = start;
+ if (start4.s_addr != 0) {
+ prefix.family = AF_INET;
+ prefix.prefixlen = 32;
+ prefix.u.prefix4 = start4;
+ } else {
+ prefix.family = AF_INET6;
+ prefix.prefixlen = 128;
+ prefix.u.prefix6 = start6;
+ }
inst = instance;
rts = routes;
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 37591fa41f..c9f333e34b 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -129,6 +129,8 @@ static int interface_state_down(int command, struct zclient *zclient,
return 0;
}
+static struct timeval t_start;
+static struct timeval t_end;
extern uint32_t total_routes;
extern uint32_t installed_routes;
extern uint32_t removed_routes;
@@ -142,13 +144,23 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
uint32_t routes)
{
uint32_t temp, i;
+ bool v4 = false;
zlog_debug("Inserting %u routes", routes);
- temp = ntohl(p->u.prefix4.s_addr);
+ if (p->family == AF_INET) {
+ v4 = true;
+ temp = ntohl(p->u.prefix4.s_addr);
+ } else
+ temp = ntohl(p->u.val32[3]);
+
+ monotime(&t_start);
for (i = 0; i < routes; i++) {
route_add(p, (uint8_t)instance, nhg);
- p->u.prefix4.s_addr = htonl(++temp);
+ if (v4)
+ p->u.prefix4.s_addr = htonl(++temp);
+ else
+ p->u.val32[3] = htonl(++temp);
}
}
@@ -156,13 +168,23 @@ void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
uint32_t routes)
{
uint32_t temp, i;
+ bool v4 = false;
zlog_debug("Removing %u routes", routes);
- temp = ntohl(p->u.prefix4.s_addr);
+ if (p->family == AF_INET) {
+ v4 = true;
+ temp = ntohl(p->u.prefix4.s_addr);
+ } else
+ temp = ntohl(p->u.val32[3]);
+
+ monotime(&t_start);
for (i = 0; i < routes; i++) {
route_delete(p, (uint8_t)instance);
- p->u.prefix4.s_addr = htonl(++temp);
+ if (v4)
+ p->u.prefix4.s_addr = htonl(++temp);
+ else
+ p->u.val32[3] = htonl(++temp);
}
}
@@ -189,6 +211,7 @@ static void handle_repeated(bool installed)
static int route_notify_owner(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
+ struct timeval r;
struct prefix p;
enum zapi_route_notify_owner note;
uint32_t table;
@@ -200,7 +223,10 @@ static int route_notify_owner(int command, struct zclient *zclient,
case ZAPI_ROUTE_INSTALLED:
installed_routes++;
if (total_routes == installed_routes) {
- zlog_debug("Installed All Items");
+ monotime(&t_end);
+ timersub(&t_end, &t_start, &r);
+ zlog_debug("Installed All Items %ld.%ld", r.tv_sec,
+ r.tv_usec);
handle_repeated(true);
}
break;
@@ -213,7 +239,10 @@ static int route_notify_owner(int command, struct zclient *zclient,
case ZAPI_ROUTE_REMOVED:
removed_routes++;
if (total_routes == removed_routes) {
- zlog_debug("Removed all Items");
+ monotime(&t_end);
+ timersub(&t_end, &t_start, &r);
+ zlog_debug("Removed all Items %ld.%ld", r.tv_sec,
+ r.tv_usec);
handle_repeated(false);
}
break;
diff --git a/staticd/static_nht.c b/staticd/static_nht.c
index 44f7fb79da..38fd53a1f2 100644
--- a/staticd/static_nht.c
+++ b/staticd/static_nht.c
@@ -29,59 +29,68 @@
#include "static_zebra.h"
#include "static_nht.h"
-void static_nht_update(struct prefix *p, uint32_t nh_num, afi_t afi,
- vrf_id_t nh_vrf_id)
+static void static_nht_update_safi(struct prefix *p, uint32_t nh_num,
+ afi_t afi, safi_t safi, struct vrf *vrf,
+ vrf_id_t nh_vrf_id)
{
struct route_table *stable;
struct static_route *si;
struct static_vrf *svrf;
struct route_node *rn;
- struct vrf *vrf;
bool orig;
bool reinstall;
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- svrf = vrf->info;
- if (!svrf)
- continue;
+ svrf = vrf->info;
+ if (!svrf)
+ return;
- stable = static_vrf_static_table(afi, SAFI_UNICAST, svrf);
- if (!stable)
- continue;
+ stable = static_vrf_static_table(afi, safi, svrf);
+ if (!stable)
+ return;
- for (rn = route_top(stable); rn; rn = route_next(rn)) {
- reinstall = false;
- for (si = rn->info; si; si = si->next) {
- if (si->nh_vrf_id != nh_vrf_id)
- continue;
+ for (rn = route_top(stable); rn; rn = route_next(rn)) {
+ reinstall = false;
+ for (si = rn->info; si; si = si->next) {
+ if (si->nh_vrf_id != nh_vrf_id)
+ return;
- if (si->type != STATIC_IPV4_GATEWAY
- && si->type != STATIC_IPV4_GATEWAY_IFNAME
- && si->type != STATIC_IPV6_GATEWAY
- && si->type != STATIC_IPV6_GATEWAY_IFNAME)
- continue;
+ if (si->type != STATIC_IPV4_GATEWAY
+ && si->type != STATIC_IPV4_GATEWAY_IFNAME
+ && si->type != STATIC_IPV6_GATEWAY
+ && si->type != STATIC_IPV6_GATEWAY_IFNAME)
+ return;
- orig = si->nh_valid;
- if (p->family == AF_INET
- && p->u.prefix4.s_addr
- == si->addr.ipv4.s_addr)
- si->nh_valid = !!nh_num;
+ orig = si->nh_valid;
+ if (p->family == AF_INET
+ && p->u.prefix4.s_addr == si->addr.ipv4.s_addr)
+ si->nh_valid = !!nh_num;
- if (p->family == AF_INET6
- && memcmp(&p->u.prefix6, &si->addr.ipv6, 16)
- == 0)
- si->nh_valid = !!nh_num;
+ if (p->family == AF_INET6
+ && memcmp(&p->u.prefix6, &si->addr.ipv6, 16) == 0)
+ si->nh_valid = !!nh_num;
- if (orig != si->nh_valid)
- reinstall = true;
+ if (orig != si->nh_valid)
+ reinstall = true;
- if (reinstall) {
- static_zebra_route_add(
- rn, si, vrf->vrf_id,
- SAFI_UNICAST, true);
- reinstall = false;
- }
+ if (reinstall) {
+ static_zebra_route_add(rn, si, vrf->vrf_id,
+ safi, true);
+ reinstall = false;
}
}
}
}
+
+void static_nht_update(struct prefix *p, uint32_t nh_num, afi_t afi,
+ vrf_id_t nh_vrf_id)
+{
+
+ struct vrf *vrf;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ static_nht_update_safi(p, nh_num, afi, SAFI_UNICAST,
+ vrf, nh_vrf_id);
+ static_nht_update_safi(p, nh_num, afi, SAFI_MULTICAST,
+ vrf, nh_vrf_id);
+ }
+}
diff --git a/zebra/connected.c b/zebra/connected.c
index 54f4394a56..ab66eb3324 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -275,7 +275,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
/* Add connected IPv4 route to the interface. */
void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
- uint8_t prefixlen, struct in_addr *broad,
+ uint16_t prefixlen, struct in_addr *broad,
const char *label)
{
struct prefix_ipv4 *p;
@@ -473,7 +473,7 @@ static void connected_delete_helper(struct connected *ifc, struct prefix *p)
/* Delete connected IPv4 route to the interface. */
void connected_delete_ipv4(struct interface *ifp, int flags,
- struct in_addr *addr, uint8_t prefixlen,
+ struct in_addr *addr, uint16_t prefixlen,
struct in_addr *broad)
{
struct prefix p, d;
@@ -499,7 +499,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
/* Add connected IPv6 route to the interface. */
void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
- struct in6_addr *broad, uint8_t prefixlen,
+ struct in6_addr *broad, uint16_t prefixlen,
const char *label)
{
struct prefix_ipv6 *p;
@@ -556,7 +556,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
}
void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
- struct in6_addr *broad, uint8_t prefixlen)
+ struct in6_addr *broad, uint16_t prefixlen)
{
struct prefix p, d;
struct connected *ifc;
diff --git a/zebra/connected.h b/zebra/connected.h
index 75b6e05bda..415ecfd965 100644
--- a/zebra/connected.h
+++ b/zebra/connected.h
@@ -35,11 +35,11 @@ extern struct connected *connected_check_ptp(struct interface *ifp,
union prefixconstptr d);
extern void connected_add_ipv4(struct interface *ifp, int flags,
- struct in_addr *addr, uint8_t prefixlen,
+ struct in_addr *addr, uint16_t prefixlen,
struct in_addr *broad, const char *label);
extern void connected_delete_ipv4(struct interface *ifp, int flags,
- struct in_addr *addr, uint8_t prefixlen,
+ struct in_addr *addr, uint16_t prefixlen,
struct in_addr *broad);
extern void connected_delete_ipv4_unnumbered(struct connected *ifc);
@@ -49,10 +49,10 @@ extern void connected_down(struct interface *ifp, struct connected *ifc);
extern void connected_add_ipv6(struct interface *ifp, int flags,
struct in6_addr *address, struct in6_addr *broad,
- uint8_t prefixlen, const char *label);
+ uint16_t prefixlen, const char *label);
extern void connected_delete_ipv6(struct interface *ifp,
struct in6_addr *address,
- struct in6_addr *broad, uint8_t prefixlen);
+ struct in6_addr *broad, uint16_t prefixlen);
extern int connected_is_unnumbered(struct interface *);
diff --git a/zebra/main.c b/zebra/main.c
index 90d3dbc180..b54c36c109 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -407,10 +407,7 @@ int main(int argc, char **argv)
/*
* Initialize NS( and implicitly the VRF module), and make kernel
* routing socket. */
- zebra_ns_init();
- if (vrf_default_name_configured)
- vrf_set_default_name(vrf_default_name_configured,
- true);
+ zebra_ns_init((const char *)vrf_default_name_configured);
zebra_vty_init();
access_list_init();
prefix_list_init();
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index f48fc6addb..b9c1f0aefd 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -177,7 +177,8 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
send_redistribute = 0;
if (is_default_prefix(p)
- && vrf_bitmap_check(client->redist_default, re->vrf_id))
+ && vrf_bitmap_check(client->redist_default[afi],
+ re->vrf_id))
send_redistribute = 1;
else if (vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL],
re->vrf_id))
@@ -246,7 +247,8 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) {
if ((is_default_prefix(p)
- && vrf_bitmap_check(client->redist_default, re->vrf_id))
+ && vrf_bitmap_check(client->redist_default[afi],
+ re->vrf_id))
|| vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL],
re->vrf_id)
|| (re->instance
@@ -354,13 +356,41 @@ stream_failure:
void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS)
{
- vrf_bitmap_set(client->redist_default, zvrf_id(zvrf));
+ afi_t afi = 0;
+
+ STREAM_GETC(msg, afi);
+
+ if (afi == 0 || afi >= AFI_MAX) {
+ flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
+ "%s: Specified afi %u does not exist",
+ __PRETTY_FUNCTION__, afi);
+ return;
+ }
+
+ vrf_bitmap_set(client->redist_default[afi], zvrf_id(zvrf));
zebra_redistribute_default(client, zvrf_id(zvrf));
+
+stream_failure:
+ return;
}
void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS)
{
- vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf));
+ afi_t afi = 0;
+
+ STREAM_GETC(msg, afi);
+
+ if (afi == 0 || afi >= AFI_MAX) {
+ flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
+ "%s: Specified afi %u does not exist",
+ __PRETTY_FUNCTION__, afi);
+ return;
+ }
+
+ vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
+
+stream_failure:
+ return;
}
/* Interface up information. */
diff --git a/zebra/rib.h b/zebra/rib.h
index ae25a0e679..a478fffddb 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -81,12 +81,20 @@ struct route_entry {
uint32_t flags;
/* RIB internal status */
- uint8_t status;
+ uint32_t status;
#define ROUTE_ENTRY_REMOVED 0x1
/* to simplify NHT logic when NHs change, instead of doing a NH by NH cmp */
#define ROUTE_ENTRY_NEXTHOPS_CHANGED 0x2
+/* The Route Entry has changed */
#define ROUTE_ENTRY_CHANGED 0x4
+/* The Label has changed on the Route entry */
#define ROUTE_ENTRY_LABELS_CHANGED 0x8
+/* Route is queued for Installation into the Data Plane */
+#define ROUTE_ENTRY_QUEUED 0x10
+/* Route is installed into the Data Plane */
+#define ROUTE_ENTRY_INSTALLED 0x20
+/* Route has Failed installation into the Data Plane in some manner */
+#define ROUTE_ENTRY_FAILED 0x40
/* Nexthop information. */
uint8_t nexthop_num;
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index faa0eb90e4..15f9da0cba 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1702,10 +1702,11 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
int i;
afi_t afi;
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
- vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf));
+ vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
+ }
vrf_bitmap_unset(client->ifinfo, zvrf_id(zvrf));
vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf));
}
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index ba0f1b41aa..feede21cd9 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -157,9 +157,9 @@ struct zebra_dplane_provider {
/* Flags */
int dp_flags;
- dplane_provider_process_fp dp_fp;
+ int (*dp_fp)(struct zebra_dplane_provider *prov);
- dplane_provider_fini_fp dp_fini;
+ int (*dp_fini)(struct zebra_dplane_provider *prov, bool early_p);
_Atomic uint32_t dp_in_counter;
_Atomic uint32_t dp_in_queued;
@@ -189,7 +189,7 @@ static struct zebra_dplane_globals {
pthread_mutex_t dg_mutex;
/* Results callback registered by zebra 'core' */
- dplane_results_fp dg_results_cb;
+ int (*dg_results_cb)(struct dplane_ctx_q *ctxlist);
/* Sentinel for beginning of shutdown */
volatile bool dg_is_shutdown;
@@ -988,12 +988,14 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
int dplane_provider_register(const char *name,
enum dplane_provider_prio prio,
int flags,
- dplane_provider_process_fp fp,
- dplane_provider_fini_fp fini_fp,
- void *data)
+ int (*fp)(struct zebra_dplane_provider *),
+ int (*fini_fp)(struct zebra_dplane_provider *,
+ bool early),
+ void *data,
+ struct zebra_dplane_provider **prov_p)
{
int ret = 0;
- struct zebra_dplane_provider *p, *last;
+ struct zebra_dplane_provider *p = NULL, *last;
/* Validate */
if (fp == NULL) {
@@ -1054,6 +1056,9 @@ int dplane_provider_register(const char *name,
p->dp_name, p->dp_id, p->dp_priority);
done:
+ if (prov_p)
+ *prov_p = p;
+
return ret;
}
@@ -1210,15 +1215,6 @@ int dplane_provider_work_ready(void)
}
/*
- * Zebra registers a results callback with the dataplane system
- */
-int dplane_results_register(dplane_results_fp fp)
-{
- zdplane_info.dg_results_cb = fp;
- return AOK;
-}
-
-/*
* Kernel dataplane provider
*/
@@ -1357,7 +1353,7 @@ static void dplane_provider_init(void)
DPLANE_PROV_FLAGS_DEFAULT,
kernel_dplane_process_func,
NULL,
- NULL);
+ NULL, NULL);
if (ret != AOK)
zlog_err("Unable to register kernel dplane provider: %d",
@@ -1370,7 +1366,7 @@ static void dplane_provider_init(void)
DPLANE_PROV_FLAGS_DEFAULT,
test_dplane_process_func,
test_dplane_shutdown_func,
- NULL /* data */);
+ NULL /* data */, NULL);
if (ret != AOK)
zlog_err("Unable to register test dplane provider: %d",
@@ -1677,27 +1673,20 @@ static int dplane_thread_loop(struct thread *event)
counter, error_counter);
/*
- * TODO -- I'd rather hand lists through the api to zebra main,
+ * Hand lists through the api to zebra main,
* to reduce the number of lock/unlock cycles
*/
- for (ctx = TAILQ_FIRST(&error_list); ctx; ) {
- TAILQ_REMOVE(&error_list, ctx, zd_q_entries);
-
- /* Call through to zebra main */
- (*zdplane_info.dg_results_cb)(ctx);
- ctx = TAILQ_FIRST(&error_list);
- }
+ /* Call through to zebra main */
+ (zdplane_info.dg_results_cb)(&error_list);
+ TAILQ_INIT(&error_list);
- for (ctx = TAILQ_FIRST(&work_list); ctx; ) {
- TAILQ_REMOVE(&work_list, ctx, zd_q_entries);
- /* Call through to zebra main */
- (*zdplane_info.dg_results_cb)(ctx);
+ /* Call through to zebra main */
+ (zdplane_info.dg_results_cb)(&work_list);
- ctx = TAILQ_FIRST(&work_list);
- }
+ TAILQ_INIT(&work_list);
done:
return 0;
@@ -1782,7 +1771,8 @@ void zebra_dplane_start(void)
/*
* Initialize the dataplane module at startup; called by zebra rib_init()
*/
-void zebra_dplane_init(void)
+void zebra_dplane_init(int (*results_fp)(struct dplane_ctx_q *))
{
zebra_dplane_init_internal(&zebrad);
+ zdplane_info.dg_results_cb = results_fp;
}
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 1336850510..1c053b85bf 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -250,21 +250,6 @@ enum dplane_provider_prio {
DPLANE_PRIO_LAST
};
-/* Provider's entry-point for incoming work, called in the context of the
- * dataplane pthread. The dataplane pthread enqueues any new work to the
- * provider's 'inbound' queue, then calls the callback. The dataplane
- * then checks the provider's outbound queue.
- */
-typedef int (*dplane_provider_process_fp)(struct zebra_dplane_provider *prov);
-
-/* Provider's entry-point for shutdown and cleanup. Called with 'early'
- * during shutdown, to indicate that the dataplane subsystem is allowing
- * work to move through the providers and finish. When called without 'early',
- * the provider should release all resources (if it has any allocated).
- */
-typedef int (*dplane_provider_fini_fp)(struct zebra_dplane_provider *prov,
- bool early);
-
/* Flags values used during provider registration. */
#define DPLANE_PROV_FLAGS_DEFAULT 0x0
@@ -273,14 +258,30 @@ typedef int (*dplane_provider_fini_fp)(struct zebra_dplane_provider *prov,
/* Provider registration: ordering or priority value, callbacks, and optional
- * opaque data value.
+ * opaque data value. If 'prov_p', return the newly-allocated provider object
+ * on success.
+ */
+
+/* Providers offer an entry-point for incoming work, called in the context of
+ * the dataplane pthread. The dataplane pthread enqueues any new work to the
+ * provider's 'inbound' queue, then calls the callback. The dataplane
+ * then checks the provider's outbound queue for completed work.
+ */
+
+/* Providers offer an entry-point for shutdown and cleanup. This is called
+ * with 'early' during shutdown, to indicate that the dataplane subsystem
+ * is allowing work to move through the providers and finish.
+ * When called without 'early', the provider should release
+ * all resources (if it has any allocated).
*/
int dplane_provider_register(const char *name,
enum dplane_provider_prio prio,
int flags,
- dplane_provider_process_fp fp,
- dplane_provider_fini_fp fini_fp,
- void *data);
+ int (*fp)(struct zebra_dplane_provider *),
+ int (*fini_fp)(struct zebra_dplane_provider *,
+ bool early),
+ void *data,
+ struct zebra_dplane_provider **prov_p);
/* Accessors for provider attributes */
const char *dplane_provider_get_name(const struct zebra_dplane_provider *prov);
@@ -318,20 +319,13 @@ void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov,
struct zebra_dplane_ctx *ctx);
/*
- * Zebra registers a results callback with the dataplane. The callback is
- * called in the dataplane pthread context, so the expectation is that the
- * context is queued for the zebra main pthread or that processing
- * is very limited.
- */
-typedef int (*dplane_results_fp)(struct zebra_dplane_ctx *ctx);
-
-int dplane_results_register(dplane_results_fp fp);
-
-/*
* Initialize the dataplane modules at zebra startup. This is currently called
- * by the rib module.
+ * by the rib module. Zebra registers a results callback with the dataplane.
+ * The callback is called in the dataplane pthread context,
+ * so the expectation is that the contexts are queued for the zebra
+ * main pthread.
*/
-void zebra_dplane_init(void);
+void zebra_dplane_init(int (*) (struct dplane_ctx_q *));
/*
* Start the dataplane pthread. This step needs to be run later than the
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index a4e1022148..ef31fcf45d 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -215,6 +215,12 @@ static int zebra_ns_ready_read(struct thread *t)
if (err < 0)
return zebra_ns_continue_read(zns_info, stop_retry);
+ /* check default name is not already set */
+ if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) {
+ zlog_warn("NS notify : NS %s is already default VRF."
+ "Cancel VRF Creation", basename(netnspath));
+ return zebra_ns_continue_read(zns_info, 1);
+ }
if (zebra_ns_notify_is_default_netns(basename(netnspath))) {
zlog_warn(
"NS notify : NS %s is default VRF."
@@ -266,9 +272,10 @@ static int zebra_ns_notify_read(struct thread *t)
break;
}
- if (event->mask & IN_DELETE)
- return zebra_ns_delete(event->name);
-
+ if (event->mask & IN_DELETE) {
+ zebra_ns_delete(event->name);
+ continue;
+ }
netnspath = ns_netns_pathname(NULL, event->name);
if (!netnspath)
continue;
@@ -311,6 +318,12 @@ void zebra_ns_notify_parse(void)
dent->d_name);
continue;
}
+ /* check default name is not already set */
+ if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) {
+ zlog_warn("NS notify : NS %s is already default VRF."
+ "Cancel VRF Creation", dent->d_name);
+ continue;
+ }
if (zebra_ns_notify_is_default_netns(dent->d_name)) {
zlog_warn(
"NS notify : NS %s is default VRF."
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 03987fcb5b..0c743d8678 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -183,7 +183,7 @@ int zebra_ns_final_shutdown(struct ns *ns)
return 0;
}
-int zebra_ns_init(void)
+int zebra_ns_init(const char *optional_default_name)
{
ns_id_t ns_id;
ns_id_t ns_id_external;
@@ -207,6 +207,10 @@ int zebra_ns_init(void)
/* Default NS is activated */
zebra_ns_enable(ns_id_external, (void **)&dzns);
+ if (optional_default_name)
+ vrf_set_default_name(optional_default_name,
+ true);
+
if (vrf_is_backend_netns()) {
ns_add_hook(NS_NEW_HOOK, zebra_ns_new);
ns_add_hook(NS_ENABLE_HOOK, zebra_ns_enabled);
diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h
index d3592f8f30..01af64c17b 100644
--- a/zebra/zebra_ns.h
+++ b/zebra/zebra_ns.h
@@ -60,7 +60,7 @@ struct zebra_ns {
struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id);
-int zebra_ns_init(void);
+int zebra_ns_init(const char *optional_default_name);
int zebra_ns_enable(ns_id_t ns_id, void **info);
int zebra_ns_disabled(struct ns *ns);
int zebra_ns_early_shutdown(struct ns *ns);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index b7f97ac612..7e4ac1ddd2 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1871,31 +1871,6 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_vrf(ctx), dest_str, ctx,
dplane_op2str(op), dplane_res2str(status));
- if (op == DPLANE_OP_ROUTE_DELETE) {
- /*
- * In the delete case, the zebra core datastructs were
- * updated (or removed) at the time the delete was issued,
- * so we're just notifying the route owner.
- */
- if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
- zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED);
-
- if (zvrf)
- zvrf->removals++;
- } else {
- zsend_route_notify_owner_ctx(ctx,
- ZAPI_ROUTE_REMOVE_FAIL);
-
- zlog_warn("%u:%s: Route Deletion failure",
- dplane_ctx_get_vrf(ctx),
- prefix2str(dest_pfx,
- dest_str, sizeof(dest_str)));
- }
-
- /* Nothing more to do in delete case */
- goto done;
- }
-
/*
* Update is a bit of a special case, where we may have both old and new
* routes to post-process.
@@ -1955,59 +1930,92 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx)
goto done;
}
- if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
- /* Update zebra nexthop FIB flag for each
- * nexthop that was installed.
- */
- for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), ctx_nexthop)) {
+ switch (op) {
+ case DPLANE_OP_NONE:
+ break;
+ case DPLANE_OP_ROUTE_INSTALL:
+ case DPLANE_OP_ROUTE_UPDATE:
+ if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
+ /* Update zebra nexthop FIB flag for each
+ * nexthop that was installed.
+ */
+ for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx),
+ ctx_nexthop)) {
- for (ALL_NEXTHOPS(re->ng, nexthop)) {
- if (nexthop_same(ctx_nexthop, nexthop))
- break;
+ for (ALL_NEXTHOPS(re->ng, nexthop)) {
+ if (nexthop_same(ctx_nexthop, nexthop))
+ break;
+ }
+
+ if (nexthop == NULL)
+ continue;
+
+ if (CHECK_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_RECURSIVE))
+ continue;
+
+ if (CHECK_FLAG(ctx_nexthop->flags,
+ NEXTHOP_FLAG_FIB))
+ SET_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB);
+ else
+ UNSET_FLAG(nexthop->flags,
+ NEXTHOP_FLAG_FIB);
}
- if (nexthop == NULL)
- continue;
+ if (zvrf) {
+ zvrf->installs++;
+ /* Set flag for nexthop tracking processing */
+ zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED;
+ }
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- continue;
+ /* Redistribute */
+ /*
+ * TODO -- still calling the redist api using the
+ * route_entries, and there's a corner-case here:
+ * if there's no client for the 'new' route, a redist
+ * deleting the 'old' route will be sent. But if the
+ * 'old' context info was stale, 'old_re' will be
+ * NULL here and that delete will not be sent.
+ */
+ redistribute_update(dest_pfx, src_pfx, re, old_re);
- if (CHECK_FLAG(ctx_nexthop->flags,
- NEXTHOP_FLAG_FIB))
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
- else
- UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
- }
+ /* Notify route owner */
+ zsend_route_notify_owner(re, dest_pfx,
+ ZAPI_ROUTE_INSTALLED);
- if (zvrf) {
- zvrf->installs++;
- /* Set flag for nexthop tracking processing */
- zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED;
- }
+ } else {
+ zsend_route_notify_owner(re, dest_pfx,
+ ZAPI_ROUTE_FAIL_INSTALL);
- /* Redistribute */
- /* TODO -- still calling the redist api using the route_entries,
- * and there's a corner-case here: if there's no client
- * for the 'new' route, a redist deleting the 'old' route
- * will be sent. But if the 'old' context info was stale,
- * 'old_re' will be NULL here and that delete will not be sent.
+ zlog_warn("%u:%s: Route install failed",
+ dplane_ctx_get_vrf(ctx),
+ prefix2str(dest_pfx,
+ dest_str, sizeof(dest_str)));
+ }
+ break;
+ case DPLANE_OP_ROUTE_DELETE:
+ /*
+ * In the delete case, the zebra core datastructs were
+ * updated (or removed) at the time the delete was issued,
+ * so we're just notifying the route owner.
*/
- redistribute_update(dest_pfx, src_pfx, re, old_re);
-
- /* Notify route owner */
- zsend_route_notify_owner(re,
- dest_pfx, ZAPI_ROUTE_INSTALLED);
+ if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
+ zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED);
- } else {
- zsend_route_notify_owner(re, dest_pfx,
- ZAPI_ROUTE_FAIL_INSTALL);
+ if (zvrf)
+ zvrf->removals++;
+ } else {
+ zsend_route_notify_owner_ctx(ctx,
+ ZAPI_ROUTE_REMOVE_FAIL);
- zlog_warn("%u:%s: Route install failed",
- dplane_ctx_get_vrf(ctx),
- prefix2str(dest_pfx,
- dest_str, sizeof(dest_str)));
+ zlog_warn("%u:%s: Route Deletion failure",
+ dplane_ctx_get_vrf(ctx),
+ prefix2str(dest_pfx,
+ dest_str, sizeof(dest_str)));
+ }
+ break;
}
-
done:
/* Return context to dataplane module */
@@ -2144,43 +2152,66 @@ static wq_item_status meta_queue_process(struct work_queue *dummy, void *data)
return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
}
-/* Look into the RN and queue it into one or more priority queues,
- * increasing the size for each data push done.
+
+/*
+ * Look into the RN and queue it into the highest priority queue
+ * at this point in time for processing.
+ *
+ * We will enqueue a route node only once per invocation.
+ *
+ * There are two possibilities here that should be kept in mind.
+ * If the original invocation has not been pulled off for processing
+ * yet, A subsuquent invocation can have a route entry with a better
+ * meta queue index value and we can have a situation where
+ * we might have the same node enqueued 2 times. Not necessarily
+ * an optimal situation but it should be ok.
+ *
+ * The other possibility is that the original invocation has not
+ * been pulled off for processing yet, A subsusquent invocation
+ * doesn't have a route_entry with a better meta-queue and the
+ * original metaqueue index value will win and we'll end up with
+ * the route node enqueued once.
*/
static void rib_meta_queue_add(struct meta_queue *mq, struct route_node *rn)
{
- struct route_entry *re;
+ struct route_entry *re = NULL, *curr_re = NULL;
+ uint8_t qindex = MQ_SIZE, curr_qindex = MQ_SIZE;
+ struct zebra_vrf *zvrf;
- RNODE_FOREACH_RE (rn, re) {
- uint8_t qindex = route_info[re->type].meta_q_map;
- struct zebra_vrf *zvrf;
+ RNODE_FOREACH_RE (rn, curr_re) {
+ curr_qindex = route_info[curr_re->type].meta_q_map;
- /* Invariant: at this point we always have rn->info set. */
- if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
- RIB_ROUTE_QUEUED(qindex))) {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- rnode_debug(
- rn, re->vrf_id,
- "rn %p is already queued in sub-queue %u",
- (void *)rn, qindex);
- continue;
+ if (curr_qindex <= qindex) {
+ re = curr_re;
+ qindex = curr_qindex;
}
+ }
- SET_FLAG(rib_dest_from_rnode(rn)->flags,
- RIB_ROUTE_QUEUED(qindex));
- listnode_add(mq->subq[qindex], rn);
- route_lock_node(rn);
- mq->size++;
+ if (!re)
+ return;
+ /* Invariant: at this point we always have rn->info set. */
+ if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
+ RIB_ROUTE_QUEUED(qindex))) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
rnode_debug(rn, re->vrf_id,
- "queued rn %p into sub-queue %u",
+ "rn %p is already queued in sub-queue %u",
(void *)rn, qindex);
-
- zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
- if (zvrf)
- zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED;
+ return;
}
+
+ SET_FLAG(rib_dest_from_rnode(rn)->flags, RIB_ROUTE_QUEUED(qindex));
+ listnode_add(mq->subq[qindex], rn);
+ route_lock_node(rn);
+ mq->size++;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ rnode_debug(rn, re->vrf_id, "queued rn %p into sub-queue %u",
+ (void *)rn, qindex);
+
+ zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
+ if (zvrf)
+ zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED;
}
/* Add route_node to work queue and schedule processing */
@@ -3165,21 +3196,34 @@ void rib_close_table(struct route_table *table)
static int rib_process_dplane_results(struct thread *thread)
{
struct zebra_dplane_ctx *ctx;
+ struct dplane_ctx_q ctxlist;
+
+ /* Dequeue a list of completed updates with one lock/unlock cycle */
do {
+ TAILQ_INIT(&ctxlist);
+
/* Take lock controlling queue of results */
pthread_mutex_lock(&dplane_mutex);
{
/* Dequeue context block */
- ctx = dplane_ctx_dequeue(&rib_dplane_q);
+ dplane_ctx_list_append(&ctxlist, &rib_dplane_q);
}
pthread_mutex_unlock(&dplane_mutex);
- if (ctx)
- rib_process_after(ctx);
- else
+ /* Dequeue context block */
+ ctx = dplane_ctx_dequeue(&ctxlist);
+
+ /* If we've emptied the results queue, we're done */
+ if (ctx == NULL)
break;
+ while (ctx) {
+ rib_process_after(ctx);
+
+ ctx = dplane_ctx_dequeue(&ctxlist);
+ }
+
} while (1);
/* Check for nexthop tracking processing after finishing with results */
@@ -3193,17 +3237,17 @@ static int rib_process_dplane_results(struct thread *thread)
* the dataplane pthread. We enqueue the results here for processing by
* the main thread later.
*/
-static int rib_dplane_results(struct zebra_dplane_ctx *ctx)
+static int rib_dplane_results(struct dplane_ctx_q *ctxlist)
{
/* Take lock controlling queue of results */
pthread_mutex_lock(&dplane_mutex);
{
- /* Enqueue context block */
- dplane_ctx_enqueue_tail(&rib_dplane_q, ctx);
+ /* Enqueue context blocks */
+ dplane_ctx_list_append(&rib_dplane_q, ctxlist);
}
pthread_mutex_unlock(&dplane_mutex);
- /* Ensure event is signalled to zebra main thread */
+ /* Ensure event is signalled to zebra main pthread */
thread_add_event(zebrad.master, rib_process_dplane_results, NULL, 0,
&t_dplane);
@@ -3218,8 +3262,7 @@ void rib_init(void)
/* Init dataplane, and register for results */
pthread_mutex_init(&dplane_mutex, NULL);
TAILQ_INIT(&rib_dplane_q);
- zebra_dplane_init();
- dplane_results_register(rib_dplane_results);
+ zebra_dplane_init(rib_dplane_results);
}
/*
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index ae18a0d290..f0cc8d4fd7 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -106,7 +106,7 @@ struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf,
info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info));
info->zvrf = zvrf;
info->afi = afi;
- info->safi = SAFI_UNICAST;
+ info->safi = safi;
route_table_set_info(zrt->table, info);
zrt->table->cleanup = zebra_rtable_node_cleanup;
@@ -127,6 +127,25 @@ unsigned long zebra_router_score_proto(uint8_t proto, unsigned short instance)
return cnt;
}
+void zebra_router_show_table_summary(struct vty *vty)
+{
+ struct zebra_router_table *zrt;
+
+ vty_out(vty,
+ "VRF NS ID VRF ID AFI SAFI Table Count\n");
+ vty_out(vty,
+ "---------------------------------------------------------------------------\n");
+ RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
+ rib_table_info_t *info = route_table_get_info(zrt->table);
+
+ vty_out(vty, "%-16s%5d %9d %7s %15s %8d %10lu\n", info->zvrf->vrf->name,
+ zrt->ns_id, info->zvrf->vrf->vrf_id,
+ afi2str(zrt->afi), safi2str(zrt->safi),
+ zrt->tableid,
+ zrt->table->count);
+ }
+}
+
void zebra_router_sweep_route(void)
{
struct zebra_router_table *zrt;
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index d6b8b66087..1e0788d1ba 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -81,4 +81,6 @@ extern int zebra_router_config_write(struct vty *vty);
extern unsigned long zebra_router_score_proto(uint8_t proto,
unsigned short instance);
extern void zebra_router_sweep_route(void);
+
+extern void zebra_router_show_table_summary(struct vty *vty);
#endif
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 38b8b43d73..f1458cb138 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -370,22 +370,10 @@ static void zebra_rnhtable_node_cleanup(struct route_table *table,
static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
safi_t safi)
{
- rib_table_info_t *info;
- struct route_table *table;
-
assert(!zvrf->table[afi][safi]);
- table = zebra_router_get_table(zvrf, zvrf->table_id, afi, safi);
-
- table->cleanup = zebra_rtable_node_cleanup;
- zvrf->table[afi][safi] = table;
-
- XFREE(MTYPE_RIB_TABLE_INFO, table->info);
- info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info));
- info->zvrf = zvrf;
- info->afi = afi;
- info->safi = safi;
- route_table_set_info(table, info);
+ zvrf->table[afi][safi] =
+ zebra_router_get_table(zvrf, zvrf->table_id, afi, safi);
}
/* Allocate new zebra VRF. */
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 8b06d2ae11..b18f0e943c 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -2857,6 +2857,20 @@ DEFUN (no_zebra_dplane_queue_limit,
return CMD_SUCCESS;
}
+DEFUN (zebra_show_routing_tables_summary,
+ zebra_show_routing_tables_summary_cmd,
+ "show zebra router table summary",
+ SHOW_STR
+ ZEBRA_STR
+ "The Zebra Router Information\n"
+ "Table Information about this Zebra Router\n"
+ "Summary Information\n")
+{
+ zebra_router_show_table_summary(vty);
+
+ return CMD_SUCCESS;
+}
+
/* Table configuration write function. */
static int config_write_table(struct vty *vty)
{
@@ -3000,4 +3014,6 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_dataplane_providers_cmd);
install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd);
install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd);
+
+ install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
}
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index b55ca60c00..86a7812780 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -687,10 +687,11 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
struct zebra_vrf *zvrf = NULL;
struct timeval detect_start_time = {0, 0};
- zvrf = zebra_vrf_lookup_by_id(n->zvni->vrf_id);
+ zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
if (!zvrf)
return;
+ zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
ipaddr2str(&n->ip, buf2, sizeof(buf2));
prefix_mac2str(&n->emac, buf1, sizeof(buf1));
type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ?
@@ -1135,7 +1136,7 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
struct zebra_vrf *zvrf;
struct timeval detect_start_time = {0, 0};
- zvrf = zebra_vrf_lookup_by_id(mac->zvni->vrf_id);
+ zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
vty = (struct vty *)ctxt;
prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
@@ -2296,7 +2297,7 @@ static void zvni_process_neigh_on_local_mac_change(zebra_vni_t *zvni,
struct zebra_vrf *zvrf = NULL;
char buf[ETHER_ADDR_STRLEN];
- zvrf = vrf_info_lookup(zvni->vrf_id);
+ zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
@@ -2891,7 +2892,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
}
}
- zvrf = vrf_info_lookup(zvni->vrf_id);
+ zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
if (!zvrf)
return -1;
@@ -6907,8 +6908,8 @@ void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s: duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
- __PRETTY_FUNCTION__,
+ "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
+ vrf_id_to_name(zvrf->vrf->vrf_id),
zvrf->dup_addr_detect ? "enable" : "disable",
zvrf->dad_max_moves,
zvrf->dad_time,
@@ -8904,16 +8905,16 @@ static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t)
nbr = THREAD_ARG(t);
/* since this is asynchronous we need sanity checks*/
- zvrf = vrf_info_lookup(nbr->zvni->vrf_id);
- if (!zvrf)
+ nbr = zvni_neigh_lookup(zvni, &nbr->ip);
+ if (!nbr)
return 0;
zvni = zvni_lookup(nbr->zvni->vni);
if (!zvni)
return 0;
- nbr = zvni_neigh_lookup(zvni, &nbr->ip);
- if (!nbr)
+ zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+ if (!zvrf)
return 0;
if (IS_ZEBRA_DEBUG_VXLAN)
@@ -8954,16 +8955,16 @@ static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t)
mac = THREAD_ARG(t);
/* since this is asynchronous we need sanity checks*/
- zvrf = vrf_info_lookup(mac->zvni->vrf_id);
- if (!zvrf)
+ mac = zvni_mac_lookup(zvni, &mac->macaddr);
+ if (!mac)
return 0;
zvni = zvni_lookup(mac->zvni->vni);
if (!zvni)
return 0;
- mac = zvni_mac_lookup(zvni, &mac->macaddr);
- if (!mac)
+ zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+ if (!zvrf)
return 0;
if (IS_ZEBRA_DEBUG_VXLAN)
diff --git a/zebra/zserv.c b/zebra/zserv.c
index a48505a514..502186d226 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -616,11 +616,12 @@ static void zserv_client_free(struct zserv *client)
pthread_mutex_destroy(&client->ibuf_mtx);
/* Free bitmaps. */
- for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++)
vrf_bitmap_free(client->redist[afi][i]);
- vrf_bitmap_free(client->redist_default);
+ vrf_bitmap_free(client->redist_default[afi]);
+ }
vrf_bitmap_free(client->ifinfo);
vrf_bitmap_free(client->ridinfo);
@@ -700,10 +701,11 @@ static struct zserv *zserv_client_create(int sock)
memory_order_relaxed);
/* Initialize flags */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
client->redist[afi][i] = vrf_bitmap_init();
- client->redist_default = vrf_bitmap_init();
+ client->redist_default[afi] = vrf_bitmap_init();
+ }
client->ifinfo = vrf_bitmap_init();
client->ridinfo = vrf_bitmap_init();
diff --git a/zebra/zserv.h b/zebra/zserv.h
index f0b8934ae1..041485cdc2 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -87,7 +87,7 @@ struct zserv {
vrf_bitmap_t redist[AFI_MAX][ZEBRA_ROUTE_MAX];
/* Redistribute default route flag. */
- vrf_bitmap_t redist_default;
+ vrf_bitmap_t redist_default[AFI_MAX];
/* Interface information. */
vrf_bitmap_t ifinfo;