]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #4269 from donaldsharp/other_tables
authorRuss White <russ@riw.us>
Thu, 16 May 2019 14:11:56 +0000 (10:11 -0400)
committerGitHub <noreply@github.com>
Thu, 16 May 2019 14:11:56 +0000 (10:11 -0400)
zebra Other tables

202 files changed:
.gitignore
Makefile.am
bfdd/bfd.c
bfdd/bfd.h
bfdd/bfd_packet.c
bfdd/bfdd.c
bfdd/bfdd_vty.c
bfdd/bsd.c [deleted file]
bfdd/config.c
bfdd/linux.c [deleted file]
bfdd/ptm_adapter.c
bfdd/subdir.am
bgpd/bgp_advertise.c
bgpd/bgp_advertise.h
bgpd/bgp_aspath.c
bgpd/bgp_aspath.h
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_bfd.c
bgpd/bgp_clist.c
bgpd/bgp_community.c
bgpd/bgp_community.h
bgpd/bgp_ecommunity.c
bgpd/bgp_ecommunity.h
bgpd/bgp_evpn.c
bgpd/bgp_evpn_vty.c
bgpd/bgp_keepalives.c
bgpd/bgp_lcommunity.c
bgpd/bgp_lcommunity.h
bgpd/bgp_mac.c
bgpd/bgp_nexthop.c
bgpd/bgp_packet.c
bgpd/bgp_pbr.c
bgpd/bgp_pbr.h
bgpd/bgp_route.c
bgpd/bgp_routemap.c
bgpd/bgp_updgrp.c
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/rfapi/bgp_rfapi_cfg.c
bgpd/rfapi/rfapi_import.c
bgpd/rfapi/rfapi_private.h
bgpd/rfapi/rfapi_vty.c
configure.ac
doc/developer/building-frr-for-ubuntu1804.rst
doc/developer/lists.rst
doc/developer/topotests.rst
doc/user/basic.rst
doc/user/bfd.rst
doc/user/bgp.rst
doc/user/ospf6d.rst
doc/user/static.rst
doc/user/zebra.rst
isisd/fabricd.c
isisd/isis_bfd.c
isisd/isis_spf_private.h
isisd/isis_tlvs.c
isisd/isis_tx_queue.c
lib/bfd.c
lib/bfd.h
lib/command.c
lib/distribute.c
lib/ferr.c
lib/frrlua.c [new file with mode: 0644]
lib/frrlua.h [new file with mode: 0644]
lib/grammar_sandbox_main.c
lib/hash.c
lib/hash.h
lib/if_rmap.c
lib/lua.c [deleted file]
lib/lua.h [deleted file]
lib/northbound.c
lib/openbsd-tree.c
lib/openbsd-tree.h
lib/prefix.c
lib/prefix.h
lib/routemap.c
lib/routemap.h
lib/subdir.am
lib/table.c
lib/table.h
lib/thread.c
lib/typesafe.h
lib/vrf.c
lib/wheel.c
lib/wheel.h
lib/yang_translator.c
lib/zebra.h
m4/ax_lua.m4 [new file with mode: 0644]
nhrpd/nhrp_cache.c
nhrpd/nhrp_peer.c
nhrpd/nhrp_vc.c
nhrpd/reqid.c
ospf6d/ospf6_asbr.c
ospf6d/ospf6_bfd.c
ospf6d/ospf6_zebra.c
ospfd/ospf_bfd.c
ospfd/ospf_routemap.c
ospfd/ospf_sr.c
ospfd/ospf_zebra.c
pbrd/pbr_nht.c
pbrd/pbr_zebra.c
pimd/pim_bfd.c
pimd/pim_ifchannel.c
pimd/pim_ifchannel.h
pimd/pim_igmp.c
pimd/pim_msdp.c
pimd/pim_oil.c
pimd/pim_routemap.c
pimd/pim_rpf.c
pimd/pim_rpf.h
pimd/pim_upstream.c
pimd/pim_upstream.h
pimd/pim_vxlan.c
pimd/pim_zebra.c
staticd/static_zebra.c
tests/isisd/test_fuzz_isis_tlv_tests.h.gz
tests/lib/test_srcdest_table.c
tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref
tests/topotests/all-protocol-startup/test_all_protocol_startup.py
tests/topotests/bfd-vrf-topo1/__init__.py [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r1/bfdd.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r1/bgp_prefixes.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r1/bgp_summary.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r1/peers.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r2/bfdd.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r2/bgp_prefixes.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r2/bgp_summary.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r2/peers.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r3/bfdd.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r3/bgp_prefixes.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r3/bgp_summary.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r3/bgpd.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r3/peers.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r3/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r4/bfdd.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r4/bgp_prefixes.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r4/bgp_summary.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r4/bgpd.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r4/peers.json [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/r4/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.dot [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.jpg [new file with mode: 0644]
tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py [new file with mode: 0755]
tests/topotests/bgp_ebgp_requires_policy/__init__.py [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/r3/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/r3/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/r4/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/r4/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_ebgp_requires_policy/test_bgp_ebgp_requires_policy.py [new file with mode: 0644]
tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf
tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/sharpd.conf [new file with mode: 0644]
tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf
tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/sharpd.conf [new file with mode: 0644]
tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf
tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf
tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py [new file with mode: 0644]
tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py [new file with mode: 0644]
tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py
tests/topotests/lib/ltemplate.py
tests/topotests/lib/topogen.py
tools/checkpatch.pl
tools/coccinelle/hash_const.cocci [new file with mode: 0644]
vtysh/extract.pl.in
vtysh/vtysh.c
zebra/main.c
zebra/redistribute.c
zebra/rib.h
zebra/rt.h
zebra/rt_netlink.c
zebra/rtadv.c
zebra/rtadv.h
zebra/zapi_msg.c
zebra/zebra_dplane.c
zebra/zebra_fpm_netlink.c
zebra/zebra_mpls.c
zebra/zebra_mpls_openbsd.c
zebra/zebra_ns.c
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zebra_ptm.c
zebra/zebra_rib.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zebra_routemap.c
zebra/zebra_router.c
zebra/zebra_router.h
zebra/zebra_vrf.c
zebra/zebra_vrf.h
zebra/zebra_vty.c
zebra/zebra_vxlan.c
zebra/zserv.h

index 7a1378d588259f364446f64ab3a290ed6946803d..6cfe23e9214740d26a7cbe8eb88b3a84d04bcd39 100644 (file)
@@ -88,5 +88,7 @@ GSYMS
 GRTAGS
 GPATH
 compile_commands.json
+.ccls-cache
 .dirstamp
 refix
+.vscode
index 546aa85fe79de8c910aa225610db609a33389961..11188ea157d78fb9023bf9f4482ddcc21195d6ff 100644 (file)
@@ -12,7 +12,9 @@ AM_CFLAGS = \
        # end
 AM_CPPFLAGS = \
        -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/lib \
-       -I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/lib
+       -I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/lib \
+       $(LUA_INCLUDE) \
+       # end
 AM_LDFLAGS = \
        -export-dynamic \
        $(AC_LDFLAGS) \
index e9645824f283d406de816b9d113388e50a7cabf9..57d8ffa6d37aacfba5afa40b0821d01b45730ed5 100644 (file)
@@ -128,15 +128,8 @@ int bfd_session_enable(struct bfd_session *bs)
         * If the interface or VRF doesn't exist, then we must register
         * the session but delay its start.
         */
-       if (bs->key.ifname[0]) {
-               ifp = if_lookup_by_name_all_vrf(bs->key.ifname);
-               if (ifp == NULL) {
-                       log_error(
-                               "session-enable: specified interface doesn't exists.");
-                       return 0;
-               }
-
-               vrf = vrf_lookup_by_id(ifp->vrf_id);
+       if (bs->key.vrfname[0]) {
+               vrf = vrf_lookup_by_name(bs->key.vrfname);
                if (vrf == NULL) {
                        log_error(
                                "session-enable: specified VRF doesn't exists.");
@@ -144,13 +137,24 @@ int bfd_session_enable(struct bfd_session *bs)
                }
        }
 
-       if (bs->key.vrfname[0]) {
-               vrf = vrf_lookup_by_name(bs->key.vrfname);
-               if (vrf == NULL) {
+       if (bs->key.ifname[0]) {
+               if (vrf)
+                       ifp = if_lookup_by_name(bs->key.ifname, vrf->vrf_id);
+               else
+                       ifp = if_lookup_by_name_all_vrf(bs->key.ifname);
+               if (ifp == NULL) {
                        log_error(
-                               "session-enable: specified VRF doesn't exists.");
+                                 "session-enable: specified interface doesn't exists.");
                        return 0;
                }
+               if (bs->key.ifname[0] && !vrf) {
+                       vrf = vrf_lookup_by_id(ifp->vrf_id);
+                       if (vrf == NULL) {
+                               log_error(
+                                         "session-enable: specified VRF doesn't exists.");
+                               return 0;
+                       }
+               }
        }
 
        /* Assign interface/VRF pointers. */
@@ -164,7 +168,7 @@ int bfd_session_enable(struct bfd_session *bs)
 
        /* Sanity check: don't leak open sockets. */
        if (bs->sock != -1) {
-               zlog_debug("session-enable: previous socket open");
+               log_debug("session-enable: previous socket open");
                close(bs->sock);
                bs->sock = -1;
        }
@@ -291,7 +295,7 @@ void ptm_bfd_echo_start(struct bfd_session *bfd)
                ptm_bfd_echo_xmt_TO(bfd);
 }
 
-void ptm_bfd_ses_up(struct bfd_session *bfd)
+void ptm_bfd_sess_up(struct bfd_session *bfd)
 {
        int old_state = bfd->ses_state;
 
@@ -315,7 +319,7 @@ void ptm_bfd_ses_up(struct bfd_session *bfd)
        }
 }
 
-void ptm_bfd_ses_dn(struct bfd_session *bfd, uint8_t diag)
+void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag)
 {
        int old_state = bfd->ses_state;
 
@@ -432,7 +436,7 @@ int bfd_recvtimer_cb(struct thread *t)
        switch (bs->ses_state) {
        case PTM_BFD_INIT:
        case PTM_BFD_UP:
-               ptm_bfd_ses_dn(bs, BD_CONTROL_EXPIRED);
+               ptm_bfd_sess_dn(bs, BD_CONTROL_EXPIRED);
                bfd_recvtimer_update(bs);
                break;
 
@@ -455,7 +459,7 @@ int bfd_echo_recvtimer_cb(struct thread *t)
        switch (bs->ses_state) {
        case PTM_BFD_INIT:
        case PTM_BFD_UP:
-               ptm_bfd_ses_dn(bs, BD_ECHO_FAILED);
+               ptm_bfd_sess_dn(bs, BD_ECHO_FAILED);
                break;
        }
 
@@ -725,7 +729,7 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
        return bfd;
 }
 
-int ptm_bfd_ses_del(struct bfd_peer_cfg *bpc)
+int ptm_bfd_sess_del(struct bfd_peer_cfg *bpc)
 {
        struct bfd_session *bs;
 
@@ -805,7 +809,7 @@ static void bs_down_handler(struct bfd_session *bs, int nstate)
                 * Remote peer told us his path is up, lets turn
                 * activate the session.
                 */
-               ptm_bfd_ses_up(bs);
+               ptm_bfd_sess_up(bs);
                break;
 
        default:
@@ -832,7 +836,7 @@ static void bs_init_handler(struct bfd_session *bs, int nstate)
        case PTM_BFD_INIT:
        case PTM_BFD_UP:
                /* We agreed on the settings and the path is up. */
-               ptm_bfd_ses_up(bs);
+               ptm_bfd_sess_up(bs);
                break;
 
        default:
@@ -847,7 +851,7 @@ static void bs_up_handler(struct bfd_session *bs, int nstate)
        case PTM_BFD_ADM_DOWN:
        case PTM_BFD_DOWN:
                /* Peer lost or asked to shutdown connection. */
-               ptm_bfd_ses_dn(bs, BD_NEIGHBOR_DOWN);
+               ptm_bfd_sess_dn(bs, BD_NEIGHBOR_DOWN);
                break;
 
        case PTM_BFD_INIT:
@@ -1197,10 +1201,6 @@ int bs_observer_add(struct bfd_session *bs)
        if (bso->bso_isinterface)
                strlcpy(bso->bso_entryname, bs->key.ifname,
                        sizeof(bso->bso_entryname));
-       else
-               strlcpy(bso->bso_entryname, bs->key.vrfname,
-                       sizeof(bso->bso_entryname));
-
        /* Handle socket binding failures caused by missing local addresses. */
        if (bs->sock == -1) {
                bso->bso_isaddress = true;
@@ -1271,16 +1271,16 @@ void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc)
 static struct hash *bfd_id_hash;
 static struct hash *bfd_key_hash;
 
-static unsigned int bfd_id_hash_do(void *p);
-static unsigned int bfd_key_hash_do(void *p);
+static unsigned int bfd_id_hash_do(const void *p);
+static unsigned int bfd_key_hash_do(const void *p);
 
 static void _bfd_free(struct hash_bucket *hb,
                      void *arg __attribute__((__unused__)));
 
 /* BFD hash for our discriminator. */
-static unsigned int bfd_id_hash_do(void *p)
+static unsigned int bfd_id_hash_do(const void *p)
 {
-       struct bfd_session *bs = p;
+       const struct bfd_session *bs = p;
 
        return jhash_1word(bs->discrs.my_discr, 0);
 }
@@ -1293,9 +1293,9 @@ static bool bfd_id_hash_cmp(const void *n1, const void *n2)
 }
 
 /* BFD hash for single hop. */
-static unsigned int bfd_key_hash_do(void *p)
+static unsigned int bfd_key_hash_do(const void *p)
 {
-       struct bfd_session *bs = p;
+       const struct bfd_session *bs = p;
 
        return jhash(&bs->key, sizeof(bs->key), 0);
 }
@@ -1322,32 +1322,105 @@ struct bfd_session *bfd_id_lookup(uint32_t id)
        return hash_lookup(bfd_id_hash, &bs);
 }
 
+struct bfd_key_walk_partial_lookup {
+       struct bfd_session *given;
+       struct bfd_session *result;
+};
+
+/* ignore some parameters */
+static int bfd_key_lookup_ignore_partial_walker(struct hash_bucket *b, void *data)
+{
+       struct bfd_key_walk_partial_lookup  *ctx =
+               (struct bfd_key_walk_partial_lookup *)data;
+       struct bfd_session *given = ctx->given;
+       struct bfd_session *parsed = b->data;
+
+       if (given->key.family != parsed->key.family)
+               return HASHWALK_CONTINUE;
+       if (given->key.mhop != parsed->key.mhop)
+               return HASHWALK_CONTINUE;
+       if (memcmp(&given->key.peer, &parsed->key.peer, sizeof(struct in6_addr)))
+               return HASHWALK_CONTINUE;
+       if (memcmp(given->key.vrfname, parsed->key.vrfname, MAXNAMELEN))
+               return HASHWALK_CONTINUE;
+       ctx->result = parsed;
+       /* ignore localaddr or interface */
+       return HASHWALK_ABORT;
+}
+
 struct bfd_session *bfd_key_lookup(struct bfd_key key)
 {
        struct bfd_session bs, *bsp;
+       struct bfd_key_walk_partial_lookup ctx;
+       char peer_buf[INET6_ADDRSTRLEN];
 
        bs.key = key;
        bsp = hash_lookup(bfd_key_hash, &bs);
+       if (bsp)
+               return bsp;
 
+       inet_ntop(bs.key.family, &bs.key.peer, peer_buf,
+                 sizeof(peer_buf));
        /* Handle cases where local-address is optional. */
-       if (bsp == NULL && bs.key.family == AF_INET) {
+       if (bs.key.family == AF_INET) {
                memset(&bs.key.local, 0, sizeof(bs.key.local));
                bsp = hash_lookup(bfd_key_hash, &bs);
+               if (bsp) {
+                       char addr_buf[INET6_ADDRSTRLEN];
+
+                       inet_ntop(bs.key.family, &key.local, addr_buf,
+                                 sizeof(addr_buf));
+                       log_debug(" peer %s found, but loc-addr %s ignored",
+                                 peer_buf, addr_buf);
+                       return bsp;
+               }
        }
 
-       /* Handle cases where ifname is optional. */
        bs.key = key;
-       if (bsp == NULL && bs.key.ifname[0]) {
+       /* Handle cases where ifname is optional. */
+       if (bs.key.ifname[0]) {
                memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
                bsp = hash_lookup(bfd_key_hash, &bs);
+               if (bsp) {
+                       log_debug(" peer %s found, but ifp %s ignored",
+                                 peer_buf, key.ifname);
+                       return bsp;
+               }
+       }
 
-               /* Handle cases where local-address and ifname are optional. */
-               if (bsp == NULL && bs.key.family == AF_INET) {
-                       memset(&bs.key.local, 0, sizeof(bs.key.local));
-                       bsp = hash_lookup(bfd_key_hash, &bs);
+       /* Handle cases where local-address and ifname are optional. */
+       if (bs.key.family == AF_INET) {
+               memset(&bs.key.local, 0, sizeof(bs.key.local));
+               bsp = hash_lookup(bfd_key_hash, &bs);
+               if (bsp) {
+                       char addr_buf[INET6_ADDRSTRLEN];
+
+                       inet_ntop(bs.key.family, &bs.key.local, addr_buf,
+                                 sizeof(addr_buf));
+                       log_debug(" peer %s found, but ifp %s"
+                                 " and loc-addr %s ignored",
+                                 peer_buf, key.ifname,
+                                 addr_buf);
+                       return bsp;
                }
        }
+       bs.key = key;
 
+       /* Handle case where a context more complex ctx is present.
+        * input has no iface nor local-address, but a context may
+        * exist
+        */
+       ctx.result = NULL;
+       ctx.given = &bs;
+       hash_walk(bfd_key_hash,
+                 &bfd_key_lookup_ignore_partial_walker,
+                 &ctx);
+       /* change key */
+       if (ctx.result) {
+               bsp = ctx.result;
+               log_debug(" peer %s found, but ifp"
+                         " and/or loc-addr params ignored");
+       }
        return bsp;
 }
 
@@ -1443,3 +1516,125 @@ void bfd_shutdown(void)
        hash_free(bfd_id_hash);
        hash_free(bfd_key_hash);
 }
+
+static int bfd_vrf_new(struct vrf *vrf)
+{
+       log_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id);
+       return 0;
+}
+
+static int bfd_vrf_delete(struct vrf *vrf)
+{
+       log_debug("VRF Deletion: %s(%u)", vrf->name, vrf->vrf_id);
+       return 0;
+}
+
+static int bfd_vrf_enable(struct vrf *vrf)
+{
+       struct bfd_vrf_global *bvrf;
+
+       /* a different name */
+       if (!vrf->info) {
+               bvrf = XCALLOC(MTYPE_BFDD_VRF, sizeof(struct bfd_vrf_global));
+               bvrf->vrf = vrf;
+               vrf->info = (void *)bvrf;
+       } else
+               bvrf = vrf->info;
+       log_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);
+
+       /* create sockets if needed */
+       if (!bvrf->bg_shop)
+               bvrf->bg_shop = bp_udp_shop(vrf->vrf_id);
+       if (!bvrf->bg_mhop)
+               bvrf->bg_mhop = bp_udp_mhop(vrf->vrf_id);
+       if (!bvrf->bg_shop6)
+               bvrf->bg_shop6 = bp_udp6_shop(vrf->vrf_id);
+       if (!bvrf->bg_mhop6)
+               bvrf->bg_mhop6 = bp_udp6_mhop(vrf->vrf_id);
+       if (!bvrf->bg_echo)
+               bvrf->bg_echo = bp_echo_socket(vrf->vrf_id);
+       if (!bvrf->bg_echov6)
+               bvrf->bg_echov6 = bp_echov6_socket(vrf->vrf_id);
+
+       /* Add descriptors to the event loop. */
+       if (!bvrf->bg_ev[0])
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,
+                               &bvrf->bg_ev[0]);
+       if (!bvrf->bg_ev[1])
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,
+                               &bvrf->bg_ev[1]);
+       if (!bvrf->bg_ev[2])
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,
+                               &bvrf->bg_ev[2]);
+       if (!bvrf->bg_ev[3])
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
+                               &bvrf->bg_ev[3]);
+       if (!bvrf->bg_ev[4])
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo,
+                               &bvrf->bg_ev[4]);
+       if (!bvrf->bg_ev[5])
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
+                               &bvrf->bg_ev[5]);
+
+       if (vrf->vrf_id != VRF_DEFAULT) {
+               bfdd_zclient_register(vrf->vrf_id);
+               bfdd_sessions_enable_vrf(vrf);
+       }
+       return 0;
+}
+
+static int bfd_vrf_disable(struct vrf *vrf)
+{
+       struct bfd_vrf_global *bvrf;
+
+       if (!vrf->info)
+               return 0;
+       bvrf = vrf->info;
+
+       if (vrf->vrf_id != VRF_DEFAULT) {
+               bfdd_sessions_disable_vrf(vrf);
+               bfdd_zclient_unregister(vrf->vrf_id);
+       }
+
+       log_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
+       /* Close all descriptors. */
+       socket_close(&bvrf->bg_echo);
+       socket_close(&bvrf->bg_shop);
+       socket_close(&bvrf->bg_mhop);
+       socket_close(&bvrf->bg_shop6);
+       socket_close(&bvrf->bg_mhop6);
+
+       /* free context */
+       XFREE(MTYPE_BFDD_VRF, bvrf);
+       vrf->info = NULL;
+
+       return 0;
+}
+
+void bfd_vrf_init(void)
+{
+       vrf_init(bfd_vrf_new, bfd_vrf_enable, bfd_vrf_disable,
+                bfd_vrf_delete, NULL);
+}
+
+void bfd_vrf_terminate(void)
+{
+       vrf_terminate();
+}
+
+struct bfd_vrf_global *bfd_vrf_look_by_session(struct bfd_session *bfd)
+{
+       struct vrf *vrf;
+
+       if (!vrf_is_backend_netns()) {
+               vrf = vrf_lookup_by_id(VRF_DEFAULT);
+               if (vrf)
+                       return (struct bfd_vrf_global *)vrf->info;
+               return NULL;
+       }
+       if (!bfd)
+               return NULL;
+       if (!bfd->vrf)
+               return NULL;
+       return bfd->vrf->info;
+}
index e08a1ff724e8bec4ec5bafde7a3dd4b432b0a39f..3f3d60383248127272ded2bf08ac1640f06fd238 100644 (file)
@@ -48,6 +48,7 @@ DECLARE_MTYPE(BFDD_LABEL);
 DECLARE_MTYPE(BFDD_CONTROL);
 DECLARE_MTYPE(BFDD_SESSION_OBSERVER);
 DECLARE_MTYPE(BFDD_NOTIFICATION);
+DECLARE_MTYPE(BFDD_VRF);
 
 struct bfd_timers {
        uint32_t desired_min_tx;
@@ -379,15 +380,19 @@ int control_accept(struct thread *t);
  *
  * Daemon specific code.
  */
-struct bfd_global {
+struct bfd_vrf_global {
        int bg_shop;
        int bg_mhop;
        int bg_shop6;
        int bg_mhop6;
        int bg_echo;
        int bg_echov6;
+       struct vrf *vrf;
+
        struct thread *bg_ev[6];
+};
 
+struct bfd_global {
        int bg_csock;
        struct thread *bg_csockev;
        struct bcslist bg_bcslist;
@@ -395,6 +400,8 @@ struct bfd_global {
        struct pllist bg_pllist;
 
        struct obslist bg_obslist;
+
+       struct zebra_privs_t bfdd_privs;
 };
 extern struct bfd_global bglobal;
 extern struct bfd_diag_str_list diag_list[];
@@ -459,14 +466,14 @@ int bp_set_tosv6(int sd, uint8_t value);
 int bp_set_tos(int sd, uint8_t value);
 int bp_bind_dev(int sd, const char *dev);
 
-int bp_udp_shop(void);
-int bp_udp_mhop(void);
-int bp_udp6_shop(void);
-int bp_udp6_mhop(void);
+int bp_udp_shop(vrf_id_t vrf_id);
+int bp_udp_mhop(vrf_id_t vrf_id);
+int bp_udp6_shop(vrf_id_t vrf_id);
+int bp_udp6_mhop(vrf_id_t vrf_id);
 int bp_peer_socket(const struct bfd_session *bs);
 int bp_peer_socketv6(const struct bfd_session *bs);
-int bp_echo_socket(void);
-int bp_echov6_socket(void);
+int bp_echo_socket(vrf_id_t vrf_id);
+int bp_echov6_socket(vrf_id_t vrf_id);
 
 void ptm_bfd_snd(struct bfd_session *bfd, int fbit);
 void ptm_bfd_echo_snd(struct bfd_session *bfd);
@@ -505,9 +512,9 @@ void bfd_echo_xmttimer_assign(struct bfd_session *bs, bfd_ev_cb cb);
 int bfd_session_enable(struct bfd_session *bs);
 void bfd_session_disable(struct bfd_session *bs);
 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);
+int ptm_bfd_sess_del(struct bfd_peer_cfg *bpc);
+void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag);
+void ptm_bfd_sess_up(struct bfd_session *bfd);
 void ptm_bfd_echo_stop(struct bfd_session *bfd);
 void ptm_bfd_echo_start(struct bfd_session *bfd);
 void ptm_bfd_xmt_TO(struct bfd_session *bfd, int fbit);
@@ -539,6 +546,9 @@ void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc);
 /* BFD hash data structures interface */
 void bfd_initialize(void);
 void bfd_shutdown(void);
+void bfd_vrf_init(void);
+void bfd_vrf_terminate(void);
+struct bfd_vrf_global *bfd_vrf_look_by_session(struct bfd_session *bfd);
 struct bfd_session *bfd_id_lookup(uint32_t id);
 struct bfd_session *bfd_key_lookup(struct bfd_key key);
 
@@ -576,6 +586,10 @@ void bfdd_vty_init(void);
  */
 void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv);
 void bfdd_zclient_stop(void);
+void bfdd_zclient_unregister(vrf_id_t vrf_id);
+void bfdd_zclient_register(vrf_id_t vrf_id);
+void bfdd_sessions_enable_vrf(struct vrf *vrf);
+void bfdd_sessions_disable_vrf(struct vrf *vrf);
 
 int ptm_bfd_notify(struct bfd_session *bs);
 
index 93677ec85aceeb7709385a07c652682b843d73aa..8edba05d126d6a531dc1cc502cc4953071733eb3 100644 (file)
 
 #include "bfd.h"
 
-
 /*
  * Prototypes
  */
-static int ptm_bfd_process_echo_pkt(int s);
+static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s);
 int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
                  size_t datalen);
 
-static void bfd_sd_reschedule(int sd);
+static void bfd_sd_reschedule(struct bfd_vrf_global *bvrf, int sd);
 ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
                      ifindex_t *ifindex, struct sockaddr_any *local,
                      struct sockaddr_any *peer);
@@ -54,7 +53,8 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
                      struct sockaddr_any *peer);
 int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
                struct sockaddr *to, socklen_t tolen);
-int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr);
+int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
+                  uint8_t *ttl, uint32_t *my_discr);
 
 /* socket related prototypes */
 static void bp_set_ipopts(int sd);
@@ -129,7 +129,10 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
        struct bfd_echo_pkt bep;
        struct sockaddr_in sin;
        struct sockaddr_in6 sin6;
+       struct bfd_vrf_global *bvrf = bfd_vrf_look_by_session(bfd);
 
+       if (!bvrf)
+               return;
        if (!BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
                BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE);
 
@@ -139,7 +142,7 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
        bep.my_discr = htonl(bfd->discrs.my_discr);
 
        if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6)) {
-               sd = bglobal.bg_echov6;
+               sd = bvrf->bg_echov6;
                memset(&sin6, 0, sizeof(sin6));
                sin6.sin6_family = AF_INET6;
                memcpy(&sin6.sin6_addr, &bfd->key.peer, sizeof(sin6.sin6_addr));
@@ -154,7 +157,7 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
                sa = (struct sockaddr *)&sin6;
                salen = sizeof(sin6);
        } else {
-               sd = bglobal.bg_echo;
+               sd = bvrf->bg_echo;
                memset(&sin6, 0, sizeof(sin6));
                sin.sin_family = AF_INET;
                memcpy(&sin.sin_addr, &bfd->key.peer, sizeof(sin.sin_addr));
@@ -174,14 +177,14 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
        bfd->stats.tx_echo_pkt++;
 }
 
-static int ptm_bfd_process_echo_pkt(int s)
+static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s)
 {
        struct bfd_session *bfd;
        uint32_t my_discr = 0;
        uint8_t ttl = 0;
 
        /* Receive and parse echo packet. */
-       if (bp_bfd_echo_in(s, &ttl, &my_discr) == -1)
+       if (bp_bfd_echo_in(bvrf, s, &ttl, &my_discr) == -1)
                return 0;
 
        /* Your discriminator not zero - use it to find session */
@@ -441,32 +444,32 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
        return mlen;
 }
 
-static void bfd_sd_reschedule(int sd)
+static void bfd_sd_reschedule(struct bfd_vrf_global *bvrf, int sd)
 {
-       if (sd == bglobal.bg_shop) {
-               THREAD_OFF(bglobal.bg_ev[0]);
-               thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop,
-                               &bglobal.bg_ev[0]);
-       } else if (sd == bglobal.bg_mhop) {
-               THREAD_OFF(bglobal.bg_ev[1]);
-               thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop,
-                               &bglobal.bg_ev[1]);
-       } else if (sd == bglobal.bg_shop6) {
-               THREAD_OFF(bglobal.bg_ev[2]);
-               thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop6,
-                               &bglobal.bg_ev[2]);
-       } else if (sd == bglobal.bg_mhop6) {
-               THREAD_OFF(bglobal.bg_ev[3]);
-               thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop6,
-                               &bglobal.bg_ev[3]);
-       } else if (sd == bglobal.bg_echo) {
-               THREAD_OFF(bglobal.bg_ev[4]);
-               thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo,
-                               &bglobal.bg_ev[4]);
-       } else if (sd == bglobal.bg_echov6) {
-               THREAD_OFF(bglobal.bg_ev[5]);
-               thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echov6,
-                               &bglobal.bg_ev[5]);
+       if (sd == bvrf->bg_shop) {
+               THREAD_OFF(bvrf->bg_ev[0]);
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,
+                               &bvrf->bg_ev[0]);
+       } else if (sd == bvrf->bg_mhop) {
+               THREAD_OFF(bvrf->bg_ev[1]);
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,
+                               &bvrf->bg_ev[1]);
+       } else if (sd == bvrf->bg_shop6) {
+               THREAD_OFF(bvrf->bg_ev[2]);
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,
+                               &bvrf->bg_ev[2]);
+       } else if (sd == bvrf->bg_mhop6) {
+               THREAD_OFF(bvrf->bg_ev[3]);
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
+                               &bvrf->bg_ev[3]);
+       } else if (sd == bvrf->bg_echo) {
+               THREAD_OFF(bvrf->bg_ev[4]);
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo,
+                               &bvrf->bg_ev[4]);
+       } else if (sd == bvrf->bg_echov6) {
+               THREAD_OFF(bvrf->bg_ev[5]);
+               thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
+                               &bvrf->bg_ev[5]);
        }
 }
 
@@ -518,13 +521,16 @@ int bfd_recv_cb(struct thread *t)
        ifindex_t ifindex = IFINDEX_INTERNAL;
        struct sockaddr_any local, peer;
        uint8_t msgbuf[1516];
+       struct bfd_vrf_global *bvrf = THREAD_ARG(t);
 
+       if (bvrf)
+               vrfid = bvrf->vrf->vrf_id;
        /* Schedule next read. */
-       bfd_sd_reschedule(sd);
+       bfd_sd_reschedule(bvrf, sd);
 
        /* Handle echo packets. */
-       if (sd == bglobal.bg_echo || sd == bglobal.bg_echov6) {
-               ptm_bfd_process_echo_pkt(sd);
+       if (sd == bvrf->bg_echo || sd == bvrf->bg_echov6) {
+               ptm_bfd_process_echo_pkt(bvrf, sd);
                return 0;
        }
 
@@ -534,12 +540,12 @@ int bfd_recv_cb(struct thread *t)
 
        /* Handle control packets. */
        is_mhop = false;
-       if (sd == bglobal.bg_shop || sd == bglobal.bg_mhop) {
-               is_mhop = sd == bglobal.bg_mhop;
+       if (sd == bvrf->bg_shop || sd == bvrf->bg_mhop) {
+               is_mhop = sd == bvrf->bg_mhop;
                mlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), &ttl, &ifindex,
                                     &local, &peer);
-       } else if (sd == bglobal.bg_shop6 || sd == bglobal.bg_mhop6) {
-               is_mhop = sd == bglobal.bg_mhop6;
+       } else if (sd == bvrf->bg_shop6 || sd == bvrf->bg_mhop6) {
+               is_mhop = sd == bvrf->bg_mhop6;
                mlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), &ttl, &ifindex,
                                     &local, &peer);
        }
@@ -682,7 +688,8 @@ int bfd_recv_cb(struct thread *t)
  *
  * Returns -1 on error or loopback or 0 on success.
  */
-int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
+int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
+                  uint8_t *ttl, uint32_t *my_discr)
 {
        struct bfd_echo_pkt *bep;
        ssize_t rlen;
@@ -691,7 +698,7 @@ int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
        vrf_id_t vrfid = VRF_DEFAULT;
        uint8_t msgbuf[1516];
 
-       if (sd == bglobal.bg_echo)
+       if (sd == bvrf->bg_echo)
                rlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), ttl, &ifindex,
                                     &local, &peer);
        else
@@ -709,7 +716,7 @@ int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
        if (*ttl == BFD_TTL_VAL) {
                bp_udp_send(sd, *ttl - 1, msgbuf, rlen,
                            (struct sockaddr *)&peer,
-                           (sd == bglobal.bg_echo) ? sizeof(peer.sa_sin)
+                           (sd == bvrf->bg_echo) ? sizeof(peer.sa_sin)
                                                    : sizeof(peer.sa_sin6));
                return -1;
        }
@@ -872,25 +879,28 @@ static void bp_bind_ip(int sd, uint16_t port)
                log_fatal("bind-ip: bind: %s", strerror(errno));
 }
 
-int bp_udp_shop(void)
+int bp_udp_shop(vrf_id_t vrf_id)
 {
        int sd;
 
-       sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
+       frr_elevate_privs(&bglobal.bfdd_privs) {
+               sd = vrf_socket(AF_INET, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
+       }
        if (sd == -1)
                log_fatal("udp-shop: socket: %s", strerror(errno));
 
        bp_set_ipopts(sd);
        bp_bind_ip(sd, BFD_DEFDESTPORT);
-
        return sd;
 }
 
-int bp_udp_mhop(void)
+int bp_udp_mhop(vrf_id_t vrf_id)
 {
        int sd;
 
-       sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
+       frr_elevate_privs(&bglobal.bfdd_privs) {
+               sd = vrf_socket(AF_INET, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
+       }
        if (sd == -1)
                log_fatal("udp-mhop: socket: %s", strerror(errno));
 
@@ -905,8 +915,18 @@ int bp_peer_socket(const struct bfd_session *bs)
        int sd, pcount;
        struct sockaddr_in sin;
        static int srcPort = BFD_SRCPORTINIT;
+       const char *device_to_bind = NULL;
+
+       if (bs->key.ifname[0])
+               device_to_bind = (const char *)bs->key.ifname;
+       else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
+           && bs->key.vrfname[0])
+               device_to_bind = (const char *)bs->key.vrfname;
 
-       sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
+       frr_elevate_privs(&bglobal.bfdd_privs) {
+               sd = vrf_socket(AF_INET, SOCK_DGRAM, PF_UNSPEC,
+                               bs->vrf->vrf_id, device_to_bind);
+       }
        if (sd == -1) {
                log_error("ipv4-new: failed to create socket: %s",
                          strerror(errno));
@@ -925,19 +945,6 @@ int bp_peer_socket(const struct bfd_session *bs)
                return -1;
        }
 
-       if (bs->key.ifname[0]) {
-               if (bp_bind_dev(sd, bs->key.ifname) != 0) {
-                       close(sd);
-                       return -1;
-               }
-       } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
-                  && bs->key.vrfname[0]) {
-               if (bp_bind_dev(sd, bs->key.vrfname) != 0) {
-                       close(sd);
-                       return -1;
-               }
-       }
-
        /* Find an available source port in the proper range */
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
@@ -975,8 +982,18 @@ int bp_peer_socketv6(const struct bfd_session *bs)
        int sd, pcount;
        struct sockaddr_in6 sin6;
        static int srcPort = BFD_SRCPORTINIT;
+       const char *device_to_bind = NULL;
 
-       sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
+       if (bs->key.ifname[0])
+               device_to_bind = (const char *)bs->key.ifname;
+       else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
+           && bs->key.vrfname[0])
+               device_to_bind = (const char *)bs->key.vrfname;
+
+       frr_elevate_privs(&bglobal.bfdd_privs) {
+               sd = vrf_socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC,
+                               bs->vrf->vrf_id, device_to_bind);
+       }
        if (sd == -1) {
                log_error("ipv6-new: failed to create socket: %s",
                          strerror(errno));
@@ -1005,19 +1022,6 @@ int bp_peer_socketv6(const struct bfd_session *bs)
        if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
                sin6.sin6_scope_id = bs->ifp->ifindex;
 
-       if (bs->key.ifname[0]) {
-               if (bp_bind_dev(sd, bs->key.ifname) != 0) {
-                       close(sd);
-                       return -1;
-               }
-       } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
-                  && bs->key.vrfname[0]) {
-               if (bp_bind_dev(sd, bs->key.vrfname) != 0) {
-                       close(sd);
-                       return -1;
-               }
-       }
-
        pcount = 0;
        do {
                if ((++pcount) > (BFD_SRCPORTMAX - BFD_SRCPORTINIT)) {
@@ -1102,11 +1106,13 @@ static void bp_bind_ipv6(int sd, uint16_t port)
                log_fatal("bind-ipv6: bind: %s", strerror(errno));
 }
 
-int bp_udp6_shop(void)
+int bp_udp6_shop(vrf_id_t vrf_id)
 {
        int sd;
 
-       sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
+       frr_elevate_privs(&bglobal.bfdd_privs) {
+               sd = vrf_socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
+       }
        if (sd == -1)
                log_fatal("udp6-shop: socket: %s", strerror(errno));
 
@@ -1116,11 +1122,13 @@ int bp_udp6_shop(void)
        return sd;
 }
 
-int bp_udp6_mhop(void)
+int bp_udp6_mhop(vrf_id_t vrf_id)
 {
        int sd;
 
-       sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
+       frr_elevate_privs(&bglobal.bfdd_privs) {
+               sd = vrf_socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
+       }
        if (sd == -1)
                log_fatal("udp6-mhop: socket: %s", strerror(errno));
 
@@ -1130,11 +1138,13 @@ int bp_udp6_mhop(void)
        return sd;
 }
 
-int bp_echo_socket(void)
+int bp_echo_socket(vrf_id_t vrf_id)
 {
        int s;
 
-       s = socket(AF_INET, SOCK_DGRAM, 0);
+       frr_elevate_privs(&bglobal.bfdd_privs) {
+               s = vrf_socket(AF_INET, SOCK_DGRAM, 0, vrf_id, NULL);
+       }
        if (s == -1)
                log_fatal("echo-socket: socket: %s", strerror(errno));
 
@@ -1144,11 +1154,13 @@ int bp_echo_socket(void)
        return s;
 }
 
-int bp_echov6_socket(void)
+int bp_echov6_socket(vrf_id_t vrf_id)
 {
        int s;
 
-       s = socket(AF_INET6, SOCK_DGRAM, 0);
+       frr_elevate_privs(&bglobal.bfdd_privs) {
+               s = vrf_socket(AF_INET6, SOCK_DGRAM, 0, vrf_id, NULL);
+       }
        if (s == -1)
                log_fatal("echov6-socket: socket: %s", strerror(errno));
 
index 6023b5e4f0a533194727e3ef67f9a2bc9844107d..218f0883c5fbd6c32e8d725a468bfdbaa2a77d89 100644 (file)
@@ -34,25 +34,13 @@ DEFINE_MTYPE(BFDD, BFDD_LABEL, "long-lived label memory");
 DEFINE_MTYPE(BFDD, BFDD_CONTROL, "long-lived control socket memory");
 DEFINE_MTYPE(BFDD, BFDD_SESSION_OBSERVER, "Session observer");
 DEFINE_MTYPE(BFDD, BFDD_NOTIFICATION, "short-lived control notification data");
+DEFINE_MTYPE(BFDD, BFDD_VRF, "BFD VRF");
 
 /* Master of threads. */
 struct thread_master *master;
 
 /* BFDd privileges */
-static zebra_capabilities_t _caps_p[] = {ZCAP_BIND};
-
-struct zebra_privs_t bfdd_privs = {
-#if defined(FRR_USER) && defined(FRR_GROUP)
-       .user = FRR_USER,
-       .group = FRR_GROUP,
-#endif
-#if defined(VTY_GROUP)
-       .vty_group = VTY_GROUP,
-#endif
-       .caps_p = _caps_p,
-       .cap_num_p = array_size(_caps_p),
-       .cap_num_i = 0,
-};
+static zebra_capabilities_t _caps_p[] = {ZCAP_BIND, ZCAP_SYS_ADMIN, ZCAP_NET_RAW};
 
 void socket_close(int *s)
 {
@@ -85,12 +73,7 @@ static void sigterm_handler(void)
        /* Shutdown and free all protocol related memory. */
        bfd_shutdown();
 
-       /* Close all descriptors. */
-       socket_close(&bglobal.bg_echo);
-       socket_close(&bglobal.bg_shop);
-       socket_close(&bglobal.bg_mhop);
-       socket_close(&bglobal.bg_shop6);
-       socket_close(&bglobal.bg_mhop6);
+       bfd_vrf_terminate();
 
        /* Terminate and free() FRR related memory. */
        frr_fini();
@@ -116,7 +99,7 @@ static struct quagga_signal_t bfd_signals[] = {
 FRR_DAEMON_INFO(bfdd, BFD, .vty_port = 2617,
                .proghelp = "Implementation of the BFD protocol.",
                .signals = bfd_signals, .n_signals = array_size(bfd_signals),
-               .privs = &bfdd_privs)
+               .privs = &bglobal.bfdd_privs)
 
 #define OPTION_CTLSOCK 1001
 static struct option longopts[] = {
@@ -153,15 +136,24 @@ struct bfd_state_str_list state_list[] = {
 
 static void bg_init(void)
 {
+       struct zebra_privs_t bfdd_privs = {
+#if defined(FRR_USER) && defined(FRR_GROUP)
+               .user = FRR_USER,
+               .group = FRR_GROUP,
+#endif
+#if defined(VTY_GROUP)
+               .vty_group = VTY_GROUP,
+#endif
+               .caps_p = _caps_p,
+               .cap_num_p = array_size(_caps_p),
+               .cap_num_i = 0,
+       };
+
        TAILQ_INIT(&bglobal.bg_bcslist);
        TAILQ_INIT(&bglobal.bg_obslist);
 
-       bglobal.bg_shop = bp_udp_shop();
-       bglobal.bg_mhop = bp_udp_mhop();
-       bglobal.bg_shop6 = bp_udp6_shop();
-       bglobal.bg_mhop6 = bp_udp6_mhop();
-       bglobal.bg_echo = bp_echo_socket();
-       bglobal.bg_echov6 = bp_echov6_socket();
+       memcpy(&bglobal.bfdd_privs, &bfdd_privs,
+              sizeof(bfdd_privs));
 }
 
 int main(int argc, char *argv[])
@@ -169,6 +161,9 @@ int main(int argc, char *argv[])
        const char *ctl_path = BFDD_CONTROL_SOCKET;
        int opt;
 
+       /* Initialize system sockets. */
+       bg_init();
+
        frr_preinit(&bfdd_di, argc, argv);
        frr_opt_add("", longopts,
                    "      --bfdctl       Specify bfdd control socket\n");
@@ -196,9 +191,6 @@ int main(int argc, char *argv[])
        /* Initialize logging API. */
        log_init(1, BLOG_DEBUG, &bfdd_di);
 
-       /* Initialize system sockets. */
-       bg_init();
-
        /* Initialize control socket. */
        control_init(ctl_path);
 
@@ -208,22 +200,11 @@ int main(int argc, char *argv[])
        /* Initialize BFD data structures. */
        bfd_initialize();
 
+       bfd_vrf_init();
+
        /* Initialize zebra connection. */
-       bfdd_zclient_init(&bfdd_privs);
-
-       /* Add descriptors to the event loop. */
-       thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop,
-                       &bglobal.bg_ev[0]);
-       thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop,
-                       &bglobal.bg_ev[1]);
-       thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop6,
-                       &bglobal.bg_ev[2]);
-       thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop6,
-                       &bglobal.bg_ev[3]);
-       thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo,
-                       &bglobal.bg_ev[4]);
-       thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echov6,
-                       &bglobal.bg_ev[5]);
+       bfdd_zclient_init(&bglobal.bfdd_privs);
+
        thread_add_read(master, control_accept, NULL, bglobal.bg_csock,
                        &bglobal.bg_csockev);
 
index 4efdd817c1c78a44a22844d84cb9b907fd9f6379..75f6632db03a80b99f0e1ba4d293e3130751ccac 100644 (file)
@@ -64,7 +64,7 @@ static struct json_object *__display_peer_json(struct bfd_session *bs);
 static struct json_object *_peer_json_header(struct bfd_session *bs);
 static void _display_peer_json(struct vty *vty, struct bfd_session *bs);
 static void _display_peer(struct vty *vty, struct bfd_session *bs);
-static void _display_all_peers(struct vty *vty, bool use_json);
+static void _display_all_peers(struct vty *vty, char *vrfname, bool use_json);
 static void _display_peer_iter(struct hash_bucket *hb, void *arg);
 static void _display_peer_json_iter(struct hash_bucket *hb, void *arg);
 static void _display_peer_counter(struct vty *vty, struct bfd_session *bs);
@@ -72,7 +72,7 @@ static struct json_object *__display_peer_counters_json(struct bfd_session *bs);
 static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs);
 static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg);
 static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg);
-static void _display_peers_counter(struct vty *vty, bool use_json);
+static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json);
 static struct bfd_session *
 _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
                    const char *label, const char *peer_str,
@@ -90,7 +90,7 @@ DEFUN_NOSH(bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n")
 
 DEFUN_NOSH(
        bfd_peer_enter, bfd_peer_enter_cmd,
-       "peer <A.B.C.D|X:X::X:X> [{[multihop] local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
+       "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]",
        PEER_STR PEER_IPV4_STR PEER_IPV6_STR
        MHOP_STR
        LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR
@@ -126,15 +126,6 @@ DEFUN_NOSH(
        if (argv_find(argv, argc, "vrf", &idx))
                vrfname = argv[idx + 1]->arg;
 
-       if (vrfname && ifname) {
-               vty_out(vty, "%% VRF is not mixable with interface\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       if (vrfname && !mhop) {
-               vty_out(vty, "%% VRF only applies with multihop.\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
        strtosa(peer, &psa);
        if (local) {
                strtosa(local, &lsa);
@@ -360,7 +351,7 @@ DEFPY(bfd_no_peer, bfd_no_peer_cmd,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       if (ptm_bfd_ses_del(&bpc) != 0) {
+       if (ptm_bfd_sess_del(&bpc) != 0) {
                vty_out(vty, "%% Failed to remove peer.\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
@@ -549,19 +540,46 @@ static void _display_peer_json(struct vty *vty, struct bfd_session *bs)
        json_object_free(jo);
 }
 
+struct bfd_vrf_tuple {
+       char *vrfname;
+       struct vty *vty;
+       struct json_object *jo;
+};
+
 static void _display_peer_iter(struct hash_bucket *hb, void *arg)
 {
-       struct vty *vty = arg;
+       struct bfd_vrf_tuple *bvt = (struct bfd_vrf_tuple *)arg;
+       struct vty *vty;
        struct bfd_session *bs = hb->data;
 
+       if (!bvt)
+               return;
+       vty = bvt->vty;
+
+       if (bvt->vrfname) {
+               if (!bs->key.vrfname[0] ||
+                   !strmatch(bs->key.vrfname, bvt->vrfname))
+                       return;
+       }
        _display_peer(vty, bs);
 }
 
 static void _display_peer_json_iter(struct hash_bucket *hb, void *arg)
 {
-       struct json_object *jo = arg, *jon = NULL;
+       struct bfd_vrf_tuple *bvt = (struct bfd_vrf_tuple *)arg;
+       struct json_object *jo, *jon = NULL;
        struct bfd_session *bs = hb->data;
 
+       if (!bvt)
+               return;
+       jo = bvt->jo;
+
+       if (bvt->vrfname) {
+               if (!bs->key.vrfname[0] ||
+                   !strmatch(bs->key.vrfname, bvt->vrfname))
+                       return;
+       }
+
        jon = __display_peer_json(bs);
        if (jon == NULL) {
                log_warning("%s: not enough memory", __func__);
@@ -571,18 +589,24 @@ static void _display_peer_json_iter(struct hash_bucket *hb, void *arg)
        json_object_array_add(jo, jon);
 }
 
-static void _display_all_peers(struct vty *vty, bool use_json)
+static void _display_all_peers(struct vty *vty, char *vrfname, bool use_json)
 {
        struct json_object *jo;
+       struct bfd_vrf_tuple bvt;
+
+       memset(&bvt, 0, sizeof(bvt));
+       bvt.vrfname = vrfname;
 
        if (!use_json) {
+               bvt.vty = vty;
                vty_out(vty, "BFD Peers:\n");
-               bfd_id_iterate(_display_peer_iter, vty);
+               bfd_id_iterate(_display_peer_iter, &bvt);
                return;
        }
 
        jo = json_object_new_array();
-       bfd_id_iterate(_display_peer_json_iter, jo);
+       bvt.jo = jo;
+       bfd_id_iterate(_display_peer_json_iter, &bvt);
 
        vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
        json_object_free(jo);
@@ -634,16 +658,38 @@ static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
 
 static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg)
 {
-       struct vty *vty = arg;
+       struct bfd_vrf_tuple *bvt = arg;
+       struct vty *vty;
        struct bfd_session *bs = hb->data;
 
+       if (!bvt)
+               return;
+       vty = bvt->vty;
+
+       if (bvt->vrfname) {
+               if (!bs->key.vrfname[0] ||
+                   !strmatch(bs->key.vrfname, bvt->vrfname))
+                       return;
+       }
+
        _display_peer_counter(vty, bs);
 }
 
 static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg)
 {
-       struct json_object *jo = arg, *jon = NULL;
+       struct json_object *jo, *jon = NULL;
        struct bfd_session *bs = hb->data;
+       struct bfd_vrf_tuple *bvt = arg;
+
+       if (!bvt)
+               return;
+       jo  = bvt->jo;
+
+       if (bvt->vrfname) {
+               if (!bs->key.vrfname[0] ||
+                   !strmatch(bs->key.vrfname, bvt->vrfname))
+                       return;
+       }
 
        jon = __display_peer_counters_json(bs);
        if (jon == NULL) {
@@ -654,17 +700,22 @@ static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg)
        json_object_array_add(jo, jon);
 }
 
-static void _display_peers_counter(struct vty *vty, bool use_json)
+static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json)
 {
        struct json_object *jo;
+       struct bfd_vrf_tuple bvt;
 
+       memset(&bvt, 0, sizeof(struct bfd_vrf_tuple));
+       bvt.vrfname = vrfname;
        if (!use_json) {
+               bvt.vty = vty;
                vty_out(vty, "BFD Peers:\n");
-               bfd_id_iterate(_display_peer_counter_iter, vty);
+               bfd_id_iterate(_display_peer_counter_iter, &bvt);
                return;
        }
 
        jo = json_object_new_array();
+       bvt.jo = jo;
        bfd_id_iterate(_display_peer_counter_json_iter, jo);
 
        vty_out(vty, "%s\n", json_object_to_json_string_ext(jo, 0));
@@ -734,24 +785,31 @@ _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
 /*
  * Show commands.
  */
-DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd peers [json]",
+DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd [vrf <NAME>] peers [json]",
       SHOW_STR
       "Bidirection Forwarding Detection\n"
+       VRF_CMD_HELP_STR
       "BFD peers status\n" JSON_STR)
 {
-       _display_all_peers(vty, use_json(argc, argv));
+       char *vrf_name = NULL;
+       int idx_vrf = 0;
+
+       if (argv_find(argv, argc, "vrf", &idx_vrf))
+               vrf_name = argv[idx_vrf + 1]->arg;
+
+       _display_all_peers(vty, vrf_name, use_json(argc, argv));
 
        return CMD_SUCCESS;
 }
 
 DEFPY(bfd_show_peer, bfd_show_peer_cmd,
-      "show bfd peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]> [json]",
+      "show bfd [vrf <NAME$vrfname>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]",
       SHOW_STR
       "Bidirection Forwarding Detection\n"
+      VRF_CMD_HELP_STR
       "BFD peers status\n"
       "Peer label\n" PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR
-             LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR VRF_STR
-                     VRF_NAME_STR JSON_STR)
+             LOCAL_IPV4_STR LOCAL_IPV6_STR INTERFACE_STR LOCAL_INTF_STR JSON_STR)
 {
        struct bfd_session *bs;
 
@@ -772,9 +830,10 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
 }
 
 DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
-      "show bfd peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]> counters [json]",
+      "show bfd [vrf <NAME$vrfname>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters [json]",
       SHOW_STR
       "Bidirection Forwarding Detection\n"
+      VRF_CMD_HELP_STR
       "BFD peers status\n"
       "Peer label\n"
       PEER_IPV4_STR
@@ -785,8 +844,6 @@ DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
       LOCAL_IPV6_STR
       INTERFACE_STR
       LOCAL_INTF_STR
-      VRF_STR
-      VRF_NAME_STR
       "Show BFD peer counters information\n"
       JSON_STR)
 {
@@ -807,14 +864,21 @@ DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
 }
 
 DEFPY(bfd_show_peers_counters, bfd_show_peers_counters_cmd,
-      "show bfd peers counters [json]",
+      "show bfd [vrf <NAME>] peers counters [json]",
       SHOW_STR
       "Bidirection Forwarding Detection\n"
+      VRF_CMD_HELP_STR
       "BFD peers status\n"
       "Show BFD peer counters information\n"
       JSON_STR)
 {
-       _display_peers_counter(vty, use_json(argc, argv));
+       char *vrf_name = NULL;
+       int idx_vrf = 0;
+
+       if (argv_find(argv, argc, "vrf", &idx_vrf))
+               vrf_name = argv[idx_vrf + 1]->arg;
+
+       _display_peers_counter(vty, vrf_name, use_json(argc, argv));
 
        return CMD_SUCCESS;
 }
diff --git a/bfdd/bsd.c b/bfdd/bsd.c
deleted file mode 100644 (file)
index 923fbd9..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * *BSD specific code
- *
- * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF")
- *
- * FRR 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, or (at your option) any
- * later version.
- *
- * FRR 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 FRR; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include <zebra.h>
-
-#ifdef BFD_BSD
-
-#include <net/if.h>
-#include <net/if_types.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <ifaddrs.h>
-
-#include "bfd.h"
-
-/*
- * Definitions.
- */
-int bp_bind_dev(int sd, const char *dev)
-{
-       /*
-        * *BSDs don't support `SO_BINDTODEVICE`, instead you must
-        * manually specify the main address of the interface or use
-        * BPF on the socket descriptor.
-        */
-       return 0;
-}
-
-#endif /* BFD_BSD */
index cd57ea9fe38b03ecd01aeb7dfe1cf4744b7299d9..74e7d63d0c6ee69790f43fb9085083a94e11f231 100644 (file)
@@ -68,7 +68,7 @@ static int config_add(struct bfd_peer_cfg *bpc,
 static int config_del(struct bfd_peer_cfg *bpc,
                      void *arg __attribute__((unused)))
 {
-       return ptm_bfd_ses_del(bpc) != 0;
+       return ptm_bfd_sess_del(bpc) != 0;
 }
 
 static int parse_config_json(struct json_object *jo, bpc_handle h, void *arg)
diff --git a/bfdd/linux.c b/bfdd/linux.c
deleted file mode 100644 (file)
index 3a76b45..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Linux specific code
- *
- * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF")
- *
- * FRR 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, or (at your option) any
- * later version.
- *
- * FRR 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 FRR; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#include <zebra.h>
-
-#ifdef BFD_LINUX
-
-#include "bfd.h"
-
-
-/*
- * Definitions.
- */
-int bp_bind_dev(int sd __attribute__((__unused__)),
-               const char *dev __attribute__((__unused__)))
-{
-       /*
-        * TODO: implement this differently. It is not possible to
-        * SO_BINDTODEVICE after the daemon has dropped its privileges.
-        */
-#if 0
-       size_t devlen = strlen(dev) + 1;
-
-       if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, dev, devlen) == -1) {
-               log_warning("%s: setsockopt(SO_BINDTODEVICE, \"%s\"): %s",
-                           __func__, dev, strerror(errno));
-               return -1;
-       }
-#endif
-
-       return 0;
-}
-
-#endif /* BFD_LINUX */
index 6f76a15a570a33c126f07dd89b800cfdfe6fa878..a12a3c196b7934bb062d8d56635ae633760c88fc 100644 (file)
@@ -58,7 +58,7 @@ static struct zclient *zclient;
 static int _ptm_msg_address(struct stream *msg, int family, const void *addr);
 
 static void _ptm_msg_read_address(struct stream *msg, struct sockaddr_any *sa);
-static int _ptm_msg_read(struct stream *msg, int command,
+static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
                         struct bfd_peer_cfg *bpc, struct ptm_client **pc);
 
 static struct ptm_client *pc_lookup(uint32_t pid);
@@ -72,8 +72,8 @@ static struct ptm_client_notification *pcn_lookup(struct ptm_client *pc,
 static void pcn_free(struct ptm_client_notification *pcn);
 
 
-static void bfdd_dest_register(struct stream *msg);
-static void bfdd_dest_deregister(struct stream *msg);
+static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id);
+static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id);
 static void bfdd_client_register(struct stream *msg);
 static void bfdd_client_deregister(struct stream *msg);
 
@@ -182,7 +182,10 @@ int ptm_bfd_notify(struct bfd_session *bs)
        stream_reset(msg);
 
        /* TODO: VRF handling */
-       zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, VRF_DEFAULT);
+       if (bs->vrf)
+               zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, bs->vrf->vrf_id);
+       else
+               zclient_create_header(msg, ZEBRA_BFD_DEST_REPLAY, VRF_DEFAULT);
 
        /* This header will be handled by `zebra_ptm.c`. */
        stream_putl(msg, ZEBRA_INTERFACE_BFD_DEST_UPDATE);
@@ -256,7 +259,7 @@ stream_failure:
        memset(sa, 0, sizeof(*sa));
 }
 
-static int _ptm_msg_read(struct stream *msg, int command,
+static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id,
                         struct bfd_peer_cfg *bpc, struct ptm_client **pc)
 {
        uint32_t pid;
@@ -355,6 +358,18 @@ static int _ptm_msg_read(struct stream *msg, int command,
                        bpc->bpc_localif[ifnamelen] = 0;
                }
        }
+       if (vrf_id != VRF_DEFAULT) {
+               struct vrf *vrf;
+
+               vrf = vrf_lookup_by_id(vrf_id);
+               if (vrf) {
+                       bpc->bpc_has_vrfname = true;
+                       strlcpy(bpc->bpc_vrfname, vrf->name, sizeof(bpc->bpc_vrfname));
+               } else {
+                       log_error("ptm-read: vrf id %u could not be identified", vrf_id);
+                       return -1;
+               }
+       }
 
        /* Sanity check: peer and local address must match IP types. */
        if (bpc->bpc_local.sa_sin.sin_family != 0
@@ -370,7 +385,7 @@ stream_failure:
        return -1;
 }
 
-static void bfdd_dest_register(struct stream *msg)
+static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id)
 {
        struct ptm_client *pc;
        struct ptm_client_notification *pcn;
@@ -378,7 +393,7 @@ static void bfdd_dest_register(struct stream *msg)
        struct bfd_peer_cfg bpc;
 
        /* Read the client context and peer data. */
-       if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_REGISTER, &bpc, &pc) == -1)
+       if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_REGISTER, vrf_id, &bpc, &pc) == -1)
                return;
 
        DEBUG_PRINTBPC(&bpc);
@@ -408,7 +423,7 @@ static void bfdd_dest_register(struct stream *msg)
        ptm_bfd_notify(bs);
 }
 
-static void bfdd_dest_deregister(struct stream *msg)
+static void bfdd_dest_deregister(struct stream *msg, vrf_id_t vrf_id)
 {
        struct ptm_client *pc;
        struct ptm_client_notification *pcn;
@@ -416,7 +431,7 @@ static void bfdd_dest_deregister(struct stream *msg)
        struct bfd_peer_cfg bpc;
 
        /* Read the client context and peer data. */
-       if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_DEREGISTER, &bpc, &pc) == -1)
+       if (_ptm_msg_read(msg, ZEBRA_BFD_DEST_DEREGISTER, vrf_id, &bpc, &pc) == -1)
                return;
 
        DEBUG_PRINTBPC(&bpc);
@@ -434,7 +449,7 @@ static void bfdd_dest_deregister(struct stream *msg)
        if (bs->refcount ||
            BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG))
                return;
-       ptm_bfd_ses_del(&bpc);
+       ptm_bfd_sess_del(&bpc);
 }
 
 /*
@@ -497,10 +512,10 @@ static int bfdd_replay(ZAPI_CALLBACK_ARGS)
        switch (rcmd) {
        case ZEBRA_BFD_DEST_REGISTER:
        case ZEBRA_BFD_DEST_UPDATE:
-               bfdd_dest_register(msg);
+               bfdd_dest_register(msg, vrf_id);
                break;
        case ZEBRA_BFD_DEST_DEREGISTER:
-               bfdd_dest_deregister(msg);
+               bfdd_dest_deregister(msg, vrf_id);
                break;
        case ZEBRA_BFD_CLIENT_REGISTER:
                bfdd_client_register(msg);
@@ -548,15 +563,21 @@ static void bfdd_sessions_enable_interface(struct interface *ifp)
 {
        struct bfd_session_observer *bso;
        struct bfd_session *bs;
+       struct vrf *vrf;
 
        TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
+               bs = bso->bso_bs;
                if (bso->bso_isinterface == false)
                        continue;
-
                /* Interface name mismatch. */
-               bs = bso->bso_bs;
                if (strcmp(ifp->name, bs->key.ifname))
                        continue;
+               vrf = vrf_lookup_by_id(ifp->vrf_id);
+               if (!vrf)
+                       continue;
+               if (bs->key.vrfname[0] &&
+                   strcmp(vrf->name, bs->key.vrfname))
+                       continue;
                /* Skip enabled sessions. */
                if (bs->sock != -1)
                        continue;
@@ -586,7 +607,52 @@ static void bfdd_sessions_disable_interface(struct interface *ifp)
                /* Try to enable it. */
                bfd_session_disable(bs);
 
-               TAILQ_INSERT_HEAD(&bglobal.bg_obslist, bso, bso_entry);
+       }
+}
+
+void bfdd_sessions_enable_vrf(struct vrf *vrf)
+{
+       struct bfd_session_observer *bso;
+       struct bfd_session *bs;
+
+       /* it may affect configs without interfaces */
+       TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
+               bs = bso->bso_bs;
+               if (bs->vrf)
+                       continue;
+               if (bs->key.vrfname[0] &&
+                   strcmp(vrf->name, bs->key.vrfname))
+                       continue;
+               /* need to update the vrf information on
+                * bs so that callbacks are handled
+                */
+               bs->vrf = vrf;
+               /* Skip enabled sessions. */
+               if (bs->sock != -1)
+                       continue;
+               /* Try to enable it. */
+               bfd_session_enable(bs);
+       }
+}
+
+void bfdd_sessions_disable_vrf(struct vrf *vrf)
+{
+       struct bfd_session_observer *bso;
+       struct bfd_session *bs;
+
+       TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
+               if (bso->bso_isinterface)
+                       continue;
+               bs = bso->bso_bs;
+               if (bs->key.vrfname[0] &&
+                   strcmp(vrf->name, bs->key.vrfname))
+                       continue;
+               /* Skip disabled sessions. */
+               if (bs->sock == -1)
+                       continue;
+
+               /* Try to enable it. */
+               bfd_session_disable(bs);
        }
 }
 
@@ -701,6 +767,20 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
        zclient->interface_address_delete = bfdd_interface_address_update;
 }
 
+void bfdd_zclient_register(vrf_id_t vrf_id)
+{
+       if (!zclient || zclient->sock < 0)
+               return;
+       zclient_send_reg_requests(zclient, vrf_id);
+}
+
+void bfdd_zclient_unregister(vrf_id_t vrf_id)
+{
+       if (!zclient || zclient->sock < 0)
+               return;
+       zclient_send_dereg_requests(zclient, vrf_id);
+}
+
 void bfdd_zclient_stop(void)
 {
        zclient_stop(zclient);
index 334e974b048a9eb1676666b4e63c8eaa65e3d97c..e88b982ec3bfcc5d9260d936f7536a613040cb95 100644 (file)
@@ -14,11 +14,9 @@ bfdd_libbfd_a_SOURCES = \
        bfdd/bfd.c \
        bfdd/bfdd_vty.c \
        bfdd/bfd_packet.c \
-       bfdd/bsd.c \
        bfdd/config.c \
        bfdd/control.c \
        bfdd/event.c \
-       bfdd/linux.c \
        bfdd/log.c \
        bfdd/ptm_adapter.c \
        # end
index c9f68d037bebc733f51d9997f1ff7dded09690f0..497fb0749e19063c9703bfa11fbf378695dbe182 100644 (file)
@@ -64,9 +64,9 @@ static void *baa_hash_alloc(void *p)
        return baa;
 }
 
-unsigned int baa_hash_key(void *p)
+unsigned int baa_hash_key(const void *p)
 {
-       struct bgp_advertise_attr *baa = (struct bgp_advertise_attr *)p;
+       const struct bgp_advertise_attr *baa = p;
 
        return attrhash_key_make(baa->attr);
 }
index cc845b93e751a025a7120231bd834080193fec3c..7d2fdf1f0b2e35454d286294bd7dd7b0a4b9ff66 100644 (file)
@@ -144,7 +144,7 @@ extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *);
 
 extern void bgp_sync_init(struct peer *);
 extern void bgp_sync_delete(struct peer *);
-extern unsigned int baa_hash_key(void *p);
+extern unsigned int baa_hash_key(const void *p);
 extern bool baa_hash_cmp(const void *p1, const void *p2);
 extern void bgp_advertise_add(struct bgp_advertise_attr *baa,
                              struct bgp_advertise *adv);
index 92c37fabd23483274b1e47adf9616aab38eda2f1..05577cb8bdb0779847fd7f04d321dc5398d9bbad 100644 (file)
@@ -2008,13 +2008,13 @@ struct aspath *aspath_str2aspath(const char *str)
 }
 
 /* Make hash value by raw aspath data. */
-unsigned int aspath_key_make(void *p)
+unsigned int aspath_key_make(const void *p)
 {
-       struct aspath *aspath = (struct aspath *)p;
+       const struct aspath *aspath = p;
        unsigned int key = 0;
 
        if (!aspath->str)
-               aspath_str_update(aspath, false);
+               aspath_str_update((struct aspath *)aspath, false);
 
        key = jhash(aspath->str, aspath->str_len, 2334325);
 
index be5725c1aea739a5aa088b0eb786aa5036f2c1a9..6f3d94cdb3f948c68f826626085a88faea2eca32 100644 (file)
@@ -102,7 +102,7 @@ extern const char *aspath_print(struct aspath *);
 extern void aspath_print_vty(struct vty *, const char *, struct aspath *,
                             const char *);
 extern void aspath_print_all_vty(struct vty *);
-extern unsigned int aspath_key_make(void *);
+extern unsigned int aspath_key_make(const void *);
 extern unsigned int aspath_get_first_as(struct aspath *);
 extern unsigned int aspath_get_last_as(struct aspath *);
 extern int aspath_loop_check(struct aspath *, as_t);
index 167ad89a5988f026f4424db02b90505601e26c6f..5a4105b4004f1ad2b4b019c878580ec897eb09ba 100644 (file)
@@ -51,7 +51,6 @@
 #include "bgp_encap_types.h"
 #include "bgp_vnc_types.h"
 #endif
-#include "bgp_encap_types.h"
 #include "bgp_evpn.h"
 #include "bgp_flowspec_private.h"
 #include "bgp_mac.h"
@@ -140,7 +139,7 @@ int cluster_loop_check(struct cluster_list *cluster, struct in_addr originator)
        return 0;
 }
 
-static unsigned int cluster_hash_key_make(void *p)
+static unsigned int cluster_hash_key_make(const void *p)
 {
        const struct cluster_list *cluster = p;
 
@@ -348,7 +347,7 @@ static void encap_unintern(struct bgp_attr_encap_subtlv **encapp,
        }
 }
 
-static unsigned int encap_hash_key_make(void *p)
+static unsigned int encap_hash_key_make(const void *p)
 {
        const struct bgp_attr_encap_subtlv *encap = p;
 
@@ -433,7 +432,7 @@ void transit_unintern(struct transit *transit)
        }
 }
 
-static unsigned int transit_hash_key_make(void *p)
+static unsigned int transit_hash_key_make(const void *p)
 {
        const struct transit *transit = p;
 
@@ -484,7 +483,7 @@ unsigned long int attr_unknown_count(void)
        return transit_hash->count;
 }
 
-unsigned int attrhash_key_make(void *p)
+unsigned int attrhash_key_make(const void *p)
 {
        const struct attr *attr = (struct attr *)p;
        uint32_t key = 0;
@@ -1256,6 +1255,32 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
        return BGP_ATTR_PARSE_PROCEED;
 }
 
+/*
+ * Check that the nexthop attribute is valid.
+ */
+bgp_attr_parse_ret_t
+bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
+{
+       in_addr_t nexthop_h;
+
+       nexthop_h = ntohl(attr->nexthop.s_addr);
+       if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h)
+            || IPV4_CLASS_DE(nexthop_h))
+           && !BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) {
+               char buf[INET_ADDRSTRLEN];
+
+               inet_ntop(AF_INET, &attr->nexthop.s_addr, buf,
+                         INET_ADDRSTRLEN);
+               flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s",
+                        buf);
+               bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
+                               BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP);
+               return BGP_ATTR_PARSE_ERROR;
+       }
+
+       return BGP_ATTR_PARSE_PROCEED;
+}
+
 /* Nexthop attribute. */
 static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
 {
@@ -1263,8 +1288,6 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
        struct attr *const attr = args->attr;
        const bgp_size_t length = args->length;
 
-       in_addr_t nexthop_h, nexthop_n;
-
        /* Check nexthop attribute length. */
        if (length != 4) {
                flog_err(EC_BGP_ATTR_LEN,
@@ -1274,30 +1297,7 @@ static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
                                          args->total);
        }
 
-       /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP
-          attribute must result in a NOTIFICATION message (this is implemented
-          below).
-          At the same time, semantically incorrect NEXT_HOP is more likely to
-          be just
-          logged locally (this is implemented somewhere else). The UPDATE
-          message
-          gets ignored in any of these cases. */
-       nexthop_n = stream_get_ipv4(peer->curr);
-       nexthop_h = ntohl(nexthop_n);
-       if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h)
-            || IPV4_CLASS_DE(nexthop_h))
-           && !BGP_DEBUG(
-                      allow_martians,
-                      ALLOW_MARTIANS)) /* loopbacks may be used in testing */
-       {
-               char buf[INET_ADDRSTRLEN];
-               inet_ntop(AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN);
-               flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s", buf);
-               return bgp_attr_malformed(
-                       args, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, args->total);
-       }
-
-       attr->nexthop.s_addr = nexthop_n;
+       attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
        attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
 
        return BGP_ATTR_PARSE_PROCEED;
@@ -1956,6 +1956,10 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
 
        }
 
+       /* Get the tunnel type from encap extended community */
+       bgp_attr_extcom_tunnel_type(attr,
+               (bgp_encap_types *)&attr->encap_tunneltype);
+
        return BGP_ATTR_PARSE_PROCEED;
 }
 
@@ -2681,6 +2685,26 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                return BGP_ATTR_PARSE_ERROR;
        }
 
+       /*
+        * RFC4271: If the NEXT_HOP attribute field is syntactically incorrect,
+        * then the Error Subcode MUST be set to Invalid NEXT_HOP Attribute.
+        * This is implemented below and will result in a NOTIFICATION. If the
+        * NEXT_HOP attribute is semantically incorrect, the error SHOULD be
+        * logged, and the route SHOULD be ignored. In this case, a NOTIFICATION
+        * message SHOULD NOT be sent. This is implemented elsewhere.
+        *
+        * RFC4760: An UPDATE message that carries no NLRI, other than the one
+        * encoded in the MP_REACH_NLRI attribute, SHOULD NOT carry the NEXT_HOP
+        * attribute. If such a message contains the NEXT_HOP attribute, the BGP
+        * speaker that receives the message SHOULD ignore this attribute.
+        */
+       if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))
+           && !CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
+               if (bgp_attr_nexthop_valid(peer, attr) < 0) {
+                       return BGP_ATTR_PARSE_ERROR;
+               }
+       }
+
        /* Check all mandatory well-known attributes are present */
        if ((ret = bgp_attr_check(peer, attr)) < 0) {
                if (as4_path)
@@ -2755,6 +2779,38 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
        return BGP_ATTR_PARSE_PROCEED;
 }
 
+/*
+ * Extract the tunnel type from extended community
+ */
+void bgp_attr_extcom_tunnel_type(struct attr *attr,
+                                bgp_encap_types *tunnel_type)
+{
+       struct ecommunity *ecom;
+       int i;
+       if (!attr)
+               return;
+
+       ecom = attr->ecommunity;
+       if (!ecom || !ecom->size)
+               return;
+
+       for (i = 0; i < ecom->size; i++) {
+               uint8_t *pnt;
+               uint8_t type, sub_type;
+
+               pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
+               type = pnt[0];
+               sub_type = pnt[1];
+               if (!(type == ECOMMUNITY_ENCODE_OPAQUE &&
+                     sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP))
+                       continue;
+               *tunnel_type = ((pnt[6] << 8) | pnt[7]);
+               return;
+       }
+
+       return;
+}
+
 size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
                               safi_t safi, struct bpacket_attr_vec_arr *vecarr,
                               struct attr *attr)
index 6d5c647b21c296f4d794f03cc2c398350f295ad6..1592a8df4edae90fe0d627dc39c13c95a8bf2082 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "mpls.h"
 #include "bgp_attr_evpn.h"
+#include "bgpd/bgp_encap_types.h"
 
 /* Simple bit mapping. */
 #define BITMAP_NBBY 8
@@ -282,7 +283,7 @@ extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
 extern void bgp_dump_routes_attr(struct stream *, struct attr *,
                                 struct prefix *);
 extern bool attrhash_cmp(const void *arg1, const void *arg2);
-extern unsigned int attrhash_key_make(void *);
+extern unsigned int attrhash_key_make(const void *);
 extern void attr_show_all(struct vty *);
 extern unsigned long int attr_count(void);
 extern unsigned long int attr_unknown_count(void);
@@ -317,6 +318,9 @@ encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
 
 extern void bgp_attr_flush_encap(struct attr *attr);
 
+extern void bgp_attr_extcom_tunnel_type(struct attr *attr,
+                                        bgp_encap_types *tunnel_type);
+
 /**
  * Set of functions to encode MP_REACH_NLRI and MP_UNREACH_NLRI attributes.
  * Typical call sequence is to call _start(), followed by multiple _prefix(),
@@ -344,6 +348,9 @@ extern void bgp_packet_mpunreach_prefix(struct stream *s, struct prefix *p,
                                        uint32_t, int, uint32_t, struct attr *);
 extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
 
+extern bgp_attr_parse_ret_t bgp_attr_nexthop_valid(struct peer *peer,
+                                                  struct attr *attr);
+
 static inline int bgp_rmap_nhop_changed(uint32_t out_rmap_flags,
                                        uint32_t in_rmap_flags)
 {
index 45e45977a4ada851fe0cfcb29e6a5aadd20840de..a9c30acafbf711d7cb314ae7317aa87ea5014403 100644 (file)
@@ -96,13 +96,12 @@ int bgp_bfd_is_peer_multihop(struct peer *peer)
 static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
 {
        struct bfd_info *bfd_info;
-       vrf_id_t vrf_id = VRF_DEFAULT;
        int multihop;
+       vrf_id_t vrf_id;
 
        bfd_info = (struct bfd_info *)peer->bfd_info;
 
-       if (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
-               vrf_id = peer->bgp->vrf_id;
+       vrf_id = peer->bgp->vrf_id;
 
        if (command == ZEBRA_BFD_DEST_DEREGISTER) {
                multihop =
@@ -244,7 +243,7 @@ static int bgp_bfd_dest_replay(ZAPI_CALLBACK_ARGS)
                zlog_debug("Zebra: BFD Dest replay request");
 
        /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id);
 
        /* Replay the peer, if BFD is enabled in BGP */
 
index e308e963b55f47e555fbb70d370e04fe48c605db..b9a5784799c6df89e0ebb8ebda00aeaeb9ae5ed8 100644 (file)
@@ -36,9 +36,9 @@
 #include "bgpd/bgp_regex.h"
 #include "bgpd/bgp_clist.h"
 
-static uint32_t bgp_clist_hash_key_community_list(void *data)
+static uint32_t bgp_clist_hash_key_community_list(const void *data)
 {
-       struct community_list *cl = data;
+       struct community_list *cl = (struct community_list *) data;
 
        if (cl->name_hash)
                return cl->name_hash;
index 67cd2be214897036c6d713d84ade54c0ba547445..82762072df0966e37d2776ecef0beeea18fd7506 100644 (file)
@@ -574,7 +574,7 @@ char *community_str(struct community *com, bool make_json)
 
 /* Make hash value of community attribute. This function is used by
    hash package.*/
-unsigned int community_hash_make(struct community *com)
+unsigned int community_hash_make(const struct community *com)
 {
        uint32_t *pnt = (uint32_t *)com->val;
 
@@ -897,7 +897,7 @@ struct hash *community_hash(void)
 void community_init(void)
 {
        comhash =
-               hash_create((unsigned int (*)(void *))community_hash_make,
+               hash_create((unsigned int (*)(const void *))community_hash_make,
                            (bool (*)(const void *, const void *))community_cmp,
                            "BGP Community Hash");
 }
@@ -957,7 +957,7 @@ void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
         */
        if (aggregate->community_hash == NULL)
                aggregate->community_hash = hash_create(
-                       (unsigned int (*)(void *))community_hash_make,
+                       (unsigned int (*)(const void *))community_hash_make,
                        (bool (*)(const void *, const void *))community_cmp,
                        "BGP Aggregator community hash");
 
index 4ff4d214a5606e0de610c909cad11ccf5f492122..f761a8f5e0f6b4d56200e8593c6d0e1788a9e1d5 100644 (file)
@@ -75,7 +75,7 @@ extern struct community *community_parse(uint32_t *, unsigned short);
 extern struct community *community_intern(struct community *);
 extern void community_unintern(struct community **);
 extern char *community_str(struct community *, bool make_json);
-extern unsigned int community_hash_make(struct community *);
+extern unsigned int community_hash_make(const struct community *);
 extern struct community *community_str2com(const char *);
 extern int community_match(const struct community *, const struct community *);
 extern bool community_cmp(const struct community *c1,
index 8ef398952d3a59217006ad37fea9aa17f6fc8c1d..76bd0e815e6771cc81bfe8ea3c59b3b8da6efa2f 100644 (file)
@@ -241,7 +241,7 @@ void ecommunity_unintern(struct ecommunity **ecom)
 }
 
 /* Utinity function to make hash key.  */
-unsigned int ecommunity_hash_make(void *arg)
+unsigned int ecommunity_hash_make(const void *arg)
 {
        const struct ecommunity *ecom = arg;
        int size = ecom->size * ECOMMUNITY_SIZE;
index 62b213775391f64f599c94567a97423cacde894c..79be4ee4227da4119b95cdaf8cbe522f3be62e3a 100644 (file)
@@ -22,6 +22,7 @@
 #define _QUAGGA_BGP_ECOMMUNITY_H
 
 #include "bgpd/bgp_route.h"
+#include "bgpd/bgpd.h"
 
 /* High-order octet of the Extended Communities type field.  */
 #define ECOMMUNITY_ENCODE_AS                0x00
@@ -162,7 +163,7 @@ extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
 extern struct ecommunity *ecommunity_intern(struct ecommunity *);
 extern bool ecommunity_cmp(const void *arg1, const void *arg2);
 extern void ecommunity_unintern(struct ecommunity **);
-extern unsigned int ecommunity_hash_make(void *);
+extern unsigned int ecommunity_hash_make(const void *);
 extern struct ecommunity *ecommunity_str2com(const char *, int, int);
 extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
 extern void ecommunity_strfree(char **s);
index 52aa923959a91cc9870799f2dfec29694b773d4c..112e4b836c2e90857663501204f17ccc88e960e4 100644 (file)
@@ -83,9 +83,9 @@ static int evpn_vtep_ip_cmp(void *p1, void *p2)
 /*
  * Make hash key for ESI.
  */
-static unsigned int esi_hash_keymake(void *p)
+static unsigned int esi_hash_keymake(const void *p)
 {
-       struct evpnes *pes = p;
+       const struct evpnes *pes = p;
        const void *pnt = (void *)pes->esi.val;
 
        return jhash(pnt, ESI_BYTES, 0xa5a5a55a);
@@ -111,9 +111,9 @@ static bool esi_cmp(const void *p1, const void *p2)
 /*
  * Make vni hash key.
  */
-static unsigned int vni_hash_key_make(void *p)
+static unsigned int vni_hash_key_make(const void *p)
 {
-       struct bgpevpn *vpn = p;
+       const struct bgpevpn *vpn = p;
        return (jhash_1word(vpn->vni, 0));
 }
 
@@ -143,10 +143,10 @@ static int vni_list_cmp(void *p1, void *p2)
 /*
  * Make vrf import route target hash key.
  */
-static unsigned int vrf_import_rt_hash_key_make(void *p)
+static unsigned int vrf_import_rt_hash_key_make(const void *p)
 {
-       struct vrf_irt_node *irt = p;
-       char *pnt = irt->rt.val;
+       const struct vrf_irt_node *irt = p;
+       const char *pnt = irt->rt.val;
 
        return jhash(pnt, 8, 0x5abc1234);
 }
@@ -259,10 +259,10 @@ static int is_vrf_present_in_irt_vrfs(struct list *vrfs, struct bgp *bgp_vrf)
 /*
  * Make import route target hash key.
  */
-static unsigned int import_rt_hash_key_make(void *p)
+static unsigned int import_rt_hash_key_make(const void *p)
 {
-       struct irt_node *irt = p;
-       char *pnt = irt->rt.val;
+       const struct irt_node *irt = p;
+       const char *pnt = irt->rt.val;
 
        return jhash(pnt, 8, 0xdeadbeef);
 }
index 1bd153639bf1d03dac82b6a2315d0aeb0c6fc47b..8414ae57493c7d975ce0e07a5ce1ccbefea33af7 100644 (file)
@@ -1048,7 +1048,20 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                rd_header = 1;
                tbl_ver = table->version;
 
-               for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm))
+               for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
+                       if (use_json) {
+                               json_array = json_object_new_array();
+                               json_prefix_info = json_object_new_object();
+
+                               json_object_string_add(json_prefix_info,
+                                       "prefix", bgp_evpn_route2str(
+                                       (struct prefix_evpn *)&rm->p, buf,
+                                       BUFSIZ));
+
+                               json_object_int_add(json_prefix_info,
+                                       "prefixLen", rm->p.prefixlen);
+                       }
+
                        for (pi = bgp_node_get_bgp_path_info(rm); pi;
                             pi = pi->next) {
                                total_count++;
@@ -1121,10 +1134,6 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                        if (use_json) {
                                                json_nroute =
                                                      json_object_new_object();
-                                               json_prefix_info =
-                                                      json_object_new_object();
-                                               json_array =
-                                                       json_object_new_array();
                                                if (type == RD_TYPE_AS
                                                    || type == RD_TYPE_AS4)
                                                        sprintf(rd_str, "%u:%d",
@@ -1140,18 +1149,6 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                                        "rd",
                                                        rd_str);
 
-                                               json_object_string_add(
-                                                       json_prefix_info,
-                                                       "prefix",
-                                                       bgp_evpn_route2str(
-                                                       (struct prefix_evpn *)
-                                                       &rm->p, buf, BUFSIZ));
-
-                                               json_object_int_add(
-                                                       json_prefix_info,
-                                                       "prefixLen",
-                                                       rm->p.prefixlen);
-
                                        } else {
                                                vty_out(vty,
                                                        "Route Distinguisher: ");
@@ -1174,6 +1171,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                        }
                                        rd_header = 0;
                                }
+
                                if (option == SHOW_DISPLAY_TAGS)
                                        route_vty_out_tag(vty, &rm->p, pi, 0,
                                                          SAFI_EVPN,
@@ -1186,14 +1184,16 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                                      SAFI_EVPN, json_array);
                                output_count++;
                        }
+                       if (use_json) {
+                               json_object_object_add(json_prefix_info,
+                                       "paths", json_array);
+                               json_object_object_add(json_nroute, buf,
+                                       json_prefix_info);
+                       }
+               }
 
-               if (use_json) {
-                       json_object_object_add(json_prefix_info, "paths",
-                               json_array);
-                       json_object_object_add(json_nroute, buf,
-                               json_prefix_info);
+               if (use_json)
                        json_object_object_add(json, rd_str, json_nroute);
-               }
        }
 
        if (use_json) {
@@ -1554,14 +1554,15 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
 
 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
       show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
-      "show [ip] bgp l2vpn evpn all overlay",
+      "show [ip] bgp l2vpn evpn all overlay [json]",
       SHOW_STR
       IP_STR
       BGP_STR
       L2VPN_HELP_STR
       EVPN_HELP_STR
       "Display information about all EVPN NLRIs\n"
-      "Display BGP Overlay Information for prefixes\n")
+      "Display BGP Overlay Information for prefixes\n"
+      JSON_STR)
 {
        return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
                                     SHOW_DISPLAY_OVERLAY,
index c2f0baff76ca4b6dda387f829cd4193aeeceb788..bec3bdcb8d0e1320b957e00b8c4f7694a2c71848 100644 (file)
@@ -131,9 +131,9 @@ static bool peer_hash_cmp(const void *f, const void *s)
        return p1->peer == p2->peer;
 }
 
-static unsigned int peer_hash_key(void *arg)
+static unsigned int peer_hash_key(const void *arg)
 {
-       struct pkat *pkat = arg;
+       const struct pkat *pkat = arg;
        return (uintptr_t)pkat->peer;
 }
 
index 44766c9b6e30700bf4718ea9860b6202ce16fb02..098374fa9f7b92b89e8f342e66afe37853ea3915 100644 (file)
@@ -301,7 +301,7 @@ char *lcommunity_str(struct lcommunity *lcom, bool make_json)
 }
 
 /* Utility function to make hash key.  */
-unsigned int lcommunity_hash_make(void *arg)
+unsigned int lcommunity_hash_make(const void *arg)
 {
        const struct lcommunity *lcom = arg;
        int size = lcom_length(lcom);
index aa4e8c69fe4744e9a8eb3c24b6898ae26224ba90..a512395492f9788e92a39273012845b4a71f66d6 100644 (file)
@@ -63,7 +63,7 @@ extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *);
 extern struct lcommunity *lcommunity_intern(struct lcommunity *);
 extern bool lcommunity_cmp(const void *arg1, const void *arg2);
 extern void lcommunity_unintern(struct lcommunity **);
-extern unsigned int lcommunity_hash_make(void *);
+extern unsigned int lcommunity_hash_make(const void *);
 extern struct hash *lcommunity_hash(void);
 extern struct lcommunity *lcommunity_str2com(const char *);
 extern int lcommunity_match(const struct lcommunity *,
index 49b585402090352723efee25f32948c72f0a6a10..f19453fecb68db648532a1da44d79f9b19d7a6e0 100644 (file)
@@ -40,9 +40,9 @@ struct bgp_self_mac {
        struct list *ifp_list;
 };
 
-static unsigned int bgp_mac_hash_key_make(void *data)
+static unsigned int bgp_mac_hash_key_make(const void *data)
 {
-       struct bgp_self_mac *bsm = data;
+       const struct bgp_self_mac *bsm = data;
 
        return jhash(&bsm->macaddr, ETH_ALEN, 0xa5a5dead);
 }
index de97b73c7210ab41d1b534d4e33b4af72c1130b0..ea5e02d00ebf97133edea39eefaf40043d7aadc7 100644 (file)
@@ -114,7 +114,7 @@ static void bgp_tip_hash_free(void *addr)
        XFREE(MTYPE_TIP_ADDR, addr);
 }
 
-static unsigned int bgp_tip_hash_key_make(void *p)
+static unsigned int bgp_tip_hash_key_make(const void *p)
 {
        const struct tip_addr *addr = p;
 
@@ -237,7 +237,7 @@ static void bgp_address_hash_free(void *data)
        XFREE(MTYPE_BGP_ADDR, addr);
 }
 
-static unsigned int bgp_address_hash_key_make(void *p)
+static unsigned int bgp_address_hash_key_make(const void *p)
 {
        const struct bgp_addr *addr = p;
 
index 130e06a6cf1ba887531db13fee05b445dc501391..b5934fb56e220a67359c29430c08b48a54581e3a 100644 (file)
@@ -1533,6 +1533,17 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
                nlris[NLRI_UPDATE].nlri = stream_pnt(s);
                nlris[NLRI_UPDATE].length = update_len;
                stream_forward_getp(s, update_len);
+
+               if (CHECK_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) {
+                       /*
+                        * We skipped nexthop attribute validation earlier so
+                        * validate the nexthop now.
+                        */
+                       if (bgp_attr_nexthop_valid(peer, &attr) < 0) {
+                               bgp_attr_unintern_sub(&attr);
+                               return BGP_Stop;
+                       }
+               }
        }
 
        if (BGP_DEBUG(update, UPDATE_IN))
index 0fddfa75a1e88a87f33cd38cefeecc8529e1be3f..5eef6ac6ccc36ad7ba6ff4ffd29c093bf27ed835 100644 (file)
@@ -964,9 +964,9 @@ static void *bgp_pbr_match_entry_alloc_intern(void *arg)
        return new;
 }
 
-uint32_t bgp_pbr_match_hash_key(void *arg)
+uint32_t bgp_pbr_match_hash_key(const void *arg)
 {
-       struct bgp_pbr_match *pbm = (struct bgp_pbr_match *)arg;
+       const struct bgp_pbr_match *pbm = arg;
        uint32_t key;
 
        key = jhash_1word(pbm->vrf_id, 0x4312abde);
@@ -1019,9 +1019,9 @@ bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
        return true;
 }
 
-uint32_t bgp_pbr_rule_hash_key(void *arg)
+uint32_t bgp_pbr_rule_hash_key(const void *arg)
 {
-       struct bgp_pbr_rule *pbr = (struct bgp_pbr_rule *)arg;
+       const struct bgp_pbr_rule *pbr = arg;
        uint32_t key;
 
        key = prefix_hash_key(&pbr->src);
@@ -1057,12 +1057,12 @@ bool bgp_pbr_rule_hash_equal(const void *arg1, const void *arg2)
        return true;
 }
 
-uint32_t bgp_pbr_match_entry_hash_key(void *arg)
+uint32_t bgp_pbr_match_entry_hash_key(const void *arg)
 {
-       struct bgp_pbr_match_entry *pbme;
+       const struct bgp_pbr_match_entry *pbme;
        uint32_t key;
 
-       pbme = (struct bgp_pbr_match_entry *)arg;
+       pbme = arg;
        key = prefix_hash_key(&pbme->src);
        key = jhash_1word(prefix_hash_key(&pbme->dst), key);
        key = jhash(&pbme->dst_port_min, 2, key);
@@ -1111,12 +1111,12 @@ bool bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2)
        return true;
 }
 
-uint32_t bgp_pbr_action_hash_key(void *arg)
+uint32_t bgp_pbr_action_hash_key(const void *arg)
 {
-       struct bgp_pbr_action *pbra;
+       const struct bgp_pbr_action *pbra;
        uint32_t key;
 
-       pbra = (struct bgp_pbr_action *)arg;
+       pbra = arg;
        key = jhash_1word(pbra->table_id, 0x4312abde);
        key = jhash_1word(pbra->fwmark, key);
        return key;
index f7fddac7fbf7ddb422c27ab1a50d933eff5fa680..b368d8892def96e76559095a0dc53e71b28016d8 100644 (file)
@@ -273,16 +273,16 @@ extern struct bgp_pbr_match *bgp_pbr_match_iptable_lookup(vrf_id_t vrf_id,
 extern void bgp_pbr_cleanup(struct bgp *bgp);
 extern void bgp_pbr_init(struct bgp *bgp);
 
-extern uint32_t bgp_pbr_rule_hash_key(void *arg);
+extern uint32_t bgp_pbr_rule_hash_key(const void *arg);
 extern bool bgp_pbr_rule_hash_equal(const void *arg1,
                                   const void *arg2);
-extern uint32_t bgp_pbr_action_hash_key(void *arg);
+extern uint32_t bgp_pbr_action_hash_key(const void *arg);
 extern bool bgp_pbr_action_hash_equal(const void *arg1,
                                     const void *arg2);
-extern uint32_t bgp_pbr_match_entry_hash_key(void *arg);
+extern uint32_t bgp_pbr_match_entry_hash_key(const void *arg);
 extern bool bgp_pbr_match_entry_hash_equal(const void *arg1,
                                          const void *arg2);
-extern uint32_t bgp_pbr_match_hash_key(void *arg);
+extern uint32_t bgp_pbr_match_hash_key(const void *arg);
 extern bool bgp_pbr_match_hash_equal(const void *arg1,
                                    const void *arg2);
 
index fc6798fdfc8ff8284c1984e122367bb6f85de14d..d5e12488d76f3b51cbfe53f2b6ea6e439279aedd 100644 (file)
@@ -1219,20 +1219,6 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p,
                }
        }
 
-       /* RFC 8212 to prevent route leaks.
-        * This specification intends to improve this situation by requiring the
-        * explicit configuration of both BGP Import and Export Policies for any
-        * External BGP (EBGP) session such as customers, peers, or
-        * confederation boundaries for all enabled address families. Through
-        * codification of the aforementioned requirement, operators will
-        * benefit from consistent behavior across different BGP
-        * implementations.
-        */
-       if (peer->bgp->ebgp_requires_policy
-           == DEFAULT_EBGP_POLICY_ENABLED)
-               if (!bgp_inbound_policy_exists(peer, filter))
-                       return RMAP_DENY;
-
        /* Route map apply. */
        if (rmap) {
                memset(&rmap_path, 0, sizeof(struct bgp_path_info));
@@ -1781,6 +1767,10 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
                peer->rmap_type = 0;
 
                if (ret == RMAP_DENYMATCH) {
+                       if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
+                               zlog_debug("%s [Update:SEND] %s is filtered by route-map",
+                               peer->host, prefix2str(p, buf, sizeof(buf)));
+
                        bgp_attr_flush(attr);
                        return 0;
                }
@@ -3049,6 +3039,22 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
                goto filtered;
        }
 
+       /* RFC 8212 to prevent route leaks.
+        * This specification intends to improve this situation by requiring the
+        * explicit configuration of both BGP Import and Export Policies for any
+        * External BGP (EBGP) session such as customers, peers, or
+        * confederation boundaries for all enabled address families. Through
+        * codification of the aforementioned requirement, operators will
+        * benefit from consistent behavior across different BGP
+        * implementations.
+        */
+       if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
+               if (!bgp_inbound_policy_exists(peer,
+                                              &peer->filter[afi][safi])) {
+                       reason = "inbound policy missing";
+                       goto filtered;
+               }
+
        bgp_attr_dup(&new_attr, attr);
 
        /* Apply incoming route-map.
@@ -7519,21 +7525,26 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
                           json_object *json_paths)
 {
        struct attr *attr;
-       char buf[BUFSIZ];
+       char buf[BUFSIZ] = {0};
        json_object *json_path = NULL;
-
-       if (json_paths)
-               json_path = json_object_new_object();
+       json_object *json_nexthop = NULL;
+       json_object *json_overlay = NULL;
 
        if (!path->extra)
                return;
 
+       if (json_paths) {
+               json_path = json_object_new_object();
+               json_overlay = json_object_new_object();
+               json_nexthop = json_object_new_object();
+       }
+
        /* short status lead text */
        route_vty_short_status_out(vty, path, json_path);
 
        /* print prefix and mask */
        if (!display)
-               route_vty_out_route(p, vty, NULL);
+               route_vty_out_route(p, vty, json_path);
        else
                vty_out(vty, "%*s", 17, " ");
 
@@ -7545,35 +7556,69 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
 
                switch (af) {
                case AF_INET:
-                       vty_out(vty, "%-16s",
-                               inet_ntop(af, &attr->mp_nexthop_global_in, buf,
-                                         BUFSIZ));
+                       inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
+                       if (!json_path) {
+                               vty_out(vty, "%-16s", buf);
+                       } else {
+                               json_object_string_add(json_nexthop, "ip", buf);
+
+                               json_object_string_add(json_nexthop, "afi",
+                                       "ipv4");
+
+                               json_object_object_add(json_path, "nexthop",
+                                       json_nexthop);
+                       }
                        break;
                case AF_INET6:
-                       vty_out(vty, "%s(%s)",
-                               inet_ntop(af, &attr->mp_nexthop_global, buf,
-                                         BUFSIZ),
-                               inet_ntop(af, &attr->mp_nexthop_local, buf1,
-                                         BUFSIZ));
+                       inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
+                       inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
+                       if (!json_path) {
+                               vty_out(vty, "%s(%s)", buf, buf1);
+                       } else {
+                               json_object_string_add(json_nexthop,
+                                       "ipv6Global", buf);
+
+                               json_object_string_add(json_nexthop,
+                                       "ipv6LinkLocal", buf1);
+
+                               json_object_string_add(json_nexthop, "afi",
+                                       "ipv6");
+
+                               json_object_object_add(json_path, "nexthop",
+                                       json_nexthop);
+                       }
                        break;
                default:
-                       vty_out(vty, "?");
+                       if (!json_path) {
+                               vty_out(vty, "?");
+                       } else {
+                               json_object_string_add(json_nexthop, "Error",
+                                       "Unsupported address-family");
+                       }
                }
 
                char *str = esi2str(&(attr->evpn_overlay.eth_s_id));
 
-               vty_out(vty, "%s", str);
+               if (!json_path)
+                       vty_out(vty, "%s", str);
+               else
+                       json_object_string_add(json_overlay, "esi", str);
+               
                XFREE(MTYPE_TMP, str);
 
                if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
-                       vty_out(vty, "/%s",
-                               inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
+                       inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4),
+                               buf, BUFSIZ);
                } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
-                       vty_out(vty, "/%s",
-                               inet_ntop(AF_INET6,
-                                         &(attr->evpn_overlay.gw_ip.ipv6), buf,
-                                         BUFSIZ));
+                       inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6),
+                               buf, BUFSIZ);
                }
+
+               if (!json_path)
+                       vty_out(vty, "/%s", buf);
+               else
+                       json_object_string_add(json_overlay, "gw", buf);
+
                if (attr->ecommunity) {
                        char *mac = NULL;
                        struct ecommunity_val *routermac = ecommunity_lookup(
@@ -7582,13 +7627,25 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
                        if (routermac)
                                mac = ecom_mac2str((char *)routermac->val);
                        if (mac) {
-                               vty_out(vty, "/%s", (char *)mac);
+                               if (!json_path) {
+                                       vty_out(vty, "/%s", (char *)mac);
+                               } else {
+                                       json_object_string_add(json_overlay,
+                                               "rmac", mac);
+                               }
                                XFREE(MTYPE_TMP, mac);
                        }
                }
-               vty_out(vty, "\n");
-       }
 
+               if (!json_path) {
+                       vty_out(vty, "\n");
+               } else {
+                       json_object_object_add(json_path, "overlay",
+                               json_overlay);
+
+                       json_object_array_add(json_paths, json_path);
+               }
+       }
 }
 
 /* dampening route */
index c276f5ef7b87ba4dbbd31f26f712f7193d3fda3b..9ff4196dae01c0b3d26b7d10b77ef5674b42ff5c 100644 (file)
@@ -28,7 +28,7 @@
 #include "plist.h"
 #include "memory.h"
 #include "log.h"
-#include "lua.h"
+#include "frrlua.h"
 #ifdef HAVE_LIBPCREPOSIX
 #include <pcreposix.h>
 #else
@@ -3447,7 +3447,7 @@ static void bgp_route_map_delete(const char *rmap_name)
        route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
 }
 
-static void bgp_route_map_event(route_map_event_t event, const char *rmap_name)
+static void bgp_route_map_event(const char *rmap_name)
 {
        if (route_map_mark_updated(rmap_name) == 0)
                bgp_route_map_mark_update(rmap_name);
index 57717bf59b5d0f22858228c087f5cfaf6618d49a..d0be2471af02b841a4ca9b376739732b26697bf9 100644 (file)
@@ -288,7 +288,7 @@ static void *updgrp_hash_alloc(void *p)
  *       16. Local-as should match, if configured.
  *      )
  */
-static unsigned int updgrp_hash_key_make(void *p)
+static unsigned int updgrp_hash_key_make(const void *p)
 {
        const struct update_group *updgrp;
        const struct peer *peer;
index 9a8da359ab11e2ae919a395cb6e62858212fbb1a..880b8778069cacd397d4c0017bda1af17972acd1 100644 (file)
@@ -119,6 +119,7 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi)
        case AFI_L2VPN:
                return BGP_EVPN_NODE;
                break;
+       case AFI_UNSPEC:
        case AFI_MAX:
                // We should never be here but to clarify the switch statement..
                return BGP_IPV4_NODE;
@@ -295,6 +296,7 @@ int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index,
  * afi  -> The parsed afi if it was included in the show command, returned here
  * safi -> The parsed safi if it was included in the show command, returned here
  * bgp  -> Pointer to the bgp data structure we need to fill in.
+ * use_json -> json is configured or not
  *
  * The function returns the correct location in the parse tree for the
  * last token found.
@@ -329,8 +331,17 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
                else {
                        *bgp = bgp_lookup_by_name(vrf_name);
                        if (!*bgp) {
-                               if (use_json)
-                                       vty_out(vty, "{}\n");
+                               if (use_json) {
+                                       json_object *json = NULL;
+                                       json = json_object_new_object();
+                                       json_object_string_add(
+                                         json, "warning",
+                                         "View/Vrf is unknown");
+                                       vty_out(vty, "%s\n",
+                                               json_object_to_json_string_ext(json,
+                                                       JSON_C_TO_STRING_PRETTY));
+                                       json_object_free(json);
+                               }
                                else
                                        vty_out(vty, "View/Vrf %s is unknown\n",
                                                vrf_name);
@@ -341,8 +352,17 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
        } else {
                *bgp = bgp_get_default();
                if (!*bgp) {
-                       if (use_json)
-                               vty_out(vty, "{}\n");
+                       if (use_json) {
+                               json_object *json = NULL;
+                               json = json_object_new_object();
+                               json_object_string_add(
+                                       json, "warning",
+                                       "Default BGP instance not found");
+                               vty_out(vty, "%s\n",
+                                       json_object_to_json_string_ext(json,
+                                               JSON_C_TO_STRING_PRETTY));
+                               json_object_free(json);
+                       }
                        else
                                vty_out(vty,
                                        "Default BGP instance not found\n");
@@ -14596,7 +14616,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc,
                vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
                vty_out(vty, "if you are using this please migrate to the below command.\n");
                vty_out(vty, "'no bgp large-community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:BB:CC>'\n");
-               zlog_warn("Deprecated option: 'no ip large-community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:BB:CC>' being used");     
+               zlog_warn("Deprecated option: 'no ip large-community-list <(1-99)|(100-500)|standard|expanded> <deny|permit> <LINE|AA:BB:CC>' being used");
        }
        argv_find(argv, argc, "permit", &idx);
        argv_find(argv, argc, "deny", &idx);
index d47c1f96388cb355246158b98cc89d7458b7c9b2..a45480fdc27c0d7a65c3978bc27b985893ca9fdb 100644 (file)
@@ -2441,7 +2441,7 @@ static void bgp_zebra_connected(struct zclient *zclient)
        bgp_zebra_instance_register(bgp);
 
        /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, bgp->vrf_id);
 
        /* tell label pool that zebra is connected */
        bgp_lp_event_zebra_up();
index b2925cd5122849f17318af7fbca8ef1ae4f40254..c0f1f3184a8a0b202bfac773c08daddc8dd9cccc 100644 (file)
@@ -812,9 +812,9 @@ int peer_cmp(struct peer *p1, struct peer *p2)
        return sockunion_cmp(&p1->su, &p2->su);
 }
 
-static unsigned int peer_hash_key_make(void *p)
+static unsigned int peer_hash_key_make(const void *p)
 {
-       struct peer *peer = p;
+       const struct peer *peer = p;
        return sockunion_hash(&peer->su);
 }
 
@@ -6186,8 +6186,15 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
 
        /* Set configuration on peer. */
        filter = &peer->filter[afi][safi];
-       if (filter->map[direct].name)
+       if (filter->map[direct].name) {
+               /* If the neighbor is configured with the same route-map
+                * again then, ignore the duplicate configuration.
+                */
+               if (strcmp(filter->map[direct].name, name) == 0)
+                       return 0;
+
                XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
+       }
        route_map_counter_decrement(filter->map[direct].map);
        filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
        filter->map[direct].map = route_map;
index 2220f0ed9abf4fd758c981288f6ac93b8ee61b35..cad33404fad3f86a1d5de781839e0e2d5df55abc 100644 (file)
@@ -2208,24 +2208,6 @@ void vnc_routemap_update(struct bgp *bgp, const char *unused)
        vnc_zlog_debug_verbose("%s done", __func__);
 }
 
-#if 0 /* superseded */
-static void vnc_routemap_event(route_map_event_t type, /* ignored */
-                              const char *rmap_name)  /* ignored */
-{
-       struct listnode *mnode, *mnnode;
-       struct bgp *bgp;
-
-       vnc_zlog_debug_verbose("%s(event type=%d)", __func__, type);
-       if (bm->bgp == NULL) /* may be called during cleanup */
-               return;
-
-       for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
-               vnc_routemap_update(bgp, rmap_name);
-
-       vnc_zlog_debug_verbose("%s: done", __func__);
-}
-#endif
-
 /*-------------------------------------------------------------------------
  *                     nve-group
  *-----------------------------------------------------------------------*/
@@ -3699,10 +3681,6 @@ bgp_rfapi_get_ecommunity_by_lni_label(struct bgp *bgp, uint32_t is_import,
 
 void bgp_rfapi_cfg_init(void)
 {
-       /* main bgpd code does not use this hook, but vnc does */
-       /* superseded by bgp_route_map_process_update_cb() */
-       /* bgp_route_map_event_hook_add(vnc_routemap_event); */
-
        install_node(&bgp_vnc_defaults_node, NULL);
        install_node(&bgp_vnc_nve_group_node, NULL);
        install_node(&bgp_vrf_policy_node, NULL);
index 568f8d68e863e72d0e106dbedfab07099c168051..d67361620db84c0967e5e91e8a740dfd4099de45 100644 (file)
@@ -374,42 +374,15 @@ int rfapiGetVncLifetime(struct attr *attr, uint32_t *lifetime)
        return ENOENT;
 }
 
-/*
- * Extract the tunnel type from the extended community
- */
-int rfapiGetTunnelType(struct attr *attr, bgp_encap_types *type)
-{
-       *type = BGP_ENCAP_TYPE_MPLS; /* default to MPLS */
-       if (attr && attr->ecommunity) {
-               struct ecommunity *ecom = attr->ecommunity;
-               int i;
-
-               for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE);
-                    i += ECOMMUNITY_SIZE) {
-                       uint8_t *ep;
-
-                       ep = ecom->val + i;
-                       if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE
-                           && ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) {
-                               *type = (ep[6] << 8) + ep[7];
-                               return 0;
-                       }
-               }
-       }
-
-       return ENOENT;
-}
-
-
 /*
  * Look for UN address in Encap attribute
  */
 int rfapiGetVncTunnelUnAddr(struct attr *attr, struct prefix *p)
 {
        struct bgp_attr_encap_subtlv *pEncap;
-       bgp_encap_types tun_type;
+       bgp_encap_types tun_type = BGP_ENCAP_TYPE_MPLS;/*Default tunnel type*/
 
-       rfapiGetTunnelType(attr, &tun_type);
+       bgp_attr_extcom_tunnel_type(attr, &tun_type);
        if (tun_type == BGP_ENCAP_TYPE_MPLS) {
                if (!p)
                        return 0;
@@ -1350,7 +1323,7 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
        }
 
        if (bpi->attr) {
-               bgp_encap_types tun_type;
+               bgp_encap_types tun_type = BGP_ENCAP_TYPE_MPLS; /*Default*/
                new->prefix.cost = rfapiRfpCost(bpi->attr);
 
                struct bgp_attr_encap_subtlv *pEncap;
@@ -1390,7 +1363,7 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
                        }
                }
 
-               rfapiGetTunnelType(bpi->attr, &tun_type);
+               bgp_attr_extcom_tunnel_type(bpi->attr, &tun_type);
                if (tun_type == BGP_ENCAP_TYPE_MPLS) {
                        struct prefix p;
                        /* MPLS carries UN address in next hop */
index 87d9a32f67c2be4085340bfadd1a9f4e99161c43..ff1cf7ef427d57119483383b7ce707a3e62d1d56 100644 (file)
@@ -306,8 +306,6 @@ extern int rfapiCliGetPrefixAddr(struct vty *vty, const char *str,
 
 extern int rfapiGetVncLifetime(struct attr *attr, uint32_t *lifetime);
 
-extern int rfapiGetTunnelType(struct attr *attr, bgp_encap_types *type);
-
 extern int rfapiGetVncTunnelUnAddr(struct attr *attr, struct prefix *p);
 
 extern int rfapi_reopen(struct rfapi_descriptor *rfd, struct bgp *bgp);
index ea82c254bcecbea7168ac2f5ef6b8b0869e7970c..46161b4f382d3afecc6bd1598cc49114dbd491d6 100644 (file)
@@ -1020,7 +1020,7 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
        struct prefix pfx_vn;
        uint8_t cost;
        uint32_t lifetime;
-       bgp_encap_types tun_type;
+       bgp_encap_types tun_type = BGP_ENCAP_TYPE_MPLS;/*Default tunnel type*/
 
        char buf_pfx[BUFSIZ];
        char buf_ntop[BUFSIZ];
@@ -1055,7 +1055,7 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
                                   BUFSIZ));
        }
 
-       rfapiGetTunnelType(bpi->attr, &tun_type);
+       bgp_attr_extcom_tunnel_type(bpi->attr, &tun_type);
        /*
         * VN addr
         */
index 86168a848731d1a88bf0ae03136959a44dba417a..b7ddf87b43f6631402bf53d3f982cf96c6d3430b 100755 (executable)
@@ -222,9 +222,12 @@ elif test "x${enable_dev_build}" = "xyes"; then
       AC_C_FLAG([-O0])
    fi
    if test "x${enable_lua}" = "xyes"; then
-      AC_CHECK_LIB([lua], [lua_newstate],
-      [LIBS="$LIBS -llua"])
-      AC_DEFINE([HAVE_LUA], [1], [Lua enabled for development])
+      AX_PROG_LUA([5.3])
+      AX_LUA_HEADERS
+      AX_LUA_LIBS([
+         AC_DEFINE([HAVE_LUA], [1], [Have support for Lua interpreter])
+         LIBS="$LIBS $LUA_LIB"
+      ])
    fi
 else
    if test "x${enable_lua}" = "xyes"; then
index 1320bda5777bbcdc6857331e014e94269b111fe2..8bdc2b9c760622de5d176154c784c23c1ff5462e 100644 (file)
@@ -104,6 +104,10 @@ And load the kernel modules on the running system:
 
    sudo modprobe mpls-router mpls-iptunnel
 
+If the above command returns an error, you may need to install the appropriate
+or latest linux-modules-extra-<kernel-version>-generic package. For example
+``apt-get install linux-modules-extra-`uname -r`-generic``
+
 Enable MPLS Forwarding
 """"""""""""""""""""""
 
index 6d60420b2fb2b675596e513bf3f2678e7286b1f6..987b3b7f4fb3a849a8971a4a8fa46d5dbb05c791 100644 (file)
@@ -119,6 +119,8 @@ The common setup pattern will look like this:
 
 .. code-block:: c
 
+   #include <typesafe.h>
+
    PREDECL_XXX(Z)
    struct item {
        int otherdata;
@@ -159,26 +161,26 @@ Common iteration macros
 
 The following iteration macros work across all data structures:
 
-.. c:function:: for_each(Z, head, item)
+.. c:function:: for_each(Z, &head, item)
 
    Equivalent to:
 
    .. code-block:: c
 
-      for (item = Z_first(head); item; item = Z_next(head, item))
+      for (item = Z_first(&head); item; item = Z_next(&head, item))
 
    Note that this will fail if the list is modified while being iterated
    over.
 
-.. c:function:: for_each_safe(Z, head, item)
+.. c:function:: for_each_safe(Z, &head, item)
 
    Same as the previous, but the next element is pre-loaded into a "hidden"
    variable (named ``Z_safe``.)  Equivalent to:
 
    .. code-block:: c
 
-      for (item = Z_first(head); item; item = next) {
-          next = Z_next_safe(head, item);
+      for (item = Z_first(&head); item; item = next) {
+          next = Z_next_safe(&head, item);
           ...
       }
 
@@ -189,7 +191,7 @@ The following iteration macros work across all data structures:
       tables is resized while iterating.  This will cause items to be
       skipped or iterated over twice.
 
-.. c:function:: for_each_from(Z, head, item, from)
+.. c:function:: for_each_from(Z, &head, item, from)
 
    Iterates over the list, starting at item ``from``.  This variant is "safe"
    as in the previous macro.  Equivalent to:
@@ -197,7 +199,7 @@ The following iteration macros work across all data structures:
    .. code-block:: c
 
       for (item = from; item; item = from) {
-          from = Z_next_safe(head, item);
+          from = Z_next_safe(&head, item);
           ...
       }
 
index 605b9c9a0cfeb588742850be73e8e94de4d13228..09f12ec43641a3a17af07f0ba1a94cbc658f2c4f 100644 (file)
@@ -105,6 +105,8 @@ Execute all tests with output to console
 
    py.test -s -v --tb=no
 
+The above command must be executed from inside the topotests directory.
+
 All test\_\* scripts in subdirectories are detected and executed (unless
 disabled in ``pytest.ini`` file).
 
@@ -119,6 +121,13 @@ Execute single test
    cd test_to_be_run
    ./test_to_be_run.py
 
+For example, and assuming you are inside the frr directory:
+
+.. code:: shell
+
+   cd tests/topotests/bgp_l3vpn_to_bgp_vrf
+   ./test_bgp_l3vpn_to_bgp_vrf.py
+
 For further options, refer to pytest documentation.
 
 Test will set exit code which can be used with ``git bisect``.
@@ -180,13 +189,12 @@ If found, then this is added with context (calling test) to
 
 Compiling for GCC AddressSanitizer requires to use ``gcc`` as a linker as well
 (instead of ``ld``). Here is a suggest way to compile frr with AddressSanitizer
-for ``stable/3.0`` branch:
+for ``master`` branch:
 
 .. code:: shell
 
    git clone https://github.com/FRRouting/frr.git
    cd frr
-   git checkout stable/3.0
    ./bootstrap.sh
    export CC=gcc
    export CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer"
@@ -199,7 +207,8 @@ for ``stable/3.0`` branch:
        --enable-exampledir=/usr/lib/frr/examples \
        --with-moduledir=/usr/lib/frr/modules \
        --enable-multipath=0 --enable-rtadv \
-       --enable-tcp-zebra --enable-fpm --enable-pimd
+       --enable-tcp-zebra --enable-fpm --enable-pimd \
+       --enable-sharpd
    make
    sudo make install
    # Create symlink for vtysh, so topotest finds it in /usr/lib/frr
index 8fbea29ee7ec42aef3cc83d2101d35baa2877422..f55b1b9d73a77a88fd350f2a282802203f709363 100644 (file)
@@ -287,8 +287,8 @@ Terminal Mode Commands
 
    Write current configuration to configuration file.
 
-.. index:: configure terminal
-.. clicmd:: configure terminal
+.. index:: configure [terminal]
+.. clicmd:: configure [terminal]
 
    Change to configuration mode. This command is the first step to
    configuration.
index 986d1494a5476a782c2cb507bea660f61749082b..a7c5cf28bc5fc09996ad906fdc52bcf9e8a07e27 100644 (file)
@@ -72,8 +72,7 @@ BFDd Commands
    peer listener to and the address we should use to send the packets.
    This option is mandatory for IPv6.
 
-   `interface` selects which interface we should use. This option
-   conflicts with `vrf`.
+   `interface` selects which interface we should use.
 
    `vrf` selects which domain we want to use.
 
@@ -82,13 +81,13 @@ BFDd Commands
 
     Stops and removes the selected peer.
 
-.. index:: show bfd peers [json]
-.. clicmd:: show bfd peers [json]
+.. index:: show bfd [vrf NAME] peers [json]
+.. clicmd:: show bfd [vrf NAME] peers [json]
 
     Show all configured BFD peers information and current status.
 
-.. index:: show bfd peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]> [json]
-.. clicmd:: show bfd peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]> [json]
+.. index:: show bfd [vrf NAME$vrfname] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]
+.. clicmd:: show bfd [vrf NAME$vrfname] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]
 
     Show status for a specific BFD peer.
 
@@ -296,6 +295,11 @@ Here are the available peer configurations:
      shutdown
     !
 
+    ! configure a peer on an interface from a separate vrf
+    peer 192.168.0.5 interface eth1 vrf vrf2
+     no shutdown
+    !
+
     ! remove a peer
     no peer 192.168.0.3 vrf foo
 
index 35e42d95cb5176038a9e69dafb2c324df04bf315..d663b4fc10f920c979ff2b2fa5d9664bf8503568 100644 (file)
@@ -942,14 +942,18 @@ Configuring Peers
 .. index:: [no] neighbor PEER maximum-prefix NUMBER
 .. clicmd:: [no] neighbor PEER maximum-prefix NUMBER
 
-.. index:: [no] neighbor PEER local-as AS-NUMBER no-prepend
-.. clicmd:: [no] neighbor PEER local-as AS-NUMBER no-prepend
-
-.. index:: [no] neighbor PEER local-as AS-NUMBER no-prepend replace-as
-.. clicmd:: [no] neighbor PEER local-as AS-NUMBER no-prepend replace-as
-
-.. index:: [no] neighbor PEER local-as AS-NUMBER
-.. clicmd:: [no] neighbor PEER local-as AS-NUMBER
+   Sets a maximum number of prefixes we can receive from a given peer. If this
+   number is exceeded, the BGP session will be destroyed.
+
+   In practice, it is generally preferable to use a prefix-list to limit what
+   prefixes are received from the peer instead of using this knob. Tearing down
+   the BGP session when a limit is exceeded is far more destructive than merely
+   rejecting undesired prefixes. The prefix-list method is also much more
+   granular and offers much smarter matching criterion than number of received
+   prefixes, making it more suited to implementing policy.
+
+.. index:: [no] neighbor PEER local-as AS-NUMBER [no-prepend] [replace-as]
+.. clicmd:: [no] neighbor PEER local-as AS-NUMBER [no-prepend] [replace-as]
 
    Specify an alternate AS for this BGP process when interacting with the
    specified peer. With no modifiers, the specified local-as is prepended to
index 71bc04772021297ef35c843baeb4b2dca6870c60..6413c6299531639057335e3e559877498d55ae73 100644 (file)
@@ -15,8 +15,8 @@ OSPF6 router
 .. index:: router ospf6
 .. clicmd:: router ospf6
 
-.. index:: router-id A.B.C.D
-.. clicmd:: router-id A.B.C.D
+.. index:: ospf6 router-id A.B.C.D
+.. clicmd:: ospf6 router-id A.B.C.D
 
    Set router's Router-ID.
 
index 1705b6379e8aa9f0e1f129d09c22b737c68d8161..09bdc9cbea0ea238c0d71cd517514abb74b4fd2c 100644 (file)
@@ -123,7 +123,7 @@ but this time, the route command will apply to the VRF.
 .. code-block:: frr
 
    # case with VRF
-   configure terminal
+   configure
    vrf r1-cust1
     ip route 10.0.0.0/24 10.0.0.2
    exit-vrf
index 51ada8bc62d306d4ab103a560e3f88b08178c56f..f38db9d24105d6b3fbccf827adfb51445b5f424c 100644 (file)
@@ -685,6 +685,40 @@ replaces the information sent in the first message.
 If the connection to the FPM goes down for some reason, zebra sends
 the FPM a complete copy of the forwarding table(s) when it reconnects.
 
+.. _zebra-dplane:
+
+Dataplane Commands
+==================
+
+The zebra dataplane subsystem provides a framework for FIB
+programming. Zebra uses the dataplane to program the local kernel as
+it makes changes to objects such as IP routes, MPLS LSPs, and
+interface IP addresses. The dataplane runs in its own pthread, in
+order to off-load work from the main zebra pthread.
+
+
+.. index:: show zebra dplane [detailed]
+.. clicmd:: show zebra dplane [detailed]
+
+   Display statistics about the updates and events passing through the
+   dataplane subsystem.
+
+
+.. index:: show zebra dplane providers
+.. clicmd:: show zebra dplane providers
+
+   Display information about the running dataplane plugins that are
+   providing updates to a FIB. By default, the local kernel plugin is
+   present.
+
+
+.. index:: zebra dplane limit [NUMBER]
+.. clicmd:: zebra dplane limit [NUMBER]
+
+   Configure the limit on the number of pending updates that are
+   waiting to be processed by the dataplane pthread.
+
+
 zebra Terminal Mode Commands
 ============================
 
index 96af28f0a1cc2037cb5a9ed9778257246cbb0b38..b9c27d51bd89d0dc6aeac9fe32b98844cc500f0b 100644 (file)
@@ -108,9 +108,9 @@ static void neighbor_lists_clear(struct fabricd *f)
        hash_clean(f->neighbors_neighbors, neighbor_entry_del_void);
 }
 
-static unsigned neighbor_entry_hash_key(void *np)
+static unsigned neighbor_entry_hash_key(const void *np)
 {
-       struct neighbor_entry *n = np;
+       const struct neighbor_entry *n = np;
 
        return jhash(n->id, sizeof(n->id), 0x55aa5a5a);
 }
index a98c44eeb0e8094169ae9dffdeb6fa4a9e20606d..fccef0169e77c29c4a0671a94b64473394adf0de 100644 (file)
@@ -139,7 +139,7 @@ static int isis_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
 
 static int isis_bfd_nbr_replay(ZAPI_CALLBACK_ARGS)
 {
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id);
 
        struct listnode *anode;
        struct isis_area *area;
@@ -167,7 +167,7 @@ static void isis_bfd_zebra_connected(struct zclient *zclient)
        if (orig_zebra_connected)
                orig_zebra_connected(zclient);
 
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
 }
 
 static void bfd_debug(struct in_addr *dst, struct in_addr *src,
index 3a2a52afac28c5b04badd9edfe67d4e53ff6dd33..a8185a8be0fec76b0a5170457d87d453e9f9d503 100644 (file)
@@ -79,9 +79,9 @@ struct isis_vertex_queue {
 };
 
 __attribute__((__unused__))
-static unsigned isis_vertex_queue_hash_key(void *vp)
+static unsigned isis_vertex_queue_hash_key(const void *vp)
 {
-       struct isis_vertex *vertex = vp;
+       const struct isis_vertex *vertex = vp;
 
        if (VTYPE_IP(vertex->type)) {
                uint32_t key;
index bc9b51473664993d02466983dc9ab77726d7e118..ae149a04284cd0cb6b8440fa13d49c82c5d17fd1 100644 (file)
@@ -405,7 +405,7 @@ static int pack_subtlvs(struct isis_subtlvs *subtlvs, struct stream *s)
 
 static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
                       struct stream *stream, struct sbuf *log, void *dest,
-                      int indent);
+                      int indent, bool *unpacked_known_tlvs);
 
 /* Functions related to TLVs 1 Area Addresses */
 
@@ -796,7 +796,7 @@ static int unpack_item_extended_reach(uint16_t mtid, uint8_t len,
                size_t subtlv_start = stream_get_getp(s);
 
                if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_NE_REACH, subtlv_len, s,
-                               log, NULL, indent + 4)) {
+                               log, NULL, indent + 4, NULL)) {
                        goto out;
                }
 
@@ -1272,6 +1272,11 @@ static void format_item_extended_ip_reach(uint16_t mtid, struct isis_item *i,
        if (mtid != ISIS_MT_IPV4_UNICAST)
                sbuf_push(buf, 0, " %s", isis_mtid2str(mtid));
        sbuf_push(buf, 0, "\n");
+
+       if (r->subtlvs) {
+               sbuf_push(buf, indent, "  Subtlvs:\n");
+               format_subtlvs(r->subtlvs, buf, indent + 4);
+       }
 }
 
 static void free_item_extended_ip_reach(struct isis_item *i)
@@ -1386,10 +1391,16 @@ static int unpack_item_extended_ip_reach(uint16_t mtid, uint8_t len,
                }
 
                rv->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IP_REACH);
+               bool unpacked_known_tlvs = false;
+
                if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_IP_REACH, subtlv_len, s,
-                               log, rv->subtlvs, indent + 4)) {
+                               log, rv->subtlvs, indent + 4, &unpacked_known_tlvs)) {
                        goto out;
                }
+               if (!unpacked_known_tlvs) {
+                       isis_free_subtlvs(rv->subtlvs);
+                       rv->subtlvs = NULL;
+               }
        }
 
        append_item(items, (struct isis_item *)rv);
@@ -1865,10 +1876,16 @@ static int unpack_item_ipv6_reach(uint16_t mtid, uint8_t len, struct stream *s,
                }
 
                rv->subtlvs = isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_IPV6_REACH);
+               bool unpacked_known_tlvs = false;
+
                if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_IPV6_REACH, subtlv_len, s,
-                               log, rv->subtlvs, indent + 4)) {
+                               log, rv->subtlvs, indent + 4, &unpacked_known_tlvs)) {
                        goto out;
                }
+               if (!unpacked_known_tlvs) {
+                       isis_free_subtlvs(rv->subtlvs);
+                       rv->subtlvs = NULL;
+               }
        }
 
        append_item(items, (struct isis_item *)rv);
@@ -2966,7 +2983,7 @@ static int unpack_tlv_unknown(enum isis_tlv_context context, uint8_t tlv_type,
 
 static int unpack_tlv(enum isis_tlv_context context, size_t avail_len,
                      struct stream *stream, struct sbuf *log, void *dest,
-                     int indent)
+                     int indent, bool *unpacked_known_tlvs)
 {
        uint8_t tlv_type, tlv_len;
        const struct tlv_ops *ops;
@@ -2997,6 +3014,8 @@ static int unpack_tlv(enum isis_tlv_context context, size_t avail_len,
 
        ops = tlv_table[context][tlv_type];
        if (ops && ops->unpack) {
+               if (unpacked_known_tlvs)
+                       *unpacked_known_tlvs = true;
                return ops->unpack(context, tlv_type, tlv_len, stream, log,
                                   dest, indent + 2);
        }
@@ -3007,7 +3026,7 @@ static int unpack_tlv(enum isis_tlv_context context, size_t avail_len,
 
 static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
                       struct stream *stream, struct sbuf *log, void *dest,
-                      int indent)
+                      int indent, bool *unpacked_known_tlvs)
 {
        int rv;
        size_t tlv_start, tlv_pos;
@@ -3020,7 +3039,7 @@ static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
 
        while (tlv_pos < avail_len) {
                rv = unpack_tlv(context, avail_len - tlv_pos, stream, log, dest,
-                               indent + 2);
+                               indent + 2, unpacked_known_tlvs);
                if (rv)
                        return rv;
 
@@ -3052,7 +3071,7 @@ int isis_unpack_tlvs(size_t avail_len, struct stream *stream,
 
        result = isis_alloc_tlvs();
        rv = unpack_tlvs(ISIS_CONTEXT_LSP, avail_len, stream, &logbuf, result,
-                        indent);
+                        indent, NULL);
 
        *log = sbuf_buf(&logbuf);
        *dest = result;
index 6f46e6bec0c24a1084feaceeb67318e2a1975994..507fd489bc621fb3e50bd9f73f1d39e665bf1c46 100644 (file)
@@ -50,9 +50,9 @@ struct isis_tx_queue_entry {
        struct isis_tx_queue *queue;
 };
 
-static unsigned tx_queue_hash_key(void *p)
+static unsigned tx_queue_hash_key(const void *p)
 {
-       struct isis_tx_queue_entry *e = p;
+       const struct isis_tx_queue_entry *e = p;
 
        uint32_t id_key = jhash(e->lsp->hdr.lsp_id,
                                ISIS_SYS_ID_LEN + 2, 0x55aa5a5a);
index 7e27a64de7bcc20f490b61e3240d0fc945977065..a8956c315cc68e2c5c845b6841d6a3aad83c65f9 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -433,7 +433,8 @@ void bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop,
  * bfd_client_sendmsg - Format and send a client register
  *                    command to Zebra to be forwarded to BFD
  */
-void bfd_client_sendmsg(struct zclient *zclient, int command)
+void bfd_client_sendmsg(struct zclient *zclient, int command,
+                       vrf_id_t vrf_id)
 {
        struct stream *s;
        int ret;
@@ -450,7 +451,7 @@ void bfd_client_sendmsg(struct zclient *zclient, int command)
 
        s = zclient->obuf;
        stream_reset(s);
-       zclient_create_header(s, command, VRF_DEFAULT);
+       zclient_create_header(s, command, vrf_id);
 
        stream_putl(s, getpid());
 
index a93875c4cf80e1a6ef74845f2ca93b681f28ef32..d02110a9970cea35d6833c157fc114bdebe46217 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -102,7 +102,8 @@ extern void bfd_show_info(struct vty *vty, struct bfd_info *bfd_info,
                          int multihop, int extra_space, bool use_json,
                          json_object *json_obj);
 
-extern void bfd_client_sendmsg(struct zclient *zclient, int command);
+extern void bfd_client_sendmsg(struct zclient *zclient, int command,
+                              vrf_id_t vrf_id);
 
 extern void bfd_gbl_init(void);
 
index b3ef028004f687dcf686c7669bc205f10a50548c..b7a323e35865c3c891a4830332107b79483be450 100644 (file)
@@ -332,7 +332,7 @@ int argv_find(struct cmd_token **argv, int argc, const char *text, int *index)
        return found;
 }
 
-static unsigned int cmd_hash_key(void *p)
+static unsigned int cmd_hash_key(const void *p)
 {
        int size = sizeof(p);
 
@@ -1386,7 +1386,7 @@ int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num)
 /* Configuration from terminal */
 DEFUN (config_terminal,
        config_terminal_cmd,
-       "configure terminal",
+       "configure [terminal]",
        "Configuration from vty interface\n"
        "Configuration terminal\n")
 {
index be40bd2603d5acf78b16e0632aca5e53279d417e..2aa6b927fb01afcc3f1f64f82ca8f2e6afc59857 100644 (file)
@@ -131,7 +131,7 @@ static struct distribute *distribute_get(struct distribute_ctx *ctx,
        return ret;
 }
 
-static unsigned int distribute_hash_make(void *arg)
+static unsigned int distribute_hash_make(const void *arg)
 {
        const struct distribute *dist = arg;
 
index d7fa1a84f8955960e010cb7a673368262103dc9b..65c0cf886d3fbfaf677b144bb6072d87354dd645 100644 (file)
@@ -72,9 +72,9 @@ static bool ferr_hash_cmp(const void *a, const void *b)
        return f_a->code == f_b->code;
 }
 
-static inline unsigned int ferr_hash_key(void *a)
+static inline unsigned int ferr_hash_key(const void *a)
 {
-       struct log_ref *f = a;
+       const struct log_ref *f = a;
 
        return f->code;
 }
diff --git a/lib/frrlua.c b/lib/frrlua.c
new file mode 100644 (file)
index 0000000..b7d8eea
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * This file defines the lua interface into
+ * FRRouting.
+ *
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FreeRangeRouting (FRR).
+ *
+ * FRR 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, or (at your option) any later version.
+ *
+ * FRR 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 FRR; see the file COPYING.  If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <stdio.h>
+
+#include <zebra.h>
+
+#if defined(HAVE_LUA)
+#include "prefix.h"
+#include "frrlua.h"
+#include "log.h"
+
+static int lua_zlog_debug(lua_State *L)
+{
+       int debug_lua = 1;
+       const char *string = lua_tostring(L, 1);
+
+       if (debug_lua)
+               zlog_debug("%s", string);
+
+       return 0;
+}
+
+const char *get_string(lua_State *L, const char *key)
+{
+       const char *str;
+
+       lua_pushstring(L, key);
+       lua_gettable(L, -2);
+
+       str = (const char *)lua_tostring(L, -1);
+       lua_pop(L, 1);
+
+       return str;
+}
+
+int get_integer(lua_State *L, const char *key)
+{
+       int result;
+
+       lua_pushstring(L, key);
+       lua_gettable(L, -2);
+
+       result = lua_tointeger(L, -1);
+       lua_pop(L, 1);
+
+       return result;
+}
+
+static void *lua_alloc(void *ud, void *ptr, size_t osize,
+                      size_t nsize)
+{
+       (void)ud;  (void)osize;  /* not used */
+       if (nsize == 0) {
+               free(ptr);
+               return NULL;
+       } else
+               return realloc(ptr, nsize);
+}
+
+lua_State *lua_initialize(const char *file)
+{
+       int status;
+       lua_State *L = lua_newstate(lua_alloc, NULL);
+
+       zlog_debug("Newstate: %p", L);
+       luaL_openlibs(L);
+       zlog_debug("Opened lib");
+       status = luaL_loadfile(L, file);
+       if (status) {
+               zlog_debug("Failure to open %s %d", file, status);
+               lua_close(L);
+               return NULL;
+       }
+
+       lua_pcall(L, 0, LUA_MULTRET, 0);
+       zlog_debug("Setting global function");
+       lua_pushcfunction(L, lua_zlog_debug);
+       lua_setglobal(L, "zlog_debug");
+
+       return L;
+}
+
+void lua_setup_prefix_table(lua_State *L, const struct prefix *prefix)
+{
+       char buffer[100];
+
+       lua_newtable(L);
+       lua_pushstring(L, prefix2str(prefix, buffer, 100));
+       lua_setfield(L, -2, "route");
+       lua_pushinteger(L, prefix->family);
+       lua_setfield(L, -2, "family");
+       lua_setglobal(L, "prefix");
+}
+
+enum lua_rm_status lua_run_rm_rule(lua_State *L, const char *rule)
+{
+       int status;
+
+       lua_getglobal(L, rule);
+       status = lua_pcall(L, 0, 1, 0);
+       if (status) {
+               zlog_debug("Executing Failure with function: %s: %d",
+                          rule, status);
+               return LUA_RM_FAILURE;
+       }
+
+       status = lua_tonumber(L, -1);
+       return status;
+}
+#endif
diff --git a/lib/frrlua.h b/lib/frrlua.h
new file mode 100644 (file)
index 0000000..374eb70
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * This file defines the lua interface into
+ * FRRouting.
+ *
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FreeRangeRouting (FRR).
+ *
+ * FRR 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, or (at your option) any later version.
+ *
+ * FRR 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 FRR; see the file COPYING.  If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef __LUA_H__
+#define __LUA_H__
+
+#if defined(HAVE_LUA)
+
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * These functions are helper functions that
+ * try to glom some of the lua_XXX functionality
+ * into what we actually need, instead of having
+ * to make multiple calls to set up what
+ * we want
+ */
+enum lua_rm_status {
+       /*
+        * Script function run failure.  This will translate into a
+        * deny
+        */
+       LUA_RM_FAILURE = 0,
+       /*
+        * No Match was found for the route map function
+        */
+       LUA_RM_NOMATCH,
+       /*
+        * Match was found but no changes were made to the
+        * incoming data.
+        */
+       LUA_RM_MATCH,
+       /*
+        * Match was found and data was modified, so
+        * figure out what changed
+        */
+       LUA_RM_MATCH_AND_CHANGE,
+};
+
+/*
+ * Open up the lua.scr file and parse
+ * initial global values, if any.
+ */
+lua_State *lua_initialize(const char *file);
+
+void lua_setup_prefix_table(lua_State *L, const struct prefix *prefix);
+
+enum lua_rm_status lua_run_rm_rule(lua_State *L, const char *rule);
+
+/*
+ * Get particular string/integer information
+ * from a table.  It is *assumed* that
+ * the table has already been selected
+ */
+const char *get_string(lua_State *L, const char *key);
+int get_integer(lua_State *L, const char *key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+#endif
index c9c942f9bf897a02599dea196ce1dcea5463556a..38494fb0074e6186c0efb0acee294e801c71f819 100644 (file)
@@ -58,6 +58,8 @@ int main(int argc, char **argv)
 
        vty_init(master);
        memory_init();
+       yang_init();
+       nb_init(master, NULL, 0);
 
        vty_stdio(vty_do_exit);
 
index 884c8f22af72baabc740bc0af1f758bded705f05..fad7de51385d4e6866e893eefb3e76fa3c543983 100644 (file)
@@ -37,7 +37,7 @@ static pthread_mutex_t _hashes_mtx = PTHREAD_MUTEX_INITIALIZER;
 static struct list *_hashes;
 
 struct hash *hash_create_size(unsigned int size,
-                             unsigned int (*hash_key)(void *),
+                             unsigned int (*hash_key)(const void *),
                              bool (*hash_cmp)(const void *, const void *),
                              const char *name)
 {
@@ -66,7 +66,7 @@ struct hash *hash_create_size(unsigned int size,
        return hash;
 }
 
-struct hash *hash_create(unsigned int (*hash_key)(void *),
+struct hash *hash_create(unsigned int (*hash_key)(const void *),
                         bool (*hash_cmp)(const void *, const void *),
                         const char *name)
 {
index 60c412b8e0716de194bfcdfc1f589ad950512076..c56a98d50c64adc3a6cbaba5a1dede33e423aa04 100644 (file)
@@ -79,7 +79,7 @@ struct hash {
        unsigned int max_size;
 
        /* Key make function. */
-       unsigned int (*hash_key)(void *);
+       unsigned int (*hash_key)(const void *);
 
        /* Data compare function. */
        bool (*hash_cmp)(const void *, const void *);
@@ -123,7 +123,7 @@ struct hash {
  * Returns:
  *    a new hash table
  */
-extern struct hash *hash_create(unsigned int (*hash_key)(void *),
+extern struct hash *hash_create(unsigned int (*hash_key)(const void *),
                                bool (*hash_cmp)(const void *, const void *),
                                const char *name);
 
@@ -158,7 +158,7 @@ extern struct hash *hash_create(unsigned int (*hash_key)(void *),
  *    a new hash table
  */
 extern struct hash *
-hash_create_size(unsigned int size, unsigned int (*hash_key)(void *),
+hash_create_size(unsigned int size, unsigned int (*hash_key)(const void *),
                 bool (*hash_cmp)(const void *, const void *),
                 const char *name);
 
index b0802da96147950c5848ed87d552b1d0e6d4e719..ca6f512ec6d6f2d85f2a4d2ff76bd0231128743a 100644 (file)
@@ -107,7 +107,7 @@ static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname)
        return ret;
 }
 
-static unsigned int if_rmap_hash_make(void *data)
+static unsigned int if_rmap_hash_make(const void *data)
 {
        const struct if_rmap *if_rmap = data;
 
diff --git a/lib/lua.c b/lib/lua.c
deleted file mode 100644 (file)
index 3d701a9..0000000
--- a/lib/lua.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * This file defines the lua interface into
- * FRRouting.
- *
- * Copyright (C) 2016 Cumulus Networks, Inc.
- * Donald Sharp
- *
- * This file is part of FreeRangeRouting (FRR).
- *
- * FRR 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, or (at your option) any later version.
- *
- * FRR 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 FRR; see the file COPYING.  If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#include <stdio.h>
-
-#include <zebra.h>
-
-#if defined(HAVE_LUA)
-#include "prefix.h"
-#include "lua.h"
-#include "log.h"
-
-static int lua_zlog_debug(lua_State *L)
-{
-       int debug_lua = 1;
-       const char *string = lua_tostring(L, 1);
-
-       if (debug_lua)
-               zlog_debug("%s", string);
-
-       return 0;
-}
-
-const char *get_string(lua_State *L, const char *key)
-{
-       const char *str;
-
-       lua_pushstring(L, key);
-       lua_gettable(L, -2);
-
-       str = (const char *)lua_tostring(L, -1);
-       lua_pop(L, 1);
-
-       return str;
-}
-
-int get_integer(lua_State *L, const char *key)
-{
-       int result;
-
-       lua_pushstring(L, key);
-       lua_gettable(L, -2);
-
-       result = lua_tointeger(L, -1);
-       lua_pop(L, 1);
-
-       return result;
-}
-
-static void *lua_alloc(void *ud, void *ptr, size_t osize,
-                      size_t nsize)
-{
-       (void)ud;  (void)osize;  /* not used */
-       if (nsize == 0) {
-               free(ptr);
-               return NULL;
-       } else
-               return realloc(ptr, nsize);
-}
-
-lua_State *lua_initialize(const char *file)
-{
-       int status;
-       lua_State *L = lua_newstate(lua_alloc, NULL);
-
-       zlog_debug("Newstate: %p", L);
-       luaL_openlibs(L);
-       zlog_debug("Opened lib");
-       status = luaL_loadfile(L, file);
-       if (status) {
-               zlog_debug("Failure to open %s %d", file, status);
-               lua_close(L);
-               return NULL;
-       }
-
-       lua_pcall(L, 0, LUA_MULTRET, 0);
-       zlog_debug("Setting global function");
-       lua_pushcfunction(L, lua_zlog_debug);
-       lua_setglobal(L, "zlog_debug");
-
-       return L;
-}
-
-void lua_setup_prefix_table(lua_State *L, const struct prefix *prefix)
-{
-       char buffer[100];
-
-       lua_newtable(L);
-       lua_pushstring(L, prefix2str(prefix, buffer, 100));
-       lua_setfield(L, -2, "route");
-       lua_pushinteger(L, prefix->family);
-       lua_setfield(L, -2, "family");
-       lua_setglobal(L, "prefix");
-}
-
-enum lua_rm_status lua_run_rm_rule(lua_State *L, const char *rule)
-{
-       int status;
-
-       lua_getglobal(L, rule);
-       status = lua_pcall(L, 0, 1, 0);
-       if (status) {
-               zlog_debug("Executing Failure with function: %s: %d",
-                          rule, status);
-               return LUA_RM_FAILURE;
-       }
-
-       status = lua_tonumber(L, -1);
-       return status;
-}
-#endif
diff --git a/lib/lua.h b/lib/lua.h
deleted file mode 100644 (file)
index a864ab3..0000000
--- a/lib/lua.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * This file defines the lua interface into
- * FRRouting.
- *
- * Copyright (C) 2016 Cumulus Networks, Inc.
- * Donald Sharp
- *
- * This file is part of FreeRangeRouting (FRR).
- *
- * FRR 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, or (at your option) any later version.
- *
- * FRR 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 FRR; see the file COPYING.  If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#ifndef __LUA_H__
-#define __LUA_H__
-
-#if defined(HAVE_LUA)
-
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * These functions are helper functions that
- * try to glom some of the lua_XXX functionality
- * into what we actually need, instead of having
- * to make multiple calls to set up what
- * we want
- */
-enum lua_rm_status {
-       /*
-        * Script function run failure.  This will translate into a
-        * deny
-        */
-       LUA_RM_FAILURE = 0,
-       /*
-        * No Match was found for the route map function
-        */
-       LUA_RM_NOMATCH,
-       /*
-        * Match was found but no changes were made to the
-        * incoming data.
-        */
-       LUA_RM_MATCH,
-       /*
-        * Match was found and data was modified, so
-        * figure out what changed
-        */
-       LUA_RM_MATCH_AND_CHANGE,
-};
-
-/*
- * Open up the lua.scr file and parse
- * initial global values, if any.
- */
-lua_State *lua_initialize(const char *file);
-
-void lua_setup_prefix_table(lua_State *L, const struct prefix *prefix);
-
-enum lua_rm_status lua_run_rm_rule(lua_State *L, const char *rule);
-
-/*
- * Get particular string/integer information
- * from a table.  It is *assumed* that
- * the table has already been selected
- */
-const char *get_string(lua_State *L, const char *key);
-int get_integer(lua_State *L, const char *key);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-#endif
index e8b3e46c19deb2c624f35ee4c9ba654204781a59..dbf90c58d4870975c4fe05d991000ec94aa39f24 100644 (file)
@@ -1654,7 +1654,7 @@ static bool running_config_entry_cmp(const void *value1, const void *value2)
        return strmatch(c1->xpath, c2->xpath);
 }
 
-static unsigned int running_config_entry_key_make(void *value)
+static unsigned int running_config_entry_key_make(const void *value)
 {
        return string_hash_make(value);
 }
index eadef9902ba5df272f51354a4cf1b3db5e259f38..ddcc59fa8f5920d0e832a400c24128c90c46639a 100644 (file)
@@ -435,7 +435,8 @@ void *_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
 }
 
 /* Finds the node with the same key as elm */
-void *_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
+void *_rb_find(const struct rb_type *t, const struct rbt_tree *rbt,
+              const void *key)
 {
        struct rb_entry *tmp = RBH_ROOT(rbt);
        void *node;
@@ -456,7 +457,8 @@ void *_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
 }
 
 /* Finds the first node greater than or equal to the search key */
-void *_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
+void *_rb_nfind(const struct rb_type *t, const struct rbt_tree *rbt,
+               const void *key)
 {
        struct rb_entry *tmp = RBH_ROOT(rbt);
        void *node;
@@ -522,14 +524,14 @@ void *_rb_prev(const struct rb_type *t, void *elm)
        return (rbe == NULL ? NULL : rb_e2n(t, rbe));
 }
 
-void *_rb_root(const struct rb_type *t, struct rbt_tree *rbt)
+void *_rb_root(const struct rb_type *t, const struct rbt_tree *rbt)
 {
        struct rb_entry *rbe = RBH_ROOT(rbt);
 
        return (rbe == NULL ? rbe : rb_e2n(t, rbe));
 }
 
-void *_rb_min(const struct rb_type *t, struct rbt_tree *rbt)
+void *_rb_min(const struct rb_type *t, const struct rbt_tree *rbt)
 {
        struct rb_entry *rbe = RBH_ROOT(rbt);
        struct rb_entry *parent = NULL;
@@ -542,7 +544,7 @@ void *_rb_min(const struct rb_type *t, struct rbt_tree *rbt)
        return (parent == NULL ? NULL : rb_e2n(t, parent));
 }
 
-void *_rb_max(const struct rb_type *t, struct rbt_tree *rbt)
+void *_rb_max(const struct rb_type *t, const struct rbt_tree *rbt)
 {
        struct rb_entry *rbe = RBH_ROOT(rbt);
        struct rb_entry *parent = NULL;
index d2f078133340ef8da4d6ebaeb808d84e1d1c89ae..832a10141eb56516737a7ebf422a071b96b86572 100644 (file)
@@ -364,18 +364,18 @@ static inline void _rb_init(struct rbt_tree *rbt)
        rbt->rbt_root = NULL;
 }
 
-static inline int _rb_empty(struct rbt_tree *rbt)
+static inline int _rb_empty(const struct rbt_tree *rbt)
 {
        return (rbt->rbt_root == NULL);
 }
 
 void *_rb_insert(const struct rb_type *, struct rbt_tree *, void *);
 void *_rb_remove(const struct rb_type *, struct rbt_tree *, void *);
-void *_rb_find(const struct rb_type *, struct rbt_tree *, const void *);
-void *_rb_nfind(const struct rb_type *, struct rbt_tree *, const void *);
-void *_rb_root(const struct rb_type *, struct rbt_tree *);
-void *_rb_min(const struct rb_type *, struct rbt_tree *);
-void *_rb_max(const struct rb_type *, struct rbt_tree *);
+void *_rb_find(const struct rb_type *, const struct rbt_tree *, const void *);
+void *_rb_nfind(const struct rb_type *, const struct rbt_tree *, const void *);
+void *_rb_root(const struct rb_type *, const struct rbt_tree *);
+void *_rb_min(const struct rb_type *, const struct rbt_tree *);
+void *_rb_max(const struct rb_type *, const struct rbt_tree *);
 void *_rb_next(const struct rb_type *, void *);
 void *_rb_prev(const struct rb_type *, void *);
 void *_rb_left(const struct rb_type *, void *);
@@ -401,56 +401,58 @@ int _rb_check(const struct rb_type *, void *, unsigned long);
        __attribute__((__unused__)) static inline struct _type                 \
                *_name##_RB_INSERT(struct _name *head, struct _type *elm)      \
        {                                                                      \
-               return (struct _type *)_rb_insert(                             \
-                       _name##_RB_TYPE, &head->rbh_root, elm);                \
+               return (struct _type *)_rb_insert(_name##_RB_TYPE,             \
+                                                 &head->rbh_root, elm);       \
        }                                                                      \
                                                                                \
        __attribute__((__unused__)) static inline struct _type                 \
                *_name##_RB_REMOVE(struct _name *head, struct _type *elm)      \
        {                                                                      \
-               return (struct _type *)_rb_remove(                             \
-                       _name##_RB_TYPE, &head->rbh_root, elm);                \
+               return (struct _type *)_rb_remove(_name##_RB_TYPE,             \
+                                                 &head->rbh_root, elm);       \
        }                                                                      \
                                                                                \
        __attribute__((__unused__)) static inline struct _type                 \
-               *_name##_RB_FIND(struct _name *head, const struct _type *key)  \
+               *_name##_RB_FIND(const struct _name *head,                     \
+                                const struct _type *key)                      \
        {                                                                      \
-               return (struct _type *)_rb_find(                               \
-                       _name##_RB_TYPE, &head->rbh_root, key);                \
+               return (struct _type *)_rb_find(_name##_RB_TYPE,               \
+                                               &head->rbh_root, key);         \
        }                                                                      \
                                                                                \
        __attribute__((__unused__)) static inline struct _type                 \
-               *_name##_RB_NFIND(struct _name *head, const struct _type *key) \
+               *_name##_RB_NFIND(const struct _name *head,                    \
+                                 const struct _type *key)                     \
        {                                                                      \
-               return (struct _type *)_rb_nfind(                              \
-                       _name##_RB_TYPE, &head->rbh_root, key);                \
+               return (struct _type *)_rb_nfind(_name##_RB_TYPE,              \
+                                                &head->rbh_root, key);        \
        }                                                                      \
                                                                                \
        __attribute__((__unused__)) static inline struct _type                 \
-               *_name##_RB_ROOT(struct _name *head)                           \
+               *_name##_RB_ROOT(const struct _name *head)                     \
        {                                                                      \
-               return (struct _type *)_rb_root(                               \
-                       _name##_RB_TYPE, &head->rbh_root);                     \
+               return (struct _type *)_rb_root(_name##_RB_TYPE,               \
+                                               &head->rbh_root);              \
        }                                                                      \
                                                                                \
        __attribute__((__unused__)) static inline int _name##_RB_EMPTY(        \
-               struct _name *head)                                            \
+               const struct _name *head)                                      \
        {                                                                      \
                return _rb_empty(&head->rbh_root);                             \
        }                                                                      \
                                                                                \
        __attribute__((__unused__)) static inline struct _type                 \
-               *_name##_RB_MIN(struct _name *head)                            \
+               *_name##_RB_MIN(const struct _name *head)                      \
        {                                                                      \
-               return (struct _type *)_rb_min(                                \
-                       _name##_RB_TYPE, &head->rbh_root);                     \
+               return (struct _type *)_rb_min(_name##_RB_TYPE,                \
+                                              &head->rbh_root);               \
        }                                                                      \
                                                                                \
        __attribute__((__unused__)) static inline struct _type                 \
-               *_name##_RB_MAX(struct _name *head)                            \
+               *_name##_RB_MAX(const struct _name *head)                      \
        {                                                                      \
-               return (struct _type *)_rb_max(                                \
-                       _name##_RB_TYPE, &head->rbh_root);                     \
+               return (struct _type *)_rb_max(_name##_RB_TYPE,                \
+                                              &head->rbh_root);               \
        }                                                                      \
                                                                                \
        __attribute__((__unused__)) static inline struct _type                 \
index 6b91969218fdb0c704e179dfc0a880342b2c69e5..d2a4c3a432351193e2c24fcb4ecb40784924ad78 100644 (file)
@@ -1543,7 +1543,7 @@ char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size)
        return ptr;
 }
 
-unsigned prefix_hash_key(void *pp)
+unsigned prefix_hash_key(const void *pp)
 {
        struct prefix copy;
 
index d3c387e102945e9df619485f6e0db9749e0d250a..d57b43dac689e10d377a7afbef3510daf230b0ee 100644 (file)
@@ -466,7 +466,7 @@ extern int is_zero_mac(struct ethaddr *mac);
 extern int prefix_str2mac(const char *str, struct ethaddr *mac);
 extern char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size);
 
-extern unsigned prefix_hash_key(void *pp);
+extern unsigned prefix_hash_key(const void *pp);
 
 extern int str_to_esi(const char *str, esi_t *esi);
 extern char *esi_to_str(const esi_t *esi, char *buf, int size);
index 4898a8d0fa776e0650a6b440f4a3e8aa4b201e97..9133b808950c64e2c0dc1718beb262c39de542eb 100644 (file)
@@ -616,14 +616,14 @@ struct route_map_list {
 
        void (*add_hook)(const char *);
        void (*delete_hook)(const char *);
-       void (*event_hook)(route_map_event_t, const char *);
+       void (*event_hook)(const char *);
 };
 
 /* Master list of route map. */
 static struct route_map_list route_map_master = {NULL, NULL, NULL, NULL, NULL};
 struct hash *route_map_master_hash = NULL;
 
-static unsigned int route_map_hash_key_make(void *p)
+static unsigned int route_map_hash_key_make(const void *p)
 {
        const struct route_map *map = p;
        return string_hash_make(map->name);
@@ -673,7 +673,7 @@ struct route_map_dep {
 /* Hashes maintaining dependency between various sublists used by route maps */
 struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX];
 
-static unsigned int route_map_dep_hash_make_key(void *p);
+static unsigned int route_map_dep_hash_make_key(const void *p);
 static void route_map_clear_all_references(char *rmap_name);
 static void route_map_rule_delete(struct route_map_rule_list *,
                                  struct route_map_rule *);
@@ -902,7 +902,7 @@ static const char *route_map_type_str(enum route_map_type type)
        case RMAP_DENY:
                return "deny";
                break;
-       default:
+       case RMAP_ANY:
                return "";
                break;
        }
@@ -1077,8 +1077,7 @@ static void route_map_index_delete(struct route_map_index *index, int notify)
 
        /* Execute event hook. */
        if (route_map_master.event_hook && notify) {
-               (*route_map_master.event_hook)(RMAP_EVENT_INDEX_DELETED,
-                                              index->map->name);
+               (*route_map_master.event_hook)(index->map->name);
                route_map_notify_dependencies(index->map->name,
                                              RMAP_EVENT_CALL_ADDED);
        }
@@ -1137,8 +1136,7 @@ route_map_index_add(struct route_map *map, enum route_map_type type, int pref)
 
        /* Execute event hook. */
        if (route_map_master.event_hook) {
-               (*route_map_master.event_hook)(RMAP_EVENT_INDEX_ADDED,
-                                              map->name);
+               (*route_map_master.event_hook)(map->name);
                route_map_notify_dependencies(map->name, RMAP_EVENT_CALL_ADDED);
        }
        return index;
@@ -1308,6 +1306,16 @@ int route_map_add_match(struct route_map_index *index, const char *match_name,
        for (rule = index->match_list.head; rule; rule = next) {
                next = rule->next;
                if (rule->cmd == cmd) {
+                       /* If the configured route-map match rule is exactly
+                        * the same as the existing configuration then,
+                        * ignore the duplicate configuration.
+                        */
+                       if (strcmp(match_arg, rule->rule_str) == 0) {
+                               if (cmd->func_free)
+                                       (*cmd->func_free)(compile);
+                               return RMAP_COMPILE_SUCCESS;
+                       }
+
                        route_map_rule_delete(&index->match_list, rule);
                        replaced = 1;
                }
@@ -1327,10 +1335,7 @@ int route_map_add_match(struct route_map_index *index, const char *match_name,
 
        /* Execute event hook. */
        if (route_map_master.event_hook) {
-               (*route_map_master.event_hook)(
-                       replaced ? RMAP_EVENT_MATCH_REPLACED
-                                : RMAP_EVENT_MATCH_ADDED,
-                       index->map->name);
+               (*route_map_master.event_hook)(index->map->name);
                route_map_notify_dependencies(index->map->name,
                                              RMAP_EVENT_CALL_ADDED);
        }
@@ -1355,9 +1360,7 @@ int route_map_delete_match(struct route_map_index *index,
                        route_map_rule_delete(&index->match_list, rule);
                        /* Execute event hook. */
                        if (route_map_master.event_hook) {
-                               (*route_map_master.event_hook)(
-                                       RMAP_EVENT_MATCH_DELETED,
-                                       index->map->name);
+                               (*route_map_master.event_hook)(index->map->name);
                                route_map_notify_dependencies(
                                        index->map->name,
                                        RMAP_EVENT_CALL_ADDED);
@@ -1415,10 +1418,7 @@ int route_map_add_set(struct route_map_index *index, const char *set_name,
 
        /* Execute event hook. */
        if (route_map_master.event_hook) {
-               (*route_map_master.event_hook)(replaced
-                                                      ? RMAP_EVENT_SET_REPLACED
-                                                      : RMAP_EVENT_SET_ADDED,
-                                              index->map->name);
+               (*route_map_master.event_hook)(index->map->name);
                route_map_notify_dependencies(index->map->name,
                                              RMAP_EVENT_CALL_ADDED);
        }
@@ -1442,9 +1442,7 @@ int route_map_delete_set(struct route_map_index *index, const char *set_name,
                        route_map_rule_delete(&index->set_list, rule);
                        /* Execute event hook. */
                        if (route_map_master.event_hook) {
-                               (*route_map_master.event_hook)(
-                                       RMAP_EVENT_SET_DELETED,
-                                       index->map->name);
+                               (*route_map_master.event_hook)(index->map->name);
                                route_map_notify_dependencies(
                                        index->map->name,
                                        RMAP_EVENT_CALL_ADDED);
@@ -1641,7 +1639,7 @@ void route_map_delete_hook(void (*func)(const char *))
        route_map_master.delete_hook = func;
 }
 
-void route_map_event_hook(void (*func)(route_map_event_t, const char *))
+void route_map_event_hook(void (*func)(const char *name))
 {
        route_map_master.event_hook = func;
 }
@@ -1711,7 +1709,7 @@ static void *route_map_name_hash_alloc(void *p)
        return ((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME, (const char *)p));
 }
 
-static unsigned int route_map_dep_hash_make_key(void *p)
+static unsigned int route_map_dep_hash_make_key(const void *p)
 {
        return (string_hash_make((char *)p));
 }
@@ -1785,7 +1783,14 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name,
                        dep = NULL;
                }
                break;
-       default:
+       case RMAP_EVENT_SET_ADDED:
+       case RMAP_EVENT_SET_DELETED:
+       case RMAP_EVENT_SET_REPLACED:
+       case RMAP_EVENT_MATCH_ADDED:
+       case RMAP_EVENT_MATCH_DELETED:
+       case RMAP_EVENT_MATCH_REPLACED:
+       case RMAP_EVENT_INDEX_ADDED:
+       case RMAP_EVENT_INDEX_DELETED:
                break;
        }
 
@@ -1828,13 +1833,26 @@ static struct hash *route_map_get_dep_hash(route_map_event_t event)
                break;
        case RMAP_EVENT_CALL_ADDED:
        case RMAP_EVENT_CALL_DELETED:
+       case RMAP_EVENT_MATCH_ADDED:
+       case RMAP_EVENT_MATCH_DELETED:
                upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_RMAP];
                break;
        case RMAP_EVENT_FILTER_ADDED:
        case RMAP_EVENT_FILTER_DELETED:
                upd8_hash = route_map_dep_hash[ROUTE_MAP_DEP_FILTER];
                break;
-       default:
+       /*
+        * Should we actually be ignoring these?
+        * I am not sure but at this point in time, let
+        * us get them into this switch and we can peel
+        * them into the appropriate place in the future
+        */
+       case RMAP_EVENT_SET_ADDED:
+       case RMAP_EVENT_SET_DELETED:
+       case RMAP_EVENT_SET_REPLACED:
+       case RMAP_EVENT_MATCH_REPLACED:
+       case RMAP_EVENT_INDEX_ADDED:
+       case RMAP_EVENT_INDEX_DELETED:
                upd8_hash = NULL;
                break;
        }
@@ -1844,13 +1862,12 @@ static struct hash *route_map_get_dep_hash(route_map_event_t event)
 static void route_map_process_dependency(struct hash_bucket *bucket, void *data)
 {
        char *rmap_name = (char *)bucket->data;
-       route_map_event_t type = (route_map_event_t)(ptrdiff_t)data;
 
        if (rmap_debug)
                zlog_debug("%s: Notifying %s of dependency",
                           __FUNCTION__, rmap_name);
        if (route_map_master.event_hook)
-               (*route_map_master.event_hook)(type, rmap_name);
+               (*route_map_master.event_hook)(rmap_name);
 }
 
 void route_map_upd8_dependency(route_map_event_t type, const char *arg,
@@ -2803,6 +2820,13 @@ DEFUN (rmap_call,
 
        assert(index);
 
+       /* If "call" is invoked with the same route-map name as
+        * the one previously configured then, ignore the duplicate
+        * configuration.
+        */
+       if (index->nextrm && (strcmp(index->nextrm, rmap) == 0))
+               return CMD_SUCCESS;
+
        if (index->nextrm) {
                route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED,
                                          index->nextrm, index->map->name);
index e43e74a633dda2424d1491f67c6b5c92698a0d55..9969936a6b9fecf684213bf43be015b05c5259bf 100644 (file)
@@ -238,7 +238,15 @@ extern route_map_result_t route_map_apply(struct route_map *map,
 
 extern void route_map_add_hook(void (*func)(const char *));
 extern void route_map_delete_hook(void (*func)(const char *));
-extern void route_map_event_hook(void (*func)(route_map_event_t, const char *));
+
+/*
+ * This is the callback for when something has changed about a
+ * route-map.  The interested parties can register to receive
+ * this data.
+ *
+ * name - Is the name of the changed route-map
+ */
+extern void route_map_event_hook(void (*func)(const char *name));
 extern int route_map_mark_updated(const char *name);
 extern void route_map_walk_update_list(void (*update_fn)(char *name));
 extern void route_map_upd8_dependency(route_map_event_t type, const char *arg,
index 0b7af18fcffaf54df27367f70e103841d6ae1d54..4897f5e8e528b7447fe7ca32a8b38b459adf2906 100644 (file)
@@ -3,7 +3,7 @@
 #
 lib_LTLIBRARIES += lib/libfrr.la
 lib_libfrr_la_LDFLAGS = -version-info 0:0:0 -Xlinker -e_libfrr_version
-lib_libfrr_la_LIBADD = $(LIBCAP) $(UNWIND_LIBS) $(LIBYANG_LIBS)
+lib_libfrr_la_LIBADD = $(LIBCAP) $(UNWIND_LIBS) $(LIBYANG_LIBS) $(LUA_LIB)
 
 lib_libfrr_la_SOURCES = \
        lib/agg_table.c \
@@ -21,6 +21,7 @@ lib_libfrr_la_SOURCES = \
        lib/distribute.c \
        lib/ferr.c \
        lib/filter.c \
+       lib/frrlua.c \
        lib/frr_pthread.c \
        lib/frrstr.c \
        lib/getopt.c \
@@ -93,7 +94,6 @@ lib_libfrr_la_SOURCES = \
        lib/yang_wrappers.c \
        lib/zclient.c \
        lib/logicalrouter.c \
-       lib/lua.c \
        # end
 
 nodist_lib_libfrr_la_SOURCES = \
@@ -151,6 +151,7 @@ pkginclude_HEADERS += \
        lib/ferr.h \
        lib/filter.h \
        lib/freebsd-queue.h \
+       lib/frrlua.h \
        lib/frr_pthread.h \
        lib/frratomic.h \
        lib/frrstr.h \
@@ -228,7 +229,6 @@ pkginclude_HEADERS += \
        lib/zclient.h \
        lib/zebra.h \
        lib/logicalrouter.h \
-       lib/lua.h \
        lib/pbr.h \
        # end
 
index edba7f1932455181bf85657c238a40bab5c21a2d..2d42e2d55c904fe8942f497df267cd979c610df9 100644 (file)
@@ -33,12 +33,14 @@ DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node")
 
 static void route_table_free(struct route_table *);
 
-static bool route_table_hash_cmp(const void *a, const void *b)
+static int route_table_hash_cmp(const void *a, const void *b)
 {
        const struct prefix *pa = a, *pb = b;
-       return prefix_cmp(pa, pb) == 0;
+       return prefix_cmp(pa, pb);
 }
 
+DECLARE_HASH(rn_hash_node, struct route_node, nodehash, route_table_hash_cmp,
+            prefix_hash_key)
 /*
  * route_table_init_with_delegate
  */
@@ -49,8 +51,7 @@ route_table_init_with_delegate(route_table_delegate_t *delegate)
 
        rt = XCALLOC(MTYPE_ROUTE_TABLE, sizeof(struct route_table));
        rt->delegate = delegate;
-       rt->hash = hash_create(prefix_hash_key, route_table_hash_cmp,
-                              "route table hash");
+       rn_hash_node_init(&rt->hash);
        return rt;
 }
 
@@ -69,15 +70,14 @@ static struct route_node *route_node_new(struct route_table *table)
 static struct route_node *route_node_set(struct route_table *table,
                                         const struct prefix *prefix)
 {
-       struct route_node *node, *inserted;
+       struct route_node *node;
 
        node = route_node_new(table);
 
        prefix_copy(&node->p, prefix);
        node->table = table;
 
-       inserted = hash_get(node->table->hash, node, hash_alloc_intern);
-       assert(inserted == node);
+       rn_hash_node_add(&node->table->hash, node);
 
        return node;
 }
@@ -99,9 +99,6 @@ static void route_table_free(struct route_table *rt)
        if (rt == NULL)
                return;
 
-       hash_clean(rt->hash, NULL);
-       hash_free(rt->hash);
-
        node = rt->top;
 
        /* Bulk deletion of nodes remaining in this table.  This function is not
@@ -123,6 +120,7 @@ static void route_table_free(struct route_table *rt)
 
                tmp_node->table->count--;
                tmp_node->lock = 0; /* to cause assert if unlocked after this */
+               rn_hash_node_del(&rt->hash, tmp_node);
                route_node_free(rt, tmp_node);
 
                if (node != NULL) {
@@ -137,6 +135,7 @@ static void route_table_free(struct route_table *rt)
 
        assert(rt->count == 0);
 
+       rn_hash_node_fini(&rt->hash);
        XFREE(MTYPE_ROUTE_TABLE, rt);
        return;
 }
@@ -257,7 +256,7 @@ struct route_node *route_node_lookup(const struct route_table *table,
        prefix_copy(&p, pu.p);
        apply_mask(&p);
 
-       node = hash_get(table->hash, (void *)&p, NULL);
+       node = rn_hash_node_find(&table->hash, (void *)&p);
        return (node && node->info) ? route_lock_node(node) : NULL;
 }
 
@@ -270,7 +269,7 @@ struct route_node *route_node_lookup_maynull(const struct route_table *table,
        prefix_copy(&p, pu.p);
        apply_mask(&p);
 
-       node = hash_get(table->hash, (void *)&p, NULL);
+       node = rn_hash_node_find(&table->hash, (void *)&p);
        return node ? route_lock_node(node) : NULL;
 }
 
@@ -282,12 +281,11 @@ struct route_node *route_node_get(struct route_table *const table,
        struct route_node *new;
        struct route_node *node;
        struct route_node *match;
-       struct route_node *inserted;
        uint16_t prefixlen = p->prefixlen;
        const uint8_t *prefix = &p->u.prefix;
 
        apply_mask((struct prefix *)p);
-       node = hash_get(table->hash, (void *)p, NULL);
+       node = rn_hash_node_find(&table->hash, (void *)p);
        if (node && node->info)
                return route_lock_node(node);
 
@@ -314,8 +312,7 @@ struct route_node *route_node_get(struct route_table *const table,
                new->p.family = p->family;
                new->table = table;
                set_link(new, node);
-               inserted = hash_get(node->table->hash, new, hash_alloc_intern);
-               assert(inserted == new);
+               rn_hash_node_add(&table->hash, new);
 
                if (match)
                        set_link(match, new);
@@ -367,7 +364,7 @@ void route_node_delete(struct route_node *node)
 
        node->table->count--;
 
-       hash_release(node->table->hash, node);
+       rn_hash_node_del(&node->table->hash, node);
 
        /* WARNING: FRAGILE CODE!
         * route_node_free may have the side effect of free'ing the entire
index ce578e795c648f782fbffc8c64aead792fb8d5bf..3e3fb658aebe011df1ded9fde4bab856489b1b7c 100644 (file)
@@ -25,6 +25,7 @@
 #include "memory.h"
 #include "hash.h"
 #include "prefix.h"
+#include "typesafe.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -59,10 +60,12 @@ struct route_table_delegate_t_ {
        route_table_destroy_node_func_t destroy_node;
 };
 
+PREDECL_HASH(rn_hash_node)
+
 /* Routing table top structure. */
 struct route_table {
        struct route_node *top;
-       struct hash *hash;
+       struct rn_hash_node_head hash;
 
        /*
         * Delegate that performs certain functions for this table.
@@ -129,6 +132,7 @@ struct route_table {
        /* Lock of this radix */                                               \
        unsigned int table_rdonly(lock);                                       \
                                                                                \
+       struct rn_hash_node_item nodehash;                                     \
        /* Each node of route. */                                              \
        void *info;                                                            \
 
index 5ca859a74d4c2d093c23a1ea1a5a6693711913d3..9489e3e923f31ed54a65639a4b3a6fa33908edef 100644 (file)
@@ -63,7 +63,7 @@ static struct list *masters;
 static void thread_free(struct thread_master *master, struct thread *thread);
 
 /* CLI start ---------------------------------------------------------------- */
-static unsigned int cpu_record_hash_key(struct cpu_thread_history *a)
+static unsigned int cpu_record_hash_key(const struct cpu_thread_history *a)
 {
        int size = sizeof(a->func);
 
@@ -433,7 +433,7 @@ struct thread_master *thread_master_create(const char *name)
                            sizeof(struct thread *) * rv->fd_limit);
 
        rv->cpu_record = hash_create_size(
-               8, (unsigned int (*)(void *))cpu_record_hash_key,
+               8, (unsigned int (*)(const void *))cpu_record_hash_key,
                (bool (*)(const void *, const void *))cpu_record_hash_cmp,
                "Thread Hash");
 
index bbf3ce8f1cb508c8aaa447064f02d67d954509ba..94002da599c23ea4d66a3184bbc63486f2825cc3 100644 (file)
@@ -275,7 +275,7 @@ macro_pure size_t prefix ## _count(struct prefix##_head *h)                    \
 #define DECLARE_SORTLIST_UNIQ(prefix, type, field, cmpfn)                      \
        _DECLARE_SORTLIST(prefix, type, field, cmpfn, cmpfn)                   \
                                                                                \
-macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item)  \
+macro_inline type *prefix ## _find(const struct prefix##_head *h, const type *item)  \
 {                                                                              \
        struct ssort_item *sitem = h->sh.first;                                \
        int cmpval = 0;                                                        \
@@ -383,7 +383,7 @@ macro_inline type *prefix ## _add(struct prefix##_head *h, type *item)         \
        *np = &item->field.hi;                                                 \
        return NULL;                                                           \
 }                                                                              \
-macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item)  \
+macro_inline type *prefix ## _find(const struct prefix##_head *h, const type *item)  \
 {                                                                              \
        if (!h->hh.tabshift)                                                   \
                return NULL;                                                   \
@@ -576,7 +576,7 @@ macro_inline int prefix ## __cmp(const struct sskip_item *a,                   \
        return cmpfn(container_of(a, type, field.si),                          \
                        container_of(b, type, field.si));                      \
 }                                                                              \
-macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item)  \
+macro_inline type *prefix ## _find(const struct prefix##_head *h, const type *item)  \
 {                                                                              \
        struct sskip_item *sitem = typesafe_skiplist_find(&h->sh,              \
                        &item->field.si, &prefix ## __cmp);                    \
index 6d9ac2e1e44ba15fb6c887752109163b8325439e..229f19f29ae877a2f2b02ae7c9b65c27e36ae634 100644 (file)
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -362,9 +362,9 @@ struct vrf_bit_set {
        bool set;
 };
 
-static unsigned int vrf_hash_bitmap_key(void *data)
+static unsigned int vrf_hash_bitmap_key(const void *data)
 {
-       struct vrf_bit_set *bit = data;
+       const struct vrf_bit_set *bit = data;
 
        return bit->vrf_id;
 }
@@ -904,10 +904,16 @@ vrf_id_t vrf_get_default_id(void)
 int vrf_bind(vrf_id_t vrf_id, int fd, const char *name)
 {
        int ret = 0;
+       struct interface *ifp;
 
        if (fd < 0 || name == NULL)
                return fd;
-       if (vrf_is_backend_netns())
+       /* the device should exist
+        * otherwise we should return
+        * case ifname = vrf in netns mode => return
+        */
+       ifp = if_lookup_by_name(name, vrf_id);
+       if (!ifp)
                return fd;
 #ifdef SO_BINDTODEVICE
        ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
index 69d2fa48dc0b382d2875049139f99a5ec589c5cf..8e479c931b5ac7c8cc590bd4dadcf2f9e48b4d46 100644 (file)
@@ -80,7 +80,7 @@ static int wheel_timer_thread(struct thread *t)
 }
 
 struct timer_wheel *wheel_init(struct thread_master *master, int period,
-                              size_t slots, unsigned int (*slot_key)(void *),
+                              size_t slots, unsigned int (*slot_key)(const void *),
                               void (*slot_run)(void *),
                               const char *run_name)
 {
index e66751c1d092a135dee1fb8f0c243ac522a34c94..401789e1a01d547446c0e6c55ac43d7d083d7f78 100644 (file)
@@ -38,7 +38,7 @@ struct timer_wheel {
        /*
         * Key to determine what slot the item belongs in
         */
-       unsigned int (*slot_key)(void *);
+       unsigned int (*slot_key)(const void *);
 
        void (*slot_run)(void *);
 };
@@ -80,9 +80,9 @@ struct timer_wheel {
  * of running your code.
  */
 struct timer_wheel *wheel_init(struct thread_master *master, int period,
-                              size_t slots, unsigned int (*slot_key)(void *),
-                              void (*slot_run)(void *),
-                              const char *run_name);
+                              size_t slots,
+                              unsigned int (*slot_key)(const void *),
+                              void (*slot_run)(void *), const char *run_name);
 
 /*
  * Delete the specified timer wheel created
index 69fff5dbffb0981f0dabd186d5115e34d005b9c5..341420eeda45e2360f143420f1c8c11c3c49591b 100644 (file)
@@ -61,7 +61,7 @@ static bool yang_mapping_hash_cmp(const void *value1, const void *value2)
        return strmatch(c1->xpath_from_canonical, c2->xpath_from_canonical);
 }
 
-static unsigned int yang_mapping_hash_key(void *value)
+static unsigned int yang_mapping_hash_key(const void *value)
 {
        return string_hash_make(value);
 }
index b1ea43c747cdde0817356a8eebc3a32b97a45424..3e1eefdb2e31efeb4dee3d6fb2ef954516c9b9ce 100644 (file)
@@ -422,7 +422,13 @@ extern const char *zserv_command_string(unsigned int command);
 #endif
 
 /* Address family numbers from RFC1700. */
-typedef enum { AFI_IP = 1, AFI_IP6 = 2, AFI_L2VPN = 3, AFI_MAX = 4 } afi_t;
+typedef enum {
+       AFI_UNSPEC = 0,
+       AFI_IP = 1,
+       AFI_IP6 = 2,
+       AFI_L2VPN = 3,
+       AFI_MAX = 4
+} afi_t;
 
 /* Subsequent Address Family Identifier. */
 typedef enum {
diff --git a/m4/ax_lua.m4 b/m4/ax_lua.m4
new file mode 100644 (file)
index 0000000..9feb352
--- /dev/null
@@ -0,0 +1,664 @@
+# ===========================================================================
+#          http://www.gnu.org/software/autoconf-archive/ax_lua.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
+#   AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
+#   AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
+#   AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])]
+#
+# DESCRIPTION
+#
+#   Detect a Lua interpreter, optionally specifying a minimum and maximum
+#   version number. Set up important Lua paths, such as the directories in
+#   which to install scripts and modules (shared libraries).
+#
+#   Also detect Lua headers and libraries. The Lua version contained in the
+#   header is checked to match the Lua interpreter version exactly. When
+#   searching for Lua libraries, the version number is used as a suffix.
+#   This is done with the goal of supporting multiple Lua installs (5.1,
+#   5.2, and 5.3 side-by-side).
+#
+#   A note on compatibility with previous versions: This file has been
+#   mostly rewritten for serial 18. Most developers should be able to use
+#   these macros without needing to modify configure.ac. Care has been taken
+#   to preserve each macro's behavior, but there are some differences:
+#
+#   1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as
+#   AX_PROG_LUA with no arguments.
+#
+#   2) AX_LUA_HEADERS now checks that the version number defined in lua.h
+#   matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore
+#   unnecessary, so it is deprecated and does not expand to anything.
+#
+#   3) The configure flag --with-lua-suffix no longer exists; the user
+#   should instead specify the LUA precious variable on the command line.
+#   See the AX_PROG_LUA description for details.
+#
+#   Please read the macro descriptions below for more information.
+#
+#   This file was inspired by Andrew Dalke's and James Henstridge's
+#   python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4
+#   (serial 17). Basically, this file is a mash-up of those two files. I
+#   like to think it combines the best of the two!
+#
+#   AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua
+#   paths. Adds precious variable LUA, which may contain the path of the Lua
+#   interpreter. If LUA is blank, the user's path is searched for an
+#   suitable interpreter.
+#
+#   If MINIMUM-VERSION is supplied, then only Lua interpreters with a
+#   version number greater or equal to MINIMUM-VERSION will be accepted. If
+#   TOO-BIG-VERSION is also supplied, then only Lua interpreters with a
+#   version number greater or equal to MINIMUM-VERSION and less than
+#   TOO-BIG-VERSION will be accepted.
+#
+#   The Lua version number, LUA_VERSION, is found from the interpreter, and
+#   substituted. LUA_PLATFORM is also found, but not currently supported (no
+#   standard representation).
+#
+#   Finally, the macro finds four paths:
+#
+#     luadir             Directory to install Lua scripts.
+#     pkgluadir          $luadir/$PACKAGE
+#     luaexecdir         Directory to install Lua modules.
+#     pkgluaexecdir      $luaexecdir/$PACKAGE
+#
+#   These paths are found based on $prefix, $exec_prefix, Lua's
+#   package.path, and package.cpath. The first path of package.path
+#   beginning with $prefix is selected as luadir. The first path of
+#   package.cpath beginning with $exec_prefix is used as luaexecdir. This
+#   should work on all reasonable Lua installations. If a path cannot be
+#   determined, a default path is used. Of course, the user can override
+#   these later when invoking make.
+#
+#     luadir             Default: $prefix/share/lua/$LUA_VERSION
+#     luaexecdir         Default: $exec_prefix/lib/lua/$LUA_VERSION
+#
+#   These directories can be used by Automake as install destinations. The
+#   variable name minus 'dir' needs to be used as a prefix to the
+#   appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES.
+#
+#   If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is
+#   performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT-
+#   FOUND is blank, then it will default to printing an error. To prevent
+#   the default behavior, give ':' as an action.
+#
+#   AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be
+#   expanded before this macro. Adds precious variable LUA_INCLUDE, which
+#   may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If
+#   LUA_INCLUDE is blank, then this macro will attempt to find suitable
+#   flags.
+#
+#   LUA_INCLUDE can be used by Automake to compile Lua modules or
+#   executables with embedded interpreters. The *_CPPFLAGS variables should
+#   be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE).
+#
+#   This macro searches for the header lua.h (and others). The search is
+#   performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE.
+#   If the search is unsuccessful, then some common directories are tried.
+#   If the headers are then found, then LUA_INCLUDE is set accordingly.
+#
+#   The paths automatically searched are:
+#
+#     * /usr/include/luaX.Y
+#     * /usr/include/lua/X.Y
+#     * /usr/include/luaXY
+#     * /usr/local/include/luaX.Y
+#     * /usr/local/include/lua-X.Y
+#     * /usr/local/include/lua/X.Y
+#     * /usr/local/include/luaXY
+#
+#   (Where X.Y is the Lua version number, e.g. 5.1.)
+#
+#   The Lua version number found in the headers is always checked to match
+#   the Lua interpreter's version number. Lua headers with mismatched
+#   version numbers are not accepted.
+#
+#   If headers are found, then ACTION-IF-FOUND is performed, otherwise
+#   ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
+#   it will default to printing an error. To prevent the default behavior,
+#   set the action to ':'.
+#
+#   AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be
+#   expanded before this macro. Adds precious variable LUA_LIB, which may
+#   contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank,
+#   then this macro will attempt to find suitable flags.
+#
+#   LUA_LIB can be used by Automake to link Lua modules or executables with
+#   embedded interpreters. The *_LIBADD and *_LDADD variables should be used
+#   for this purpose, e.g. mymod_LIBADD = $(LUA_LIB).
+#
+#   This macro searches for the Lua library. More technically, it searches
+#   for a library containing the function lua_load. The search is performed
+#   with a combination of LIBS, LIBRARY_PATH, and LUA_LIB.
+#
+#   If the search determines that some linker flags are missing, then those
+#   flags will be added to LUA_LIB.
+#
+#   If libraries are found, then ACTION-IF-FOUND is performed, otherwise
+#   ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then
+#   it will default to printing an error. To prevent the default behavior,
+#   set the action to ':'.
+#
+#   AX_LUA_READLINE: Search for readline headers and libraries. Requires the
+#   AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the
+#   Autoconf Archive.
+#
+#   If a readline compatible library is found, then ACTION-IF-FOUND is
+#   performed, otherwise ACTION-IF-NOT-FOUND is performed.
+#
+# LICENSE
+#
+#   Copyright (c) 2015 Reuben Thomas <rrt@sc3d.org>
+#   Copyright (c) 2014 Tim Perkins <tprk77@gmail.com>
+#
+#   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 3 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. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 39
+
+dnl =========================================================================
+dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION],
+dnl             [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl =========================================================================
+AC_DEFUN([AX_PROG_LUA],
+[
+  dnl Check for required tools.
+  AC_REQUIRE([AC_PROG_GREP])
+  AC_REQUIRE([AC_PROG_SED])
+
+  dnl Make LUA a precious variable.
+  AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1])
+
+  dnl Find a Lua interpreter.
+  m4_define_default([_AX_LUA_INTERPRETER_LIST],
+    [lua lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua50])
+
+  m4_if([$1], [],
+  [ dnl No version check is needed. Find any Lua interpreter.
+    AS_IF([test "x$LUA" = 'x'],
+      [AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])])
+    ax_display_LUA='lua'
+
+    AS_IF([test "x$LUA" != 'x:'],
+      [ dnl At least check if this is a Lua interpreter.
+        AC_MSG_CHECKING([if $LUA is a Lua interpreter])
+        _AX_LUA_CHK_IS_INTRP([$LUA],
+          [AC_MSG_RESULT([yes])],
+          [ AC_MSG_RESULT([no])
+            AC_MSG_ERROR([not a Lua interpreter])
+          ])
+      ])
+  ],
+  [ dnl A version check is needed.
+    AS_IF([test "x$LUA" != 'x'],
+    [ dnl Check if this is a Lua interpreter.
+      AC_MSG_CHECKING([if $LUA is a Lua interpreter])
+      _AX_LUA_CHK_IS_INTRP([$LUA],
+        [AC_MSG_RESULT([yes])],
+        [ AC_MSG_RESULT([no])
+          AC_MSG_ERROR([not a Lua interpreter])
+        ])
+      dnl Check the version.
+      m4_if([$2], [],
+        [_ax_check_text="whether $LUA version >= $1"],
+        [_ax_check_text="whether $LUA version >= $1, < $2"])
+      AC_MSG_CHECKING([$_ax_check_text])
+      _AX_LUA_CHK_VER([$LUA], [$1], [$2],
+        [AC_MSG_RESULT([yes])],
+        [ AC_MSG_RESULT([no])
+          AC_MSG_ERROR([version is out of range for specified LUA])])
+      ax_display_LUA=$LUA
+    ],
+    [ dnl Try each interpreter until we find one that satisfies VERSION.
+      m4_if([$2], [],
+        [_ax_check_text="for a Lua interpreter with version >= $1"],
+        [_ax_check_text="for a Lua interpreter with version >= $1, < $2"])
+      AC_CACHE_CHECK([$_ax_check_text],
+        [ax_cv_pathless_LUA],
+        [ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do
+            test "x$ax_cv_pathless_LUA" = 'xnone' && break
+            _AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue])
+            _AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break])
+          done
+        ])
+      dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA.
+      AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'],
+        [LUA=':'],
+        [AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])])
+      ax_display_LUA=$ax_cv_pathless_LUA
+    ])
+  ])
+
+  AS_IF([test "x$LUA" = 'x:'],
+  [ dnl Run any user-specified action, or abort.
+    m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])])
+  ],
+  [ dnl Query Lua for its version number.
+    AC_CACHE_CHECK([for $ax_display_LUA version],
+      [ax_cv_lua_version],
+      [ dnl Get the interpreter version in X.Y format. This should work for
+        dnl interpreters version 5.0 and beyond.
+        ax_cv_lua_version=[`$LUA -e '
+          -- return a version number in X.Y format
+          local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)")
+          print(ver)'`]
+      ])
+    AS_IF([test "x$ax_cv_lua_version" = 'x'],
+      [AC_MSG_ERROR([invalid Lua version number])])
+    AC_SUBST([LUA_VERSION], [$ax_cv_lua_version])
+    AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`])
+
+    dnl The following check is not supported:
+    dnl At times (like when building shared libraries) you may want to know
+    dnl which OS platform Lua thinks this is.
+    AC_CACHE_CHECK([for $ax_display_LUA platform],
+      [ax_cv_lua_platform],
+      [ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]])
+    AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform])
+
+    dnl Use the values of $prefix and $exec_prefix for the corresponding
+    dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct
+    dnl variables so they can be overridden if need be. However, the general
+    dnl consensus is that you shouldn't need this ability.
+    AC_SUBST([LUA_PREFIX], ['${prefix}'])
+    AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}'])
+
+    dnl Lua provides no way to query the script directory, and instead
+    dnl provides LUA_PATH. However, we should be able to make a safe educated
+    dnl guess. If the built-in search path contains a directory which is
+    dnl prefixed by $prefix, then we can store scripts there. The first
+    dnl matching path will be used.
+    AC_CACHE_CHECK([for $ax_display_LUA script directory],
+      [ax_cv_lua_luadir],
+      [ AS_IF([test "x$prefix" = 'xNONE'],
+          [ax_lua_prefix=$ac_default_prefix],
+          [ax_lua_prefix=$prefix])
+
+        dnl Initialize to the default path.
+        ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION"
+
+        dnl Try to find a path with the prefix.
+        _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script])
+        AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
+        [ dnl Fix the prefix.
+          _ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'`
+          ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \
+            $SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"`
+        ])
+      ])
+    AC_SUBST([luadir], [$ax_cv_lua_luadir])
+    AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE])
+
+    dnl Lua provides no way to query the module directory, and instead
+    dnl provides LUA_PATH. However, we should be able to make a safe educated
+    dnl guess. If the built-in search path contains a directory which is
+    dnl prefixed by $exec_prefix, then we can store modules there. The first
+    dnl matching path will be used.
+    AC_CACHE_CHECK([for $ax_display_LUA module directory],
+      [ax_cv_lua_luaexecdir],
+      [ AS_IF([test "x$exec_prefix" = 'xNONE'],
+          [ax_lua_exec_prefix=$ax_lua_prefix],
+          [ax_lua_exec_prefix=$exec_prefix])
+
+        dnl Initialize to the default path.
+        ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION"
+
+        dnl Try to find a path with the prefix.
+        _AX_LUA_FND_PRFX_PTH([$LUA],
+          [$ax_lua_exec_prefix], [module])
+        AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
+        [ dnl Fix the prefix.
+          _ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'`
+          ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \
+            $SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"`
+        ])
+      ])
+    AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir])
+    AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE])
+
+    dnl Run any user specified action.
+    $3
+  ])
+])
+
+dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA.
+AC_DEFUN([AX_WITH_LUA],
+[
+  AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]])
+  AX_PROG_LUA
+])
+
+
+dnl =========================================================================
+dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+dnl =========================================================================
+AC_DEFUN([_AX_LUA_CHK_IS_INTRP],
+[
+  dnl A minimal Lua factorial to prove this is an interpreter. This should work
+  dnl for Lua interpreters version 5.0 and beyond.
+  _ax_lua_factorial=[`$1 2>/dev/null -e '
+    -- a simple factorial
+    function fact (n)
+      if n == 0 then
+        return 1
+      else
+        return n * fact(n-1)
+      end
+    end
+    print("fact(5) is " .. fact(5))'`]
+  AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'],
+    [$2], [$3])
+])
+
+
+dnl =========================================================================
+dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION],
+dnl                 [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+dnl =========================================================================
+AC_DEFUN([_AX_LUA_CHK_VER],
+[
+  dnl Check that the Lua version is within the bounds. Only the major and minor
+  dnl version numbers are considered. This should work for Lua interpreters
+  dnl version 5.0 and beyond.
+  _ax_lua_good_version=[`$1 -e '
+    -- a script to compare versions
+    function verstr2num(verstr)
+      local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)")
+      if majorver and minorver then
+        return tonumber(majorver) * 100 + tonumber(minorver)
+      end
+    end
+    local minver = verstr2num("$2")
+    local _, _, trimver = string.find(_VERSION, "^Lua (.*)")
+    local ver = verstr2num(trimver)
+    local maxver = verstr2num("$3") or 1e9
+    if minver <= ver and ver < maxver then
+      print("yes")
+    else
+      print("no")
+    end'`]
+    AS_IF([test "x$_ax_lua_good_version" = "xyes"],
+      [$4], [$5])
+])
+
+
+dnl =========================================================================
+dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR)
+dnl =========================================================================
+AC_DEFUN([_AX_LUA_FND_PRFX_PTH],
+[
+  dnl Get the script or module directory by querying the Lua interpreter,
+  dnl filtering on the given prefix, and selecting the shallowest path. If no
+  dnl path is found matching the prefix, the result will be an empty string.
+  dnl The third argument determines the type of search, it can be 'script' or
+  dnl 'module'. Supplying 'script' will perform the search with package.path
+  dnl and LUA_PATH, and supplying 'module' will search with package.cpath and
+  dnl LUA_CPATH. This is done for compatibility with Lua 5.0.
+
+  ax_lua_prefixed_path=[`$1 -e '
+    -- get the path based on search type
+    local searchtype = "$3"
+    local paths = ""
+    if searchtype == "script" then
+      paths = (package and package.path) or LUA_PATH
+    elseif searchtype == "module" then
+      paths = (package and package.cpath) or LUA_CPATH
+    end
+    -- search for the prefix
+    local prefix = "'$2'"
+    local minpath = ""
+    local mindepth = 1e9
+    string.gsub(paths, "(@<:@^;@:>@+)",
+      function (path)
+        path = string.gsub(path, "%?.*$", "")
+        path = string.gsub(path, "/@<:@^/@:>@*$", "")
+        if string.find(path, prefix) then
+          local depth = string.len(string.gsub(path, "@<:@^/@:>@", ""))
+          if depth < mindepth then
+            minpath = path
+            mindepth = depth
+          end
+        end
+      end)
+    print(minpath)'`]
+])
+
+
+dnl =========================================================================
+dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl =========================================================================
+AC_DEFUN([AX_LUA_HEADERS],
+[
+  dnl Check for LUA_VERSION.
+  AC_MSG_CHECKING([if LUA_VERSION is defined])
+  AS_IF([test "x$LUA_VERSION" != 'x'],
+    [AC_MSG_RESULT([yes])],
+    [ AC_MSG_RESULT([no])
+      AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION])
+    ])
+
+  dnl Make LUA_INCLUDE a precious variable.
+  AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1])
+
+  dnl Some default directories to search.
+  LUA_SHORT_VERSION=`echo "$LUA_VERSION" | $SED 's|\.||'`
+  m4_define_default([_AX_LUA_INCLUDE_LIST],
+    [ /usr/include/lua$LUA_VERSION \
+      /usr/include/lua-$LUA_VERSION \
+      /usr/include/lua/$LUA_VERSION \
+      /usr/include/lua$LUA_SHORT_VERSION \
+      /usr/local/include/lua$LUA_VERSION \
+      /usr/local/include/lua-$LUA_VERSION \
+      /usr/local/include/lua/$LUA_VERSION \
+      /usr/local/include/lua$LUA_SHORT_VERSION \
+    ])
+
+  dnl Try to find the headers.
+  _ax_lua_saved_cppflags=$CPPFLAGS
+  CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
+  AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
+  CPPFLAGS=$_ax_lua_saved_cppflags
+
+  dnl Try some other directories if LUA_INCLUDE was not set.
+  AS_IF([test "x$LUA_INCLUDE" = 'x' &&
+         test "x$ac_cv_header_lua_h" != 'xyes'],
+    [ dnl Try some common include paths.
+      for _ax_include_path in _AX_LUA_INCLUDE_LIST; do
+        test ! -d "$_ax_include_path" && continue
+
+        AC_MSG_CHECKING([for Lua headers in])
+        AC_MSG_RESULT([$_ax_include_path])
+
+        AS_UNSET([ac_cv_header_lua_h])
+        AS_UNSET([ac_cv_header_lualib_h])
+        AS_UNSET([ac_cv_header_lauxlib_h])
+        AS_UNSET([ac_cv_header_luaconf_h])
+
+        _ax_lua_saved_cppflags=$CPPFLAGS
+        CPPFLAGS="$CPPFLAGS -I$_ax_include_path"
+        AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
+        CPPFLAGS=$_ax_lua_saved_cppflags
+
+        AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
+          [ LUA_INCLUDE="-I$_ax_include_path"
+            break
+          ])
+      done
+    ])
+
+  AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
+    [ dnl Make a program to print LUA_VERSION defined in the header.
+      dnl TODO It would be really nice if we could do this without compiling a
+      dnl program, then it would work when cross compiling. But I'm not sure how
+      dnl to do this reliably. For now, assume versions match when cross compiling.
+
+      AS_IF([test "x$cross_compiling" != 'xyes'],
+        [ AC_CACHE_CHECK([for Lua header version],
+            [ax_cv_lua_header_version],
+            [ _ax_lua_saved_cppflags=$CPPFLAGS
+              CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
+              AC_RUN_IFELSE(
+                [ AC_LANG_SOURCE([[
+#include <lua.h>
+#include <stdlib.h>
+#include <stdio.h>
+int main(int argc, char ** argv)
+{
+  if(argc > 1) printf("%s", LUA_VERSION);
+  exit(EXIT_SUCCESS);
+}
+]])
+                ],
+                [ ax_cv_lua_header_version=`./conftest$EXEEXT p | \
+                    $SED -n "s|^Lua \(@<:@0-9@:>@\{1,\}\.@<:@0-9@:>@\{1,\}\).\{0,\}|\1|p"`
+                ],
+                [ax_cv_lua_header_version='unknown'])
+              CPPFLAGS=$_ax_lua_saved_cppflags
+            ])
+
+          dnl Compare this to the previously found LUA_VERSION.
+          AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
+          AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
+            [ AC_MSG_RESULT([yes])
+              ax_header_version_match='yes'
+            ],
+            [ AC_MSG_RESULT([no])
+              ax_header_version_match='no'
+            ])
+        ],
+        [ AC_MSG_WARN([cross compiling so assuming header version number matches])
+          ax_header_version_match='yes'
+        ])
+    ])
+
+  dnl Was LUA_INCLUDE specified?
+  AS_IF([test "x$ax_header_version_match" != 'xyes' &&
+         test "x$LUA_INCLUDE" != 'x'],
+    [AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])])
+
+  dnl Test the final result and run user code.
+  AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1],
+    [m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])])
+])
+
+dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS.
+AC_DEFUN([AX_LUA_HEADERS_VERSION],
+[
+  AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]])
+])
+
+
+dnl =========================================================================
+dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl =========================================================================
+AC_DEFUN([AX_LUA_LIBS],
+[
+  dnl TODO Should this macro also check various -L flags?
+
+  dnl Check for LUA_VERSION.
+  AC_MSG_CHECKING([if LUA_VERSION is defined])
+  AS_IF([test "x$LUA_VERSION" != 'x'],
+    [AC_MSG_RESULT([yes])],
+    [ AC_MSG_RESULT([no])
+      AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION])
+    ])
+
+  dnl Make LUA_LIB a precious variable.
+  AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1])
+
+  AS_IF([test "x$LUA_LIB" != 'x'],
+  [ dnl Check that LUA_LIBS works.
+    _ax_lua_saved_libs=$LIBS
+    LIBS="$LIBS $LUA_LIB"
+    AC_SEARCH_LIBS([lua_load], [],
+      [_ax_found_lua_libs='yes'],
+      [_ax_found_lua_libs='no'])
+    LIBS=$_ax_lua_saved_libs
+
+    dnl Check the result.
+    AS_IF([test "x$_ax_found_lua_libs" != 'xyes'],
+      [AC_MSG_ERROR([cannot find libs for specified LUA_LIB])])
+  ],
+  [ dnl First search for extra libs.
+    _ax_lua_extra_libs=''
+
+    _ax_lua_saved_libs=$LIBS
+    LIBS="$LIBS $LUA_LIB"
+    AC_SEARCH_LIBS([exp], [m])
+    AC_SEARCH_LIBS([dlopen], [dl])
+    LIBS=$_ax_lua_saved_libs
+
+    AS_IF([test "x$ac_cv_search_exp" != 'xno' &&
+           test "x$ac_cv_search_exp" != 'xnone required'],
+      [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"])
+
+    AS_IF([test "x$ac_cv_search_dlopen" != 'xno' &&
+           test "x$ac_cv_search_dlopen" != 'xnone required'],
+      [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"])
+
+    dnl Try to find the Lua libs.
+    _ax_lua_saved_libs=$LIBS
+    LIBS="$LIBS $LUA_LIB"
+    AC_SEARCH_LIBS([lua_load],
+      [ lua$LUA_VERSION \
+        lua$LUA_SHORT_VERSION \
+        lua-$LUA_VERSION \
+        lua-$LUA_SHORT_VERSION \
+        lua \
+      ],
+      [_ax_found_lua_libs='yes'],
+      [_ax_found_lua_libs='no'],
+      [$_ax_lua_extra_libs])
+    LIBS=$_ax_lua_saved_libs
+
+    AS_IF([test "x$ac_cv_search_lua_load" != 'xno' &&
+           test "x$ac_cv_search_lua_load" != 'xnone required'],
+      [LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"])
+  ])
+
+  dnl Test the result and run user code.
+  AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1],
+    [m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])])
+])
+
+
+dnl =========================================================================
+dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl =========================================================================
+AC_DEFUN([AX_LUA_READLINE],
+[
+  AX_LIB_READLINE
+  AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' &&
+         test "x$ac_cv_header_readline_history_h" != 'x'],
+    [ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS"
+      $1
+    ],
+    [$2])
+])
index 5508778243d557e055baccc3617a764f99ec67d0..cc18b36f6ae585081b268149574434b302ea9201 100644 (file)
@@ -30,9 +30,9 @@ const char *const nhrp_cache_type_str[] = {
                [NHRP_CACHE_LOCAL] = "local",
 };
 
-static unsigned int nhrp_cache_protocol_key(void *peer_data)
+static unsigned int nhrp_cache_protocol_key(const void *peer_data)
 {
-       struct nhrp_cache *p = peer_data;
+       const struct nhrp_cache *p = peer_data;
        return sockunion_hash(&p->remote_addr);
 }
 
index db2f72ac2211e4d4e19ba320c9e51f6448f151c9..ca309f25061e936d439859394e1ca7c285e0069a 100644 (file)
@@ -151,9 +151,9 @@ static void nhrp_peer_ifp_notify(struct notifier_block *n, unsigned long cmd)
        nhrp_peer_unref(p);
 }
 
-static unsigned int nhrp_peer_key(void *peer_data)
+static unsigned int nhrp_peer_key(const void *peer_data)
 {
-       struct nhrp_peer *p = peer_data;
+       const struct nhrp_peer *p = peer_data;
        return sockunion_hash(&p->vc->remote.nbma);
 }
 
index fa3549f5edac0f8902dbc056f438fa3388acc4b2..605aa34ff9bd454e57be63d33f135a00153c2347 100644 (file)
@@ -28,9 +28,9 @@ struct child_sa {
 static struct hash *nhrp_vc_hash;
 static struct list_head childlist_head[512];
 
-static unsigned int nhrp_vc_key(void *peer_data)
+static unsigned int nhrp_vc_key(const void *peer_data)
 {
-       struct nhrp_vc *vc = peer_data;
+       const struct nhrp_vc *vc = peer_data;
        return jhash_2words(sockunion_hash(&vc->local.nbma),
                            sockunion_hash(&vc->remote.nbma), 0);
 }
index 08a007bdf933c19adb3537e16f1aef517a997419..e56bbe3bf779b238c7598a4c66f1bc100bd8a492 100644 (file)
@@ -2,9 +2,9 @@
 #include "hash.h"
 #include "nhrpd.h"
 
-static unsigned int nhrp_reqid_key(void *data)
+static unsigned int nhrp_reqid_key(const void *data)
 {
-       struct nhrp_reqid *r = data;
+       const struct nhrp_reqid *r = data;
        return r->request_id;
 }
 
index 2795bb9abdfb46c99ad369bb6d162bd359e8cea9..946bbf8cc9423f8fb9a5309f2c79203b4f3f6a16 100644 (file)
@@ -956,7 +956,7 @@ static void ospf6_asbr_routemap_update(const char *mapname)
        }
 }
 
-static void ospf6_asbr_routemap_event(route_map_event_t event, const char *name)
+static void ospf6_asbr_routemap_event(const char *name)
 {
        int type;
 
index 3394bd75db854706db7c2ce821dc8fe4ea7199ba..7a26af1f09ac36fb08360fedf14c149c9e28e74f 100644 (file)
@@ -151,7 +151,7 @@ static int ospf6_bfd_nbr_replay(ZAPI_CALLBACK_ARGS)
                zlog_debug("Zebra: BFD Dest replay request");
 
        /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id);
 
        /* Replay the neighbor, if BFD is enabled on the interface*/
        FOR_ALL_INTERFACES (vrf, ifp) {
index 8db4ffef18c603f52b5e3d74a7782a678d293d4f..af16c5aa7cded703f57dfca72dfd986a0347f913 100644 (file)
@@ -571,7 +571,7 @@ uint8_t ospf6_distance_apply(struct prefix_ipv6 *p, struct ospf6_route * or)
 static void ospf6_zebra_connected(struct zclient *zclient)
 {
        /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
 
        zclient_send_reg_requests(zclient, VRF_DEFAULT);
 }
index 6bff5b8ddbf2951ca514d20ae7b12704273a7db0..c8ad6d04f49ec6de3352bffe4ffccd5f314e9143 100644 (file)
@@ -156,7 +156,7 @@ static int ospf_bfd_nbr_replay(ZAPI_CALLBACK_ARGS)
        }
 
        /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id);
 
        /* Replay the neighbor, if BFD is enabled in OSPF */
        for (ALL_LIST_ELEMENTS(om->ospf, node, onode, ospf)) {
index 30b2a50bb38f4c57826f8577c4172130c2a387dc..ab2d5ae5844cec5584445526bfb5a768baeb76f6 100644 (file)
@@ -97,7 +97,7 @@ static void ospf_route_map_update(const char *name)
        }
 }
 
-static void ospf_route_map_event(route_map_event_t event, const char *name)
+static void ospf_route_map_event(const char *name)
 {
        struct ospf *ospf;
        int type;
index a49352086828ef72692f70d72de54638459c265d..6947393a6086b1983cfa0b3a77f7cadec4b91487 100644 (file)
@@ -86,7 +86,7 @@ static inline void del_sid_nhlfe(struct sr_nhlfe nhlfe);
  */
 
 /* Hash function for Segment Routing entry */
-static unsigned int sr_hash(void *p)
+static unsigned int sr_hash(const void *p)
 {
        const struct in_addr *rid = p;
 
index 16796e68fb6ec6c635069863288f6fbe5547a5a7..c178e367d390a032fcc37df14163950328d8ce69 100644 (file)
@@ -1565,7 +1565,7 @@ void ospf_zebra_vrf_deregister(struct ospf *ospf)
 static void ospf_zebra_connected(struct zclient *zclient)
 {
        /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
 
        zclient_send_reg_requests(zclient, VRF_DEFAULT);
 }
index 7504752725df4d601454ab2b617dc80d296d6819..52506542bc89657e2065181768556e589bac3b36 100644 (file)
@@ -129,10 +129,10 @@ static void pbr_nh_delete_iterate(struct hash_bucket *b, void *p)
        pbr_nh_delete((struct pbr_nexthop_cache **)&b->data);
 }
 
-static uint32_t pbr_nh_hash_key(void *arg)
+static uint32_t pbr_nh_hash_key(const void *arg)
 {
        uint32_t key;
-       struct pbr_nexthop_cache *pbrnc = (struct pbr_nexthop_cache *)arg;
+       const struct pbr_nexthop_cache *pbrnc = arg;
 
        key = nexthop_hash(pbrnc->nexthop);
 
@@ -789,10 +789,9 @@ void pbr_nht_nexthop_interface_update(struct interface *ifp)
                     ifp);
 }
 
-static uint32_t pbr_nhg_hash_key(void *arg)
+static uint32_t pbr_nhg_hash_key(const void *arg)
 {
-       struct pbr_nexthop_group_cache *nhgc =
-               (struct pbr_nexthop_group_cache *)arg;
+       const struct pbr_nexthop_group_cache *nhgc = arg;
 
        return jhash(&nhgc->name, strlen(nhgc->name), 0x52c34a96);
 }
@@ -940,7 +939,7 @@ void pbr_nht_init(void)
        pbr_nhg_hash = hash_create_size(
                16, pbr_nhg_hash_key, pbr_nhg_hash_equal, "PBR NHG Cache Hash");
        pbr_nhrc_hash =
-               hash_create_size(16, (unsigned int (*)(void *))nexthop_hash,
+               hash_create_size(16, (unsigned int (*)(const void *))nexthop_hash,
                                 pbr_nhrc_hash_equal, "PBR NH Hash");
 
        pbr_nhg_low_table = PBR_NHT_DEFAULT_LOW_TABLEID;
index aad0e4275fb913d1ca8d53b64e6316ed0261c8fc..466a9a13ae1ae6451148b5d8282fd0b0f20a128d 100644 (file)
@@ -349,6 +349,11 @@ void route_add(struct pbr_nexthop_group_cache *pnhgc, struct nexthop_group nhg,
                       "%s: Asked to install unsupported route type: L2VPN",
                       __PRETTY_FUNCTION__);
                break;
+       case AFI_UNSPEC:
+               DEBUGD(&pbr_dbg_zebra,
+                      "%s: Asked to install unspecified route type",
+                      __PRETTY_FUNCTION__);
+               break;
        }
 }
 
@@ -391,6 +396,11 @@ void route_delete(struct pbr_nexthop_group_cache *pnhgc, afi_t afi)
                       "%s: Asked to delete unsupported route type: L2VPN",
                       __PRETTY_FUNCTION__);
                break;
+       case AFI_UNSPEC:
+               DEBUGD(&pbr_dbg_zebra,
+                      "%s: Asked to delete unspecified route type",
+                      __PRETTY_FUNCTION__);
+               break;
        }
 }
 
index 82087c4c5635d43704b3093f99c3a07782d530b7..300261e5a996909113c0737bcde1d545d78d75bc 100644 (file)
@@ -297,7 +297,7 @@ static int pim_bfd_nbr_replay(ZAPI_CALLBACK_ARGS)
        struct vrf *vrf = NULL;
 
        /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id);
 
        RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
                FOR_ALL_INTERFACES (vrf, ifp) {
index cbc3c6a640c747b9a94731192e4b9763983f0ab5..352177db2bb44f3e44b11de347b62657a82bd33b 100644 (file)
@@ -135,9 +135,20 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
                if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
                        mask = PIM_OIF_FLAG_PROTO_IGMP;
 
-               /* SGRpt entry could have empty oil */
-               pim_channel_del_oif(ch->upstream->channel_oil, ch->interface,
-                                   mask);
+               /*
+                * A S,G RPT channel can have an empty oil, we also
+                * need to take into account the fact that a ifchannel
+                * might have been suppressing a *,G ifchannel from
+                * being inherited.  So let's figure out what
+                * needs to be done here
+                */
+               if (pim_upstream_evaluate_join_desired_interface(
+                           ch->upstream, ch, ch->parent))
+                       pim_channel_add_oif(ch->upstream->channel_oil,
+                                           ch->interface, mask);
+               else
+                       pim_channel_del_oif(ch->upstream->channel_oil,
+                                           ch->interface, mask);
                /*
                 * Do we have any S,G's that are inheriting?
                 * Nuke from on high too.
@@ -1414,9 +1425,9 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
                pim_jp_agg_single_upstream_send(&starup->rpf, starup, true);
 }
 
-unsigned int pim_ifchannel_hash_key(void *arg)
+unsigned int pim_ifchannel_hash_key(const void *arg)
 {
-       struct pim_ifchannel *ch = (struct pim_ifchannel *)arg;
+       const struct pim_ifchannel *ch = arg;
 
        return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0);
 }
index b9d4d291d854d910aeb96bd58048878b1786050d..b36c3236b0bd2f649d24c45a6ce010cf8ee764ea 100644 (file)
@@ -155,5 +155,5 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
 int pim_ifchannel_compare(const struct pim_ifchannel *ch1,
                          const struct pim_ifchannel *ch2);
 
-unsigned int pim_ifchannel_hash_key(void *arg);
+unsigned int pim_ifchannel_hash_key(const void *arg);
 #endif /* PIM_IFCHANNEL_H */
index cdd156b96fa331b428748bce2b71499a93300a16..213ca48bb502efd8b74245985c6b791a3530ea73 100644 (file)
@@ -829,9 +829,9 @@ void igmp_sock_delete_all(struct interface *ifp)
        }
 }
 
-static unsigned int igmp_group_hash_key(void *arg)
+static unsigned int igmp_group_hash_key(const void *arg)
 {
-       struct igmp_group *group = (struct igmp_group *)arg;
+       const struct igmp_group *group = arg;
 
        return jhash_1word(group->group_addr.s_addr, 0);
 }
index 395c4af35f941b93f6778f691e4e599cc3f6a096..3287e137193c3eb6083036d9ff0e109b64dc9187 100644 (file)
@@ -680,9 +680,9 @@ void pim_msdp_up_del(struct pim_instance *pim, struct prefix_sg *sg)
 }
 
 /* sa hash and peer list helpers */
-static unsigned int pim_msdp_sa_hash_key_make(void *p)
+static unsigned int pim_msdp_sa_hash_key_make(const void *p)
 {
-       struct pim_msdp_sa *sa = p;
+       const struct pim_msdp_sa *sa = p;
 
        return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0));
 }
@@ -1215,9 +1215,9 @@ enum pim_msdp_err pim_msdp_peer_del(struct pim_instance *pim,
 }
 
 /* peer hash and peer list helpers */
-static unsigned int pim_msdp_peer_hash_key_make(void *p)
+static unsigned int pim_msdp_peer_hash_key_make(const void *p)
 {
-       struct pim_msdp_peer *mp = p;
+       const struct pim_msdp_peer *mp = p;
        return (jhash_1word(mp->peer.s_addr, 0));
 }
 
index 5945bc55fd9299577ef155fb863a248e92e1ed1d..22045c2d337c99ac27aa2b60fa2a768e43959018 100644 (file)
@@ -91,9 +91,9 @@ static bool pim_oil_equal(const void *arg1, const void *arg2)
        return false;
 }
 
-static unsigned int pim_oil_hash_key(void *arg)
+static unsigned int pim_oil_hash_key(const void *arg)
 {
-       struct channel_oil *oil = (struct channel_oil *)arg;
+       const struct channel_oil *oil = arg;
 
        return jhash_2words(oil->oil.mfcc_mcastgrp.s_addr,
                            oil->oil.mfcc_origin.s_addr, 0);
index 4230c127ad31031f89ef4784ad3fd395bd847391..2de94e9031ebd4f783b4caff129bd955d1d2e217 100644 (file)
@@ -36,7 +36,7 @@ static void pim_route_map_delete(const char *rmap_name)
        route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
 }
 
-static void pim_route_map_event(route_map_event_t event, const char *rmap_name)
+static void pim_route_map_event(const char *rmap_name)
 {
        route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
 }
index afe3886aa5b98e32f7d2bdb41352f89eeadf20cc..dba46e63f03a3006cdb1d7b8adc675131a98267e 100644 (file)
@@ -426,9 +426,9 @@ int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2)
        return 0;
 }
 
-unsigned int pim_rpf_hash_key(void *arg)
+unsigned int pim_rpf_hash_key(const void *arg)
 {
-       struct pim_nexthop_cache *r = (struct pim_nexthop_cache *)arg;
+       const struct pim_nexthop_cache *r = arg;
 
        return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0);
 }
index 57bb22674fa6209b64d9935b5c70b24f86e9b2ba..1172acb4b229c6196739d859f25591af2ae8e762 100644 (file)
@@ -56,7 +56,7 @@ enum pim_rpf_result { PIM_RPF_OK = 0, PIM_RPF_CHANGED, PIM_RPF_FAILURE };
 
 struct pim_upstream;
 
-unsigned int pim_rpf_hash_key(void *arg);
+unsigned int pim_rpf_hash_key(const void *arg);
 bool pim_rpf_equal(const void *arg1, const void *arg2);
 
 bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop,
index b708e86a2050891625ab06f6a1c44e4beed6d5a7..55d998f27084bdf2e68ab7e9835c351a2fcc1dcc 100644 (file)
@@ -1181,8 +1181,16 @@ struct pim_upstream *pim_upstream_keep_alive_timer_proc(
                                "kat expired on %s[%s]; remove stream reference",
                                up->sg_str, pim->vrf->name);
                PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags);
-               up = pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
-       } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) {
+
+               /* Return if upstream entry got deleted.*/
+               if (!pim_upstream_del(pim, up, __PRETTY_FUNCTION__))
+                       return NULL;
+       }
+       /* upstream reference would have been added to track the local
+        * membership if it is LHR. We have to clear it when KAT expires.
+        * Otherwise would result in stale entry with uncleared ref count.
+        */
+       if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) {
                struct pim_upstream *parent = up->parent;
 
                PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags);
@@ -1621,9 +1629,9 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
        }
 }
 
-unsigned int pim_upstream_hash_key(void *arg)
+unsigned int pim_upstream_hash_key(const void *arg)
 {
-       struct pim_upstream *up = (struct pim_upstream *)arg;
+       const struct pim_upstream *up = arg;
 
        return jhash_2words(up->sg.src.s_addr, up->sg.grp.s_addr, 0);
 }
index 13a3dcdf8ca7472c0b26fcc5b742df64ea0e2d06..102826ac71ca84af665ad5c73e5986da4352d058 100644 (file)
@@ -308,7 +308,7 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
 void pim_upstream_spt_prefix_list_update(struct pim_instance *pim,
                                         struct prefix_list *pl);
 
-unsigned int pim_upstream_hash_key(void *arg);
+unsigned int pim_upstream_hash_key(const void *arg);
 bool pim_upstream_equal(const void *arg1, const void *arg2);
 struct pim_upstream *pim_upstream_keep_alive_timer_proc(
                struct pim_upstream *up);
index af76c6d732cbf548c77741076b81c60b4f8752a2..1c6b56568f62202fca1803966b04012f881d84da 100644 (file)
@@ -623,9 +623,9 @@ static void pim_vxlan_term_mr_del(struct pim_vxlan_sg *vxlan_sg)
 }
 
 /************************** vxlan SG cache management ************************/
-static unsigned int pim_vxlan_sg_hash_key_make(void *p)
+static unsigned int pim_vxlan_sg_hash_key_make(const void *p)
 {
-       struct pim_vxlan_sg *vxlan_sg = p;
+       const struct pim_vxlan_sg *vxlan_sg = p;
 
        return (jhash_2words(vxlan_sg->sg.src.s_addr,
                                vxlan_sg->sg.grp.s_addr, 0));
index 11d39bb84f8582b7852e9bb9f0b673d5c9782433..25ac307ac43defc1b51e27ba89d169df7da729db 100644 (file)
@@ -780,7 +780,7 @@ void sched_rpf_cache_refresh(struct pim_instance *pim)
 static void pim_zebra_connected(struct zclient *zclient)
 {
        /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, router->vrf_id);
 
        zclient_send_reg_requests(zclient, router->vrf_id);
 }
@@ -1296,8 +1296,16 @@ void pim_forward_stop(struct pim_ifchannel *ch, bool install_it)
                           install_it, up->channel_oil->installed);
        }
 
-       pim_channel_del_oif(up->channel_oil, ch->interface,
-                           PIM_OIF_FLAG_PROTO_PIM);
+       /*
+        * If a channel is being removed, check to see if we still need
+        * to inherit the interface.  If so make sure it is added in
+        */
+       if (pim_upstream_evaluate_join_desired_interface(up, ch, ch->parent))
+               pim_channel_add_oif(up->channel_oil, ch->interface,
+                                   PIM_OIF_FLAG_PROTO_PIM);
+       else
+               pim_channel_del_oif(up->channel_oil, ch->interface,
+                                   PIM_OIF_FLAG_PROTO_PIM);
 
        if (install_it && !up->channel_oil->installed)
                pim_mroute_add(up->channel_oil, __PRETTY_FUNCTION__);
index c03a371d885f4d2ef6383b355b9d7ca63c1a486a..c6da00418b4ab9408b056c07c17871ac6560f76b 100644 (file)
@@ -223,9 +223,9 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap)
        mpls_enabled = cap->mpls_enabled;
 }
 
-static unsigned int static_nht_hash_key(void *data)
+static unsigned int static_nht_hash_key(const void *data)
 {
-       struct static_nht_data *nhtd = data;
+       const struct static_nht_data *nhtd = data;
        unsigned int key = 0;
 
        key = prefix_hash_key(nhtd->nh);
index 4a89bda84eac865059ab1755ffddc96497bc9691..6f8bc2218e2f7bcca388a9f7185bcb2816223ca9 100644 (file)
Binary files a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz and b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz differ
index 19a40b21841f964ac583c9121106191a980391a2..0fca571d28b07220342e48aff13c4e016c867ef0 100644 (file)
@@ -81,9 +81,9 @@ static char *format_srcdest(const struct prefix_ipv6 *dst_p,
        return rv;
 }
 
-static unsigned int log_key(void *data)
+static unsigned int log_key(const void *data)
 {
-       struct prefix *hash_entry = data;
+       const struct prefix *hash_entry = data;
        struct prefix_ipv6 *dst_p = (struct prefix_ipv6 *)&hash_entry[0];
        struct prefix_ipv6 *src_p = (struct prefix_ipv6 *)&hash_entry[1];
        unsigned int hash = 0;
index c29ed3db6195d245a9c68cdd22d4e8c8d5960d6c..1e8f67f3f9a6d6e2749eee21c6a601497cc2a03b 100644 (file)
@@ -1,5 +1,5 @@
 r1-eth0 is up
-  ifindex 2, MTU 1500 bytes, BW XX Mbit <UP,BROADCAST,RUNNING,MULTICAST>
+  ifindex X, MTU 1500 bytes, BW XX Mbit <UP,BROADCAST,RUNNING,MULTICAST>
   Internet Address 192.168.0.1/24, Broadcast 192.168.0.255, Area 0.0.0.0
   MTU mismatch detection: enabled
   Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10
@@ -10,7 +10,7 @@ r1-eth0 is up
     Hello due in XX.XXXs
   Neighbor Count is 0, Adjacent neighbor count is 0
 r1-eth3 is up
-  ifindex 5, MTU 1500 bytes, BW XX Mbit <UP,BROADCAST,RUNNING,MULTICAST>
+  ifindex X, MTU 1500 bytes, BW XX Mbit <UP,BROADCAST,RUNNING,MULTICAST>
   Internet Address 192.168.3.1/26, Broadcast 192.168.3.63, Area 0.0.0.0
   MTU mismatch detection: enabled
   Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10
index 239de55bd6f27baf5cea9245cfc5da0945ae9ae4..9658c080c0c396a5f33ba1c34533db4943eff9ec 100755 (executable)
@@ -480,6 +480,8 @@ def test_ospfv2_interfaces():
             actual = net['r%s' % i].cmd('vtysh -c "show ip ospf interface" 2> /dev/null').rstrip()
             # Mask out Bandwidth portion. They may change..
             actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual)
+           actual = re.sub(r"ifindex [0-9]", "ifindex X", actual)
+
             # Drop time in next due 
             actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual)
             # Fix 'MTU mismatch detection: enabled' vs 'MTU mismatch detection:enabled' - accept both
diff --git a/tests/topotests/bfd-vrf-topo1/__init__.py b/tests/topotests/bfd-vrf-topo1/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bfd-vrf-topo1/r1/bfdd.conf b/tests/topotests/bfd-vrf-topo1/r1/bfdd.conf
new file mode 100644 (file)
index 0000000..3466e6a
--- /dev/null
@@ -0,0 +1,6 @@
+bfd
+ peer 192.168.0.2 vrf r1-cust1
+  echo-mode
+  no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r1/bgp_prefixes.json b/tests/topotests/bfd-vrf-topo1/r1/bgp_prefixes.json
new file mode 100644 (file)
index 0000000..4b2cc1a
--- /dev/null
@@ -0,0 +1,52 @@
+{
+  "routes": {
+    "10.254.254.2/32": [
+      {
+        "aspath": "102",
+        "prefix": "10.254.254.2",
+        "valid": true,
+        "peerId": "192.168.0.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.0.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ],
+    "10.254.254.3/32": [
+      {
+        "aspath": "102 103",
+        "prefix": "10.254.254.3",
+        "valid": true,
+        "peerId": "192.168.0.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.0.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ],
+    "10.254.254.4/32": [
+      {
+        "aspath": "102 104",
+        "prefix": "10.254.254.4",
+        "valid": true,
+        "peerId": "192.168.0.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.0.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/tests/topotests/bfd-vrf-topo1/r1/bgp_summary.json b/tests/topotests/bfd-vrf-topo1/r1/bgp_summary.json
new file mode 100644 (file)
index 0000000..fa07d60
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "ipv4Unicast": {
+    "as": 101,
+    "peers": {
+      "192.168.0.2": {
+        "remoteAs": 102,
+        "state": "Established"
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bfd-vrf-topo1/r1/bgpd.conf b/tests/topotests/bfd-vrf-topo1/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..7ad4e2b
--- /dev/null
@@ -0,0 +1,8 @@
+router bgp 101 vrf r1-cust1
+ neighbor 192.168.0.2 remote-as 102
+! neighbor 192.168.0.2 ebgp-multihop 10
+ neighbor 192.168.0.2 bfd
+ address-family ipv4 unicast
+  network 10.254.254.1/32
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r1/peers.json b/tests/topotests/bfd-vrf-topo1/r1/peers.json
new file mode 100644 (file)
index 0000000..f49768f
--- /dev/null
@@ -0,0 +1,8 @@
+[
+  {
+    "remote-receive-interval": 1000,
+    "remote-transmit-interval": 500,
+    "peer": "192.168.0.2",
+    "status": "up"
+  }
+]
diff --git a/tests/topotests/bfd-vrf-topo1/r1/zebra.conf b/tests/topotests/bfd-vrf-topo1/r1/zebra.conf
new file mode 100644 (file)
index 0000000..fcd1e7d
--- /dev/null
@@ -0,0 +1,3 @@
+interface r1-eth0 vrf r1-cust1
+ ip address 192.168.0.1/24
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r2/bfdd.conf b/tests/topotests/bfd-vrf-topo1/r2/bfdd.conf
new file mode 100644 (file)
index 0000000..3481ea8
--- /dev/null
@@ -0,0 +1,12 @@
+bfd
+ peer 192.168.0.1 vrf r2-cust1
+  receive-interval 1000
+  transmit-interval 500
+  echo-mode
+  no shutdown
+ !
+ peer 192.168.1.1 vrf r2-cust1
+  echo-mode
+  no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r2/bgp_prefixes.json b/tests/topotests/bfd-vrf-topo1/r2/bgp_prefixes.json
new file mode 100644 (file)
index 0000000..39f3c0a
--- /dev/null
@@ -0,0 +1,52 @@
+{
+  "routes": {
+    "10.254.254.1/32": [
+      {
+        "aspath": "101",
+        "prefix": "10.254.254.1",
+        "valid": true,
+        "peerId": "192.168.0.1",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.0.1",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ],
+    "10.254.254.3/32": [
+      {
+        "aspath": "103",
+        "prefix": "10.254.254.3",
+        "valid": true,
+        "peerId": "192.168.1.1",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.1.1",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ],
+    "10.254.254.4/32": [
+      {
+        "aspath": "104",
+        "prefix": "10.254.254.4",
+        "valid": true,
+        "peerId": "192.168.2.1",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.2.1",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/tests/topotests/bfd-vrf-topo1/r2/bgp_summary.json b/tests/topotests/bfd-vrf-topo1/r2/bgp_summary.json
new file mode 100644 (file)
index 0000000..c0ef11a
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "ipv4Unicast": {
+    "as": 102,
+    "peers": {
+      "192.168.0.1": {
+        "remoteAs": 101,
+        "state": "Established"
+      },
+      "192.168.1.1": {
+        "remoteAs": 103,
+        "state": "Established"
+      },
+      "192.168.2.1": {
+        "remoteAs": 104,
+        "state": "Established"
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bfd-vrf-topo1/r2/bgpd.conf b/tests/topotests/bfd-vrf-topo1/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..0715ea3
--- /dev/null
@@ -0,0 +1,11 @@
+router bgp 102 vrf r2-cust1
+ neighbor 192.168.0.1 remote-as 101
+ neighbor 192.168.0.1 bfd
+ neighbor 192.168.1.1 remote-as 103
+ neighbor 192.168.1.1 bfd
+ neighbor 192.168.2.1 remote-as 104
+ neighbor 192.168.2.1 bfd
+ address-family ipv4 unicast
+  network 10.254.254.2/32
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r2/peers.json b/tests/topotests/bfd-vrf-topo1/r2/peers.json
new file mode 100644 (file)
index 0000000..5035d64
--- /dev/null
@@ -0,0 +1,17 @@
+[
+  {
+    "peer": "192.168.0.1",
+    "status": "up"
+  },
+  {
+    "remote-echo-interval": 100,
+    "peer": "192.168.1.1",
+    "status": "up"
+  },
+  {
+    "remote-transmit-interval": 2000,
+    "remote-receive-interval": 2000,
+    "peer": "192.168.2.1",
+    "status": "up"
+  }
+]
diff --git a/tests/topotests/bfd-vrf-topo1/r2/zebra.conf b/tests/topotests/bfd-vrf-topo1/r2/zebra.conf
new file mode 100644 (file)
index 0000000..daffd19
--- /dev/null
@@ -0,0 +1,9 @@
+interface r2-eth0 vrf r2-cust1
+ ip address 192.168.0.2/24
+!
+interface r2-eth1 vrf r2-cust1
+ ip address 192.168.1.2/24
+!
+interface r2-eth2 vrf r2-cust1
+ ip address 192.168.2.2/24
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r3/bfdd.conf b/tests/topotests/bfd-vrf-topo1/r3/bfdd.conf
new file mode 100644 (file)
index 0000000..f6921b7
--- /dev/null
@@ -0,0 +1,7 @@
+bfd
+ peer 192.168.1.2 vrf r3-cust1
+  echo-interval 100
+  echo-mode
+  no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r3/bgp_prefixes.json b/tests/topotests/bfd-vrf-topo1/r3/bgp_prefixes.json
new file mode 100644 (file)
index 0000000..c92d4e0
--- /dev/null
@@ -0,0 +1,52 @@
+{
+  "routes": {
+    "10.254.254.1/32": [
+      {
+        "aspath": "102 101",
+        "prefix": "10.254.254.1",
+        "valid": true,
+        "peerId": "192.168.1.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.1.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ],
+    "10.254.254.2/32": [
+      {
+        "aspath": "102",
+        "prefix": "10.254.254.2",
+        "valid": true,
+        "peerId": "192.168.1.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.1.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ],
+    "10.254.254.4/32": [
+      {
+        "aspath": "102 104",
+        "prefix": "10.254.254.4",
+        "valid": true,
+        "peerId": "192.168.1.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.1.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/tests/topotests/bfd-vrf-topo1/r3/bgp_summary.json b/tests/topotests/bfd-vrf-topo1/r3/bgp_summary.json
new file mode 100644 (file)
index 0000000..d478333
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "ipv4Unicast": {
+    "as": 103,
+    "peers": {
+      "192.168.1.2": {
+        "remoteAs": 102,
+        "state": "Established"
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bfd-vrf-topo1/r3/bgpd.conf b/tests/topotests/bfd-vrf-topo1/r3/bgpd.conf
new file mode 100644 (file)
index 0000000..277f027
--- /dev/null
@@ -0,0 +1,7 @@
+router bgp 103 vrf r3-cust1
+ neighbor 192.168.1.2 remote-as 102
+ neighbor 192.168.1.2 bfd
+ address-family ipv4 unicast
+  network 10.254.254.3/32
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r3/peers.json b/tests/topotests/bfd-vrf-topo1/r3/peers.json
new file mode 100644 (file)
index 0000000..ef38008
--- /dev/null
@@ -0,0 +1,6 @@
+[
+  {
+    "peer": "192.168.1.2",
+    "status": "up"
+  }
+]
diff --git a/tests/topotests/bfd-vrf-topo1/r3/zebra.conf b/tests/topotests/bfd-vrf-topo1/r3/zebra.conf
new file mode 100644 (file)
index 0000000..f727c2d
--- /dev/null
@@ -0,0 +1,3 @@
+interface r3-eth0 vrf r3-cust1
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r4/bfdd.conf b/tests/topotests/bfd-vrf-topo1/r4/bfdd.conf
new file mode 100644 (file)
index 0000000..a56a3a0
--- /dev/null
@@ -0,0 +1,7 @@
+bfd
+ peer 192.168.2.2 vrf r4-cust1
+  transmit-interval 2000
+  receive-interval 2000
+  no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r4/bgp_prefixes.json b/tests/topotests/bfd-vrf-topo1/r4/bgp_prefixes.json
new file mode 100644 (file)
index 0000000..cc8510d
--- /dev/null
@@ -0,0 +1,52 @@
+{
+  "routes": {
+    "10.254.254.1/32": [
+      {
+        "aspath": "102 101",
+        "prefix": "10.254.254.1",
+        "valid": true,
+        "peerId": "192.168.2.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.2.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ],
+    "10.254.254.2/32": [
+      {
+        "aspath": "102",
+        "prefix": "10.254.254.2",
+        "valid": true,
+        "peerId": "192.168.2.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.2.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ],
+    "10.254.254.3/32": [
+      {
+        "aspath": "102 103",
+        "prefix": "10.254.254.3",
+        "valid": true,
+        "peerId": "192.168.2.2",
+        "prefixLen": 32,
+        "nexthops": [
+          {
+            "ip": "192.168.2.2",
+            "used": true,
+            "afi": "ipv4"
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/tests/topotests/bfd-vrf-topo1/r4/bgp_summary.json b/tests/topotests/bfd-vrf-topo1/r4/bgp_summary.json
new file mode 100644 (file)
index 0000000..7d81784
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "ipv4Unicast": {
+    "as": 104,
+    "peers": {
+      "192.168.2.2": {
+        "remoteAs": 102,
+        "state": "Established"
+      }
+    }
+  }
+}
diff --git a/tests/topotests/bfd-vrf-topo1/r4/bgpd.conf b/tests/topotests/bfd-vrf-topo1/r4/bgpd.conf
new file mode 100644 (file)
index 0000000..66bf285
--- /dev/null
@@ -0,0 +1,7 @@
+router bgp 104 vrf r4-cust1
+ neighbor 192.168.2.2 remote-as 102
+ neighbor 192.168.2.2 bfd
+ address-family ipv4 unicast
+  network 10.254.254.4/32
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-vrf-topo1/r4/peers.json b/tests/topotests/bfd-vrf-topo1/r4/peers.json
new file mode 100644 (file)
index 0000000..3714008
--- /dev/null
@@ -0,0 +1,6 @@
+[
+  {
+    "peer": "192.168.2.2",
+    "status": "up"
+  }
+]
diff --git a/tests/topotests/bfd-vrf-topo1/r4/zebra.conf b/tests/topotests/bfd-vrf-topo1/r4/zebra.conf
new file mode 100644 (file)
index 0000000..69770dd
--- /dev/null
@@ -0,0 +1,3 @@
+interface r4-eth0 vrf r4-cust1
+ ip address 192.168.2.1/24
+!
diff --git a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.dot b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.dot
new file mode 100644 (file)
index 0000000..c84ace2
--- /dev/null
@@ -0,0 +1,73 @@
+## Color coding:
+#########################
+##  Main FRR: #f08080  red
+##  Switches: #d0e0d0  gray
+##  RIP:      #19e3d9  Cyan
+##  RIPng:    #fcb314  dark yellow
+##  OSPFv2:   #32b835  Green
+##  OSPFv3:   #19e3d9  Cyan
+##  ISIS IPv4 #fcb314  dark yellow
+##  ISIS IPv6 #9a81ec  purple
+##  BGP IPv4  #eee3d3  beige
+##  BGP IPv6  #fdff00  yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+  label="bfd-topo1";
+
+  # Routers
+  r1 [
+    shape=doubleoctagon,
+    label="r1",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r2 [
+    shape=doubleoctagon
+    label="r2",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r3 [
+    shape=doubleoctagon
+    label="r3",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r4 [
+    shape=doubleoctagon
+    label="r4",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+
+  # Switches
+  sw1 [
+    shape=oval,
+    label="sw1\n192.168.0.0/24",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+  sw2 [
+    shape=oval,
+    label="sw2\n192.168.1.0/24",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+  sw3 [
+    shape=oval,
+    label="sw3\n192.168.2.0/24",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+
+  # Connections
+  r1 -- sw1 [label="eth0\n.1"];
+  r2 -- sw1 [label="eth0\n.2"];
+
+  r3 -- sw2 [label="eth0\n.1"];
+  r2 -- sw2 [label="eth1\n.2"];
+
+  r4 -- sw3 [label="eth0\n.1"];
+  r2 -- sw3 [label="eth2\n.2"];
+}
diff --git a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.jpg b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.jpg
new file mode 100644 (file)
index 0000000..4d6d56e
Binary files /dev/null and b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.jpg differ
diff --git a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py
new file mode 100755 (executable)
index 0000000..e293382
--- /dev/null
@@ -0,0 +1,292 @@
+#!/usr/bin/env python
+
+#
+# test_bfd_vrf_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2018 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+# Copyright (c) 2019 by 6WIND
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_bfd_vrf_topo1.py: Test the FRR/Quagga BFD daemon.
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+class BFDTopo(Topo):
+    "Test topology builder"
+    def build(self, *_args, **_opts):
+        "Build function"
+        tgen = get_topogen(self)
+
+        # Create 4 routers
+        for routern in range(1, 5):
+            tgen.add_router('r{}'.format(routern))
+
+        switch = tgen.add_switch('s1')
+        switch.add_link(tgen.gears['r1'])
+        switch.add_link(tgen.gears['r2'])
+
+        switch = tgen.add_switch('s2')
+        switch.add_link(tgen.gears['r2'])
+        switch.add_link(tgen.gears['r3'])
+
+        switch = tgen.add_switch('s3')
+        switch.add_link(tgen.gears['r2'])
+        switch.add_link(tgen.gears['r4'])
+
+
+def setup_module(mod):
+    "Sets up the pytest environment"
+    tgen = Topogen(BFDTopo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+
+    # check for zebra capability
+    for rname, router in router_list.iteritems():
+        if router.check_capability(
+                TopoRouter.RD_ZEBRA,
+                '--vrfwnetns'
+        ) == False:
+            return  pytest.skip('Skipping BFD Topo1 VRF NETNS feature. VRF NETNS backend not available on FRR')
+
+    if os.system('ip netns list') != 0:
+        return  pytest.skip('Skipping BFD Topo1 VRF NETNS Test. NETNS not available on System')
+
+    logger.info('Testing with VRF Namespace support')
+
+    cmds = ['if [ -e /var/run/netns/{0}-cust1 ] ; then ip netns del {0}-cust1 ; fi',
+            'ip netns add {0}-cust1',
+            'ip link set dev {0}-eth0 netns {0}-cust1',
+            'ip netns exec {0}-cust1 ifconfig {0}-eth0 up']
+    cmds2 = ['ip link set dev {0}-eth1 netns {0}-cust1',
+             'ip netns exec {0}-cust1 ifconfig {0}-eth1 up',
+             'ip link set dev {0}-eth2 netns {0}-cust1',
+             'ip netns exec {0}-cust1 ifconfig {0}-eth2 up']
+
+    for rname, router in router_list.iteritems():
+        # create VRF rx-cust1 and link rx-eth0 to rx-cust1
+        for cmd in cmds:
+            output = tgen.net[rname].cmd(cmd.format(rname))
+        if rname == 'r2':
+            for cmd in cmds2:
+                output = tgen.net[rname].cmd(cmd.format(rname))
+
+    for rname, router in router_list.iteritems():
+        router.load_config(
+            TopoRouter.RD_ZEBRA,
+            os.path.join(CWD, '{}/zebra.conf'.format(rname)),
+            '--vrfwnetns'
+        )
+        router.load_config(
+            TopoRouter.RD_BFD,
+            os.path.join(CWD, '{}/bfdd.conf'.format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_BGP,
+            os.path.join(CWD, '{}/bgpd.conf'.format(rname))
+        )
+
+    # Initialize all routers.
+    tgen.start_router()
+
+    # Verify that we are using the proper version and that the BFD
+    # daemon exists.
+    for router in router_list.values():
+        # Check for Version
+        if router.has_version('<', '5.1'):
+            tgen.set_error('Unsupported FRR version')
+            break
+
+def teardown_module(_mod):
+    "Teardown the pytest environment"
+    tgen = get_topogen()
+    # move back rx-eth0 to default VRF
+    # delete rx-vrf
+    cmds = ['ip netns exec {0}-cust1 ip link set {0}-eth0 netns 1',
+            'ip netns delete {0}-cust1']
+    cmds2 = ['ip netns exec {0}-cust1 ip link set {0}-eth1 netns 1',
+             'ip netns exec {0}-cust2 ip link set {0}-eth1 netns 1']
+
+    router_list = tgen.routers()
+    for rname, router in router_list.iteritems():
+        if rname == 'r2':
+            for cmd in cmds2:
+                tgen.net[rname].cmd(cmd.format(rname))
+        for cmd in cmds:
+            tgen.net[rname].cmd(cmd.format(rname))
+    tgen.stop_topology()
+
+def test_bfd_connection():
+    "Assert that the BFD peers can find themselves."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info('waiting for bfd peers to go up')
+    for router in tgen.routers().values():
+        json_file = '{}/{}/peers.json'.format(CWD, router.name)
+        expected = json.loads(open(json_file).read())
+
+        test_func = partial(topotest.router_json_cmp,
+            router, 'show bfd peers json', expected)
+        _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
+        assertmsg = '"{}" JSON output mismatches'.format(router.name)
+        assert result is None, assertmsg
+
+
+def test_bgp_convergence():
+    "Assert that BGP is converging."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info('waiting for bgp peers to go up')
+
+    for router in tgen.routers().values():
+        ref_file = '{}/{}/bgp_summary.json'.format(CWD, router.name)
+        expected = json.loads(open(ref_file).read())
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show ip bgp vrf {}-cust1 summary json'.format(router.name), expected)
+        _, res = topotest.run_and_expect(test_func, None, count=125, wait=1.0)
+        assertmsg = '{}: bgp did not converge'.format(router.name)
+        assert res is None, assertmsg
+
+
+def test_bgp_fast_convergence():
+    "Assert that BGP is converging before setting a link down."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info('waiting for bgp peers converge')
+
+    for router in tgen.routers().values():
+        ref_file = '{}/{}/bgp_prefixes.json'.format(CWD, router.name)
+        expected = json.loads(open(ref_file).read())
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show ip bgp vrf {}-cust1 json'.format(router.name), expected)
+        _, res = topotest.run_and_expect(test_func, None, count=40, wait=0.5)
+        assertmsg = '{}: bgp did not converge'.format(router.name)
+        assert res is None, assertmsg
+
+
+def test_bfd_fast_convergence():
+    """
+    Assert that BFD notices the link down after simulating network
+    failure.
+    """
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    # Disable r2-eth0 link
+    router2 = tgen.gears['r2']
+    topotest.interface_set_status(router2, 'r2-eth0', ifaceaction=False, vrf_name='r2-cust1')
+
+    # Wait the minimum time we can before checking that BGP/BFD
+    # converged.
+    logger.info('waiting for BFD converge')
+
+    # Check that BGP converged quickly.
+    for router in tgen.routers().values():
+        json_file = '{}/{}/peers.json'.format(CWD, router.name)
+        expected = json.loads(open(json_file).read())
+
+        # Load the same file as previous test, but expect R1 to be down.
+        if router.name == 'r1':
+            for peer in expected:
+                if peer['peer'] == '192.168.0.2':
+                    peer['status'] = 'down'
+        else:
+            for peer in expected:
+                if peer['peer'] == '192.168.0.1':
+                    peer['status'] = 'down'
+
+        test_func = partial(topotest.router_json_cmp,
+            router, 'show bfd peers json', expected)
+        _, res = topotest.run_and_expect(test_func, None, count=20, wait=0.5)
+        assertmsg = '"{}" JSON output mismatches'.format(router.name)
+        assert res is None, assertmsg
+
+
+def test_bgp_fast_reconvergence():
+    "Assert that BGP is converging after setting a link down."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info('waiting for BGP re convergence')
+
+    # Check that BGP converged quickly.
+    for router in tgen.routers().values():
+        ref_file = '{}/{}/bgp_prefixes.json'.format(CWD, router.name)
+        expected = json.loads(open(ref_file).read())
+
+        # Load the same file as previous test, but set networks to None
+        # to test absence.
+        if router.name == 'r1':
+            expected['routes']['10.254.254.2/32'] = None
+            expected['routes']['10.254.254.3/32'] = None
+            expected['routes']['10.254.254.4/32'] = None
+        else:
+            expected['routes']['10.254.254.1/32'] = None
+
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show ip bgp vrf {}-cust1 json'.format(router.name), expected)
+        _, res = topotest.run_and_expect(
+            test_func,
+            None,
+            count=3,
+            wait=1
+        )
+        assertmsg = '{}: bgp did not converge'.format(router.name)
+        assert res is None, assertmsg
+
+
+def test_memory_leak():
+    "Run the memory leak test and report results."
+    tgen = get_topogen()
+    if not tgen.is_memleak_enabled():
+        pytest.skip('Memory leak test/report is disabled')
+
+    tgen.report_memory_leaks()
+
+
+if __name__ == '__main__':
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_ebgp_requires_policy/__init__.py b/tests/topotests/bgp_ebgp_requires_policy/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp_ebgp_requires_policy/r1/bgpd.conf b/tests/topotests/bgp_ebgp_requires_policy/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..e06fa08
--- /dev/null
@@ -0,0 +1,12 @@
+router bgp 65000
+  bgp ebgp-requires-policy
+  neighbor 192.168.255.2 remote-as 1000
+  neighbor 192.168.255.2 local-as 500
+  address-family ipv4 unicast
+    redistribute connected
+    neighbor 192.168.255.2 route-map outgoing out
+!
+ip prefix-list peer-out permit 172.16.255.254/32
+route-map outgoing permit 10
+  match ip address prefix-list peer-out
+!
diff --git a/tests/topotests/bgp_ebgp_requires_policy/r1/zebra.conf b/tests/topotests/bgp_ebgp_requires_policy/r1/zebra.conf
new file mode 100644 (file)
index 0000000..0a283c0
--- /dev/null
@@ -0,0 +1,9 @@
+!
+interface lo
+ ip address 172.16.255.254/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_ebgp_requires_policy/r2/bgpd.conf b/tests/topotests/bgp_ebgp_requires_policy/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..0549697
--- /dev/null
@@ -0,0 +1,2 @@
+router bgp 1000
+  neighbor 192.168.255.1 remote-as 500
diff --git a/tests/topotests/bgp_ebgp_requires_policy/r2/zebra.conf b/tests/topotests/bgp_ebgp_requires_policy/r2/zebra.conf
new file mode 100644 (file)
index 0000000..606c17b
--- /dev/null
@@ -0,0 +1,6 @@
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_ebgp_requires_policy/r3/bgpd.conf b/tests/topotests/bgp_ebgp_requires_policy/r3/bgpd.conf
new file mode 100644 (file)
index 0000000..b4e304d
--- /dev/null
@@ -0,0 +1,6 @@
+router bgp 65000
+  bgp ebgp-requires-policy
+  neighbor 192.168.255.2 remote-as 1000
+  neighbor 192.168.255.2 local-as 500
+  address-family ipv4 unicast
+    redistribute connected
diff --git a/tests/topotests/bgp_ebgp_requires_policy/r3/zebra.conf b/tests/topotests/bgp_ebgp_requires_policy/r3/zebra.conf
new file mode 100644 (file)
index 0000000..39499a1
--- /dev/null
@@ -0,0 +1,9 @@
+!
+interface lo
+ ip address 172.16.255.254/32
+!
+interface r3-eth0
+ ip address 192.168.255.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_ebgp_requires_policy/r4/bgpd.conf b/tests/topotests/bgp_ebgp_requires_policy/r4/bgpd.conf
new file mode 100644 (file)
index 0000000..0549697
--- /dev/null
@@ -0,0 +1,2 @@
+router bgp 1000
+  neighbor 192.168.255.1 remote-as 500
diff --git a/tests/topotests/bgp_ebgp_requires_policy/r4/zebra.conf b/tests/topotests/bgp_ebgp_requires_policy/r4/zebra.conf
new file mode 100644 (file)
index 0000000..b859115
--- /dev/null
@@ -0,0 +1,6 @@
+!
+interface r4-eth0
+ ip address 192.168.255.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_ebgp_requires_policy/test_bgp_ebgp_requires_policy.py b/tests/topotests/bgp_ebgp_requires_policy/test_bgp_ebgp_requires_policy.py
new file mode 100644 (file)
index 0000000..eecacfd
--- /dev/null
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+
+#
+# bgp_ebgp_requires_policy.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+bgp_ebgp_requires_policy.py:
+
+Test if eBGP sender without a filter applied to the peer is allowed
+to send advertisements.
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+class TemplateTopo(Topo):
+    def build(self, *_args, **_opts):
+        tgen = get_topogen(self)
+
+        for routern in range(1, 5):
+            tgen.add_router('r{}'.format(routern))
+
+        switch = tgen.add_switch('s1')
+        switch.add_link(tgen.gears['r1'])
+        switch.add_link(tgen.gears['r2'])
+
+        switch = tgen.add_switch('s2')
+        switch.add_link(tgen.gears['r3'])
+        switch.add_link(tgen.gears['r4'])
+
+def setup_module(mod):
+    tgen = Topogen(TemplateTopo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+
+    for i, (rname, router) in enumerate(router_list.iteritems(), 1):
+        router.load_config(
+            TopoRouter.RD_ZEBRA,
+            os.path.join(CWD, '{}/zebra.conf'.format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_BGP,
+            os.path.join(CWD, '{}/bgpd.conf'.format(rname))
+        )
+
+    tgen.start_router()
+
+def teardown_module(mod):
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+def test_bgp_remove_private_as():
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    def _bgp_converge(router):
+        while True:
+            cmd = "show ip bgp neighbor 192.168.255.1 json"
+            output = json.loads(tgen.gears[router].vtysh_cmd(cmd))
+            if output['192.168.255.1']['bgpState'] == 'Established':
+                time.sleep(3)
+                return True
+
+    def _bgp_ebgp_requires_policy(router):
+        cmd = "show ip bgp 172.16.255.254/32 json"
+        output = json.loads(tgen.gears[router].vtysh_cmd(cmd))
+        if 'prefix' in output:
+            return True
+        return False
+
+    if _bgp_converge('r2'):
+        assert _bgp_ebgp_requires_policy('r2') == True
+
+    if _bgp_converge('r4'):
+        assert _bgp_ebgp_requires_policy('r4') == False
+
+if __name__ == '__main__':
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
index 4bd0f95f2c813bc2d3ff8112aef20072c9497b17..a38fb1e9a1766012bfb3fec44236068e65a02d81 100644 (file)
@@ -15,6 +15,7 @@ router bgp 5227
      network 99.0.0.1/32
      network 5.1.0.0/24 route-map rm-nh
      network 5.1.1.0/24 route-map rm-nh
+     redistribute sharp route-map sharp-nh
      neighbor 192.168.1.1 activate
  exit-address-family
 !
@@ -29,6 +30,15 @@ route-map rm-nh permit 10
  set extcommunity rt 89:123
  set community 0:67
 !
+route-map sharp-nh permit 10
+ match ip address al-any
+ set ip next-hop 99.0.0.1
+ set local-preference 200
+ set metric 200
+ set large-community 90:12:34
+ set extcommunity rt 80:987
+ set community 0:65
+!
 
 end
    
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/sharpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/sharpd.conf
new file mode 100644 (file)
index 0000000..e69de29
index 2115f08741392ae615280bed7df3da689753b921..3aeb9f9c9f591db4b1ba76b0a6276eff57cc1b01 100644 (file)
@@ -15,6 +15,7 @@ router bgp 5227
      network 99.0.0.2/32
      network 5.1.0.0/24 route-map rm-nh
      network 5.1.1.0/24 route-map rm-nh
+     redistribute sharp route-map sharp-nh
      neighbor 192.168.1.1 activate
  exit-address-family
 !
@@ -29,6 +30,15 @@ route-map rm-nh permit 10
  set extcommunity rt 89:123
  set community 0:67
 !
+route-map sharp-nh permit 10
+ match ip address al-any
+ set ip next-hop 99.0.0.2
+ set local-preference 200
+ set metric 200
+ set large-community 78:90:12
+ set extcommunity rt 70:456
+ set community 0:66
+!
 
 end
    
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/sharpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/sharpd.conf
new file mode 100644 (file)
index 0000000..e69de29
index 200461255710b049a1446252c917e6720d93164e..c4b6ac9bb4575c3579aa236776ce5d3878ba9884 100644 (file)
@@ -7,7 +7,7 @@ log monitor notifications
 log commands
 log file bgpd.log
 
-debug bgp vpn label
+#debug bgp vpn label
 router bgp 5226
    bgp router-id 3.3.3.3
    bgp cluster-id 3.3.3.3
index b2df5990ce3116175844e7b934c4b5c6469745ea..6295406e69e35ffb5b95692df89430d4378f8192 100644 (file)
@@ -7,9 +7,9 @@ log monitor notifications
 log commands
 log file bgpd.log debug
 
-debug bgp vpn label
-debug bgp nht
-debug bgp zebra
+#debug bgp vpn label
+#debug bgp nht
+#debug bgp zebra
 
 router bgp 5226
    bgp router-id 4.4.4.4
index f5d73a8c490ef41ee394aa6fccd355dd84b84461..149a420a320a33882bcd2526848746df2fcdfea6 100644 (file)
@@ -1,5 +1,6 @@
 from lutil import luCommand
 from customize import l3mdev_accept
+
 l3mdev_rtrs = ['r1', 'r3', 'r4', 'ce4']
 for rtr in l3mdev_rtrs:
     luCommand(rtr,'sysctl net.ipv4.tcp_l3mdev_accept',' = \d*','none','')
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py
new file mode 100644 (file)
index 0000000..897fc48
--- /dev/null
@@ -0,0 +1,20 @@
+from lutil import luCommand
+ret = luCommand('ce1', 'vtysh -c "show ip route" | grep -c \\ 10\\.\\*/32','(.*)','pass', 'Looking for sharp routes')
+found = luLast()
+if ret != False and found != None:
+    num = int(found.group())
+    luCommand('ce3', 'vtysh -c "show bgp sum"',
+             '.', 'pass', 'See %s sharp routes' % num)
+    if num > 0:
+        wait = num/500
+        luCommand('ce1', 'vtysh -c "sharp remove routes 10.0.0.0 {}"'.format(num),'.','none','Removing {} routes'.format(num))
+        luCommand('ce2', 'vtysh -c "sharp remove routes 10.0.0.0 {}"'.format(num),'.','none','Removing {} routes'.format(num))
+        rtrs = ['ce1', 'ce2', 'ce3']
+        for rtr in rtrs:
+            luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep -c 10\\.\\*/32','^0$', 'wait', 'BGP routes removed', wait)
+        for rtr in rtrs:
+            luCommand(rtr, 'ip route show | grep -c \\^10\\.','^0$', 'wait', 'Linux routes removed', wait)
+        rtrs = ['r1', 'r3', 'r4']
+        for rtr in rtrs:
+            luCommand(rtr, 'ip route show vrf {}-cust1 | grep -c \\^10\\.'.format(rtr),'^0$','wait','VRF route removed',wait)
+#done
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
new file mode 100644 (file)
index 0000000..3b3aac5
--- /dev/null
@@ -0,0 +1,66 @@
+from lutil import luCommand
+num = 50000
+b = int(num/(256*256))
+if b > 0:
+    r = num - b * (256*256)
+else:
+    r = num
+c = int(r/256)
+if c > 0:
+    d = r - c * 256 - 1 
+else:
+    d = r
+wait = num/1000
+mem = {}
+rtrs = ['ce1', 'ce2', 'ce3', 'r1', 'r2', 'r3', 'r4']
+for rtr in rtrs:
+    mem[rtr] = {'value': 0, 'units': 'unknown'}
+    ret = luCommand(rtr, 'vtysh -c "show memory"', 'bgpd: System allocator statistics:   Total heap allocated: *(\d*) ([A-Za-z]*)', 'none', 'collect bgpd memory stats')
+    found = luLast()
+    if ret != False and found != None:
+        mem[rtr] = {'value': int(found.group(1)), 'units': found.group(2)}
+
+luCommand('ce1', 'vtysh -c "sharp data nexthop"', 'sharpd is not running', 'none','check if sharpd running')
+doSharp = True
+found = luLast()
+if ret != False and found != None:
+    if len(found.group()):
+        luCommand('ce1', 'vtysh -c "sharp data nexthop"', 'sharpd is not running', 'pass','sharpd NOT running, skipping test')
+        doSharp = False
+
+if doSharp == True:
+    luCommand('ce1', 'vtysh -c "sharp install routes 10.0.0.0 nexthop 99.0.0.1 {}"'.format(num),'','pass','Adding {} routes'.format(num))
+    luCommand('ce2', 'vtysh -c "sharp install routes 10.0.0.0 nexthop 99.0.0.2 {}"'.format(num),'','pass','Adding {} routes'.format(num))
+    rtrs = ['ce1', 'ce2', 'ce3']
+    for rtr in rtrs:
+        luCommand(rtr, 'vtysh -c "show bgp ipv4 uni 10.{}.{}.{}"'.format(b,c,d), 'Last update:', 'wait', 'RXed last route, 10.{}.{}.{}'.format(b,c,d), wait)
+        luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep -c 10\\.\\*/32', str(num), 'wait', 'See all sharp routes in BGP', wait)
+    luCommand('r1', 'vtysh -c "show bgp vrf r1-cust1 ipv4 uni 10.{}.{}.{}"'.format(b,c,d),'99.0.0.1','wait','RXed -> 10.{}.{}.{} from CE1'.format(b,c,d), wait)
+    luCommand('r3', 'vtysh -c "show bgp vrf r3-cust1 ipv4 uni 10.{}.{}.{}"'.format(b,c,d),'99.0.0.2','wait','RXed -> 10.{}.{}.{} from CE2'.format(b,c,d), wait)
+    luCommand('r1', 'vtysh -c "show bgp  ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'99.0.0.1','wait','see VPN safi -> 10.{}.{}.{} from CE1'.format(b,c,d))
+    luCommand('r3', 'vtysh -c "show bgp  ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'99.0.0.2','wait','see VPN safi -> 10.{}.{}.{} from CE2'.format(b,c,d))
+    luCommand('r3', 'vtysh -c "show bgp  ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'1.1.1.1','wait','see VPN safi -> 10.{}.{}.{} from CE1'.format(b,c,d))
+    luCommand('r1', 'vtysh -c "show bgp  ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'3.3.3.3','wait','see VPN safi -> 10.{}.{}.{} from CE2'.format(b,c,d))
+    luCommand('r4', 'vtysh -c "show bgp  ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'1.1.1.1','wait','see VPN safi -> 10.{}.{}.{} from CE1'.format(b,c,d))
+    luCommand('r4', 'vtysh -c "show bgp  ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'3.3.3.3','wait','see VPN safi -> 10.{}.{}.{} from CE2'.format(b,c,d))
+    rtrs = ['ce1', 'ce2', 'ce3']
+    for rtr in rtrs:
+        luCommand(rtr, 'ip route get 10.{}.{}.{}'.format(b,c,d),'dev','wait','Route to 10.{}.{}.{} available'.format(b,c,d), wait)
+        luCommand(rtr, 'ip route show | grep -c \\^10\\.', str(num), 'wait', 'See {} linux routes'.format(num), wait)
+
+    rtrs = ['r1', 'r3', 'r4']
+    for rtr in rtrs:
+        luCommand(rtr, 'ip route get vrf {}-cust1 10.{}.{}.{}'.format(rtr,b,c,d),'dev','wait','VRF route available',wait)
+        luCommand(rtr, 'ip route show vrf {}-cust1 | grep -c \\^10\\.'.format(rtr), str(num), 'wait','See {} linux routes'.format(num), wait)
+    rtrs = ['ce1', 'ce2', 'ce3', 'r1', 'r2', 'r3', 'r4']
+    for rtr in rtrs:
+        ret = luCommand(rtr, 'vtysh -c "show memory"', 'bgpd: System allocator statistics:   Total heap allocated: *(\d*) ([A-Za-z]*)', 'none', 'collect bgpd memory stats')
+        found = luLast()
+        if ret != False and found != None:
+            val = int(found.group(1))
+            if mem[rtr]['units'] != found.group(2):
+                val *= 1000
+            delta = val - int(mem[rtr]['value'])
+            ave = float(delta)/float(num)
+            luCommand(rtr, 'vtysh -c "show thread cpu"', '.', 'pass', 'BGPd heap: {0} {1} --> {2} {3} ({4} {1}/route)'.format(mem[rtr]['value'], mem[rtr]['units'], found.group(1), found.group(2), round(ave,4)))
+#done
index 1da1066f0e1c6ea433349b11bb585792eccdda89..2dad5e7687a06daae1f960968ed5189202f5abd2 100755 (executable)
@@ -75,6 +75,24 @@ def test_check_linux_mpls():
     #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True, iproute2=\'4.9\')'
     ltemplateTest('scripts/check_linux_mpls.py', False, CliOnFail, CheckFunc)
 
+def test_check_scale_up():
+    CliOnFail = None
+    # For debugging, uncomment the next line
+    #CliOnFail = 'tgen.mininet_cli'
+    CheckFunc = 'ltemplateVersionCheck(\'4.1\', iproute2=\'4.9\')'
+    #uncomment next line to start cli *before* script is run
+    #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True, iproute2=\'4.9\')'
+    ltemplateTest('scripts/scale_up.py', False, CliOnFail, CheckFunc)
+
+def test_check_scale_down():
+    CliOnFail = None
+    # For debugging, uncomment the next line
+    #CliOnFail = 'tgen.mininet_cli'
+    CheckFunc = 'ltemplateVersionCheck(\'4.1\', iproute2=\'4.9\')'
+    #uncomment next line to start cli *before* script is run
+    #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True, iproute2=\'4.9\')'
+    ltemplateTest('scripts/scale_down.py', False, CliOnFail, CheckFunc)
+
 def SKIP_test_cleanup_all():
     CliOnFail = None
     # For debugging, uncomment the next line
index 31eaec700978df0e4cc6fda9349a5af0808e0fcf..1d12d11a2670c3765abf86c9eac736a361a53321 100644 (file)
@@ -83,22 +83,15 @@ class LTemplate():
 
         # For all registred routers, load the zebra configuration file
         for rname, router in router_list.iteritems():
-            print("Setting up %s" % rname)
-            config = os.path.join(self.testdir, '{}/zebra.conf'.format(rname))
-            if os.path.exists(config):
-                router.load_config(TopoRouter.RD_ZEBRA, config)
-            config = os.path.join(self.testdir, '{}/ospfd.conf'.format(rname))
-            if os.path.exists(config):
-                router.load_config(TopoRouter.RD_OSPF, config)
-            config = os.path.join(self.testdir, '{}/ldpd.conf'.format(rname))
-            if os.path.exists(config):
-                router.load_config(TopoRouter.RD_LDP, config)
-            config = os.path.join(self.testdir, '{}/bgpd.conf'.format(rname))
-            if os.path.exists(config):
-                router.load_config(TopoRouter.RD_BGP, config)
-            config = os.path.join(self.testdir, '{}/isisd.conf'.format(rname))
-            if os.path.exists(config):
-                router.load_config(TopoRouter.RD_ISIS, config)
+            logger.info("Setting up %s" % rname)
+            for rd_val in TopoRouter.RD:
+                config = os.path.join(self.testdir, '{}/{}.conf'.format(rname,TopoRouter.RD[rd_val]))
+                prog = os.path.join(tgen.net[rname].daemondir, TopoRouter.RD[rd_val])
+                if os.path.exists(config):
+                    if os.path.exists(prog):
+                        router.load_config(rd_val, config)
+                    else:
+                        logger.warning("{} not found, but have {}.conf file".format(prog, TopoRouter.RD[rd_val]))
 
         # After loading the configurations, this function loads configured daemons.
         logger.info('Starting routers')
index 0bc1596eb24234e77e609885fdc747e704b80300..d7145c3be0ffb25c4a60943c08847f5d2e9f3953 100644 (file)
@@ -540,6 +540,7 @@ class TopoRouter(TopoGear):
     RD_NHRP = 11
     RD_STATIC = 12
     RD_BFD = 13
+    RD_SHARP = 14
     RD = {
         RD_ZEBRA: 'zebra',
         RD_RIP: 'ripd',
@@ -554,6 +555,7 @@ class TopoRouter(TopoGear):
         RD_NHRP: 'nhrpd',
         RD_STATIC: 'staticd',
         RD_BFD: 'bfdd',
+        RD_SHARP: 'sharpd',
     }
 
     def __init__(self, tgen, cls, name, **params):
index 77e6e9a3301fc79e0d53d62f0b6862f100b94539..1b48d10a09a0cab9b810a5c2017f9ef26730d28f 100755 (executable)
@@ -6347,6 +6347,35 @@ sub process {
                             "Please, only use 32 bit atomics.\n" . $herecurr);
                }
 
+# check for use of strcpy()
+               if ($line =~ /\bstrcpy\s*\(.*\)/) {
+                       ERROR("STRCPY",
+                             "strcpy() is error-prone; please use strlcpy()"  . $herecurr);
+               }
+
+# check for use of strncpy()
+               if ($line =~ /\bstrncpy\s*\(.*\)/) {
+                       WARN("STRNCPY",
+                            "strncpy() is error-prone; please use strlcpy() if possible, or memcpy()"  . $herecurr);
+               }
+
+# check for use of strcat()
+               if ($line =~ /\bstrcat\s*\(.*\)/) {
+                       ERROR("STRCAT",
+                             "strcat() is error-prone; please use strlcat() if possible"  . $herecurr);
+               }
+
+# check for use of strncat()
+               if ($line =~ /\bstrncat\s*\(.*\)/) {
+                       WARN("STRNCAT",
+                            "strncat() is error-prone; please use strlcat() if possible"  . $herecurr);
+               }
+
+# check for use of bzero()
+               if ($line =~ /\bbzero\s*\(.*\)/) {
+                       ERROR("BZERO",
+                             "bzero() is deprecated; use memset()"  . $herecurr);
+               }
        }
 
        # If we have no input at all, then there is nothing to report on
diff --git a/tools/coccinelle/hash_const.cocci b/tools/coccinelle/hash_const.cocci
new file mode 100644 (file)
index 0000000..9c53cb0
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Transition hash key signatures to take their argument as const.
+// Does not handle headers or weirdly named hash functions.
+//
+@noconst disable optional_qualifier@
+identifier A;
+identifier func =~ ".*key$|.*key_make$|.*hash_make$|.*hash_keymake$|.*hash_key$|.*hash_key.*";
+@@
+
+- func (void *A)
++ func (const void *A)
+  { ... }
+
+@ depends on noconst disable optional_qualifier @
+identifier noconst.A;
+identifier noconst.func;
+identifier b;
+type T;
+@@
+
+func( ... ) {
+<...
+-  T b = A;
++  const T b = A;
+...>
+  }
+
+@ depends on noconst disable optional_qualifier @
+identifier noconst.A;
+identifier noconst.func;
+identifier b;
+type T;
+@@
+
+func(...)
+  {
+<...
+-  T b = (T) A;
++  const T b = A;
+...>
+  }
+
+@ depends on noconst disable optional_qualifier @
+identifier noconst.A;
+identifier noconst.func;
+identifier b;
+type T;
+@@
+
+func(...)
+  {
+<...
+-  T b;
++  const T b;
+...
+   b = A;
+...>
+  }
+
+@ depends on noconst disable optional_qualifier @
+identifier noconst.A;
+identifier noconst.func;
+identifier b;
+type T;
+@@
+
+func(...)
+  {
+<...
+-  T b;
++  const T b;
+...
+-  b = (T) A;
++  b = A;
+...>
+  }
index 332fd248caf5312c6fc865b1efabf34fb6a15286..4dc34d10efb7d39709c70e33a034fd3f5a053a70 100755 (executable)
@@ -40,7 +40,7 @@ sub scan_file {
 
     $cppadd = $fabricd ? "-DFABRICD=1" : "";
 
-    open (FH, "@CPP@ -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @CPPFLAGS@ $cppadd $file |");
+    open (FH, "@CPP@ -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -Ivtysh/@top_builddir@ -Ivtysh/@top_srcdir@ -Ivtysh/@top_srcdir@/lib -Ivtysh/@top_builddir@/lib -Ivtysh/@top_srcdir@/bgpd -Ivtysh/@top_srcdir@/bgpd/rfapi @LUA_INCLUDE@ @CPPFLAGS@ $cppadd $file |");
     local $/; undef $/;
     $line = <FH>;
     close (FH);
index eff1e996ed144a95f69151e1dff2e82e71b6bdc1..24effa70472460f9ac90225471d7bfebf503c743 100644 (file)
@@ -502,7 +502,7 @@ static int vtysh_execute_func(const char *line, int pager)
                        vtysh_execute("exit");
                } else if (tried) {
                        vtysh_execute("end");
-                       vtysh_execute("configure terminal");
+                       vtysh_execute("configure");
                }
        }
        /*
@@ -540,7 +540,7 @@ static int vtysh_execute_func(const char *line, int pager)
                if (pager && strncmp(line, "exit", 4))
                        vty_open_pager(vty);
 
-               if (!strcmp(cmd->string, "configure terminal")) {
+               if (!strcmp(cmd->string, "configure")) {
                        for (i = 0; i < array_size(vtysh_client); i++) {
                                cmd_stat = vtysh_client_execute(
                                        &vtysh_client[i], line);
@@ -674,7 +674,7 @@ int vtysh_mark_file(const char *filename)
        vty->node = CONFIG_NODE;
 
        vtysh_execute_no_pager("enable");
-       vtysh_execute_no_pager("configure terminal");
+       vtysh_execute_no_pager("configure");
        vty_buf_copy = XCALLOC(MTYPE_VTYSH_CMD, VTY_BUFSIZ);
 
        while (fgets(vty->buf, VTY_BUFSIZ, confp)) {
@@ -1744,7 +1744,7 @@ DEFUNSH(VTYSH_REALLYALL, vtysh_disable, vtysh_disable_cmd, "disable",
 }
 
 DEFUNSH(VTYSH_REALLYALL, vtysh_config_terminal, vtysh_config_terminal_cmd,
-       "configure terminal",
+       "configure [terminal]",
        "Configuration from vty interface\n"
        "Configuration terminal\n")
 {
@@ -1786,7 +1786,7 @@ static int vtysh_exit(struct vty *vty)
        case BFD_NODE:
        case RPKI_NODE:
                vtysh_execute("end");
-               vtysh_execute("configure terminal");
+               vtysh_execute("configure");
                vty->node = CONFIG_NODE;
                break;
        case BGP_VPNV4_NODE:
index 184e798bd070f1484804082a8df794dc14d46774..cff5e069337e4c81ad85e5fdecf059a8dc92f377 100644 (file)
@@ -119,8 +119,6 @@ struct zebra_privs_t zserv_privs = {
        .cap_num_p = array_size(_caps_p),
        .cap_num_i = 0};
 
-unsigned int multipath_num = MULTIPATH_NUM;
-
 /* SIGHUP handler. */
 static void sighup(void)
 {
@@ -322,9 +320,9 @@ int main(int argc, char **argv)
                        keep_kernel_mode = 1;
                        break;
                case 'e':
-                       multipath_num = atoi(optarg);
-                       if (multipath_num > MULTIPATH_NUM
-                           || multipath_num <= 0) {
+                       zrouter.multipath_num = atoi(optarg);
+                       if (zrouter.multipath_num > MULTIPATH_NUM
+                           || zrouter.multipath_num <= 0) {
                                flog_err(
                                        EC_ZEBRA_BAD_MULTIPATH_NUM,
                                        "Multipath Number specified must be less than %d and greater than 0",
index d2bebb0e29674740c5911308bc06cce84a8733e7..f3155deb146cfdccb3f905a9be708cae37bf538e 100644 (file)
@@ -614,7 +614,7 @@ int zebra_add_import_table_entry(struct route_node *rn, struct route_entry *re,
        newre->mtu = re->mtu;
        newre->table = 0;
        newre->nexthop_num = 0;
-       newre->uptime = time(NULL);
+       newre->uptime = monotime(NULL);
        newre->instance = re->table;
        route_entry_copy_nexthops(newre, re->ng.nexthop);
 
index e26831e1a6427b7d4e2dda7f625aff06aa735d37..c39abaffccdc0a4b6188848c4fd7c3771a5cd680 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "zebra.h"
 #include "hook.h"
+#include "typesafe.h"
 #include "linklist.h"
 #include "prefix.h"
 #include "table.h"
 extern "C" {
 #endif
 
+typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t;
+
+PREDECL_LIST(rnh_list)
+
+/* Nexthop structure. */
+struct rnh {
+       uint8_t flags;
+
+#define ZEBRA_NHT_CONNECTED     0x1
+#define ZEBRA_NHT_DELETED       0x2
+#define ZEBRA_NHT_EXACT_MATCH   0x4
+
+       /* VRF identifier. */
+       vrf_id_t vrf_id;
+
+       afi_t afi;
+
+       rnh_type_t type;
+
+       uint32_t seqno;
+
+       struct route_entry *state;
+       struct prefix resolved_route;
+       struct list *client_list;
+
+       /* pseudowires dependent on this nh */
+       struct list *zebra_pseudowire_list;
+
+       struct route_node *node;
+
+       /*
+        * if this has been filtered for the client
+        */
+       int filtered[ZEBRA_ROUTE_MAX];
+
+       struct rnh_list_item rnh_list_item;
+};
+
 #define DISTANCE_INFINITY  255
 #define ZEBRA_KERNEL_TABLE_MAX 252 /* support for no more than this rt tables */
 
+PREDECL_LIST(re_list)
+
 struct route_entry {
        /* Link list. */
-       struct route_entry *next;
-       struct route_entry *prev;
+       struct re_list_item next;
 
        /* Nexthop structure */
        struct nexthop_group ng;
@@ -108,6 +148,10 @@ struct route_entry {
        uint32_t dplane_sequence;
 };
 
+#define RIB_SYSTEM_ROUTE(R) RSYSTEM_ROUTE((R)->type)
+
+#define RIB_KERNEL_ROUTE(R) RKERNEL_ROUTE((R)->type)
+
 /* meta-queue structure:
  * sub-queue 0: connected, kernel
  * sub-queue 1: static
@@ -135,7 +179,7 @@ typedef struct rib_dest_t_ {
        /*
         * Doubly-linked list of routes for this prefix.
         */
-       struct route_entry *routes;
+       struct re_list_head routes;
 
        struct route_entry *selected_fib;
 
@@ -151,7 +195,7 @@ typedef struct rib_dest_t_ {
         * the data plane we will run evaluate_rnh
         * on these prefixes.
         */
-       struct list *nht;
+       struct rnh_list_head nht;
 
        /*
         * Linkage to put dest on the FPM processing queue.
@@ -160,6 +204,9 @@ typedef struct rib_dest_t_ {
 
 } rib_dest_t;
 
+DECLARE_LIST(rnh_list, struct rnh, rnh_list_item);
+DECLARE_LIST(re_list, struct route_entry, next);
+
 #define RIB_ROUTE_QUEUED(x)    (1 << (x))
 // If MQ_SIZE is modified this value needs to be updated.
 #define RIB_ROUTE_ANY_QUEUED    0x1F
@@ -187,14 +234,16 @@ typedef struct rib_dest_t_ {
  * Macro to iterate over each route for a destination (prefix).
  */
 #define RE_DEST_FOREACH_ROUTE(dest, re)                                        \
-       for ((re) = (dest) ? (dest)->routes : NULL; (re); (re) = (re)->next)
+       for ((re) = (dest) ? re_list_first(&((dest)->routes)) : NULL; (re);    \
+            (re) = re_list_next(&((dest)->routes), (re)))
 
 /*
  * Same as above, but allows the current node to be unlinked.
  */
 #define RE_DEST_FOREACH_ROUTE_SAFE(dest, re, next)                             \
-       for ((re) = (dest) ? (dest)->routes : NULL;                            \
-            (re) && ((next) = (re)->next, 1); (re) = (next))
+       for ((re) = (dest) ? re_list_first(&((dest)->routes)) : NULL;          \
+            (re) && ((next) = re_list_next(&((dest)->routes), (re)), 1);      \
+            (re) = (next))
 
 #define RNODE_FOREACH_RE(rn, re)                                               \
        RE_DEST_FOREACH_ROUTE (rib_dest_from_rnode(rn), re)
@@ -406,7 +455,7 @@ static inline struct route_entry *rnode_to_ribs(struct route_node *rn)
        if (!dest)
                return NULL;
 
-       return dest->routes;
+       return re_list_first(&dest->routes);
 }
 
 /*
index 08b51fcc0bcf4ba5fdf11df10bd030049c3b2637..04576671fe54f085409b4759a04a4ee8ecb0574f 100644 (file)
 extern "C" {
 #endif
 
-#define RSYSTEM_ROUTE(type)                                            \
-       ((type) == ZEBRA_ROUTE_KERNEL || (type) == ZEBRA_ROUTE_CONNECT)
+#define RKERNEL_ROUTE(type) ((type) == ZEBRA_ROUTE_KERNEL)
+
+#define RSYSTEM_ROUTE(type)                                                    \
+       ((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT)
 
 /*
  * Update or delete a route, LSP, or pseudowire from the kernel,
index 289ed5a15b147acda0cfe996c384ba967cbeff29..def5bf7d88947db03ff7ec48e67feb78dadf4efe 100644 (file)
@@ -583,7 +583,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                        re->vrf_id = vrf_id;
                        re->table = table;
                        re->nexthop_num = 0;
-                       re->uptime = time(NULL);
+                       re->uptime = monotime(NULL);
                        re->tag = tag;
 
                        for (;;) {
index 5088e2e8e1f62ad95c04be4477bbf44a7efc0f58..817c65bf28730d9ccad04f12f54ddd2baaacbf3d 100644 (file)
@@ -42,7 +42,6 @@
 #include "zebra/debug.h"
 #include "zebra/rib.h"
 #include "zebra/zapi_msg.h"
-#include "zebra/zebra_ns.h"
 #include "zebra/zebra_vrf.h"
 #include "zebra/zebra_errors.h"
 #include "zebra/zebra_router.h"
@@ -81,18 +80,25 @@ enum rtadv_event {
        RTADV_READ
 };
 
-static void rtadv_event(struct zebra_ns *, enum rtadv_event, int);
+static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
 
 static int if_join_all_router(int, struct interface *);
 static int if_leave_all_router(int, struct interface *);
 
-static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
+static int rtadv_get_socket(struct zebra_vrf *zvrf)
+{
+       if (zvrf->rtadv.sock >= 0)
+               return zvrf->rtadv.sock;
+       return zrouter.rtadv_sock;
+}
+
+static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
 {
        int ret = -1;
        struct interface *iface;
        struct zebra_if *zif;
 
-       iface = if_lookup_by_index_per_ns(zns, *ifindex);
+       iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id);
        if (iface && iface->info) {
                zif = iface->info;
                zif->ra_rcvd++;
@@ -101,7 +107,7 @@ static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
        return ret;
 }
 
-static int rtadv_recv_packet(struct zebra_ns *zns, int sock, uint8_t *buf,
+static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
                             int buflen, struct sockaddr_in6 *from,
                             ifindex_t *ifindex, int *hoplimit)
 {
@@ -149,7 +155,7 @@ static int rtadv_recv_packet(struct zebra_ns *zns, int sock, uint8_t *buf,
                }
        }
 
-       rtadv_increment_received(zns, ifindex);
+       rtadv_increment_received(zvrf, ifindex);
        return ret;
 }
 
@@ -461,19 +467,19 @@ no_more_opts:
 
 static int rtadv_timer(struct thread *thread)
 {
-       struct zebra_ns *zns = THREAD_ARG(thread);
+       struct zebra_vrf *zvrf = THREAD_ARG(thread);
        struct vrf *vrf;
        struct interface *ifp;
        struct zebra_if *zif;
        int period;
 
-       zrouter.rtadv.ra_timer = NULL;
-       if (zrouter.rtadv.adv_msec_if_count == 0) {
+       zvrf->rtadv.ra_timer = NULL;
+       if (zvrf->rtadv.adv_msec_if_count == 0) {
                period = 1000; /* 1 s */
-               rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */);
+               rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
        } else {
                period = 10; /* 10 ms */
-               rtadv_event(zns, RTADV_TIMER_MSEC, 10 /* 10 ms */);
+               rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
        }
 
        RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
@@ -500,7 +506,7 @@ static int rtadv_timer(struct thread *thread)
                                                        "Fast RA Rexmit on interface %s",
                                                        ifp->name);
 
-                                       rtadv_send_packet(zrouter.rtadv.sock,
+                                       rtadv_send_packet(rtadv_get_socket(zvrf),
                                                          ifp);
                                } else {
                                        zif->rtadv.AdvIntervalTimer -= period;
@@ -514,8 +520,8 @@ static int rtadv_timer(struct thread *thread)
                                                        zif->rtadv
                                                                .MaxRtrAdvInterval;
                                                rtadv_send_packet(
-                                                       zrouter.rtadv.sock,
-                                                       ifp);
+                                                         rtadv_get_socket(zvrf),
+                                                         ifp);
                                        }
                                }
                        }
@@ -527,10 +533,9 @@ static int rtadv_timer(struct thread *thread)
 static void rtadv_process_solicit(struct interface *ifp)
 {
        struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
-       struct zebra_ns *zns = zvrf->zns;
 
-       assert(zns);
-       rtadv_send_packet(zrouter.rtadv.sock, ifp);
+       assert(zvrf);
+       rtadv_send_packet(rtadv_get_socket(zvrf), ifp);
 }
 
 /*
@@ -652,7 +657,7 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
 static void rtadv_process_packet(uint8_t *buf, unsigned int len,
                                 ifindex_t ifindex, int hoplimit,
                                 struct sockaddr_in6 *from,
-                                struct zebra_ns *zns)
+                                struct zebra_vrf *zvrf)
 {
        struct icmp6_hdr *icmph;
        struct interface *ifp;
@@ -662,7 +667,7 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len,
        inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
 
        /* Interface search. */
-       ifp = if_lookup_by_index_per_ns(zns, ifindex);
+       ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
        if (ifp == NULL) {
                flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
                          "RA/RS received on unknown IF %u from %s", ifindex,
@@ -724,15 +729,15 @@ static int rtadv_read(struct thread *thread)
        struct sockaddr_in6 from;
        ifindex_t ifindex = 0;
        int hoplimit = -1;
-       struct zebra_ns *zns = THREAD_ARG(thread);
+       struct zebra_vrf *zvrf = THREAD_ARG(thread);
 
        sock = THREAD_FD(thread);
-       zrouter.rtadv.ra_read = NULL;
+       zvrf->rtadv.ra_read = NULL;
 
        /* Register myself. */
-       rtadv_event(zns, RTADV_READ, sock);
+       rtadv_event(zvrf, RTADV_READ, sock);
 
-       len = rtadv_recv_packet(zns, sock, buf, sizeof(buf), &from, &ifindex,
+       len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
                                &hoplimit);
 
        if (len < 0) {
@@ -742,7 +747,7 @@ static int rtadv_read(struct thread *thread)
                return len;
        }
 
-       rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns);
+       rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
 
        return 0;
 }
@@ -875,29 +880,27 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
 {
        struct zebra_if *zif;
        struct zebra_vrf *zvrf;
-       struct zebra_ns *zns;
 
        zif = ifp->info;
        zvrf = vrf_info_lookup(ifp->vrf_id);
-       zns = zvrf->zns;
 
        if (status == RA_SUPPRESS) {
                /* RA is currently enabled */
                if (zif->rtadv.AdvSendAdvertisements) {
                        zif->rtadv.AdvSendAdvertisements = 0;
                        zif->rtadv.AdvIntervalTimer = 0;
-                       zrouter.rtadv.adv_if_count--;
+                       zvrf->rtadv.adv_if_count--;
 
-                       if_leave_all_router(zrouter.rtadv.sock, ifp);
+                       if_leave_all_router(rtadv_get_socket(zvrf), ifp);
 
-                       if (zrouter.rtadv.adv_if_count == 0)
-                               rtadv_event(zns, RTADV_STOP, 0);
+                       if (zvrf->rtadv.adv_if_count == 0)
+                               rtadv_event(zvrf, RTADV_STOP, 0);
                }
        } else {
                if (!zif->rtadv.AdvSendAdvertisements) {
                        zif->rtadv.AdvSendAdvertisements = 1;
                        zif->rtadv.AdvIntervalTimer = 0;
-                       zrouter.rtadv.adv_if_count++;
+                       zvrf->rtadv.adv_if_count++;
 
                        if (zif->rtadv.MaxRtrAdvInterval >= 1000) {
                                /* Enable Fast RA only when RA interval is in
@@ -907,11 +910,11 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
                                        RTADV_NUM_FAST_REXMITS;
                        }
 
-                       if_join_all_router(zrouter.rtadv.sock, ifp);
+                       if_join_all_router(rtadv_get_socket(zvrf), ifp);
 
-                       if (zrouter.rtadv.adv_if_count == 1)
-                               rtadv_event(zns, RTADV_START,
-                                           zrouter.rtadv.sock);
+                       if (zvrf->rtadv.adv_if_count == 1)
+                               rtadv_event(zvrf, RTADV_START,
+                                           rtadv_get_socket(zvrf));
                }
        }
 }
@@ -944,7 +947,7 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
                           zebra_route_string(client->proto), ra_interval);
 
        /* Locate interface and check VRF match. */
-       ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
+       ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
        if (!ifp) {
                flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
                          "%u: IF %u RA %s client %s - interface unknown",
@@ -1051,6 +1054,9 @@ DEFUN (ipv6_nd_ra_interval_msec,
        VTY_DECLVAR_CONTEXT(interface, ifp);
        unsigned interval;
        struct zebra_if *zif = ifp->info;
+       struct zebra_vrf *zvrf;
+
+       zvrf = vrf_info_lookup(ifp->vrf_id);
 
        interval = strtoul(argv[idx_number]->arg, NULL, 10);
        if ((zif->rtadv.AdvDefaultLifetime != -1
@@ -1061,10 +1067,10 @@ DEFUN (ipv6_nd_ra_interval_msec,
        }
 
        if (zif->rtadv.MaxRtrAdvInterval % 1000)
-               zrouter.rtadv.adv_msec_if_count--;
+               zvrf->rtadv.adv_msec_if_count--;
 
        if (interval % 1000)
-               zrouter.rtadv.adv_msec_if_count++;
+               zvrf->rtadv.adv_msec_if_count++;
 
        SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
        zif->rtadv.MaxRtrAdvInterval = interval;
@@ -1086,6 +1092,9 @@ DEFUN (ipv6_nd_ra_interval,
        VTY_DECLVAR_CONTEXT(interface, ifp);
        unsigned interval;
        struct zebra_if *zif = ifp->info;
+       struct zebra_vrf *zvrf;
+
+       zvrf = vrf_info_lookup(ifp->vrf_id);
 
        interval = strtoul(argv[idx_number]->arg, NULL, 10);
        if ((zif->rtadv.AdvDefaultLifetime != -1
@@ -1096,7 +1105,7 @@ DEFUN (ipv6_nd_ra_interval,
        }
 
        if (zif->rtadv.MaxRtrAdvInterval % 1000)
-               zrouter.rtadv.adv_msec_if_count--;
+               zvrf->rtadv.adv_msec_if_count--;
 
        /* convert to milliseconds */
        interval = interval * 1000;
@@ -1122,9 +1131,12 @@ DEFUN (no_ipv6_nd_ra_interval,
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        struct zebra_if *zif = ifp->info;
+       struct zebra_vrf *zvrf = NULL;
+
+       zvrf = vrf_info_lookup(ifp->vrf_id);
 
        if (zif->rtadv.MaxRtrAdvInterval % 1000)
-               zrouter.rtadv.adv_msec_if_count--;
+               zvrf->rtadv.adv_msec_if_count--;
 
        UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
 
@@ -2094,15 +2106,15 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
 }
 
 
-static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
+static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
 {
-       struct rtadv *rtadv = &zrouter.rtadv;
+       struct rtadv *rtadv = &zvrf->rtadv;
 
        switch (event) {
        case RTADV_START:
-               thread_add_read(zrouter.master, rtadv_read, zns, val,
+               thread_add_read(zrouter.master, rtadv_read, zvrf, val,
                                &rtadv->ra_read);
-               thread_add_event(zrouter.master, rtadv_timer, zns, 0,
+               thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
                                 &rtadv->ra_timer);
                break;
        case RTADV_STOP:
@@ -2116,15 +2128,15 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
                }
                break;
        case RTADV_TIMER:
-               thread_add_timer(zrouter.master, rtadv_timer, zns, val,
+               thread_add_timer(zrouter.master, rtadv_timer, zvrf, val,
                                 &rtadv->ra_timer);
                break;
        case RTADV_TIMER_MSEC:
-               thread_add_timer_msec(zrouter.master, rtadv_timer, zns, val,
+               thread_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
                                      &rtadv->ra_timer);
                break;
        case RTADV_READ:
-               thread_add_read(zrouter.master, rtadv_read, zns, val,
+               thread_add_read(zrouter.master, rtadv_read, zvrf, val,
                                &rtadv->ra_read);
                break;
        default:
@@ -2133,21 +2145,29 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
        return;
 }
 
-void rtadv_init(struct zebra_ns *zns)
+void rtadv_init(struct zebra_vrf *zvrf)
 {
-       zrouter.rtadv.sock = rtadv_make_socket(zns->ns_id);
+       if (vrf_is_backend_netns()) {
+               zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
+               zrouter.rtadv_sock = -1;
+       } else if (!zrouter.rtadv_sock) {
+               zvrf->rtadv.sock = -1;
+               zrouter.rtadv_sock = rtadv_make_socket(zvrf->zns->ns_id);
+       }
 }
 
-void rtadv_terminate(struct zebra_ns *zns)
+void rtadv_terminate(struct zebra_vrf *zvrf)
 {
-       rtadv_event(zns, RTADV_STOP, 0);
-       if (zrouter.rtadv.sock >= 0) {
-               close(zrouter.rtadv.sock);
-               zrouter.rtadv.sock = -1;
+       rtadv_event(zvrf, RTADV_STOP, 0);
+       if (zvrf->rtadv.sock >= 0) {
+               close(zvrf->rtadv.sock);
+               zvrf->rtadv.sock = -1;
+       } else if (zrouter.rtadv_sock >= 0) {
+               close(zrouter.rtadv_sock);
+               zrouter.rtadv_sock = -1;
        }
-
-       zrouter.rtadv.adv_if_count = 0;
-       zrouter.rtadv.adv_msec_if_count = 0;
+       zvrf->rtadv.adv_if_count = 0;
+       zvrf->rtadv.adv_msec_if_count = 0;
 }
 
 void rtadv_cmd_init(void)
@@ -2243,11 +2263,11 @@ static int if_leave_all_router(int sock, struct interface *ifp)
 }
 
 #else
-void rtadv_init(struct zebra_ns *zns)
+void rtadv_init(struct zebra_vrf *zvrf)
 {
        /* Empty.*/;
 }
-void rtadv_terminate(struct zebra_ns *zns)
+void rtadv_terminate(struct zebra_vrf *zvrf)
 {
        /* Empty.*/;
 }
index 53c497fc09c49b4823c96e12d515c0c07e0fae6d..8ad3de7f17a6064dae1576d982a8ce7f79405562 100644 (file)
@@ -135,8 +135,8 @@ typedef enum {
        RA_SUPPRESS,
 } ipv6_nd_suppress_ra_status;
 
-extern void rtadv_init(struct zebra_ns *);
-extern void rtadv_terminate(struct zebra_ns *);
+extern void rtadv_init(struct zebra_vrf *);
+extern void rtadv_terminate(struct zebra_vrf *);
 extern void rtadv_cmd_init(void);
 extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS);
 extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);
index 7f6af820185750e0fa43c2a31e83e2153d75a7e9..03b9653ce6eda1a40acc1c872f093dbcd31a3275 100644 (file)
@@ -1339,14 +1339,14 @@ static void zread_interface_delete(ZAPI_HANDLER_ARGS)
 void zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
                            const unsigned int nexthop_num)
 {
-       if (nexthop_num > multipath_num) {
+       if (nexthop_num > zrouter.multipath_num) {
                char buff[PREFIX2STR_BUFFER];
 
                prefix2str(p, buff, sizeof(buff));
                flog_warn(
                        EC_ZEBRA_MORE_NH_THAN_MULTIPATH,
                        "%s: Prefix %s has %d nexthops, but we can only use the first %d",
-                       caller, buff, nexthop_num, multipath_num);
+                       caller, buff, nexthop_num, zrouter.multipath_num);
        }
 }
 
@@ -1388,7 +1388,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
        re->type = api.type;
        re->instance = api.instance;
        re->flags = api.flags;
-       re->uptime = time(NULL);
+       re->uptime = monotime(NULL);
        re->vrf_id = vrf_id;
        if (api.tableid && vrf_id == VRF_DEFAULT)
                re->table = api.tableid;
@@ -1651,7 +1651,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
        zclient_create_header(s, ZEBRA_CAPABILITIES, zvrf->vrf->vrf_id);
        stream_putl(s, vrf_get_backend());
        stream_putc(s, mpls_enabled);
-       stream_putl(s, multipath_num);
+       stream_putl(s, zrouter.multipath_num);
        stream_putc(s, zebra_mlag_get_role());
 
        stream_putw_at(s, 0, stream_get_endp(s));
index ae52762c5a8b2690b07712be97bef5cffc97c8e2..6fc62147c815c6c9ac4663bf1b08c160bdb6f3fa 100644 (file)
@@ -1574,8 +1574,7 @@ done:
        else {
                atomic_fetch_add_explicit(&zdplane_info.dg_lsp_errors, 1,
                                          memory_order_relaxed);
-               if (ctx)
-                       dplane_ctx_free(&ctx);
+               dplane_ctx_free(&ctx);
        }
 
        return result;
@@ -1609,8 +1608,7 @@ done:
        else {
                atomic_fetch_add_explicit(&zdplane_info.dg_pw_errors, 1,
                                          memory_order_relaxed);
-               if (ctx)
-                       dplane_ctx_free(&ctx);
+               dplane_ctx_free(&ctx);
        }
 
        return result;
@@ -1737,8 +1735,7 @@ static enum zebra_dplane_result intf_addr_update_internal(
                /* Error counter */
                atomic_fetch_add_explicit(&zdplane_info.dg_intf_addr_errors,
                                          1, memory_order_relaxed);
-               if (ctx)
-                       dplane_ctx_free(&ctx);
+               dplane_ctx_free(&ctx);
        }
 
        return result;
index bdc1dcdff3197716b1a39504bf0280030dd9c957..065bdee208607fd3bde130cffe27b1370dad5f3a 100644 (file)
@@ -32,6 +32,7 @@
 #include "prefix.h"
 
 #include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 #include "zebra/zebra_dplane.h"
 #include "zebra/zebra_ns.h"
 #include "zebra/zebra_vrf.h"
@@ -251,7 +252,7 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
        ri->metric = &re->metric;
 
        for (ALL_NEXTHOPS(re->ng, nexthop)) {
-               if (ri->num_nhs >= multipath_num)
+               if (ri->num_nhs >= zrouter.multipath_num)
                        break;
 
                if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
@@ -270,7 +271,6 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
                                ri->rtm_type = RTN_BLACKHOLE;
                                break;
                        }
-                       return 1;
                }
 
                if ((cmd == RTM_NEWROUTE
index 5c375a6befc00018e8015c09052021644036c824..5356a7f498de3ef60fc82c2afde806e7b7ccd6ef 100644 (file)
@@ -76,7 +76,7 @@ static zebra_fec_t *fec_add(struct route_table *table, struct prefix *p,
                            uint32_t label_index);
 static int fec_del(zebra_fec_t *fec);
 
-static unsigned int label_hash(void *p);
+static unsigned int label_hash(const void *p);
 static bool label_cmp(const void *p1, const void *p2);
 static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe,
                                     struct nexthop *nexthop);
@@ -577,7 +577,7 @@ static int fec_del(zebra_fec_t *fec)
 /*
  * Hash function for label.
  */
-static unsigned int label_hash(void *p)
+static unsigned int label_hash(const void *p)
 {
        const zebra_ile_t *ile = p;
 
@@ -2874,7 +2874,11 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
                                        ifp = if_lookup_by_index_per_ns(
                                                        zns,
                                                        nexthop->ifindex);
-                                       vty_out(vty, "%15s", ifp->name);
+                                       if (ifp)
+                                               vty_out(vty, "%15s", ifp->name);
+                                       else
+                                               vty_out(vty, "%15s", "Null");
+
                                        break;
                                }
                                case NEXTHOP_TYPE_IPV4:
@@ -2999,11 +3003,30 @@ int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *zvrf)
 /*
  * Called when VRF becomes inactive, cleans up information but keeps
  * the table itself.
- * NOTE: Currently supported only for default VRF.
  */
 void zebra_mpls_cleanup_tables(struct zebra_vrf *zvrf)
 {
-       hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL);
+       struct zebra_vrf *def_zvrf;
+       afi_t afi;
+
+       if (zvrf_id(zvrf) == VRF_DEFAULT)
+               hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL);
+       else {
+               /*
+                * For other vrfs, we try to remove associated LSPs; we locate
+                * the LSPs in the default vrf.
+                */
+               def_zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
+
+               /* At shutdown, the default may be gone already */
+               if (def_zvrf == NULL)
+                       return;
+
+               for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+                       if (zvrf->label[afi] != MPLS_LABEL_NONE)
+                               lsp_uninstall(def_zvrf, zvrf->label[afi]);
+               }
+       }
 }
 
 /*
index 977a8eaf3c7711d7a3c9b464f1d70c909d33cbc7..e7fdaf127d38ad30368f585edeb1083781db0198 100644 (file)
@@ -27,6 +27,7 @@
 #include "zebra/zebra_mpls.h"
 #include "zebra/debug.h"
 #include "zebra/zebra_errors.h"
+#include "zebra/zebra_router.h"
 
 #include "privs.h"
 #include "prefix.h"
@@ -262,7 +263,7 @@ static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx)
                if (!nexthop)
                        continue;
 
-               if (nexthop_num >= multipath_num)
+               if (nexthop_num >= zrouter.multipath_num)
                        break;
 
                if (((action == RTM_ADD || action == RTM_CHANGE)
index 0c743d86784b1ab848ab45ee44f1bae82b3cc1f9..db4f9d0015c0df099394ff766af38119233043d9 100644 (file)
@@ -27,7 +27,6 @@
 #include "lib/prefix.h"
 #include "lib/memory.h"
 
-#include "rtadv.h"
 #include "zebra_ns.h"
 #include "zebra_vrf.h"
 #include "zebra_memory.h"
@@ -122,10 +121,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
 
        zns->ns_id = ns_id;
 
-#if defined(HAVE_RTADV)
-       rtadv_init(zns);
-#endif
-
        kernel_init(zns);
        interface_list(zns);
        route_read(zns);
@@ -142,9 +137,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
 static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete)
 {
        route_table_finish(zns->if_table);
-#if defined(HAVE_RTADV)
-       rtadv_terminate(zns);
-#endif
 
        kernel_terminate(zns, complete);
 
index 73db567eace35a52a1e6427f120504060025ae27..a82dd4c24a856e0fb1921950b68ef6081d8589c6 100644 (file)
@@ -135,12 +135,12 @@ void zebra_pbr_rules_free(void *arg)
        XFREE(MTYPE_TMP, rule);
 }
 
-uint32_t zebra_pbr_rules_hash_key(void *arg)
+uint32_t zebra_pbr_rules_hash_key(const void *arg)
 {
-       struct zebra_pbr_rule *rule;
+       const struct zebra_pbr_rule *rule;
        uint32_t key;
 
-       rule = (struct zebra_pbr_rule *)arg;
+       rule = arg;
        key = jhash_3words(rule->rule.seq, rule->rule.priority,
                           rule->rule.action.table,
                           prefix_hash_key(&rule->rule.filter.src_ip));
@@ -250,9 +250,9 @@ void zebra_pbr_ipset_free(void *arg)
        XFREE(MTYPE_TMP, ipset);
 }
 
-uint32_t zebra_pbr_ipset_hash_key(void *arg)
+uint32_t zebra_pbr_ipset_hash_key(const void *arg)
 {
-       struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg;
+       const struct zebra_pbr_ipset *ipset = arg;
        uint32_t *pnt = (uint32_t *)&ipset->ipset_name;
        uint32_t key = jhash_1word(ipset->vrf_id, 0x63ab42de);
 
@@ -290,12 +290,12 @@ void zebra_pbr_ipset_entry_free(void *arg)
        XFREE(MTYPE_TMP, ipset);
 }
 
-uint32_t zebra_pbr_ipset_entry_hash_key(void *arg)
+uint32_t zebra_pbr_ipset_entry_hash_key(const void *arg)
 {
-       struct zebra_pbr_ipset_entry *ipset;
+       const struct zebra_pbr_ipset_entry *ipset;
        uint32_t key;
 
-       ipset = (struct zebra_pbr_ipset_entry *)arg;
+       ipset = arg;
        key = prefix_hash_key(&ipset->src);
        key = jhash_1word(ipset->unique, key);
        key = jhash_1word(prefix_hash_key(&ipset->dst), key);
@@ -359,9 +359,9 @@ void zebra_pbr_iptable_free(void *arg)
        XFREE(MTYPE_TMP, iptable);
 }
 
-uint32_t zebra_pbr_iptable_hash_key(void *arg)
+uint32_t zebra_pbr_iptable_hash_key(const void *arg)
 {
-       struct zebra_pbr_iptable *iptable = (struct zebra_pbr_iptable *)arg;
+       const struct zebra_pbr_iptable *iptable = arg;
        uint32_t *pnt = (uint32_t *)&(iptable->ipset_name);
        uint32_t key;
 
index 0d55491107604c39635939a8475b7affe9b43eaa..cc1cc5acd58d127386c008c6f712bb24d4b4ec6b 100644 (file)
@@ -211,7 +211,7 @@ extern void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
 extern int kernel_pbr_rule_del(struct zebra_pbr_rule *rule);
 
 extern void zebra_pbr_rules_free(void *arg);
-extern uint32_t zebra_pbr_rules_hash_key(void *arg);
+extern uint32_t zebra_pbr_rules_hash_key(const void *arg);
 extern bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2);
 
 /* has operates on 32bit pointer
@@ -220,16 +220,16 @@ extern bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2);
 #define ZEBRA_IPSET_NAME_HASH_SIZE (ZEBRA_IPSET_NAME_SIZE / 4)
 
 extern void zebra_pbr_ipset_free(void *arg);
-extern uint32_t zebra_pbr_ipset_hash_key(void *arg);
+extern uint32_t zebra_pbr_ipset_hash_key(const void *arg);
 extern bool zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2);
 
 extern void zebra_pbr_ipset_entry_free(void *arg);
-extern uint32_t zebra_pbr_ipset_entry_hash_key(void *arg);
+extern uint32_t zebra_pbr_ipset_entry_hash_key(const void *arg);
 extern bool zebra_pbr_ipset_entry_hash_equal(const void *arg1,
                                             const void *arg2);
 
 extern void zebra_pbr_iptable_free(void *arg);
-extern uint32_t zebra_pbr_iptable_hash_key(void *arg);
+extern uint32_t zebra_pbr_iptable_hash_key(const void *arg);
 extern bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2);
 
 extern void zebra_pbr_init(void);
index bb352dc2ffd698fb3176500324cbf928b4c7979c..d3ecd3695adb6457e3eeb84b46b5eb76e3b65c2a 100644 (file)
@@ -1188,8 +1188,8 @@ static void pp_free_all(void);
 static void zebra_ptm_send_bfdd(struct stream *msg);
 static void zebra_ptm_send_clients(struct stream *msg);
 static int _zebra_ptm_bfd_client_deregister(struct zserv *zs);
-static void _zebra_ptm_reroute(struct zserv *zs, struct stream *msg,
-                              uint32_t command);
+static void _zebra_ptm_reroute(struct zserv *zs, struct zebra_vrf *zvrf,
+                              struct stream *msg, uint32_t command);
 
 
 /*
@@ -1392,8 +1392,8 @@ void zebra_ptm_finish(void)
 /*
  * Message handling.
  */
-static void _zebra_ptm_reroute(struct zserv *zs, struct stream *msg,
-                              uint32_t command)
+static void _zebra_ptm_reroute(struct zserv *zs, struct zebra_vrf *zvrf,
+                              struct stream *msg, uint32_t command)
 {
        struct stream *msgc;
        size_t zmsglen, zhdrlen;
@@ -1420,7 +1420,7 @@ static void _zebra_ptm_reroute(struct zserv *zs, struct stream *msg,
         * one callback at the `bfdd` side, however the real command
         * number will be included right after the zebra header.
         */
-       zclient_create_header(msgc, ZEBRA_BFD_DEST_REPLAY, 0);
+       zclient_create_header(msgc, ZEBRA_BFD_DEST_REPLAY, zvrf->vrf->vrf_id);
        stream_putl(msgc, command);
 
        /* Update the data pointers. */
@@ -1446,7 +1446,7 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
                zlog_debug("bfd_dst_register msg from client %s: length=%d",
                           zebra_route_string(client->proto), hdr->length);
 
-       _zebra_ptm_reroute(client, msg, ZEBRA_BFD_DEST_REGISTER);
+       _zebra_ptm_reroute(client, zvrf, msg, ZEBRA_BFD_DEST_REGISTER);
 }
 
 void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
@@ -1455,7 +1455,7 @@ void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
                zlog_debug("bfd_dst_deregister msg from client %s: length=%d",
                           zebra_route_string(client->proto), hdr->length);
 
-       _zebra_ptm_reroute(client, msg, ZEBRA_BFD_DEST_DEREGISTER);
+       _zebra_ptm_reroute(client, zvrf, msg, ZEBRA_BFD_DEST_DEREGISTER);
 }
 
 void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS)
@@ -1464,7 +1464,7 @@ void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS)
                zlog_debug("bfd_client_register msg from client %s: length=%d",
                           zebra_route_string(client->proto), hdr->length);
 
-       _zebra_ptm_reroute(client, msg, ZEBRA_BFD_CLIENT_REGISTER);
+       _zebra_ptm_reroute(client, zvrf, msg, ZEBRA_BFD_CLIENT_REGISTER);
 }
 
 void zebra_ptm_bfd_dst_replay(ZAPI_HANDLER_ARGS)
@@ -1488,7 +1488,7 @@ void zebra_ptm_bfd_dst_replay(ZAPI_HANDLER_ARGS)
         * special treatment.
         */
        if (client->proto != ZEBRA_ROUTE_BFD) {
-               _zebra_ptm_reroute(client, msg, ZEBRA_BFD_DEST_REPLAY);
+               _zebra_ptm_reroute(client, zvrf, msg, ZEBRA_BFD_DEST_REPLAY);
                return;
        }
 
index af29443aabe724e2db2daf3c0f917e688f83eefd..8d4f49e3ee7647763f2059593e586a266d2a4dd3 100644 (file)
@@ -797,12 +797,6 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
        return NULL;
 }
 
-#define RIB_SYSTEM_ROUTE(R)                                                    \
-       ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT)
-
-#define RIB_KERNEL_ROUTE(R)                                            \
-       ((R)->type == ZEBRA_ROUTE_KERNEL)
-
 /* This function verifies reachability of one given nexthop, which can be
  * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
  * in nexthop->flags field. The nexthop->ifindex will be updated
@@ -961,7 +955,8 @@ static int nexthop_active_update(struct route_node *rn, struct route_entry *re)
                 * decision point.
                 */
                new_active = nexthop_active_check(rn, re, nexthop);
-               if (new_active && re->nexthop_active_num >= multipath_num) {
+               if (new_active
+                   && re->nexthop_active_num >= zrouter.multipath_num) {
                        UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
                        new_active = 0;
                }
@@ -1174,7 +1169,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
  */
 static int rib_can_delete_dest(rib_dest_t *dest)
 {
-       if (dest->routes) {
+       if (re_list_first(&dest->routes)) {
                return 0;
        }
 
@@ -1202,7 +1197,6 @@ static int rib_can_delete_dest(rib_dest_t *dest)
 void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq)
 {
        rib_dest_t *dest = rib_dest_from_rnode(rn);
-       struct listnode *node, *nnode;
        struct rnh *rnh;
 
        /*
@@ -1234,7 +1228,7 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq)
                 * nht resolution and as such we need to call the
                 * nexthop tracking evaluation code
                 */
-               for (ALL_LIST_ELEMENTS(dest->nht, node, nnode, rnh)) {
+               for_each (rnh_list, &dest->nht, rnh) {
                        struct zebra_vrf *zvrf =
                                zebra_vrf_lookup_by_id(rnh->vrf_id);
                        struct prefix *p = &rnh->node->p;
@@ -1310,7 +1304,7 @@ int rib_gc_dest(struct route_node *rn)
        zebra_rib_evaluate_rn_nexthops(rn, zebra_router_get_next_sequence());
 
        dest->rnode = NULL;
-       list_delete(&dest->nht);
+       rnh_list_fini(&dest->nht);
        XFREE(MTYPE_RIB_DEST, dest);
        rn->info = NULL;
 
@@ -2355,7 +2349,7 @@ rib_dest_t *zebra_rib_create_dest(struct route_node *rn)
        rib_dest_t *dest;
 
        dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t));
-       dest->nht = list_new();
+       rnh_list_init(&dest->nht);
        route_lock_node(rn); /* rn route table reference */
        rn->info = dest;
        dest->rnode = rn;
@@ -2403,7 +2397,6 @@ rib_dest_t *zebra_rib_create_dest(struct route_node *rn)
 /* Add RE to head of the route node. */
 static void rib_link(struct route_node *rn, struct route_entry *re, int process)
 {
-       struct route_entry *head;
        rib_dest_t *dest;
        afi_t afi;
        const char *rmap_name;
@@ -2418,12 +2411,7 @@ static void rib_link(struct route_node *rn, struct route_entry *re, int process)
                dest = zebra_rib_create_dest(rn);
        }
 
-       head = dest->routes;
-       if (head) {
-               head->prev = re;
-       }
-       re->next = head;
-       dest->routes = re;
+       re_list_add_head(&dest->routes, re);
 
        afi = (rn->p.family == AF_INET)
                      ? AFI_IP
@@ -2473,14 +2461,7 @@ void rib_unlink(struct route_node *rn, struct route_entry *re)
 
        dest = rib_dest_from_rnode(rn);
 
-       if (re->next)
-               re->next->prev = re->prev;
-
-       if (re->prev)
-               re->prev->next = re->next;
-       else {
-               dest->routes = re->next;
-       }
+       re_list_del(&dest->routes, re);
 
        if (dest->selected_fib == re)
                dest->selected_fib = NULL;
@@ -3017,7 +2998,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
        re->table = table_id;
        re->vrf_id = vrf_id;
        re->nexthop_num = 0;
-       re->uptime = time(NULL);
+       re->uptime = monotime(NULL);
        re->tag = tag;
 
        /* Add nexthop. */
index 220a8006d011c8cd08d1c5dafbe778a4e9adf37b..2917d0e7a8ff19c8604df1a70609d137db79ecc0 100644 (file)
@@ -119,7 +119,7 @@ static void zebra_rnh_remove_from_routing_table(struct rnh *rnh)
        }
 
        dest = rib_dest_from_rnode(rn);
-       listnode_delete(dest->nht, rnh);
+       rnh_list_del(&dest->nht, rnh);
        route_unlock_node(rn);
 }
 
@@ -145,7 +145,7 @@ static void zebra_rnh_store_in_routing_table(struct rnh *rnh)
        }
 
        dest = rib_dest_from_rnode(rn);
-       listnode_add(dest->nht, rnh);
+       rnh_list_add_tail(&dest->nht, rnh);
        route_unlock_node(rn);
 }
 
@@ -251,7 +251,7 @@ void zebra_free_rnh(struct rnh *rnh)
                        route_unlock_node(rern);
 
                        dest = rib_dest_from_rnode(rern);
-                       listnode_delete(dest->nht, rnh);
+                       rnh_list_del(&dest->nht, rnh);
                }
        }
        free_state(rnh->vrf_id, rnh->state, rnh->node);
index 9cd9116eed01c9673ad1ecb4593c9dde5d26bf02..95a39411816ff4be7920f95c5934cd548deb2205 100644 (file)
 extern "C" {
 #endif
 
-typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t;
-
-/* Nexthop structure. */
-struct rnh {
-       uint8_t flags;
-
-#define ZEBRA_NHT_CONNECTED    0x1
-#define ZEBRA_NHT_DELETED       0x2
-#define ZEBRA_NHT_EXACT_MATCH   0x4
-
-       /* VRF identifier. */
-       vrf_id_t vrf_id;
-
-       afi_t afi;
-
-       rnh_type_t type;
-
-       uint32_t seqno;
-
-       struct route_entry *state;
-       struct prefix resolved_route;
-       struct list *client_list;
-
-       /* pseudowires dependent on this nh */
-       struct list *zebra_pseudowire_list;
-
-       struct route_node *node;
-
-       /*
-        * if this has been filtered for the client
-        */
-       int filtered[ZEBRA_ROUTE_MAX];
-};
-
 extern int zebra_rnh_ip_default_route;
 extern int zebra_rnh_ipv6_default_route;
 
index 5d1cbbe781d5de5b2f5ebbb5ae45000e946ab719..5355fa062e9c127c60f8d2dc195259730550d3f8 100644 (file)
@@ -1798,8 +1798,7 @@ static void zebra_route_map_delete(const char *rmap_name)
        route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
 }
 
-static void zebra_route_map_event(route_map_event_t event,
-                                 const char *rmap_name)
+static void zebra_route_map_event(const char *rmap_name)
 {
        if (route_map_mark_updated(rmap_name) == 0)
                zebra_route_map_mark_update(rmap_name);
index fec2fa21f18c57d86e741b5565e42d2273a9a900..610d51d3ea34b0c666ea0a70ed7b60aba377d6bd 100644 (file)
@@ -30,7 +30,9 @@
 #include "zebra_vxlan.h"
 #include "zebra_mlag.h"
 
-struct zebra_router zrouter;
+struct zebra_router zrouter = {
+       .multipath_num = MULTIPATH_NUM,
+};
 
 static inline int
 zebra_router_table_entry_compare(const struct zebra_router_table *e1,
index c68e90695a9e9d93eda645bef1b9a0e870533406..dcbf333b1c124d1aa857c26cf54c4d9c975b7da7 100644 (file)
@@ -82,9 +82,8 @@ struct zebra_router {
 
        struct hash *iptable_hash;
 
-#if defined(HAVE_RTADV)
-       struct rtadv rtadv;
-#endif /* HAVE_RTADV */
+       /* used if vrf backend is not network namespace */
+       int rtadv_sock;
 
        /* A sequence number used for tracking routes */
        _Atomic uint32_t sequence_num;
@@ -110,6 +109,8 @@ struct zebra_router {
         * The EVPN instance, if any
         */
        struct zebra_vrf *evpn_vrf;
+
+       uint32_t multipath_num;
 };
 
 extern struct zebra_router zrouter;
index 4883729c96d1572e07cab8d8c59940a2866da0cd..fdf0cbc693fc282b4570c443333f0d639baee37e 100644 (file)
@@ -29,6 +29,7 @@
 #include "vty.h"
 
 #include "zebra/zebra_router.h"
+#include "zebra/rtadv.h"
 #include "zebra/debug.h"
 #include "zebra/zapi_msg.h"
 #include "zebra/rib.h"
@@ -119,6 +120,10 @@ static int zebra_vrf_enable(struct vrf *vrf)
                zvrf->zns = zebra_ns_lookup((ns_id_t)vrf->vrf_id);
        else
                zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
+#if defined(HAVE_RTADV)
+       rtadv_init(zvrf);
+#endif
+
        /* Inform clients that the VRF is now active. This is an
         * add for the clients.
         */
@@ -161,6 +166,10 @@ static int zebra_vrf_disable(struct vrf *vrf)
        /* Stop any VxLAN-EVPN processing. */
        zebra_vxlan_vrf_disable(zvrf);
 
+#if defined(HAVE_RTADV)
+       rtadv_terminate(zvrf);
+#endif
+
        /* Inform clients that the VRF is now inactive. This is a
         * delete for the clients.
         */
@@ -381,7 +390,7 @@ void zebra_rtable_node_cleanup(struct route_table *table,
        if (node->info) {
                rib_dest_t *dest = node->info;
 
-               list_delete(&dest->nht);
+               rnh_list_fini(&dest->nht);
                XFREE(MTYPE_RIB_DEST, node->info);
        }
 }
index febaf3c844efa0351b80e734514b7339cc2e87c7..972fe381cc1fbb89aa105d23cfa1559ec8cdbbba 100644 (file)
@@ -169,6 +169,10 @@ struct zebra_vrf {
        uint64_t lsp_removals_queued;
        uint64_t lsp_installs;
        uint64_t lsp_removals;
+
+#if defined(HAVE_RTADV)
+       struct rtadv rtadv;
+#endif /* HAVE_RTADV */
 };
 #define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name
 #define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name
index 77795c6152393b74920c80d0055d65d49a337451..ece8f40dcf52ee6819b1c545b54d3a74d41771a7 100644 (file)
@@ -62,7 +62,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
                            bool supernets_only, int type,
                            unsigned short ospf_instance_id);
 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
-                                    int mcast);
+                                    int mcast, bool use_fib);
 static void vty_show_ip_route_summary(struct vty *vty,
                                      struct route_table *table);
 static void vty_show_ip_route_summary_prefix(struct vty *vty,
@@ -154,7 +154,7 @@ DEFUN (show_ip_rpf_addr,
        re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
 
        if (re)
-               vty_show_ip_route_detail(vty, rn, 1);
+               vty_show_ip_route_detail(vty, rn, 1, false);
        else
                vty_out(vty, "%% No match for RPF lookup\n");
 
@@ -186,14 +186,24 @@ static char re_status_output_char(struct route_entry *re, struct nexthop *nhop)
 
 /* New RIB.  Detailed information for IPv4 route. */
 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
-                                    int mcast)
+                                    int mcast, bool use_fib)
 {
        struct route_entry *re;
        struct nexthop *nexthop;
        char buf[SRCDEST2STR_BUFFER];
        struct zebra_vrf *zvrf;
+       rib_dest_t *dest;
+
+       dest = rib_dest_from_rnode(rn);
 
        RNODE_FOREACH_RE (rn, re) {
+               /*
+                * If re not selected for forwarding, skip re
+                * for "show ip/ipv6 fib <prefix>"
+                */
+               if (use_fib && re != dest->selected_fib)
+                       continue;
+
                const char *mcast_info = "";
                if (mcast) {
                        rib_table_info_t *info = srcdest_rnode_table_info(rn);
@@ -230,7 +240,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
                time_t uptime;
                struct tm *tm;
 
-               uptime = time(NULL);
+               uptime = monotime(NULL);
                uptime -= re->uptime;
                tm = gmtime(&uptime);
 
@@ -385,7 +395,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
        struct tm *tm;
        rib_dest_t *dest = rib_dest_from_rnode(rn);
 
-       uptime = time(NULL);
+       uptime = monotime(NULL);
        uptime -= re->uptime;
        tm = gmtime(&uptime);
 
@@ -749,17 +759,26 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
 }
 
 static void vty_show_ip_route_detail_json(struct vty *vty,
-                                       struct route_node *rn)
+                                       struct route_node *rn, bool use_fib)
 {
        json_object *json = NULL;
        json_object *json_prefix = NULL;
        struct route_entry *re;
        char buf[BUFSIZ];
+       rib_dest_t *dest;
+
+       dest = rib_dest_from_rnode(rn);
 
        json = json_object_new_object();
        json_prefix = json_object_new_array();
 
        RNODE_FOREACH_RE (rn, re) {
+               /*
+                * If re not selected for forwarding, skip re
+                * for "show ip/ipv6 fib <prefix> json"
+                */
+               if (use_fib && re != dest->selected_fib)
+                       continue;
                vty_show_ip_route(vty, rn, re, json_prefix);
        }
 
@@ -1177,12 +1196,12 @@ DEFPY (show_route_detail,
        show_route_detail_cmd,
        "show\
          <\
-          ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
+          ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
           <\
           A.B.C.D$address\
           |A.B.C.D/M$prefix\
          >\
-          |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
+          |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
           <\
           X:X::X:X$address\
           |X:X::X:X/M$prefix\
@@ -1191,12 +1210,14 @@ DEFPY (show_route_detail,
         [json$json]",
        SHOW_STR
        IP_STR
+       "IPv6 forwarding table\n"
        "IP routing table\n"
        VRF_FULL_CMD_HELP_STR
        "Network in the IP routing table to display\n"
        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
        IP6_STR
-       "IP routing table\n"
+       "IPv6 forwarding table\n"
+       "IPv6 routing table\n"
        VRF_FULL_CMD_HELP_STR
        "IPv6 Address\n"
        "IPv6 prefix\n"
@@ -1206,6 +1227,9 @@ DEFPY (show_route_detail,
        struct route_table *table;
        struct prefix p;
        struct route_node *rn;
+       bool use_fib = !!fib;
+       rib_dest_t *dest;
+       bool network_found = false;
 
        if (address_str)
                prefix_str = address_str;
@@ -1231,13 +1255,35 @@ DEFPY (show_route_detail,
                                continue;
                        }
 
+                       dest = rib_dest_from_rnode(rn);
+                       if (use_fib && !dest->selected_fib) {
+                               route_unlock_node(rn);
+                               continue;
+                       }
+
+                       network_found = true;
                        if (json)
-                               vty_show_ip_route_detail_json(vty, rn);
+                               vty_show_ip_route_detail_json(vty, rn,
+                                                               use_fib);
                        else
-                               vty_show_ip_route_detail(vty, rn, 0);
+                               vty_show_ip_route_detail(vty, rn, 0, use_fib);
 
                        route_unlock_node(rn);
                }
+
+               if (!network_found) {
+                       if (json)
+                               vty_out(vty, "{}\n");
+                       else {
+                               if (use_fib)
+                                       vty_out(vty,
+                                               "%% Network not in FIB\n");
+                               else
+                                       vty_out(vty,
+                                               "%% Network not in RIB\n");
+                       }
+                       return CMD_WARNING;
+               }
        } else {
                vrf_id_t vrf_id = VRF_DEFAULT;
 
@@ -1249,20 +1295,30 @@ DEFPY (show_route_detail,
                        return CMD_SUCCESS;
 
                rn = route_node_match(table, &p);
-               if (!rn) {
-                       vty_out(vty, "%% Network not in table\n");
-                       return CMD_WARNING;
-               }
-               if (!address_str && rn->p.prefixlen != p.prefixlen) {
-                       vty_out(vty, "%% Network not in table\n");
-                       route_unlock_node(rn);
+               if (rn)
+                       dest = rib_dest_from_rnode(rn);
+
+               if (!rn || (!address_str && rn->p.prefixlen != p.prefixlen) ||
+                       (use_fib && dest && !dest->selected_fib)) {
+                       if (json)
+                               vty_out(vty, "{}\n");
+                       else {
+                               if (use_fib)
+                                       vty_out(vty,
+                                               "%% Network not in FIB\n");
+                               else
+                                       vty_out(vty,
+                                               "%% Network not in table\n");
+                       }
+                       if (rn)
+                               route_unlock_node(rn);
                        return CMD_WARNING;
                }
 
                if (json)
-                       vty_show_ip_route_detail_json(vty, rn);
+                       vty_show_ip_route_detail_json(vty, rn, use_fib);
                else
-                       vty_show_ip_route_detail(vty, rn, 0);
+                       vty_show_ip_route_detail(vty, rn, 0, use_fib);
 
                route_unlock_node(rn);
        }
index baa050c9b90e1d19828f10f2c1b930a54b4a11c6..feb0aadfa814ad396c0415ff2fdd83625f0dc6e5 100644 (file)
@@ -93,7 +93,7 @@ static void zvni_print_hash(struct hash_bucket *bucket, void *ctxt[]);
 static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
                                         struct ipaddr *ip, uint8_t flags,
                                         uint32_t seq, int state, uint16_t cmd);
-static unsigned int neigh_hash_keymake(void *p);
+static unsigned int neigh_hash_keymake(const void *p);
 static void *zvni_neigh_alloc(void *p);
 static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
                                     struct ethaddr *mac);
@@ -149,7 +149,7 @@ static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni);
 static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni);
 static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni);
 
-static unsigned int mac_hash_keymake(void *p);
+static unsigned int mac_hash_keymake(const void *p);
 static bool mac_cmp(const void *p1, const void *p2);
 static void *zvni_mac_alloc(void *p);
 static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr);
@@ -168,7 +168,7 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac);
 static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac);
 static void zvni_install_mac_hash(struct hash_bucket *bucket, void *ctxt);
 
-static unsigned int vni_hash_keymake(void *p);
+static unsigned int vni_hash_keymake(const void *p);
 static void *zvni_alloc(void *p);
 static zebra_vni_t *zvni_lookup(vni_t vni);
 static zebra_vni_t *zvni_add(vni_t vni);
@@ -213,7 +213,7 @@ static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
                                                bool do_dad,
                                                bool *is_dup_detect,
                                                bool is_local);
-static unsigned int zebra_vxlan_sg_hash_key_make(void *p);
+static unsigned int zebra_vxlan_sg_hash_key_make(const void *p);
 static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2);
 static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
                struct in_addr sip, struct in_addr mcast_grp);
@@ -2158,10 +2158,10 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
 /*
  * Make hash key for neighbors.
  */
-static unsigned int neigh_hash_keymake(void *p)
+static unsigned int neigh_hash_keymake(const void *p)
 {
-       zebra_neigh_t *n = p;
-       struct ipaddr *ip = &n->ip;
+       const zebra_neigh_t *n = p;
+       const struct ipaddr *ip = &n->ip;
 
        if (IS_IPADDR_V4(ip))
                return jhash_1word(ip->ipaddr_v4.s_addr, 0);
@@ -3296,9 +3296,9 @@ static int zvni_remote_neigh_update(zebra_vni_t *zvni,
 /*
  * Make hash key for MAC.
  */
-static unsigned int mac_hash_keymake(void *p)
+static unsigned int mac_hash_keymake(const void *p)
 {
-       zebra_mac_t *pmac = p;
+       const zebra_mac_t *pmac = p;
        const void *pnt = (void *)pmac->macaddr.octet;
 
        return jhash(pnt, ETH_ALEN, 0xa5a5a55a);
@@ -3815,7 +3815,7 @@ static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp)
 /*
  * Hash function for VNI.
  */
-static unsigned int vni_hash_keymake(void *p)
+static unsigned int vni_hash_keymake(const void *p)
 {
        const zebra_vni_t *zvni = p;
 
@@ -4688,7 +4688,7 @@ static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *ip)
 /*
  * Hash function for L3 VNI.
  */
-static unsigned int l3vni_hash_keymake(void *p)
+static unsigned int l3vni_hash_keymake(const void *p)
 {
        const zebra_l3vni_t *zl3vni = p;
 
@@ -7505,9 +7505,9 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
 
        if (IS_ZEBRA_DEBUG_VXLAN)
                zlog_debug(
-                       "Add/update remote MAC %s intf %s(%u) VNI %u - del local",
+                       "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
                        prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
-                       ifp->ifindex, vni);
+                       ifp->ifindex, vni, mac->flags);
 
        /* Remove MAC from BGP. */
        zvni_mac_send_del_to_client(zvni->vni, macaddr);
@@ -7520,6 +7520,7 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
                zvni_mac_del(zvni, mac);
        } else {
                UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
+               UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
                SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
        }
 
@@ -7603,11 +7604,6 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
                return -1;
        }
 
-       if (IS_ZEBRA_DEBUG_VXLAN)
-               zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u",
-                          prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
-                          ifp->ifindex, vid, zvni->vni);
-
        /* If entry doesn't exist, nothing to do. */
        mac = zvni_mac_lookup(zvni, macaddr);
        if (!mac)
@@ -7617,6 +7613,11 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
        if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
                return 0;
 
+       if (IS_ZEBRA_DEBUG_VXLAN)
+               zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u flags 0x%x",
+                          prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
+                          ifp->ifindex, vid, zvni->vni, mac->flags);
+
        /* Update all the neigh entries associated with this mac */
        zvni_process_neigh_on_local_mac_del(zvni, mac);
 
@@ -7631,6 +7632,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
                zvni_mac_del(zvni, mac);
        } else {
                UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
+               UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
                SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
        }
 
@@ -9455,9 +9457,9 @@ static int zebra_vxlan_sg_send(struct prefix_sg *sg,
        return zserv_send_message(client, s);
 }
 
-static unsigned int zebra_vxlan_sg_hash_key_make(void *p)
+static unsigned int zebra_vxlan_sg_hash_key_make(const void *p)
 {
-       zebra_vxlan_sg_t *vxlan_sg = p;
+       const zebra_vxlan_sg_t *vxlan_sg = p;
 
        return (jhash_2words(vxlan_sg->sg.src.s_addr,
                                vxlan_sg->sg.grp.s_addr, 0));
index d6fdc0537419a7892f3916b10114f12ba4230c42..34965618f220a0bf14221cd50f336f43aa2c12e2 100644 (file)
@@ -173,8 +173,6 @@ struct zserv {
 DECLARE_HOOK(zserv_client_connect, (struct zserv *client), (client));
 DECLARE_KOOH(zserv_client_close, (struct zserv *client), (client));
 
-extern unsigned int multipath_num;
-
 /*
  * Initialize Zebra API server.
  *