]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #3605 from donaldsharp/bfd_24_minutes
authorRafael Zalamena <rzalamena@users.noreply.github.com>
Mon, 14 Jan 2019 13:20:54 +0000 (11:20 -0200)
committerGitHub <noreply@github.com>
Mon, 14 Jan 2019 13:20:54 +0000 (11:20 -0200)
bfdd: Fix timer print-out function

35 files changed:
bfdd/bfd.c
bfdd/bfd.h
bfdd/bfd_packet.c
bfdd/bsd.c
bfdd/linux.c
bfdd/ptm_adapter.c
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_keepalives.c
bgpd/bgp_mac.c [new file with mode: 0644]
bgpd/bgp_mac.h [new file with mode: 0644]
bgpd/bgp_mplsvpn.c
bgpd/bgp_route.c
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
bgpd/subdir.am
lib/frr_pthread.c
lib/frr_pthread.h
lib/prefix.h
lib/thread.c
sharpd/sharp_vty.c
sharpd/sharp_zebra.c
staticd/static_nht.c
zebra/rib.h
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_netns_notify.c
zebra/zebra_rib.c
zebra/zebra_router.c
zebra/zebra_router.h
zebra/zebra_vrf.c
zebra/zebra_vty.c
zebra/zebra_vxlan.c

index 7ab71511a6880da0e6bd5eb6957a59aca26f9381..df263a91c97a3d787c995918df358d1417a576f0 100644 (file)
@@ -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 */
@@ -552,6 +553,24 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
                        return NULL;
        }
 
+       /*
+        * 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
@@ -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 */
index 3a58a8d53cfeab25e889167cb18a1267c19bc882..a3e5ad14477ac07861281e6bec89c6fa4dd4b1f4 100644 (file)
@@ -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_ */
index 606f739b4606a884c5e791883b7c0c1e4ad798c7..9cfd7e866f8441338865d20ddac489b5fa4f0277 100644 (file)
@@ -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) {
index e0fb340e30e3087bd6fdb935b2bd42380f6d0f93..923fbd909eba6aab953257dfc6bdac1c7842b9a3 100644 (file)
 /*
  * 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)
 {
        /*
index e260851ddba6a229573406c7540c3e20b3a99ec0..3a76b459d7ea0b1f96a14772514d39049b233bb6 100644 (file)
 /*
  * 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__)))
 {
index f9c7c16fb1349e860c981ba223ae8e4336ed6bc7..a57167376a75eaf32b16716f5736b79c6589ce2c 100644 (file)
@@ -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)
index b990e99bda00569b56a9679666f170b6af077dd0..03f31eddfc1582d469686572d8a2b1585d88e532 100644 (file)
@@ -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. */
index 47a4182fee5a8de8d6ac9af972b0fe0b55bc836b..6d5c647b21c296f4d794f03cc2c398350f295ad6 100644 (file)
@@ -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;
index 50aad70ddc56fd70eb5ea32d4292e8b13cd29d33..87e3ff2495270c8285657fcb30146d58f7398fe4 100644 (file)
@@ -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 (file)
index 0000000..24f93e4
--- /dev/null
@@ -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 (file)
index 0000000..1dd987e
--- /dev/null
@@ -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
index cf91faf964a9b93eda47effb2b57374a8913ae3d..d0ccdcedfbfdd216d51dbfb0cf342f55118ad3c8 100644 (file)
@@ -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;
 }
index 31cd3d1f051ee9aba04ef9f216986227e34f7d52..356167470071946c36f04c536b08eab2bba52daf 100644 (file)
@@ -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);
index 2a4421aa54d30089d77699025c5100ec70f8075e..cf1421f5a6e3b733d492aad7e5b29ebc7bc938cd 100644 (file)
@@ -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);
 
index 66d33337395b49b0dfe02537fc7cae9cfc4c7d10..3c4b219466ce37d643cb77eb16151b8aa733a39d 100644 (file)
@@ -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);
 
index 7a3afbd18d543fa0bf99e30ba168e553c766c152..5b8ceb054149e1999990d802cd1872a6aca531ed 100644 (file)
@@ -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();
 }
index f28ca9fa0b88a1d1832f2d2a6c967362e82aa28c..484fc105e808dccee102462faad766bdf0776e9d 100644 (file)
@@ -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;
 
index 7d7d3ca189068c685bd797a5e52b0407068b71a6..7dd1d73f69ce929813095392aa76c1adc6334b94 100644 (file)
@@ -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 \
index a0223730b8e4a6e87e2dbe61743c1ddd96305af5..d5a2007c4df64c7b1b1ca3046dcf6ff350516d60 100644 (file)
@@ -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);
 
index b9e60511d56aa7e725593e87c8533bad699e1202..e6b3f031b3325447e09235c0e7b4316a03224989 100644 (file)
@@ -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.
index 4247569137dd4a4b5a3e3e917e9e6c0190d670ad..04c62b19e29cbb47ef504a8346ef600d4292f840 100644 (file)
@@ -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 */
index 44c9e2b2f1689d93af58cadd431e4b123fb2709b..867ca2dc6040c43955aec479d0c7476e92790a47 100644 (file)
@@ -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));
 }
 
 /*
index d0a34c0f9376c18113f2a83ef5992ac13613438e..86c8bfe1c2e79945398cd24f8d3631a823ec58ab 100644 (file)
@@ -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;
index 37591fa41fc30db4dc57e87fb9f24b5463249b52..c9f333e34be84f3ec274db895f2be178fb208ea3 100644 (file)
@@ -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;
index 44f7fb79da8d45eb6fba677a93078d1d9cb6941e..38fd53a1f2a75818dc4230d7cf5b892d0d19b7d9 100644 (file)
 #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);
+       }
+}
index ae25a0e67980acd6593863782c42d039938197fa..a478fffddb3dacb9bc43c0fbca053005f498e041 100644 (file)
@@ -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;
index ba0f1b41aa3c8da3e45001209f90bb1766296602..feede21cd9241984c52247957c79fd420fa58df1 100644 (file)
@@ -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;
 }
 
@@ -1209,15 +1214,6 @@ int dplane_provider_work_ready(void)
        return AOK;
 }
 
-/*
- * 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;
 }
index 133685051034c473e51d098f20c1ed46a4c8c2d7..1c053b85bfeb0f2d4db03a228134a833f189fb44 100644 (file)
@@ -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);
@@ -317,21 +318,14 @@ int dplane_provider_dequeue_in_list(struct zebra_dplane_provider *prov,
 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
index a6b17303b9c451e880fc71c49f637602fba52677..ef31fcf45d3bbc9891cebaaf30cc663be1051cd0 100644 (file)
@@ -272,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;
index b7f97ac612e910bd9ed8b886614696f723a500d2..7e4ac1ddd22bf22ee9bd9446e600f7f6140325d8 100644 (file)
@@ -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);
 }
 
 /*
index ae18a0d290423a7e720ae344fc016fab1cb2e1b5..f0cc8d4fd759c72cfa60e5dcabf51454578294e9 100644 (file)
@@ -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;
index d6b8b66087ad001c1c61f13f0ad731f959d60f80..1e0788d1ba9ce1d68e06d42fb2289bca868b6a1e 100644 (file)
@@ -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
index 38b8b43d73f45dfb0db3f01afc55994cd409cd76..f1458cb138b1eabc92161befbe79fe02b57e453a 100644 (file)
@@ -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. */
index 8b06d2ae115a9683f0714e91503efc3ffdc225f9..b18f0e943cf8a1d3f57efc7fac438bde05dc5ad6 100644 (file)
@@ -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);
 }
index b55ca60c00270b08f325c7fbf812051286413348..86a78127807d42855038d1ddc02a34438b3c603b 100644 (file)
@@ -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)