]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #4496 from chiragshah6/evpn_dev2
authorRuss White <russ@riw.us>
Tue, 2 Jul 2019 14:55:25 +0000 (10:55 -0400)
committerGitHub <noreply@github.com>
Tue, 2 Jul 2019 14:55:25 +0000 (10:55 -0400)
bgpd: vrf route leak handle bgp instance delete recreate

144 files changed:
README.md
babeld/babel_interface.c
babeld/babel_memory.c [deleted file]
babeld/babel_memory.h [deleted file]
babeld/babeld.c
babeld/subdir.am
babeld/util.h
bfdd/bfd.c
bfdd/bfd.h
bfdd/bfdd.c
bfdd/config.c
bgpd/bgp_clist.c
bgpd/bgp_clist.h
bgpd/bgp_errors.c
bgpd/bgp_errors.h
bgpd/bgp_evpn.c
bgpd/bgp_evpn_vty.c
bgpd/bgp_mac.c
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_routemap.c
bgpd/bgp_updgrp.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.conf.sample
bgpd/bgpd.h
bgpd/rfapi/rfapi_import.c
doc/developer/building-frr-for-fedora.rst
doc/developer/memtypes.rst
doc/user/bgp.rst
doc/user/filter.rst
doc/user/pim.rst
doc/user/routemap.rst
doc/user/routeserver.rst
doc/user/vnc.rst
docker/debian/Dockerfile
docker/debian/README.md
docker/debian/daemons [deleted file]
lib/command.c
lib/command.h
lib/command_parse.y
lib/frr_pthread.c
lib/frr_pthread.h
lib/hash.c
lib/hash.h
lib/if.c
lib/if.h
lib/memory.h
lib/plist.c
lib/routemap.c
lib/routemap.h
lib/table.c
lib/table.h
lib/vty.c
lib/yang.c
lib/yang.h
ospfd/ospf_routemap.c
pimd/pim_assert.c
pimd/pim_bsm.c
pimd/pim_cmd.c
pimd/pim_iface.c
pimd/pim_ifchannel.c
pimd/pim_igmp.c
pimd/pim_igmp.h
pimd/pim_igmpv3.c
pimd/pim_mroute.c
pimd/pim_msg.h
pimd/pim_oil.c
pimd/pim_oil.h
pimd/pim_static.c
pimd/pim_upstream.c
pimd/pim_vty.c
pimd/pim_zebra.c
ripd/rip_interface.c
ripd/rip_interface.h
ripd/rip_memory.c [deleted file]
ripd/rip_memory.h [deleted file]
ripd/rip_northbound.c
ripd/rip_offset.c
ripd/rip_peer.c
ripd/rip_routemap.c
ripd/ripd.c
ripd/ripd.h
ripd/subdir.am
ripngd/ripng_interface.c
ripngd/ripng_memory.c [deleted file]
ripngd/ripng_memory.h [deleted file]
ripngd/ripng_nexthop.c
ripngd/ripng_offset.c
ripngd/ripng_peer.c
ripngd/ripng_route.c
ripngd/ripngd.c
ripngd/ripngd.h
ripngd/subdir.am
staticd/static_nht.c
tests/topotests/bgp_instance_del_test/__init__.py [new file with mode: 0644]
tests/topotests/bgp_instance_del_test/ce1 [new symlink]
tests/topotests/bgp_instance_del_test/ce2 [new symlink]
tests/topotests/bgp_instance_del_test/ce3 [new symlink]
tests/topotests/bgp_instance_del_test/ce4 [new symlink]
tests/topotests/bgp_instance_del_test/customize.py [new symlink]
tests/topotests/bgp_instance_del_test/r1 [new symlink]
tests/topotests/bgp_instance_del_test/r2 [new symlink]
tests/topotests/bgp_instance_del_test/r3 [new symlink]
tests/topotests/bgp_instance_del_test/r4 [new symlink]
tests/topotests/bgp_instance_del_test/scripts [new symlink]
tests/topotests/bgp_instance_del_test/test_bgp_instance_del_test.py [new file with mode: 0755]
tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/del_bgp_instances.py [new file with mode: 0644]
tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py
tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
tests/topotests/bgp_multiview_topo1/README.md
tests/topotests/bgp_multiview_topo1/r1/bgpd.conf
tests/topotests/lib/lutil.py
vrrpd/subdir.am
vrrpd/vrrp.c
vrrpd/vrrp.h
vrrpd/vrrp_main.c
vrrpd/vrrp_memory.c [deleted file]
vrrpd/vrrp_memory.h [deleted file]
vrrpd/vrrp_packet.c
vrrpd/vrrp_packet.h
vrrpd/vrrp_vty.c
vtysh/vtysh_config.c
vtysh/vtysh_user.c
zebra/kernel_netlink.c
zebra/main.c
zebra/rt_netlink.c
zebra/rtadv.c
zebra/zebra_dplane.c
zebra/zebra_fpm.c
zebra/zebra_fpm_netlink.c
zebra/zebra_fpm_private.h
zebra/zebra_memory.c
zebra/zebra_memory.h
zebra/zebra_rib.c
zebra/zebra_rnh.c
zebra/zebra_rnh.h
zebra/zebra_routemap.c
zebra/zebra_router.c
zebra/zebra_vrf.c
zebra/zebra_vxlan.c
zebra/zebra_vxlan.h
zebra/zebra_vxlan_private.h

index a7725d5e4ed80f1c87f7384a405b40b913f6fd34..e8c775684a5b5e86627fe8a5120a6958bac9a25c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@ FRR currently supports the following protocols:
 * Babel
 * PBR
 * OpenFabric
+* VRRP
 * EIGRP (alpha)
 * NHRP (alpha)
 
index b84bc39cd8dfb58b1e6662f3b87440d2492d7bf6..0eeb9b2bbbfaac3d459ed23831a15e16cfd6cea7 100644 (file)
@@ -39,9 +39,10 @@ THE SOFTWARE.
 #include "neighbour.h"
 #include "route.h"
 #include "xroute.h"
-#include "babel_memory.h"
 #include "babel_errors.h"
 
+DEFINE_MTYPE_STATIC(BABELD, BABEL_IF, "Babel Interface")
+
 #define IS_ENABLE(ifp) (babel_enable_if_lookup(ifp->name) >= 0)
 
 static int babel_enable_if_lookup (const char *ifname);
diff --git a/babeld/babel_memory.c b/babeld/babel_memory.c
deleted file mode 100644 (file)
index a10b779..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* babeld memory type definitions
- *
- * Copyright (C) 2017  Donald Sharp
- *
- * This file is part of 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.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "babel_memory.h"
-
-DEFINE_MGROUP(BABELD, "babeld")
-DEFINE_MTYPE(BABELD, BABEL,             "Babel Structure")
-DEFINE_MTYPE(BABELD, BABEL_IF,          "Babel Interface")
diff --git a/babeld/babel_memory.h b/babeld/babel_memory.h
deleted file mode 100644 (file)
index 4283498..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* babel memory type declarations
- *
- * Copyright (C) 2017  Donald Sharp
- *
- * This file is part of 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 _FRR_BABEL_MEMORY_H
-#define _FRR_BABEL_MEMORY_H
-
-#include "memory.h"
-
-DECLARE_MGROUP(BABELD)
-DECLARE_MTYPE(BABEL)
-DECLARE_MTYPE(BABEL_IF)
-
-#endif /* _FRR_BABELD_MEMORY_H */
index 39451b435a44ec59b7876dafcb2dbdf39cc0ac42..6ad004a4a41a011f738df0b6e70daf2b10999a6d 100644 (file)
@@ -43,9 +43,11 @@ THE SOFTWARE.
 #include "resend.h"
 #include "babel_filter.h"
 #include "babel_zebra.h"
-#include "babel_memory.h"
 #include "babel_errors.h"
 
+DEFINE_MGROUP(BABELD, "babeld")
+DEFINE_MTYPE_STATIC(BABELD, BABEL, "Babel Structure")
+
 static int babel_init_routing_process(struct thread *thread);
 static void babel_get_myid(void);
 static void babel_initial_noise(void);
index 7081c730aa2db7a1613bbd55c6a485d3832d12ec..dd46675f2233134d2849c5d5b7d430e0dc61f468 100644 (file)
@@ -17,7 +17,6 @@ babeld_libbabel_a_SOURCES = \
        babeld/babel_errors.c \
        babeld/babel_filter.c \
        babeld/babel_interface.c \
-       babeld/babel_memory.c \
        babeld/babel_zebra.c \
        babeld/babeld.c \
        babeld/kernel.c \
@@ -36,7 +35,6 @@ noinst_HEADERS += \
        babeld/babel_filter.h \
        babeld/babel_interface.h \
        babeld/babel_main.h \
-       babeld/babel_memory.h \
        babeld/babel_zebra.h \
        babeld/babeld.h \
        babeld/kernel.h \
index 7b836c2e4c19d9051e219868bb124623e6848c9d..00a025ff93eb3eef0aa33054926546777f6807a7 100644 (file)
@@ -27,6 +27,9 @@ THE SOFTWARE.
 #include "babeld.h"
 #include "babel_main.h"
 #include "log.h"
+#include "memory.h"
+
+DECLARE_MGROUP(BABELD)
 
 #if defined(i386) || defined(__mc68020__) || defined(__x86_64__)
 #define DO_NTOHS(_d, _s) do{ _d = ntohs(*(const unsigned short*)(_s)); }while(0)
index 43544318204f9de701990cf603f247d2a5654b4f..08a70abc1ea29435d94e0b1b4516175382280764 100644 (file)
 
 #include "bfd.h"
 
-DEFINE_QOBJ_TYPE(bfd_session);
+DEFINE_MTYPE_STATIC(BFDD, BFDD_CONFIG, "long-lived configuration memory")
+DEFINE_MTYPE_STATIC(BFDD, BFDD_SESSION_OBSERVER, "Session observer")
+DEFINE_MTYPE_STATIC(BFDD, BFDD_VRF, "BFD VRF")
+DEFINE_QOBJ_TYPE(bfd_session)
 
 /*
  * Prototypes
@@ -1552,41 +1555,41 @@ static int bfd_vrf_enable(struct vrf *vrf)
        } 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 ||
+           vrf_get_backend() == VRF_BACKEND_NETNS) {
+               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);
index 213e905bf0a86ab169f0b6f973d5c6a65bbf4003..ec31c8cbc6e9d9d56eca8735c2b3866bcf9d1c1c 100644 (file)
 #define BFDD_JSON_CONV_OPTIONS (0)
 #endif
 
-DECLARE_MGROUP(BFDD);
-DECLARE_MTYPE(BFDD_TMP);
-DECLARE_MTYPE(BFDD_CONFIG);
-DECLARE_MTYPE(BFDD_LABEL);
-DECLARE_MTYPE(BFDD_CONTROL);
-DECLARE_MTYPE(BFDD_SESSION_OBSERVER);
-DECLARE_MTYPE(BFDD_NOTIFICATION);
-DECLARE_MTYPE(BFDD_VRF);
+DECLARE_MGROUP(BFDD)
+DECLARE_MTYPE(BFDD_CONTROL)
+DECLARE_MTYPE(BFDD_NOTIFICATION)
 
 struct bfd_timers {
        uint32_t desired_min_tx;
@@ -259,9 +254,9 @@ struct bfd_session {
        uint64_t refcount; /* number of pointers referencing this. */
 
        /* VTY context data. */
-       QOBJ_FIELDS;
+       QOBJ_FIELDS
 };
-DECLARE_QOBJ_TYPE(bfd_session);
+DECLARE_QOBJ_TYPE(bfd_session)
 
 struct peer_label {
        TAILQ_ENTRY(peer_label) pl_entry;
index 06e01abcfa31031f4f8162c4d9cb3a2f5ed07778..6c277c98f53a4e69bb174cda2c866b85a141e613 100644 (file)
 /*
  * FRR related code.
  */
-DEFINE_MGROUP(BFDD, "Bidirectional Forwarding Detection Daemon");
-DEFINE_MTYPE(BFDD, BFDD_TMP, "short-lived temporary memory");
-DEFINE_MTYPE(BFDD, BFDD_CONFIG, "long-lived configuration memory");
-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");
+DEFINE_MGROUP(BFDD, "Bidirectional Forwarding Detection Daemon")
+DEFINE_MTYPE(BFDD, BFDD_CONTROL, "long-lived control socket memory")
+DEFINE_MTYPE(BFDD, BFDD_NOTIFICATION, "short-lived control notification data")
 
 /* Master of threads. */
 struct thread_master *master;
index 74e7d63d0c6ee69790f43fb9085083a94e11f231..0c0bac0aaa3150e99522cbf5be19c1ae26bb43d4 100644 (file)
@@ -30,6 +30,8 @@
 
 #include "bfd.h"
 
+DEFINE_MTYPE_STATIC(BFDD, BFDD_LABEL, "long-lived label memory")
+
 /*
  * Definitions
  */
index b9a5784799c6df89e0ebb8ebda00aeaeb9ae5ed8..ce617fe6b51b82fd5cb8feca246d1e9f361692a3 100644 (file)
@@ -695,6 +695,32 @@ int lcommunity_list_match(struct lcommunity *lcom, struct community_list *list)
        return 0;
 }
 
+
+/* Perform exact matching.  In case of expanded large-community-list, do
+ * same thing as lcommunity_list_match().
+ */
+int lcommunity_list_exact_match(struct lcommunity *lcom,
+                              struct community_list *list)
+{
+       struct community_entry *entry;
+
+       for (entry = list->head; entry; entry = entry->next) {
+               if (entry->any)
+                       return entry->direct == COMMUNITY_PERMIT ? 1 : 0;
+
+               if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) {
+                       if (lcommunity_cmp(lcom, entry->u.com))
+                               return entry->direct == COMMUNITY_PERMIT ? 1
+                                                                        : 0;
+               } else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) {
+                       if (lcommunity_regexp_match(lcom, entry->reg))
+                               return entry->direct == COMMUNITY_PERMIT ? 1
+                                                                        : 0;
+               }
+       }
+       return 0;
+}
+
 int ecommunity_list_match(struct ecommunity *ecom, struct community_list *list)
 {
        struct community_entry *entry;
index 75a31611bae86b16dd771fadb1f20933f1301283..87b29ac3bebe92a21a12024c7f9c88e8c7f3ddef 100644 (file)
@@ -165,6 +165,8 @@ extern int ecommunity_list_match(struct ecommunity *, struct community_list *);
 extern int lcommunity_list_match(struct lcommunity *, struct community_list *);
 extern int community_list_exact_match(struct community *,
                                      struct community_list *);
+extern int lcommunity_list_exact_match(struct lcommunity *lcom,
+                                      struct community_list *list);
 extern struct community *community_list_match_delete(struct community *,
                                                     struct community_list *);
 extern struct lcommunity *
index 6e181697d64c07bf6da7cee88f00ae1678ef2051..d9aba87e35ceda8d0f37eeb4f5738a6437f8ccc7 100644 (file)
@@ -426,12 +426,6 @@ static struct log_ref ferr_bgp_err[] = {
                .description = "BGP attempted to create an EVPN ES entry and failed",
                .suggestion = "Most likely a bug. If the problem persists, report the problem for troubleshooting"
        },
-       {
-               .code = EC_BGP_MULTI_INSTANCE,
-               .title = "BGP config multi-instance issue",
-               .description = "BGP configuration attempting multiple instances without enabling the feature",
-               .suggestion = "Correct the configuration so that bgp multiple-instance is enabled if desired"
-       },
        {
                .code = EC_BGP_EVPN_AS_MISMATCH,
                .title = "BGP AS configuration issue",
index 39d043ff13c43662dde54ce999132bcc8fa748df..35c5cc3998eabdb30e57fc69ec13f2f568ec4e3a 100644 (file)
@@ -67,7 +67,6 @@ enum bgp_log_refs {
        EC_BGP_EVPN_ROUTE_INVALID,
        EC_BGP_EVPN_ROUTE_CREATE,
        EC_BGP_ES_CREATE,
-       EC_BGP_MULTI_INSTANCE,
        EC_BGP_EVPN_AS_MISMATCH,
        EC_BGP_EVPN_INSTANCE_MISMATCH,
        EC_BGP_FLOWSPEC_PACKET,
index c4b2a606c58e96d260766607ef06c982f6c4bf1f..94022ec1bed933540afaaa08f59b17f5405ed080 100644 (file)
@@ -5533,10 +5533,6 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
                              vrf_id == VRF_DEFAULT ? BGP_INSTANCE_TYPE_DEFAULT
                                                    : BGP_INSTANCE_TYPE_VRF);
                switch (ret) {
-               case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET:
-                       flog_err(EC_BGP_MULTI_INSTANCE,
-                                "'bgp multiple-instance' not present\n");
-                       return -1;
                case BGP_ERR_AS_MISMATCH:
                        flog_err(EC_BGP_EVPN_AS_MISMATCH,
                                 "BGP is already running; AS is %u\n", as);
index 67b0079c37bf4a03d6dfcdf3363e0a7c66f0b981..44e9375dc99c6c04819c8f104d7dd0c57e2121a9 100644 (file)
@@ -1060,6 +1060,9 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
 
                                json_object_int_add(json_prefix_info,
                                        "prefixLen", rm->p.prefixlen);
+
+                               if (rd_header)
+                                       json_nroute = json_object_new_object();
                        }
 
                        for (pi = bgp_node_get_bgp_path_info(rm); pi;
@@ -1132,8 +1135,6 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                        else if (type == RD_TYPE_IP)
                                                decode_rd_ip(pnt + 2, &rd_ip);
                                        if (use_json) {
-                                               json_nroute =
-                                                     json_object_new_object();
                                                if (type == RD_TYPE_AS
                                                    || type == RD_TYPE_AS4)
                                                        sprintf(rd_str, "%u:%d",
@@ -1184,6 +1185,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
                                                      SAFI_EVPN, json_array);
                                output_count++;
                        }
+                       rd_header = 0;
                        if (use_json) {
                                json_object_object_add(json_prefix_info,
                                        "paths", json_array);
@@ -2478,6 +2480,8 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
                                        bgp_evpn_show_route_header(vty, bgp,
                                                                   tbl_ver,
                                                                   json);
+                                       vty_out(vty, "%19s Extended Community\n"
+                                                       , " ");
                                        header = 0;
                                }
 
index f19453fecb68db648532a1da44d79f9b19d7a6e0..61c7b4080c8600790769a6283c6d889e817753ae 100644 (file)
@@ -29,6 +29,7 @@
 #include "bgpd/bgp_memory.h"
 #include "bgpd/bgp_route.h"
 #include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_rd.h"
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_evpn_private.h"
 
@@ -133,11 +134,11 @@ static struct bgp_self_mac *bgp_mac_find_interface_name(const char *ifname)
 }
 
 static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
-                                        struct bgp_table *table)
+                                        struct bgp_table *table,
+                                        struct ethaddr *macaddr)
 {
        struct bgp_node *prn, *rn;
        struct bgp_path_info *pi;
-       uint32_t count = 0;
 
        for (prn = bgp_table_top(table); prn; prn = bgp_route_next(prn)) {
                struct bgp_table *sub = prn->info;
@@ -146,12 +147,21 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
                        continue;
 
                for (rn = bgp_table_top(sub); rn; rn = bgp_route_next(rn)) {
+                       bool rn_affected;
+                       struct prefix_evpn *pevpn = (struct prefix_evpn *)&rn->p;
                        struct prefix_rd prd;
                        uint32_t num_labels = 0;
                        mpls_label_t *label_pnt = NULL;
                        struct bgp_route_evpn evpn;
 
-                       count++;
+                       if (pevpn->family == AF_EVPN &&
+                           pevpn->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
+                           memcmp(&rn->p.u.prefix_evpn.macip_addr.mac,
+                                  macaddr, ETH_ALEN) == 0)
+                               rn_affected = true;
+                       else
+                               rn_affected = false;
+
                        for (pi = rn->info; pi; pi = pi->next) {
                                if (pi->peer == peer)
                                        break;
@@ -160,6 +170,14 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
                        if (!pi)
                                continue;
 
+                       /*
+                        * If the mac address is not the same then
+                        * we don't care and since we are looking
+                        */
+                       if ((memcmp(&pi->attr->rmac, macaddr, ETH_ALEN) != 0) &&
+                           !rn_affected)
+                               continue;
+
                        if (pi->extra)
                                num_labels = pi->extra->num_labels;
                        if (num_labels)
@@ -169,6 +187,23 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
                        prd.prefixlen = 64;
                        memcpy(&prd.val, &prn->p.u.val, 8);
 
+                       if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
+                               if (bgp_debug_update(peer, &rn->p, NULL, 1)) {
+                                       char pfx_buf[BGP_PRD_PATH_STRLEN];
+
+                                       bgp_debug_rdpfxpath2str(
+                                               AFI_L2VPN, SAFI_EVPN, &prd,
+                                               &rn->p, label_pnt, num_labels,
+                                               pi->addpath_rx_id ? 1 : 0,
+                                               pi->addpath_rx_id, pfx_buf,
+                                               sizeof(pfx_buf));
+                                       zlog_debug(
+                                                  "%s skip update of %s marked as removed",
+                                                  peer->host, pfx_buf);
+                               }
+                               continue;
+                       }
+
                        memcpy(&evpn, &pi->attr->evpn_overlay, sizeof(evpn));
                        int32_t ret = bgp_update(peer, &rn->p,
                                                 pi->addpath_rx_id,
@@ -184,7 +219,7 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
        }
 }
 
-static void bgp_mac_rescan_evpn_table(struct bgp *bgp)
+static void bgp_mac_rescan_evpn_table(struct bgp *bgp, struct ethaddr *macaddr)
 {
        struct listnode *node;
        struct peer *peer;
@@ -214,12 +249,12 @@ static void bgp_mac_rescan_evpn_table(struct bgp *bgp)
                        if (bgp_debug_update(peer, NULL, NULL, 1))
                                zlog_debug("Processing EVPN MAC interface change on peer %s",
                                           peer->host);
-                       bgp_process_mac_rescan_table(bgp, peer, table);
+                       bgp_process_mac_rescan_table(bgp, peer, table, macaddr);
                }
        }
 }
 
-static void bgp_mac_rescan_all_evpn_tables(void)
+static void bgp_mac_rescan_all_evpn_tables(struct ethaddr *macaddr)
 {
        struct listnode *node;
        struct bgp *bgp;
@@ -228,11 +263,12 @@ static void bgp_mac_rescan_all_evpn_tables(void)
                struct bgp_table *table = bgp->rib[AFI_L2VPN][SAFI_EVPN];
 
                if (table)
-                       bgp_mac_rescan_evpn_table(bgp);
+                       bgp_mac_rescan_evpn_table(bgp, macaddr);
        }
 }
 
-static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname)
+static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname,
+                                       struct ethaddr *macaddr)
 {
        struct listnode *node = NULL;
        char *name;
@@ -252,7 +288,7 @@ static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname)
                list_delete(&bsm->ifp_list);
                XFREE(MTYPE_BSM, bsm);
 
-               bgp_mac_rescan_all_evpn_tables();
+               bgp_mac_rescan_all_evpn_tables(macaddr);
        }
 }
 
@@ -276,22 +312,26 @@ void bgp_mac_add_mac_entry(struct interface *ifp)
 
                listnode_add(bsm->ifp_list, ifname);
                if (old_bsm)
-                       bgp_mac_remove_ifp_internal(old_bsm, ifname);
+                       bgp_mac_remove_ifp_internal(old_bsm, ifname,
+                                                   &old_bsm->macaddr);
        } else {
                /*
                 * If old mac address is the same as the new,
                 * then there is nothing to do here
                 */
-               if (old_bsm == bsm)
+               if (old_bsm == bsm) {
+                       XFREE(MTYPE_BSM_STRING, ifname);
                        return;
+               }
 
                if (old_bsm)
-                       bgp_mac_remove_ifp_internal(old_bsm, ifp->name);
+                       bgp_mac_remove_ifp_internal(old_bsm, ifp->name,
+                                                   &old_bsm->macaddr);
 
                listnode_add(bsm->ifp_list, ifname);
        }
 
-       bgp_mac_rescan_all_evpn_tables();
+       bgp_mac_rescan_all_evpn_tables(&bsm->macaddr);
 }
 
 void bgp_mac_del_mac_entry(struct interface *ifp)
@@ -308,7 +348,7 @@ void bgp_mac_del_mac_entry(struct interface *ifp)
         * Write code to allow old mac address to no-longer
         * win if we happen to have received it from a peer.
         */
-       bgp_mac_remove_ifp_internal(bsm, ifp->name);
+       bgp_mac_remove_ifp_internal(bsm, ifp->name, &bsm->macaddr);
 }
 
 /* This API checks MAC address against any of local
index ae1821c43a324ad1dd8a753017ad40cfad5e76fe..a3aba447b5e5d2c78cccab57a9e6411ba66e8212 100644 (file)
@@ -2311,6 +2311,17 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
        char pfx_buf[PREFIX2STR_BUFFER];
        int debug = 0;
 
+       if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
+               if (rn)
+                       debug = bgp_debug_bestpath(&rn->p);
+               if (debug) {
+                       prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
+                       zlog_debug(
+                            "%s: bgp delete in progress, ignoring event, p=%s",
+                            __func__, pfx_buf);
+               }
+               return;
+       }
        /* Is it end of initial update? (after startup) */
        if (!rn) {
                quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
@@ -6532,28 +6543,38 @@ DEFUN (no_aggregate_address_mask,
 
 DEFUN (ipv6_aggregate_address,
        ipv6_aggregate_address_cmd,
-       "aggregate-address X:X::X:X/M [summary-only]",
+       "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>]",
        "Configure BGP aggregate entries\n"
        "Aggregate prefix\n"
-       "Filter more specific routes from updates\n")
+       "Generate AS set path information\n"
+       "Filter more specific routes from updates\n"
+       "Filter more specific routes from updates\n"
+       "Generate AS set path information\n")
 {
        int idx = 0;
        argv_find(argv, argc, "X:X::X:X/M", &idx);
        char *prefix = argv[idx]->arg;
+       int as_set =
+               argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
+
+       idx = 0;
        int sum_only = argv_find(argv, argc, "summary-only", &idx)
                               ? AGGREGATE_SUMMARY_ONLY
                               : 0;
        return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
-                                0);
+                                as_set);
 }
 
 DEFUN (no_ipv6_aggregate_address,
        no_ipv6_aggregate_address_cmd,
-       "no aggregate-address X:X::X:X/M [summary-only]",
+       "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>]",
        NO_STR
        "Configure BGP aggregate entries\n"
        "Aggregate prefix\n"
-       "Filter more specific routes from updates\n")
+       "Generate AS set path information\n"
+       "Filter more specific routes from updates\n"
+       "Filter more specific routes from updates\n"
+       "Generate AS set path information\n")
 {
        int idx = 0;
        argv_find(argv, argc, "X:X::X:X/M", &idx);
@@ -6955,6 +6976,7 @@ void route_vty_out(struct vty *vty, struct prefix *p,
        json_object *json_nexthops = NULL;
        json_object *json_nexthop_global = NULL;
        json_object *json_nexthop_ll = NULL;
+       json_object *json_ext_community = NULL;
        char vrf_id_str[VRF_NAMSIZ] = {0};
        bool nexthop_self =
                CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
@@ -7320,6 +7342,17 @@ void route_vty_out(struct vty *vty, struct prefix *p,
                vty_out(vty, "%s", bgp_origin_str[attr->origin]);
 
        if (json_paths) {
+               if (safi == SAFI_EVPN &&
+                   attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
+                       json_ext_community = json_object_new_object();
+                       json_object_string_add(json_ext_community,
+                                              "string",
+                                              attr->ecommunity->str);
+                       json_object_object_add(json_path,
+                                              "extendedCommunity",
+                                              json_ext_community);
+               }
+
                if (nexthop_self)
                        json_object_boolean_true_add(json_path,
                                "announceNexthopSelf");
@@ -7353,6 +7386,13 @@ void route_vty_out(struct vty *vty, struct prefix *p,
                json_object_array_add(json_paths, json_path);
        } else {
                vty_out(vty, "\n");
+
+               if (safi == SAFI_EVPN &&
+                   attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
+                       vty_out(vty, "%*s", 20, " ");
+                       vty_out(vty, "%s\n", attr->ecommunity->str);
+               }
+
 #if ENABLE_BGP_VNC
                /* prints an additional line, indented, with VNC info, if
                 * present */
@@ -7512,10 +7552,9 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr,
                json_object_object_add(json_net, "appliedStatusSymbols",
                                       json_status);
                char buf_cut[BUFSIZ];
-               json_object_object_add(
-                       json_ar,
-                       inet_ntop(p->family, &p->u.prefix, buf_cut, BUFSIZ),
-                       json_net);
+
+               prefix2str(p, buf_cut, PREFIX_STRLEN);
+               json_object_object_add(json_ar, buf_cut, json_net);
        } else
                vty_out(vty, "\n");
 }
@@ -9158,6 +9197,15 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                                                         lcom))
                                        continue;
                        }
+
+                       if (type == bgp_show_type_lcommunity_exact) {
+                               struct lcommunity *lcom = output_arg;
+
+                               if (!pi->attr->lcommunity
+                                   || !lcommunity_cmp(pi->attr->lcommunity,
+                                                     lcom))
+                                       continue;
+                       }
                        if (type == bgp_show_type_lcommunity_list) {
                                struct community_list *list = output_arg;
 
@@ -9165,6 +9213,14 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                                                           list))
                                        continue;
                        }
+                       if (type
+                           == bgp_show_type_lcommunity_list_exact) {
+                               struct community_list *list = output_arg;
+
+                               if (!lcommunity_list_exact_match(
+                                           pi->attr->lcommunity, list))
+                                       continue;
+                       }
                        if (type == bgp_show_type_lcommunity_all) {
                                if (!pi->attr->lcommunity)
                                        continue;
@@ -9788,8 +9844,8 @@ static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
 }
 
 static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
-                              struct cmd_token **argv, afi_t afi, safi_t safi,
-                              bool uj)
+                              struct cmd_token **argv, bool exact, afi_t afi,
+                              safi_t safi, bool uj)
 {
        struct lcommunity *lcom;
        struct buffer *b;
@@ -9820,13 +9876,15 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
                return CMD_WARNING;
        }
 
-       return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity, lcom,
-                       uj);
+       return bgp_show(vty, bgp, afi, safi,
+                       (exact ? bgp_show_type_lcommunity_exact
+                        : bgp_show_type_lcommunity),
+                       lcom, uj);
 }
 
 static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
-                                   const char *lcom, afi_t afi, safi_t safi,
-                                   bool uj)
+                                   const char *lcom, bool exact, afi_t afi,
+                                   safi_t safi, bool uj)
 {
        struct community_list *list;
 
@@ -9838,13 +9896,15 @@ static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
                return CMD_WARNING;
        }
 
-       return bgp_show(vty, bgp, afi, safi, bgp_show_type_lcommunity_list,
+       return bgp_show(vty, bgp, afi, safi,
+                       (exact ? bgp_show_type_lcommunity_list_exact
+                        : bgp_show_type_lcommunity_list),
                        list, uj);
 }
 
 DEFUN (show_ip_bgp_large_community_list,
        show_ip_bgp_large_community_list_cmd,
-       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [json]",
+       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
        SHOW_STR
        IP_STR
        BGP_STR
@@ -9854,12 +9914,14 @@ DEFUN (show_ip_bgp_large_community_list,
        "Display routes matching the large-community-list\n"
        "large-community-list number\n"
        "large-community-list name\n"
+       "Exact match of the large-communities\n"
        JSON_STR)
 {
        char *vrf = NULL;
        afi_t afi = AFI_IP6;
        safi_t safi = SAFI_UNICAST;
        int idx = 0;
+       bool exact_match = 0;
 
        if (argv_find(argv, argc, "ip", &idx))
                afi = AFI_IP;
@@ -9883,12 +9945,18 @@ DEFUN (show_ip_bgp_large_community_list,
        }
 
        argv_find(argv, argc, "large-community-list", &idx);
-       return bgp_show_lcommunity_list(vty, bgp, argv[idx + 1]->arg, afi, safi,
-                                       uj);
+
+       const char *clist_number_or_name = argv[++idx]->arg;
+
+       if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
+               exact_match = 1;
+
+       return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
+                                       exact_match, afi, safi, uj);
 }
 DEFUN (show_ip_bgp_large_community,
        show_ip_bgp_large_community_cmd,
-       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [AA:BB:CC] [json]",
+       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community [<AA:BB:CC> [exact-match]] [json]",
        SHOW_STR
        IP_STR
        BGP_STR
@@ -9897,12 +9965,14 @@ DEFUN (show_ip_bgp_large_community,
        BGP_SAFI_WITH_LABEL_HELP_STR
        "Display routes matching the large-communities\n"
        "List of large-community numbers\n"
+       "Exact match of the large-communities\n"
        JSON_STR)
 {
        char *vrf = NULL;
        afi_t afi = AFI_IP6;
        safi_t safi = SAFI_UNICAST;
        int idx = 0;
+       bool exact_match = 0;
 
        if (argv_find(argv, argc, "ip", &idx))
                afi = AFI_IP;
@@ -9925,9 +9995,12 @@ DEFUN (show_ip_bgp_large_community,
                return CMD_WARNING;
        }
 
-       if (argv_find(argv, argc, "AA:BB:CC", &idx))
-               return bgp_show_lcommunity(vty, bgp, argc, argv, afi, safi, uj);
-       else
+       if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
+               if (argv_find(argv, argc, "exact-match", &idx))
+                       exact_match = 1;
+               return bgp_show_lcommunity(vty, bgp, argc, argv,
+                                       exact_match, afi, safi, uj);
+       } else
                return bgp_show(vty, bgp, afi, safi,
                                bgp_show_type_lcommunity_all, NULL, uj);
 }
index f7150844509704e199fc85ab273e197997cd2f25..0f2363dc6f49f9959f5372ce45a0952bf4025633 100644 (file)
@@ -45,7 +45,9 @@ enum bgp_show_type {
        bgp_show_type_community_list_exact,
        bgp_show_type_lcommunity_all,
        bgp_show_type_lcommunity,
+       bgp_show_type_lcommunity_exact,
        bgp_show_type_lcommunity_list,
+       bgp_show_type_lcommunity_list_exact,
        bgp_show_type_flap_statistics,
        bgp_show_type_flap_neighbor,
        bgp_show_type_dampend_paths,
index 28a763ed5e51ed17f21f67f68ee61acb827eb44a..a212523b194b552ac29c9e115665605472680d94 100644 (file)
@@ -1173,8 +1173,17 @@ static route_map_result_t route_match_lcommunity(void *rule,
                if (!list)
                        return RMAP_NOMATCH;
 
-               if (lcommunity_list_match(path->attr->lcommunity, list))
-                       return RMAP_MATCH;
+               if (rcom->exact) {
+                       if (lcommunity_list_exact_match(
+                                               path->attr->lcommunity,
+                                               list))
+                               return RMAP_MATCH;
+               } else {
+                       if (lcommunity_list_match(
+                                               path->attr->lcommunity,
+                                               list))
+                               return RMAP_MATCH;
+               }
        }
        return RMAP_NOMATCH;
 }
@@ -1193,6 +1202,7 @@ static void *route_match_lcommunity_compile(const char *arg)
                len = p - arg;
                rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
                memcpy(rcom->name, arg, len);
+               rcom->exact = 1;
        } else {
                rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
                rcom->exact = 0;
@@ -3796,26 +3806,45 @@ DEFUN (no_match_community,
 
 DEFUN (match_lcommunity,
        match_lcommunity_cmd,
-       "match large-community <(1-99)|(100-500)|WORD>",
+       "match large-community <(1-99)|(100-500)|WORD> [exact-match]",
        MATCH_STR
        "Match BGP large community list\n"
        "Large Community-list number (standard)\n"
        "Large Community-list number (expanded)\n"
-       "Large Community-list name\n")
+       "Large Community-list name\n"
+       "Do exact matching of communities\n")
 {
-       return bgp_route_match_add(vty, "large-community", argv[2]->arg,
+       int idx_lcomm_list = 2;
+       int ret;
+       char *argstr;
+
+       if (argc == 4) {
+               argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
+                               strlen(argv[idx_lcomm_list]->arg)
+                               + strlen("exact-match") + 2);
+
+               sprintf(argstr, "%s exact-match", argv[idx_lcomm_list]->arg);
+       } else
+               argstr = argv[idx_lcomm_list]->arg;
+
+       ret = bgp_route_match_add(vty, "large-community", argstr,
                                   RMAP_EVENT_LLIST_ADDED);
+       if (argstr != argv[idx_lcomm_list]->arg)
+               XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
+
+       return ret;
 }
 
 DEFUN (no_match_lcommunity,
        no_match_lcommunity_cmd,
-       "no match large-community [<(1-99)|(100-500)|WORD>]",
+       "no match large-community [<(1-99)|(100-500)|WORD> [exact-match]]",
        NO_STR
        MATCH_STR
        "Match BGP large community list\n"
        "Large Community-list number (standard)\n"
        "Large Community-list number (expanded)\n"
-       "Large Community-list name\n")
+       "Large Community-list name\n"
+       "Do exact matching of communities\n")
 {
        return bgp_route_match_delete(vty, "large-community", NULL,
                                      RMAP_EVENT_LLIST_DELETED);
index d0be2471af02b841a4ca9b376739732b26697bf9..82df1905ba5c7615f598c6a3b6f54ffb54d2204b 100644 (file)
@@ -885,6 +885,9 @@ static void update_subgroup_add_peer(struct update_subgroup *subgrp,
        bpacket_add_peer(pkt, paf);
 
        bpacket_queue_sanity_check(SUBGRP_PKTQ(subgrp));
+       if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
+               zlog_debug("peer %s added to subgroup s%" PRIu64,
+                               paf->peer->host, subgrp->id);
 }
 
 /*
@@ -910,6 +913,10 @@ static void update_subgroup_remove_peer_internal(struct update_subgroup *subgrp,
        paf->subgroup = NULL;
        subgrp->peer_count--;
 
+       if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
+               zlog_debug("peer %s deleted from subgroup s%"
+                          PRIu64 "peer cnt %d",
+                          paf->peer->host, subgrp->id, subgrp->peer_count);
        SUBGRP_INCR_STAT(subgrp, prune_events);
 }
 
@@ -1826,9 +1833,9 @@ void peer_af_announce_route(struct peer_af *paf, int combine)
         */
        if (!combine || !all_pending) {
                update_subgroup_split_peer(paf, NULL);
-               if (!paf->subgroup)
-                       return;
+               subgrp = paf->subgroup;
 
+               assert(subgrp && subgrp->update_group);
                if (bgp_debug_update(paf->peer, NULL, subgrp->update_group, 0))
                        zlog_debug("u%" PRIu64 ":s%" PRIu64
                                   " %s announcing routes",
index ef7cf89450d68659b28a350eb8bedad205e8681f..6e0e079cd8a31ffaeeed0362c565b1c95bef0ade 100644 (file)
@@ -979,10 +979,6 @@ DEFUN_NOSH (router_bgp,
 
                ret = bgp_get(&bgp, &as, name, inst_type);
                switch (ret) {
-               case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET:
-                       vty_out(vty,
-                               "Please specify 'bgp multiple-instance' first\n");
-                       return CMD_WARNING_CONFIG_FAILED;
                case BGP_ERR_AS_MISMATCH:
                        vty_out(vty, "BGP is already running; AS is %u\n", as);
                        return CMD_WARNING_CONFIG_FAILED;
@@ -4830,14 +4826,15 @@ static int peer_default_originate_set_vty(struct vty *vty, const char *peer_str,
 {
        int ret;
        struct peer *peer;
-       struct route_map *route_map;
+       struct route_map *route_map = NULL;
 
        peer = peer_and_group_lookup_vty(vty, peer_str);
        if (!peer)
                return CMD_WARNING_CONFIG_FAILED;
 
        if (set) {
-               route_map = route_map_lookup_warn_noexist(vty, rmap);
+               if (rmap)
+                       route_map = route_map_lookup_warn_noexist(vty, rmap);
                ret = peer_default_originate_set(peer, afi, safi,
                                                 rmap, route_map);
        } else
@@ -7731,14 +7728,6 @@ DEFUN (show_bgp_memory,
                                     count * sizeof(struct peer_group)));
 
        /* Other */
-       if ((count = mtype_stats_alloc(MTYPE_HASH)))
-               vty_out(vty, "%ld hash tables, using %s of memory\n", count,
-                       mtype_memstr(memstrbuf, sizeof(memstrbuf),
-                                    count * sizeof(struct hash)));
-       if ((count = mtype_stats_alloc(MTYPE_HASH_BACKET)))
-               vty_out(vty, "%ld hash buckets, using %s of memory\n", count,
-                       mtype_memstr(memstrbuf, sizeof(memstrbuf),
-                                    count * sizeof(struct hash_bucket)));
        if ((count = mtype_stats_alloc(MTYPE_BGP_REGEXP)))
                vty_out(vty, "%ld compiled regexes, using %s of memory\n",
                        count, mtype_memstr(memstrbuf, sizeof(memstrbuf),
@@ -12329,7 +12318,7 @@ ALIAS_HIDDEN(
 
 DEFUN (no_bgp_redistribute_ipv4_ospf,
        no_bgp_redistribute_ipv4_ospf_cmd,
-       "no redistribute <ospf|table> (1-65535) [metric (0-4294967295)] [route-map WORD]",
+       "no redistribute <ospf|table> (1-65535) [{metric (0-4294967295)|route-map WORD}]",
        NO_STR
        "Redistribute information from another routing protocol\n"
        "Open Shortest Path First (OSPFv2)\n"
@@ -12357,7 +12346,7 @@ DEFUN (no_bgp_redistribute_ipv4_ospf,
 
 ALIAS_HIDDEN(
        no_bgp_redistribute_ipv4_ospf, no_bgp_redistribute_ipv4_ospf_hidden_cmd,
-       "no redistribute <ospf|table> (1-65535) [metric (0-4294967295)] [route-map WORD]",
+       "no redistribute <ospf|table> (1-65535) [{metric (0-4294967295)|route-map WORD}]",
        NO_STR
        "Redistribute information from another routing protocol\n"
        "Open Shortest Path First (OSPFv2)\n"
@@ -12370,7 +12359,7 @@ ALIAS_HIDDEN(
 
 DEFUN (no_bgp_redistribute_ipv4,
        no_bgp_redistribute_ipv4_cmd,
-       "no redistribute " FRR_IP_REDIST_STR_BGPD " [metric (0-4294967295)] [route-map WORD]",
+       "no redistribute " FRR_IP_REDIST_STR_BGPD " [{metric (0-4294967295)|route-map WORD}]",
        NO_STR
        "Redistribute information from another routing protocol\n"
        FRR_IP_REDIST_HELP_STR_BGPD
@@ -12394,7 +12383,7 @@ DEFUN (no_bgp_redistribute_ipv4,
 ALIAS_HIDDEN(
        no_bgp_redistribute_ipv4, no_bgp_redistribute_ipv4_hidden_cmd,
        "no redistribute " FRR_IP_REDIST_STR_BGPD
-       " [metric (0-4294967295)] [route-map WORD]",
+       " [{metric (0-4294967295)|route-map WORD}]",
        NO_STR
        "Redistribute information from another routing protocol\n" FRR_IP_REDIST_HELP_STR_BGPD
        "Metric for redistributed routes\n"
@@ -12553,7 +12542,7 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap,
 
 DEFUN (no_bgp_redistribute_ipv6,
        no_bgp_redistribute_ipv6_cmd,
-       "no redistribute " FRR_IP6_REDIST_STR_BGPD " [metric (0-4294967295)] [route-map WORD]",
+       "no redistribute " FRR_IP6_REDIST_STR_BGPD " [{metric (0-4294967295)|route-map WORD}]",
        NO_STR
        "Redistribute information from another routing protocol\n"
        FRR_IP6_REDIST_HELP_STR_BGPD
index af90e9841a2e04f3b00a490fde113e3bfb3bde28..3ca209676f276e170e2513801dd0d45f97ec6e39 100644 (file)
@@ -3183,7 +3183,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
                if (bgp->inst_type != inst_type)
                        return BGP_ERR_INSTANCE_MISMATCH;
                *bgp_val = bgp;
-               return 0;
+               return BGP_SUCCESS;
        }
 
        bgp = bgp_create(as, name, inst_type);
@@ -3217,7 +3217,7 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
                bgp_zebra_instance_register(bgp);
        }
 
-       return 0;
+       return BGP_SUCCESS;
 }
 
 /*
index cb12a925224270dbfe6cd71437789fe6155832ed..1fb4f1600bd4b9ee0a581d690f94b466be11aa6a 100644 (file)
@@ -8,7 +8,6 @@ hostname bgpd
 password zebra
 !enable password please-set-at-here
 !
-!bgp multiple-instance
 !
 router bgp 7675
 ! bgp router-id 10.0.0.1
index 088c6411b4729a98a8500e09602d9b56c376efe7..4bce73898f4991b384b9e873f36aab12939d92ec 100644 (file)
@@ -1453,12 +1453,10 @@ enum bgp_clear_type {
 #define BGP_ERR_INVALID_AS                       -3
 #define BGP_ERR_INVALID_BGP                      -4
 #define BGP_ERR_PEER_GROUP_MEMBER                -5
-#define BGP_ERR_MULTIPLE_INSTANCE_USED           -6
 #define BGP_ERR_PEER_GROUP_NO_REMOTE_AS          -7
 #define BGP_ERR_PEER_GROUP_CANT_CHANGE           -8
 #define BGP_ERR_PEER_GROUP_MISMATCH              -9
 #define BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT  -10
-#define BGP_ERR_MULTIPLE_INSTANCE_NOT_SET       -11
 #define BGP_ERR_AS_MISMATCH                     -12
 #define BGP_ERR_PEER_FLAG_CONFLICT              -13
 #define BGP_ERR_PEER_GROUP_SHUTDOWN             -14
index 583adcda77cc17bf98b4ff3b68e78d588f5c8c46..87a05a4f8c12da32980638b13c4ffed218c03b14 100644 (file)
@@ -2402,6 +2402,18 @@ static int rfapiWithdrawTimerVPN(struct thread *t)
        struct rfapi_monitor_vpn *moved;
        afi_t afi;
 
+       if (bgp == NULL) {
+               vnc_zlog_debug_verbose(
+                   "%s: NULL BGP pointer, assume shutdown race condition!!!",
+                   __func__);
+               return 0;
+       }
+       if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
+               vnc_zlog_debug_verbose(
+                   "%s: BGP delete in progress, assume shutdown race condition!!!",
+                   __func__);
+               return 0;
+       }
        assert(wcb->node);
        assert(bpi);
        assert(wcb->import_table);
index 0208f1146b401949597747862378d917a4b6eacf..0bfd43e93cbdb8c73cb1a6aab38e813eb8750633 100644 (file)
@@ -98,6 +98,18 @@ And load the kernel modules on the running system:
 
    sudo modprobe mpls-router mpls-iptunnel
 
+
+.. note::
+   Fedora ships with the ``firewalld`` service enabled. You may run into some
+   issues with the iptables rules it installs by default. If you wish to just
+   stop the service and clear `ALL` rules do these commands:
+
+   .. code-block:: console
+
+      sudo systemctl disable firewalld.service
+      sudo systemctl stop firewalld.service
+      sudo iptables -F
+
 Install service files
 ^^^^^^^^^^^^^^^^^^^^^
 
index 153131bab927d2144a8a7c5989930f1232cac04e..13f6b43bbfd6510b8a5615186346a46ecf0eaaf7 100644 (file)
@@ -42,6 +42,16 @@ Example:
 Definition
 ----------
 
+.. c:type:: struct memtype
+
+   This is the (internal) type used for MTYPE definitions.  The macros below
+   should be used to create these, but in some cases it is useful to pass a
+   ``struct memtype *`` pointer to some helper function.
+
+   The ``MTYPE_name`` created by the macros is declared as an array, i.e.
+   a function taking a ``struct memtype *`` argument can be called with an
+   ``MTYPE_name`` argument (as opposed to ``&MTYPE_name``.)
+
 .. c:macro:: DECLARE_MGROUP(name)
 
    This macro forward-declares a memory group and should be placed in a
index 1831363e19d3f87b6a67ab08047aadce1e9ea34a..f2b132807529f980f3fa35099355c144207342a3 100644 (file)
@@ -267,29 +267,6 @@ An example configuration with multiple autonomous systems might look like this:
     neighbor 10.0.0.6 remote-as 70
    ...
 
-In the past this feature done differently and the following commands were
-required to enable the functionality. They are now deprecated.
-
-.. deprecated:: 5.0
-   This command is deprecated and may be safely removed from the config.
-
-.. index:: bgp multiple-instance
-.. clicmd:: bgp multiple-instance
-
-   Enable BGP multiple instance feature. Because this is now the default
-   configuration this command will not be displayed in the running
-   configuration.
-
-.. deprecated:: 5.0
-   This command is deprecated and may be safely removed from the config.
-
-.. index:: no bgp multiple-instance
-.. clicmd:: no bgp multiple-instance
-
-   In previous versions of FRR, this command disabled the BGP multiple instance
-   feature. This functionality is automatically turned on when BGP multiple
-   instances or views exist so this command no longer does anything.
-
 .. seealso:: :ref:`bgp-vrf-route-leaking`
 .. seealso:: :ref:`zebra-vrf`
 
@@ -688,6 +665,11 @@ Networks
 Route Aggregation
 -----------------
 
+.. _bgp-route-aggregation-ipv4:
+
+Route Aggregation-IPv4 Address Family
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 .. index:: aggregate-address A.B.C.D/M
 .. clicmd:: aggregate-address A.B.C.D/M
 
@@ -707,6 +689,62 @@ Route Aggregation
 
 .. index:: no aggregate-address A.B.C.D/M
 .. clicmd:: no aggregate-address A.B.C.D/M
+   
+   This command removes an aggregate address.
+
+
+   This configuration example setup the aggregate-address under 
+   ipv4 address-family.
+
+   .. code-block:: frr
+
+      router bgp 1
+       address-family ipv4 unicast
+        aggregate-address 10.0.0.0/8
+        aggregate-address 20.0.0.0/8 as-set
+        aggregate-address 40.0.0.0/8 summary-only
+       exit-address-family
+
+
+.. _bgp-route-aggregation-ipv6:
+
+Route Aggregation-IPv6 Address Family
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. index:: aggregate-address X:X::X:X/M
+.. clicmd:: aggregate-address X:X::X:X/M
+
+   This command specifies an aggregate address.
+
+.. index:: aggregate-address X:X::X:X/M as-set
+.. clicmd:: aggregate-address X:X::X:X/M as-set
+
+   This command specifies an aggregate address. Resulting routes include
+   AS set.
+
+.. index:: aggregate-address X:X::X:X/M summary-only
+.. clicmd:: aggregate-address X:X::X:X/M summary-only
+
+   This command specifies an aggregate address. Aggregated routes will
+   not be announce.
+
+.. index:: no aggregate-address X:X::X:X/M
+.. clicmd:: no aggregate-address X:X::X:X/M
+
+   This command removes an aggregate address.
+
+
+   This configuration example setup the aggregate-address under 
+   ipv4 address-family.
+
+   .. code-block:: frr
+
+      router bgp 1
+       address-family ipv6 unicast
+        aggregate-address 10::0/64
+       aggregate-address 20::0/64 as-set
+       aggregate-address 40::0/64 summary-only
+       exit-address-family
 
 .. _bgp-redistribute-to-bgp:
 
@@ -1736,13 +1774,15 @@ Two types of large community lists are supported, namely `standard` and
 Large Communities in Route Map
 """"""""""""""""""""""""""""""
 
-.. index:: match large-community LINE
-.. clicmd:: match large-community LINE
+.. index:: match large-community LINE [exact-match]
+.. clicmd:: match large-community LINE [exact-match]
 
    Where `line` can be a simple string to match, or a regular expression. It
    is very important to note that this match occurs on the entire
    large-community string as a whole, where each large-community is ordered
-   from lowest to highest.
+   from lowest to highest. When `exact-match` keyword is specified, match
+   happen only when BGP updates have completely same large communities value
+   specified in the large community list.
 
 .. index:: set large-community LARGE-COMMUNITY
 .. clicmd:: set large-community LARGE-COMMUNITY
@@ -2235,8 +2275,49 @@ attribute.
    match the specified community list. When `exact-match` is specified, it
    displays only routes that have an exact match.
 
+.. _bgp-display-routes-by-lcommunity:
+
+Displaying Routes by Large Community Attribute
+----------------------------------------------
+
+The following commands allow displaying routes based on their 
+large community attribute.
+
+.. index:: show [ip] bgp <ipv4|ipv6> large-community
+.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community
+
+.. index:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY
+.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY
+
+.. index:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY exact-match
+.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY exact-match
+
+.. index:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY json
+.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY json
+
+   These commands display BGP routes which have the large community attribute.
+   attribute. When ``LARGE-COMMUNITY`` is specified, BGP routes that match that
+   large community are displayed. When `exact-match` is specified, it display 
+   only routes that have an exact match. When `json` is specified, it display 
+   routes in json format.
+
+.. index:: show [ip] bgp <ipv4|ipv6> large-community-list WORD
+.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community-list WORD
+
+.. index:: show [ip] bgp <ipv4|ipv6> large-community-list WORD exact-match
+.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community-list WORD exact-match
+
+.. index:: show [ip] bgp <ipv4|ipv6> large-community-list WORD json
+.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community-list WORD json
+
+   These commands display BGP routes for the address family specified that
+   match the specified large community list. When `exact-match` is specified, 
+   it displays only routes that have an exact match. When `json` is specified, 
+   it display routes in json format.
+
 .. _bgp-display-routes-by-as-path:
 
+
 Displaying Routes by AS Path
 ----------------------------
 
@@ -2302,7 +2383,6 @@ different filter for a peer.
 
 .. code-block:: frr
 
-   bgp multiple-instance
    !
    router bgp 1 view 1
     neighbor 10.0.0.1 remote-as 2
index 9d7361443d2ef23129378f667ab9ee0d376c2bab..8c86d0608753b0450c2d0d7d4f1a0748d3948daa 100644 (file)
@@ -165,14 +165,8 @@ Showing ip prefix-list
 Clear counter of ip prefix-list
 -------------------------------
 
-.. index:: clear ip prefix-list
-.. clicmd:: clear ip prefix-list
+.. index:: clear ip prefix-list [NAME [A.B.C.D/M]]
+.. clicmd:: clear ip prefix-list [NAME [A.B.C.D/M]]
 
    Clears the counters of all IP prefix lists. Clear IP Prefix List can be used
-   with a specified name and prefix.
-
-.. index:: clear ip prefix-list NAME
-.. clicmd:: clear ip prefix-list NAME
-
-.. index:: clear ip prefix-list NAME A.B.C.D/M
-.. clicmd:: clear ip prefix-list NAME A.B.C.D/M
+   with a specified NAME or NAME and prefix.
index e8c74f7b87d4416cab22514694c57fc5309ff931..805d6264a87291f943c8d869267a44bc24de98c3 100644 (file)
@@ -151,6 +151,12 @@ Certain signals have special meanings to *pimd*.
    urib-only
       Lookup in the Unicast Rib only.
 
+.. index:: ip igmp generate-query-once [version (2-3)]
+.. clicmd:: ip igmp generate-query-once [version (2-3)]
+
+   Generate IGMP query (v2/v3) on user requirement. This will not depend on
+   the existing IGMP general query timer.If no version is provided in the cli,
+   it will be considered as default v2 query.This is a hidden command.
 
 .. _pim-interface-configuration:
 
index ef9ebe8ddc3d4caba1e0c132a18d50f4a2612738..bac61cbc58e435dc6e2fcba62777be48e3aedbe1 100644 (file)
@@ -85,6 +85,23 @@ deny
 cont
    goto next route-map entry
 
+.. _route-map-show-command:
+
+.. index:: show route-map [WORD]
+.. clicmd:: show route-map [WORD]
+
+   Display data about each daemons knowledge of individual route-maps.
+   If WORD is supplied narrow choice to that particular route-map.
+
+.. _route-map-clear-counter-command:
+
+.. index:: clear route-map counter [WORD]
+.. clicmd:: clear route-map counter [WORD]
+
+   Clear counters that are being stored about the route-map utilization
+   so that subsuquent show commands will indicate since the last clear.
+   If WORD is specified clear just that particular route-map's counters.
+
 .. _route-map-command:
 
 Route Map Command
@@ -315,6 +332,7 @@ Route Map Exit Action Command
 
    Proceed processing the route-map at the first entry whose order is >= N
 
+
 Route Map Examples
 ==================
 
index e677a3030d9004d1351974336d63eb785ccc2d4c..474a68db251e8e8d9d37938d2dde560e29210463 100644 (file)
@@ -369,8 +369,6 @@ the policies for client RA):
    hostname RS
    password ix
    !
-   bgp multiple-instance
-   !
    router bgp 65000 view RS
      no bgp default ipv4-unicast
      neighbor 2001:0DB8::A  remote-as 65001
index d0934fe6face99b55f6db3f48c1aa46eb5f55444..cb9c74ceea00374ada7a0cd8a5d0cde6edbc8edd 100644 (file)
@@ -468,8 +468,8 @@ redistributed to VNC as bgp-direct-to-nve-groups routes. These routes are NOT
 announced via BGP, but they are made available for local RFP lookup in response
 to queries from NVEs.
 
-A non-main/default BGP instance is configured using the `bgp multiple-instance`
-and `router bgp AS view NAME` commands as described elsewhere in this document.
+A non-main/default BGP instance is configured using the
+`router bgp AS view NAME` command as described elsewhere in this document.
 
 In order for a route in the unicast BGP RIB to be made available to a querying
 NVE, there must already be, available to that NVE, an (interior) VNC route
index fde29d4911dc9601ab3a5b28d67044ff502abbd1..6ffdd0ccb3ff0cb70d8342413d68d6781bc1a20b 100644 (file)
@@ -9,6 +9,5 @@ RUN curl -s https://deb.frrouting.org/frr/keys.asc | apt-key add -
 RUN echo deb https://deb.frrouting.org/frr $(lsb_release -s -c) frr-stable | tee -a /etc/apt/sources.list.d/frr.list
 RUN apt-get update
 RUN apt-get install -y frr frr-pythontools
-ADD daemons /etc/frr/daemons
 ADD docker-start /usr/sbin/docker-start
 ENTRYPOINT ["/usr/sbin/docker-start"]
index b10d696a78a105b0dbd0384e636b3cc87df5f757..3c1209bc97caa85a4e4244c6ab5e5726b50cfe28 100644 (file)
@@ -1,14 +1,17 @@
-# Debian9 Docker
-This is a binary docker container build of debian9.
+# Debian 10 Docker
+
+This is a binary docker container build of Debian 10 (buster) with FRR.
 
 # Build
+
 ```
-docker build --rm -t frr:6.0.2 .
+docker build -t frr-debian:latest .
 ```
 
 # Running
+
 ```
-docker run -itd --privileged --name frr frr:latest
+docker run -itd --privileged --name frr frr-debian:latest
 ```
 
 vtysh
diff --git a/docker/debian/daemons b/docker/debian/daemons
deleted file mode 100644 (file)
index ed4d98e..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-# This file tells the frr package which daemons to start.
-#
-# Sample configurations for these daemons can be found in
-# /usr/share/doc/frr/examples/.
-#
-# ATTENTION:
-#
-# When activation a daemon at the first time, a config file, even if it is
-# empty, has to be present *and* be owned by the user and group "frr", else
-# the daemon will not be started by /etc/init.d/frr. The permissions should
-# be u=rw,g=r,o=.
-# When using "vtysh" such a config file is also needed. It should be owned by
-# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
-#
-# The watchfrr and zebra daemons are always started.
-#
-bgpd=yes
-ospfd=no
-ospf6d=no
-ripd=no
-ripngd=no
-isisd=no
-pimd=no
-ldpd=no
-nhrpd=no
-eigrpd=no
-babeld=no
-sharpd=no
-pbrd=no
-bfdd=no
-fabricd=no
-
-#
-# If this option is set the /etc/init.d/frr script automatically loads
-# the config via "vtysh -b" when the servers are started.
-# Check /etc/pam.d/frr if you intend to use "vtysh"!
-#
-vtysh_enable=yes
-zebra_options="  -A 127.0.0.1 -s 90000000"
-bgpd_options="   -A 127.0.0.1"
-ospfd_options="  -A 127.0.0.1"
-ospf6d_options=" -A ::1"
-ripd_options="   -A 127.0.0.1"
-ripngd_options=" -A ::1"
-isisd_options="  -A 127.0.0.1"
-pimd_options="   -A 127.0.0.1"
-ldpd_options="   -A 127.0.0.1"
-nhrpd_options="  -A 127.0.0.1"
-eigrpd_options=" -A 127.0.0.1"
-babeld_options=" -A 127.0.0.1"
-sharpd_options=" -A 127.0.0.1"
-pbrd_options="   -A 127.0.0.1"
-staticd_options="-A 127.0.0.1"
-bfdd_options="   -A 127.0.0.1"
-fabricd_options="-A 127.0.0.1"
-
-# The list of daemons to watch is automatically generated by the init script.
-watchfrr_options="-r '/usr/lib/frr/watchfrr.sh restart %s' -s '/usr/lib/frr/watchfrr.sh start %s' -k '/usr/lib/frr/watchfrr.sh stop %s'"
-
-# for debugging purposes, you can specify a "wrap" command to start instead
-# of starting the daemon directly, e.g. to use valgrind on ospfd:
-#   ospfd_wrap="/usr/bin/valgrind"
-# or you can use "all_wrap" for all daemons, e.g. to use perf record:
-#   all_wrap="/usr/bin/perf record --call-graph -"
-# the normal daemon command is added to this at the end.
index 0e16f30a8a29f6ddfc27f287203aba3d98c84ce5..f257c7d0f9565b11193381b5f4137c86eaeb5ce8 100644 (file)
@@ -48,7 +48,7 @@
 #include "lib_errors.h"
 #include "northbound_cli.h"
 
-DEFINE_MTYPE(LIB, HOST, "Host config")
+DEFINE_MTYPE_STATIC(LIB, HOST, "Host config")
 DEFINE_MTYPE(LIB, COMPLETION, "Completion item")
 
 #define item(x)                                                                \
@@ -84,6 +84,7 @@ const char *node_names[] = {
        "vrf debug",                // VRF_DEBUG_NODE,
        "northbound debug",         // NORTHBOUND_DEBUG_NODE,
        "vnc debug",                // DEBUG_VNC_NODE,
+       "route-map debug",          /* RMAP_DEBUG_NODE */
        "aaa",                      // AAA_NODE,
        "keychain",                 // KEYCHAIN_NODE,
        "keychain key",             // KEYCHAIN_KEY_NODE,
index d6c41e08244cf372a5606f0b68833179e24c4182..fd8b56d62e9e8a8911ac5d752853b23fbc730779 100644 (file)
@@ -34,7 +34,6 @@
 extern "C" {
 #endif
 
-DECLARE_MTYPE(HOST)
 DECLARE_MTYPE(COMPLETION)
 
 /*
@@ -94,6 +93,7 @@ enum node_type {
        VRF_DEBUG_NODE,          /* Vrf Debug node. */
        NORTHBOUND_DEBUG_NODE,   /* Northbound Debug node. */
        DEBUG_VNC_NODE,          /* Debug VNC node. */
+       RMAP_DEBUG_NODE,         /* Route-map debug node */
        AAA_NODE,                /* AAA node. */
        KEYCHAIN_NODE,           /* Key-chain node. */
        KEYCHAIN_KEY_NODE,       /* Key-chain key node. */
index 1b304a98b2b151dcaa51084d98383b7c340a31cc..062a4bb30c0395c3e02fbd72866c46d86cf1fc5a 100644 (file)
@@ -46,6 +46,7 @@
 %code requires {
   #include "config.h"
 
+  #include <stdbool.h>
   #include <stdlib.h>
   #include <string.h>
   #include <ctype.h>
   static void
   cleanup (struct parser_ctx *ctx);
 
+  static void loopcheck(struct parser_ctx *ctx, struct subgraph *sg);
+
   #define scanner ctx->scanner
 }
 
@@ -335,6 +338,7 @@ selector: '{' selector_seq_seq '}' varname_token
    * just use [{a|b}] if neccessary, that will work perfectly fine, and reason
    * #1 is good enough to keep it this way. */
 
+  loopcheck(ctx, &$$);
   cmd_token_varname_set ($2.end->data, $4);
   XFREE (MTYPE_LEX, $4);
 };
@@ -396,6 +400,38 @@ cmd_graph_parse (struct graph *graph, struct cmd_element *cmd)
 
 /* parser helper functions */
 
+static bool loopcheck_inner(struct graph_node *start, struct graph_node *node,
+                           struct graph_node *end, size_t depth)
+{
+       size_t i;
+       bool ret;
+
+       /* safety check */
+       if (depth++ == 64)
+               return true;
+
+       for (i = 0; i < vector_active(node->to); i++) {
+               struct graph_node *next = vector_slot(node->to, i);
+               struct cmd_token *tok = next->data;
+
+               if (next == end || next == start)
+                       return true;
+               if (tok->type < SPECIAL_TKN)
+                       continue;
+               ret = loopcheck_inner(start, next, end, depth);
+               if (ret)
+                       return true;
+       }
+       return false;
+}
+
+static void loopcheck(struct parser_ctx *ctx, struct subgraph *sg)
+{
+       if (loopcheck_inner(sg->start, sg->start, sg->end, 0))
+               zlog_err("FATAL: '%s': {} contains an empty path! Use [{...}]",
+                        ctx->el->string);
+}
+
 void
 yyerror (CMD_YYLTYPE *loc, struct parser_ctx *ctx, char const *msg)
 {
index 2a18e5cfc6ac1c8692a359268efdd8bb39e0087b..e588571c014acbf227148da41fd6cf3636a0e5cd 100644 (file)
@@ -28,8 +28,8 @@
 #include "memory.h"
 #include "linklist.h"
 
-DEFINE_MTYPE(LIB, FRR_PTHREAD, "FRR POSIX Thread");
-DEFINE_MTYPE(LIB, PTHREAD_PRIM, "POSIX synchronization primitives");
+DEFINE_MTYPE_STATIC(LIB, FRR_PTHREAD, "FRR POSIX Thread")
+DEFINE_MTYPE_STATIC(LIB, PTHREAD_PRIM, "POSIX sync primitives")
 
 /* default frr_pthread start/stop routine prototypes */
 static void *fpt_run(void *arg);
index 9bc7b94033b2dd6688d2dcf84cc2bfb227101e2d..3afe7ba966a5d293e0e586c6b5978768e447b948 100644 (file)
@@ -29,9 +29,6 @@
 extern "C" {
 #endif
 
-DECLARE_MTYPE(FRR_PTHREAD);
-DECLARE_MTYPE(PTHREAD_PRIM);
-
 #define OS_THREAD_NAMELEN 16
 
 struct frr_pthread;
index fad7de51385d4e6866e893eefb3e76fa3c543983..9d9d39702ec9deacb8d85e45849e9ce60e0ac592 100644 (file)
@@ -29,8 +29,8 @@
 #include "command.h"
 #include "libfrr.h"
 
-DEFINE_MTYPE(LIB, HASH, "Hash")
-DEFINE_MTYPE(LIB, HASH_BACKET, "Hash Bucket")
+DEFINE_MTYPE_STATIC(LIB, HASH, "Hash")
+DEFINE_MTYPE_STATIC(LIB, HASH_BACKET, "Hash Bucket")
 DEFINE_MTYPE_STATIC(LIB, HASH_INDEX, "Hash Index")
 
 static pthread_mutex_t _hashes_mtx = PTHREAD_MUTEX_INITIALIZER;
index c56a98d50c64adc3a6cbaba5a1dede33e423aa04..7b3372d433871e28d62835db10fa9f799d26b8a7 100644 (file)
@@ -28,9 +28,6 @@
 extern "C" {
 #endif
 
-DECLARE_MTYPE(HASH)
-DECLARE_MTYPE(HASH_BACKET)
-
 /* Default hash table size.  */
 #define HASH_INITIAL_SIZE 256
 /* Expansion threshold */
index 4314252d76bb5616ee86cc623f7214b894195461..f7a167f251b95d2e524933ca708e5041d86dfcc7 100644 (file)
--- a/lib/if.c
+++ b/lib/if.c
@@ -39,7 +39,7 @@
 #include "lib/if_clippy.c"
 #endif
 
-DEFINE_MTYPE(LIB, IF, "Interface")
+DEFINE_MTYPE_STATIC(LIB, IF, "Interface")
 DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected")
 DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected")
 DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label")
index 2dc1a7b2de237a6e9c4849499aa8b0089ac1fa9e..603c9c3780cfd2beed09e9ec20d18b9cce21a619 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -31,7 +31,6 @@
 extern "C" {
 #endif
 
-DECLARE_MTYPE(IF)
 DECLARE_MTYPE(CONNECTED_LABEL)
 
 /* Interface link-layer type, if known. Derived from:
index 0002ea3349ad20e68175f3e3350a0e13dd48609a..14cd76f2f50937dcd8d1e84d080b1dc1946bf974 100644 (file)
@@ -102,9 +102,14 @@ struct memgroup {
        }
 
 
+/* the array is a trick to make the "MTYPE_FOO" name work as a pointer without
+ * putting a & in front of it, so we can do "XMALLOC(MTYPE_FOO, ...)" instead
+ * of "XMALLOC(&MTYPE_FOO, ...)".
+ */
 #define DECLARE_MTYPE(name)                                                    \
        extern struct memtype _mt_##name;                                      \
-       static struct memtype *const MTYPE_##name = &_mt_##name;
+       extern struct memtype MTYPE_##name[1];                                 \
+       /* end */
 
 #define DEFINE_MTYPE_ATTR(group, mname, attr, desc)                            \
        attr struct memtype _mt_##mname                                        \
@@ -130,12 +135,21 @@ struct memgroup {
                if (_mt_##mname.next)                                          \
                        _mt_##mname.next->ref = _mt_##mname.ref;               \
                *_mt_##mname.ref = _mt_##mname.next;                           \
-       }
-
-#define DEFINE_MTYPE(group, name, desc) DEFINE_MTYPE_ATTR(group, name, , desc)
+       }                                                                      \
+       /* end */
+
+/* can't quite get gcc to emit the alias correctly, so asm-alias it is :/ */
+#define DEFINE_MTYPE(group, name, desc)                                        \
+       DEFINE_MTYPE_ATTR(group, name, , desc)                                 \
+       __asm__(".equiv MTYPE_" #name ", _mt_" #name "\n\t"                    \
+               ".global MTYPE_" #name "\n");                                  \
+       /* end */
+/* and this one's borked on clang, it drops static on aliases :/, so... asm */
 #define DEFINE_MTYPE_STATIC(group, name, desc)                                 \
        DEFINE_MTYPE_ATTR(group, name, static, desc)                           \
-       static struct memtype *const MTYPE_##name = &_mt_##name;
+       extern struct memtype MTYPE_##name[1];                                 \
+       __asm__(".equiv MTYPE_" #name ", _mt_" #name "\n");                    \
+       /* end */
 
 DECLARE_MGROUP(LIB)
 DECLARE_MTYPE(TMP)
index 54ea742c66c8a22522a2a38b1dfccf94e8f0c23c..1ba898249966096ed039d916cc2134b4b180c074 100644 (file)
@@ -750,6 +750,7 @@ enum prefix_list_type prefix_list_apply_which_prefix(
        if (pbest == NULL)
                return PREFIX_DENY;
 
+       pbest->hitcnt++;
        return pbest->type;
 }
 
index 9336154b1af5039b9c495c8e0ffaec78445cc6ac..2fee3a479efe110cf8cc896d309c18cbe817c887 100644 (file)
@@ -112,14 +112,14 @@ struct route_map_match_set_hooks {
                                                const char *arg,
                                                route_map_event_t type);
 
-       /* match ip next hop type */
+       /* match ip next-hop type */
        int (*match_ip_next_hop_type)(struct vty *vty,
                                             struct route_map_index *index,
                                             const char *command,
                                             const char *arg,
                                             route_map_event_t type);
 
-       /* no match ip next hop type */
+       /* no match ip next-hop type */
        int (*no_match_ip_next_hop_type)(struct vty *vty,
                                                struct route_map_index *index,
                                                const char *command,
@@ -160,7 +160,7 @@ struct route_map_match_set_hooks {
                                              const char *arg,
                                              route_map_event_t type);
 
-       /* no match ipv6next-hop type */
+       /* no match ipv6 next-hop type */
        int (*no_match_ipv6_next_hop_type)(struct vty *vty,
                                           struct route_map_index *index,
                                           const char *command, const char *arg,
@@ -303,7 +303,7 @@ void route_map_no_match_ip_next_hop_prefix_list_hook(int (*func)(
        rmap_match_set_hook.no_match_ip_next_hop_prefix_list = func;
 }
 
-/* match ip next hop type */
+/* match ip next-hop type */
 void route_map_match_ip_next_hop_type_hook(int (*func)(
        struct vty *vty, struct route_map_index *index, const char *command,
        const char *arg, route_map_event_t type))
@@ -311,7 +311,7 @@ void route_map_match_ip_next_hop_type_hook(int (*func)(
        rmap_match_set_hook.match_ip_next_hop_type = func;
 }
 
-/* no match ip next hop type */
+/* no match ip next-hop type */
 void route_map_no_match_ip_next_hop_type_hook(int (*func)(
        struct vty *vty, struct route_map_index *index, const char *command,
        const char *arg, route_map_event_t type))
@@ -688,7 +688,7 @@ 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 *);
-static int rmap_debug = 0;
+static bool rmap_debug;
 
 static void route_map_index_delete(struct route_map_index *, int);
 
@@ -739,6 +739,9 @@ static struct route_map *route_map_add(const char *name)
                (*route_map_master.add_hook)(name);
                route_map_notify_dependencies(name, RMAP_EVENT_CALL_ADDED);
        }
+
+       if (rmap_debug)
+               zlog_debug("Add route-map %s", name);
        return map;
 }
 
@@ -757,6 +760,9 @@ static void route_map_free_map(struct route_map *map)
        while ((index = map->head) != NULL)
                route_map_index_delete(index, 0);
 
+       if (rmap_debug)
+               zlog_debug("Deleting route-map %s", map->name);
+
        list = &route_map_master;
 
        QOBJ_UNREG(map);
@@ -921,6 +927,24 @@ static const char *route_map_type_str(enum route_map_type type)
        return "";
 }
 
+static const char *route_map_result_str(route_map_result_t res)
+{
+       switch (res) {
+       case RMAP_MATCH:
+               return "match";
+       case RMAP_DENYMATCH:
+               return "deny";
+       case RMAP_NOMATCH:
+               return "no match";
+       case RMAP_ERROR:
+               return "error";
+       case RMAP_OKAY:
+               return "okay";
+       }
+
+       return "invalid";
+}
+
 static int route_map_empty(struct route_map *map)
 {
        if (map->head == NULL && map->tail == NULL)
@@ -936,12 +960,12 @@ static void vty_show_route_map_entry(struct vty *vty, struct route_map *map)
        struct route_map_rule *rule;
 
        vty_out(vty, "route-map: %s Invoked: %" PRIu64 "\n",
-               map->name, map->applied);
+               map->name, map->applied - map->applied_clear);
 
        for (index = map->head; index; index = index->next) {
                vty_out(vty, " %s, sequence %d Invoked %" PRIu64 "\n",
                        route_map_type_str(index->type), index->pref,
-                       index->applied);
+                       index->applied - index->applied_clear);
 
                /* Description */
                if (index->description)
@@ -1066,6 +1090,10 @@ static void route_map_index_delete(struct route_map_index *index, int notify)
 
        QOBJ_UNREG(index);
 
+       if (rmap_debug)
+               zlog_debug("Deleting route-map %s sequence %d",
+                          index->map->name, index->pref);
+
        /* Free route match. */
        while ((rule = index->match_list.head) != NULL)
                route_map_rule_delete(&index->match_list, rule);
@@ -1152,6 +1180,11 @@ route_map_index_add(struct route_map *map, enum route_map_type type, int pref)
                (*route_map_master.event_hook)(map->name);
                route_map_notify_dependencies(map->name, RMAP_EVENT_CALL_ADDED);
        }
+
+       if (rmap_debug)
+               zlog_debug("Route-map %s add sequence %d, type: %s",
+                          map->name, pref, route_map_type_str(type));
+
        return index;
 }
 
@@ -1612,6 +1645,7 @@ route_map_result_t route_map_apply(struct route_map *map,
        int ret = 0;
        struct route_map_index *index;
        struct route_map_rule *set;
+       char buf[PREFIX_STRLEN];
 
        if (recursion > RMAP_RECURSION_LIMIT) {
                flog_warn(
@@ -1622,8 +1656,10 @@ route_map_result_t route_map_apply(struct route_map *map,
                return RMAP_DENYMATCH;
        }
 
-       if (map == NULL)
-               return RMAP_DENYMATCH;
+       if (map == NULL) {
+               ret = RMAP_DENYMATCH;
+               goto route_map_apply_end;
+       }
 
        map->applied++;
        for (index = map->head; index; index = index->next) {
@@ -1632,6 +1668,13 @@ route_map_result_t route_map_apply(struct route_map *map,
                ret = route_map_apply_match(&index->match_list, prefix, type,
                                            object);
 
+               if (rmap_debug) {
+                       zlog_debug("Route-map: %s, sequence: %d, prefix: %s, result: %s",
+                                  map->name, index->pref,
+                                  prefix2str(prefix, buf, sizeof(buf)),
+                                  route_map_result_str(ret));
+               }
+
                /* Now we apply the matrix from above */
                if (ret == RMAP_NOMATCH)
                        /* 'cont' from matrix - continue to next route-map
@@ -1666,12 +1709,12 @@ route_map_result_t route_map_apply(struct route_map *map,
 
                                        /* If nextrm returned 'deny', finish. */
                                        if (ret == RMAP_DENYMATCH)
-                                               return ret;
+                                               goto route_map_apply_end;
                                }
 
                                switch (index->exitpolicy) {
                                case RMAP_EXIT:
-                                       return ret;
+                                       goto route_map_apply_end;
                                case RMAP_NEXT:
                                        continue;
                                case RMAP_GOTO: {
@@ -1686,19 +1729,30 @@ route_map_result_t route_map_apply(struct route_map *map,
                                        }
                                        if (next == NULL) {
                                                /* No clauses match! */
-                                               return ret;
+                                               goto route_map_apply_end;
                                        }
                                }
                                }
                        } else if (index->type == RMAP_DENY)
                        /* 'deny' */
                        {
-                               return RMAP_DENYMATCH;
+                               ret = RMAP_DENYMATCH;
+                               goto route_map_apply_end;
                        }
                }
        }
        /* Finally route-map does not match at all. */
-       return RMAP_DENYMATCH;
+       ret = RMAP_DENYMATCH;
+
+route_map_apply_end:
+       if (rmap_debug) {
+               zlog_debug("Route-map: %s, prefix: %s, result: %s",
+                          (map ? map->name : "null"),
+                          prefix2str(prefix, buf, sizeof(buf)),
+                          route_map_result_str(ret));
+       }
+
+       return (ret);
 }
 
 void route_map_add_hook(void (*func)(const char *))
@@ -1835,8 +1889,8 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name,
        case RMAP_EVENT_CALL_ADDED:
        case RMAP_EVENT_FILTER_ADDED:
                if (rmap_debug)
-                       zlog_debug("%s: Adding dependency for %s in %s",
-                                  __FUNCTION__, dep_name, rmap_name);
+                       zlog_debug("Adding dependency for filter %s in route-map %s",
+                                  dep_name, rmap_name);
                dep = (struct route_map_dep *)hash_get(
                        dephash, dname, route_map_dep_hash_alloc);
                if (!dep) {
@@ -1864,8 +1918,8 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name,
        case RMAP_EVENT_CALL_DELETED:
        case RMAP_EVENT_FILTER_DELETED:
                if (rmap_debug)
-                       zlog_debug("%s: Deleting dependency for %s in %s",
-                                  __FUNCTION__, dep_name, rmap_name);
+                       zlog_debug("Deleting dependency for filter %s in route-map %s",
+                                  dep_name, rmap_name);
                dep = (struct route_map_dep *)hash_get(dephash, dname, NULL);
                if (!dep) {
                        goto out;
@@ -1979,8 +2033,7 @@ static void route_map_process_dependency(struct hash_bucket *bucket, void *data)
        rmap_name = dep_data->rname;
 
        if (rmap_debug)
-               zlog_debug("%s: Notifying %s of dependency",
-                          __FUNCTION__, rmap_name);
+               zlog_debug("Notifying %s of dependency", rmap_name);
        if (route_map_master.event_hook)
                (*route_map_master.event_hook)(rmap_name);
 }
@@ -2027,6 +2080,8 @@ void route_map_notify_dependencies(const char *affected_name,
                if (!dep->this_hash)
                        dep->this_hash = upd8_hash;
 
+               if (rmap_debug)
+                       zlog_debug("Filter %s updated", dep->dep_name);
                hash_iterate(dep->dep_rmap_hash, route_map_process_dependency,
                             (void *)event);
        }
@@ -2379,7 +2434,7 @@ DEFUN (no_match_ipv6_address_prefix_list,
 DEFUN(match_ipv6_next_hop_type, match_ipv6_next_hop_type_cmd,
       "match ipv6 next-hop type <blackhole>",
       MATCH_STR IPV6_STR
-      "Match address of route\n"
+      "Match next-hop address of route\n"
       "Match entries by type\n"
       "Blackhole\n")
 {
@@ -2901,6 +2956,46 @@ DEFUN (no_rmap_continue,
        return no_rmap_onmatch_goto(self, vty, argc, argv);
 }
 
+static void clear_route_map_helper(struct route_map *map)
+{
+       struct route_map_index *index;
+
+       map->applied_clear = map->applied;
+       for (index = map->head; index; index = index->next)
+               index->applied_clear = index->applied;
+}
+
+DEFUN (rmap_clear_counters,
+       rmap_clear_counters_cmd,
+       "clear route-map counters [WORD]",
+       CLEAR_STR
+       "route-map information\n"
+       "counters associated with the specified route-map\n"
+       "route-map name\n")
+{
+       int idx_word = 2;
+       struct route_map *map;
+
+       const char *name = (argc == 3 ) ? argv[idx_word]->arg : NULL;
+
+       if (name) {
+               map = route_map_lookup_by_name(name);
+
+               if (map)
+                       clear_route_map_helper(map);
+               else {
+                       vty_out(vty, "%s: 'route-map %s' not found\n",
+                               frr_protonameinst, name);
+                       return CMD_SUCCESS;
+               }
+       } else {
+               for (map = route_map_master.head; map; map = map->next)
+                       clear_route_map_helper(map);
+       }
+
+       return CMD_SUCCESS;
+
+}
 
 DEFUN (rmap_show_name,
        rmap_show_name_cmd,
@@ -3006,6 +3101,30 @@ DEFUN (no_rmap_description,
        return CMD_SUCCESS;
 }
 
+DEFUN (debug_rmap,
+       debug_rmap_cmd,
+       "debug route-map",
+       DEBUG_STR
+       "Debug option set for route-maps\n")
+{
+       rmap_debug = true;
+       return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_rmap,
+       no_debug_rmap_cmd,
+       "no debug route-map",
+       NO_STR
+       DEBUG_STR
+       "Debug option set for route-maps\n")
+{
+       rmap_debug = false;
+       return CMD_SUCCESS;
+}
+
+/* Debug node. */
+static struct cmd_node rmap_debug_node = {RMAP_DEBUG_NODE, "", 1};
+
 /* Configuration write function. */
 static int route_map_config_write(struct vty *vty)
 {
@@ -3014,8 +3133,15 @@ static int route_map_config_write(struct vty *vty)
        struct route_map_rule *rule;
        int first = 1;
        int write = 0;
+       struct listnode *ln;
+       struct list *maplist = list_new();
 
        for (map = route_map_master.head; map; map = map->next)
+               listnode_add(maplist, map);
+
+       list_sort(maplist, sort_route_map);
+
+       for (ALL_LIST_ELEMENTS_RO(maplist, ln, map))
                for (index = map->head; index; index = index->next) {
                        if (!first)
                                vty_out(vty, "!\n");
@@ -3048,6 +3174,20 @@ static int route_map_config_write(struct vty *vty)
 
                        write++;
                }
+
+       list_delete(&maplist);
+       return write;
+}
+
+static int rmap_config_write_debug(struct vty *vty)
+{
+       int write = 0;
+
+       if (rmap_debug) {
+               vty_out(vty, "debug route-map\n");
+               write++;
+       }
+
        return write;
 }
 
@@ -3164,15 +3304,22 @@ void route_map_init(void)
 
        cmd_variable_handler_register(rmap_var_handlers);
 
+       rmap_debug = false;
+
        /* Install route map top node. */
        install_node(&rmap_node, route_map_config_write);
 
+       install_node(&rmap_debug_node, rmap_config_write_debug);
+
        /* Install route map commands. */
        install_default(RMAP_NODE);
        install_element(CONFIG_NODE, &route_map_cmd);
        install_element(CONFIG_NODE, &no_route_map_cmd);
        install_element(CONFIG_NODE, &no_route_map_all_cmd);
 
+       install_element(CONFIG_NODE, &debug_rmap_cmd);
+       install_element(CONFIG_NODE, &no_debug_rmap_cmd);
+
        /* Install the on-match stuff */
        install_element(RMAP_NODE, &route_map_cmd);
        install_element(RMAP_NODE, &rmap_onmatch_next_cmd);
@@ -3193,9 +3340,14 @@ void route_map_init(void)
        install_element(RMAP_NODE, &no_rmap_description_cmd);
 
        /* Install show command */
+       install_element(ENABLE_NODE, &rmap_clear_counters_cmd);
+
        install_element(ENABLE_NODE, &rmap_show_name_cmd);
        install_element(ENABLE_NODE, &rmap_show_unused_cmd);
 
+       install_element(ENABLE_NODE, &debug_rmap_cmd);
+       install_element(ENABLE_NODE, &no_debug_rmap_cmd);
+
        install_element(RMAP_NODE, &match_interface_cmd);
        install_element(RMAP_NODE, &no_match_interface_cmd);
 
index 3781d227df8ae45e2557edfb712ec17dd9c46792..90df1048ed4b7e5780a20e0b1468dad77bcb498e 100644 (file)
@@ -153,6 +153,7 @@ struct route_map_index {
 
        /* Keep track how many times we've try to apply */
        uint64_t applied;
+       uint64_t applied_clear;
 
        QOBJ_FIELDS
 };
@@ -177,6 +178,7 @@ struct route_map {
 
        /* How many times have we applied this route-map */
        uint64_t applied;
+       uint64_t applied_clear;
 
        /* Counter to track active usage of this route-map */
        uint16_t use_count;
index 728615c7760180eb22ae9899f402b4f513f5a534..1a89a95f4f9fb9a8a7d8991ead0ad285b704639c 100644 (file)
@@ -28,7 +28,7 @@
 #include "memory.h"
 #include "sockunion.h"
 
-DEFINE_MTYPE(LIB, ROUTE_TABLE, "Route table")
+DEFINE_MTYPE_STATIC(LIB, ROUTE_TABLE, "Route table")
 DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node")
 
 static void route_table_free(struct route_table *);
index eefd992546a5614e2b10e6ac9030d794452e411e..57b65ac4ba90cb3f93d8c596a0e4172cb894cbc3 100644 (file)
@@ -31,7 +31,6 @@
 extern "C" {
 #endif
 
-DECLARE_MTYPE(ROUTE_TABLE)
 DECLARE_MTYPE(ROUTE_NODE)
 
 /*
index 0db3dc36f2249c6b61b6b18d21e9b2c4888039c9..18a449f647ad017a3c3292067d5876b43dde95df 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -1335,7 +1335,6 @@ static int vty_read(struct thread *thread)
 
        int vty_sock = THREAD_FD(thread);
        struct vty *vty = THREAD_ARG(thread);
-       vty->t_read = NULL;
 
        /* Read raw data from socket */
        if ((nbytes = read(vty->fd, buf, VTY_READ_BUFSIZ)) <= 0) {
@@ -1529,13 +1528,9 @@ static int vty_flush(struct thread *thread)
        int vty_sock = THREAD_FD(thread);
        struct vty *vty = THREAD_ARG(thread);
 
-       vty->t_write = NULL;
-
        /* Tempolary disable read thread. */
-       if ((vty->lines == 0) && vty->t_read) {
-               thread_cancel(vty->t_read);
-               vty->t_read = NULL;
-       }
+       if (vty->lines == 0)
+               THREAD_OFF(vty->t_read);
 
        /* Function execution continue. */
        erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE));
@@ -1713,12 +1708,9 @@ void vty_stdio_suspend(void)
        if (!stdio_vty)
                return;
 
-       if (stdio_vty->t_write)
-               thread_cancel(stdio_vty->t_write);
-       if (stdio_vty->t_read)
-               thread_cancel(stdio_vty->t_read);
-       if (stdio_vty->t_timeout)
-               thread_cancel(stdio_vty->t_timeout);
+       THREAD_OFF(stdio_vty->t_write);
+       THREAD_OFF(stdio_vty->t_read);
+       THREAD_OFF(stdio_vty->t_timeout);
 
        if (stdio_termios)
                tcsetattr(0, TCSANOW, &stdio_orig_termios);
@@ -2077,7 +2069,6 @@ static int vtysh_read(struct thread *thread)
 
        sock = THREAD_FD(thread);
        vty = THREAD_ARG(thread);
-       vty->t_read = NULL;
 
        if ((nbytes = read(sock, buf, VTY_READ_BUFSIZ)) <= 0) {
                if (nbytes < 0) {
@@ -2157,7 +2148,6 @@ static int vtysh_write(struct thread *thread)
 {
        struct vty *vty = THREAD_ARG(thread);
 
-       vty->t_write = NULL;
        vtysh_flush(vty);
        return 0;
 }
@@ -2193,12 +2183,9 @@ void vty_close(struct vty *vty)
        bool was_stdio = false;
 
        /* Cancel threads.*/
-       if (vty->t_read)
-               thread_cancel(vty->t_read);
-       if (vty->t_write)
-               thread_cancel(vty->t_write);
-       if (vty->t_timeout)
-               thread_cancel(vty->t_timeout);
+       THREAD_OFF(vty->t_read);
+       THREAD_OFF(vty->t_write);
+       THREAD_OFF(vty->t_timeout);
 
        /* Flush buffer. */
        buffer_flush_all(vty->obuf, vty->wfd);
@@ -2254,7 +2241,6 @@ static int vty_timeout(struct thread *thread)
        struct vty *vty;
 
        vty = THREAD_ARG(thread);
-       vty->t_timeout = NULL;
        vty->v_timeout = 0;
 
        /* Clear buffer*/
@@ -2651,25 +2637,20 @@ static void vty_event(enum event event, int sock, struct vty *vty)
                vector_set_index(Vvty_serv_thread, sock, vty_serv_thread);
                break;
        case VTYSH_READ:
-               vty->t_read = NULL;
                thread_add_read(vty_master, vtysh_read, vty, sock,
                                &vty->t_read);
                break;
        case VTYSH_WRITE:
-               vty->t_write = NULL;
                thread_add_write(vty_master, vtysh_write, vty, sock,
                                 &vty->t_write);
                break;
 #endif /* VTYSH */
        case VTY_READ:
-               vty->t_read = NULL;
                thread_add_read(vty_master, vty_read, vty, sock, &vty->t_read);
 
                /* Time out treatment. */
                if (vty->v_timeout) {
-                       if (vty->t_timeout)
-                               thread_cancel(vty->t_timeout);
-                       vty->t_timeout = NULL;
+                       THREAD_OFF(vty->t_timeout);
                        thread_add_timer(vty_master, vty_timeout, vty,
                                         vty->v_timeout, &vty->t_timeout);
                }
@@ -2679,15 +2660,10 @@ static void vty_event(enum event event, int sock, struct vty *vty)
                                 &vty->t_write);
                break;
        case VTY_TIMEOUT_RESET:
-               if (vty->t_timeout) {
-                       thread_cancel(vty->t_timeout);
-                       vty->t_timeout = NULL;
-               }
-               if (vty->v_timeout) {
-                       vty->t_timeout = NULL;
+               THREAD_OFF(vty->t_timeout);
+               if (vty->v_timeout)
                        thread_add_timer(vty_master, vty_timeout, vty,
                                         vty->v_timeout, &vty->t_timeout);
-               }
                break;
        }
 }
@@ -3024,7 +3000,7 @@ void vty_reset(void)
        for (i = 0; i < vector_active(Vvty_serv_thread); i++)
                if ((vty_serv_thread = vector_slot(Vvty_serv_thread, i))
                    != NULL) {
-                       thread_cancel(vty_serv_thread);
+                       THREAD_OFF(vty_serv_thread);
                        vector_slot(Vvty_serv_thread, i) = NULL;
                        close(i);
                }
index 2f9a9aa5a3d79f76c7f46a1070044a270aa30429..674f3610d6f004b47c34b738c3885458908f1b7f 100644 (file)
@@ -27,8 +27,8 @@
 
 #include <libyang/user_types.h>
 
-DEFINE_MTYPE(LIB, YANG_MODULE, "YANG module")
-DEFINE_MTYPE(LIB, YANG_DATA, "YANG data structure")
+DEFINE_MTYPE_STATIC(LIB, YANG_MODULE, "YANG module")
+DEFINE_MTYPE_STATIC(LIB, YANG_DATA, "YANG data structure")
 
 /* libyang container. */
 struct ly_ctx *ly_native_ctx;
index 6f8c84ab64276050933cbff90639e1b3bc98ea06..322c74c76a5fe6458bd7d303cf81479a02736106 100644 (file)
@@ -33,9 +33,6 @@
 extern "C" {
 #endif
 
-DECLARE_MTYPE(YANG_MODULE)
-DECLARE_MTYPE(YANG_DATA)
-
 /* Maximum XPath length. */
 #define XPATH_MAXLEN 256
 
index ab2d5ae5844cec5584445526bfb5a768baeb76f6..bb7e97bf7beba4d50026a673599d8ea84bd79682 100644 (file)
@@ -210,6 +210,40 @@ struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
        route_match_ip_next_hop_prefix_list_compile,
        route_match_ip_next_hop_prefix_list_free};
 
+/* `match ip next-hop type <blackhole>' */
+
+static route_map_result_t
+route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
+                            route_map_object_t type, void *object)
+{
+       struct external_info *ei = object;
+
+       if (type == RMAP_OSPF && prefix->family == AF_INET) {
+               ei = (struct external_info *)object;
+               if (!ei)
+                       return RMAP_DENYMATCH;
+
+               if (ei->nexthop.s_addr == INADDR_ANY && !ei->ifindex)
+                       return RMAP_MATCH;
+       }
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ip_next_hop_type_compile(const char *arg)
+{
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ip_next_hop_type_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
+       "ip next-hop type", route_match_ip_next_hop_type,
+       route_match_ip_next_hop_type_compile,
+       route_match_ip_next_hop_type_free};
+
 /* `match ip address IP_ACCESS_LIST' */
 /* Match function should return 1 if match is success else return
    zero. */
@@ -566,6 +600,9 @@ void ospf_route_map_init(void)
        route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
        route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
 
+       route_map_match_ip_next_hop_type_hook(generic_match_add);
+       route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
+
        route_map_match_tag_hook(generic_match_add);
        route_map_no_match_tag_hook(generic_match_delete);
 
@@ -579,6 +616,7 @@ void ospf_route_map_init(void)
        route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
        route_map_install_match(&route_match_ip_address_cmd);
        route_map_install_match(&route_match_ip_address_prefix_list_cmd);
+       route_map_install_match(&route_match_ip_next_hop_type_cmd);
        route_map_install_match(&route_match_interface_cmd);
        route_map_install_match(&route_match_tag_cmd);
 
index 438a0c9b64dba825bc817f2fb0eebf6c2d9af0e8..228218e3a31879dfd29e332bc9f74c617d944e0c 100644 (file)
@@ -148,12 +148,6 @@ static int dispatch_assert(struct interface *ifp, struct in_addr source_addr,
        sg.src = source_addr;
        sg.grp = group_addr;
        ch = pim_ifchannel_add(ifp, &sg, 0, 0);
-       if (!ch) {
-               zlog_warn(
-                       "%s: (S,G)=%s failure creating channel on interface %s",
-                       __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), ifp->name);
-               return -1;
-       }
 
        switch (ch->ifassert_state) {
        case PIM_IFASSERT_NOINFO:
index 266d3ffcf521824ce13f4721a6fc55af6fdc162f..9995b5e31f0afae70f28ac9e820d6b46a2bfd259 100644 (file)
@@ -152,14 +152,6 @@ static struct bsgrp_node *pim_bsm_new_bsgrp_node(struct route_table *rt,
        }
        bsgrp = XCALLOC(MTYPE_PIM_BSGRP_NODE, sizeof(struct bsgrp_node));
 
-       if (!bsgrp) {
-               if (PIM_DEBUG_BSM)
-                       zlog_debug("%s: bsgrp alloc failed",
-                                  __PRETTY_FUNCTION__);
-               route_unlock_node(rn);
-               return NULL;
-       }
-
        rn->info = bsgrp;
        bsgrp->bsrp_list = pim_alloc_bsrp_list();
        bsgrp->partial_bsrp_list = pim_alloc_bsrp_list();
@@ -730,12 +722,6 @@ static bool pim_bsm_frag_send(uint8_t *buf, uint32_t len, struct interface *ifp,
 
        pak_start = XCALLOC(MTYPE_PIM_BSM_PKT_VAR_MEM, pim_mtu);
 
-       if (!pak_start) {
-               if (PIM_DEBUG_BSM)
-                       zlog_debug("%s: malloc failed", __PRETTY_FUNCTION__);
-               return false;
-       }
-
        pkt = pak_start;
 
        /* Fill PIM header later before sending packet to calc checksum */
@@ -1057,13 +1043,6 @@ static bool pim_install_bsm_grp_rp(struct pim_instance *pim,
        /*memory allocation for bsm_rpinfo */
        bsm_rpinfo = XCALLOC(MTYPE_PIM_BSRP_NODE, sizeof(*bsm_rpinfo));
 
-       if (!bsm_rpinfo) {
-               if (PIM_DEBUG_BSM)
-                       zlog_debug("%s, Memory allocation failed.\r\n",
-                                  __PRETTY_FUNCTION__);
-               return false;
-       }
-
        bsm_rpinfo->rp_prio = rp->rp_pri;
        bsm_rpinfo->rp_holdtime = rp->rp_holdtime;
        memcpy(&bsm_rpinfo->rp_address, &rp->rpaddr.addr,
@@ -1387,18 +1366,8 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf,
        if (!no_fwd) {
                pim_bsm_fwd_whole_sz(pim_ifp->pim, buf, buf_size, sz);
                bsminfo = XCALLOC(MTYPE_PIM_BSM_INFO, sizeof(struct bsm_info));
-               if (!bsminfo) {
-                       zlog_warn("%s: bsminfo alloc failed",
-                                 __PRETTY_FUNCTION__);
-                       return 0;
-               }
 
                bsminfo->bsm = XCALLOC(MTYPE_PIM_BSM_PKT_VAR_MEM, buf_size);
-               if (!bsminfo->bsm) {
-                       zlog_warn("%s: bsm alloc failed", __PRETTY_FUNCTION__);
-                       XFREE(MTYPE_PIM_BSM_INFO, bsminfo);
-                       return 0;
-               }
 
                bsminfo->size = buf_size;
                memcpy(bsminfo->bsm, buf, buf_size);
index c6617d9d212d451623aafc5bce5e29a30581b7f9..72d7916b20ee416e3a8adf69ef0dfb86f81d2039 100644 (file)
@@ -6653,13 +6653,7 @@ static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)
        pim_ifp = ifp->info;
 
        if (!pim_ifp) {
-               pim_ifp = pim_if_new(ifp, true, false, false,
-                       false /*vxlan_term*/);
-               if (!pim_ifp) {
-                       vty_out(vty, "Could not enable IGMP on interface %s\n",
-                               ifp->name);
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
+               (void)pim_if_new(ifp, true, false, false, false);
                need_startup = 1;
        } else {
                if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
@@ -7360,19 +7354,40 @@ DEFUN (interface_no_ip_pim_drprio,
        return CMD_SUCCESS;
 }
 
+DEFPY_HIDDEN (interface_ip_igmp_query_generate,
+       interface_ip_igmp_query_generate_cmd,
+       "ip igmp generate-query-once [version (2-3)]",
+       IP_STR
+       IFACE_IGMP_STR
+       "Generate igmp general query once\n"
+       "IGMP version\n"
+       "IGMP version number\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       int igmp_version = 2;
+
+       if (!ifp->info) {
+               vty_out(vty, "IGMP/PIM is not enabled on the interface %s\n",
+                       ifp->name);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       if (argc > 3)
+               igmp_version = atoi(argv[4]->arg);
+
+       igmp_send_query_on_intf(ifp, igmp_version);
+
+       return CMD_SUCCESS;
+}
+
 static int pim_cmd_interface_add(struct interface *ifp)
 {
        struct pim_interface *pim_ifp = ifp->info;
 
-       if (!pim_ifp) {
-               pim_ifp = pim_if_new(ifp, false, true, false,
-                       false /*vxlan_term*/);
-               if (!pim_ifp) {
-                       return 0;
-               }
-       } else {
+       if (!pim_ifp)
+               (void)pim_if_new(ifp, false, true, false, false);
+       else
                PIM_IF_DO_PIM(pim_ifp->options);
-       }
 
        pim_if_addr_add_all(ifp);
        pim_if_membership_refresh(ifp);
@@ -10289,6 +10304,7 @@ void pim_cmd_init(void)
        install_element(INTERFACE_NODE, &interface_no_ip_pim_hello_cmd);
        install_element(INTERFACE_NODE, &interface_ip_pim_boundary_oil_cmd);
        install_element(INTERFACE_NODE, &interface_no_ip_pim_boundary_oil_cmd);
+       install_element(INTERFACE_NODE, &interface_ip_igmp_query_generate_cmd);
 
        // Static mroutes NEB
        install_element(INTERFACE_NODE, &interface_ip_mroute_cmd);
index 7b8f045697884cd7de1a85f7e8c7e841a77b883a..0511a1a157cb539d9f7f08d548ba2223d61b5c6d 100644 (file)
@@ -1293,11 +1293,7 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
                return ferr_ok();
        }
 
-       ij = igmp_join_new(ifp, group_addr, source_addr);
-       if (!ij) {
-               return ferr_cfg_invalid(
-                       "Failure to create new join data structure, see log file for more information");
-       }
+       (void)igmp_join_new(ifp, group_addr, source_addr);
 
        if (PIM_DEBUG_IGMP_EVENTS) {
                char group_str[INET_ADDRSTRLEN];
index 9b242e9be5fdf572b6097a425879de3ed6acad91..96c7e8052ceda38c08f16a24ad0038bf697e328b 100644 (file)
@@ -133,7 +133,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
        if (ch->upstream->channel_oil) {
                uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
                if (ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
-                       mask = PIM_OIF_FLAG_PROTO_IGMP;
+                       mask |= PIM_OIF_FLAG_PROTO_IGMP;
 
                /*
                 * A S,G RPT channel can have an empty oil, we also
@@ -142,13 +142,15 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
                 * 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))
+               if ((ch->sg.src.s_addr != INADDR_ANY) &&
+                               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);
+                                       ch->interface,
+                                       PIM_OIF_FLAG_PROTO_STAR);
+
+               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.
@@ -227,6 +229,8 @@ void pim_ifchannel_delete_all(struct interface *ifp)
        while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
                ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
 
+               pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__,
+                               ch, PIM_IFJOIN_NOINFO);
                pim_ifchannel_delete(ch);
        }
 }
@@ -613,6 +617,10 @@ static int on_ifjoin_expiry_timer(struct thread *t)
 
        ch = THREAD_ARG(t);
 
+       if (PIM_DEBUG_TRACE)
+               zlog_debug("%s: ifchannel %s expiry timer", __PRETTY_FUNCTION__,
+                          ch->sg_str);
+
        ifjoin_to_noinfo(ch, true);
        /* ch may have been deleted */
 
@@ -787,8 +795,6 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
 
        ch = pim_ifchannel_add(ifp, sg, source_flags,
                               PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
-       if (!ch)
-               return;
 
        /*
          RFC 4601: 4.6.1.  (S,G) Assert Message State Machine
@@ -949,8 +955,6 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
 
        ch = pim_ifchannel_add(ifp, sg, source_flags,
                               PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
-       if (!ch)
-               return;
 
        pim_ifp = ifp->info;
 
@@ -1078,13 +1082,6 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
        }
 
        ch = pim_ifchannel_add(ifp, sg, 0, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
-       if (!ch) {
-               if (PIM_DEBUG_EVENTS)
-                       zlog_debug("%s:%s Unable to add ifchannel",
-                                  __PRETTY_FUNCTION__,
-                                  pim_str_sg_dump(sg));
-               return 0;
-       }
 
        ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE);
 
index 4ae6f69d3eee39dd92f408b71b9dbf738b647a96..7dfd26ea655d9c67662c5510ebf0313c15876223 100644 (file)
@@ -305,6 +305,13 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version,
                return -1;
        }
 
+       if (!pim_if_connected_to_source(ifp, from)) {
+               if (PIM_DEBUG_IGMP_PACKETS)
+                       zlog_debug("Recv IGMP query on interface: %s from a non-connected source: %s",
+                                  ifp->name, from_str);
+               return 0;
+       }
+
        /* Collecting IGMP Rx stats */
        switch (query_version) {
        case 1:
@@ -1180,3 +1187,42 @@ void igmp_send_query(int igmp_version, struct igmp_group *group, int fd,
                                   group_addr, query_max_response_time_dsec);
        }
 }
+
+void igmp_send_query_on_intf(struct interface *ifp, int igmp_ver)
+{
+       struct pim_interface *pim_ifp = ifp->info;
+       struct listnode *sock_node = NULL;
+       struct igmp_sock *igmp = NULL;
+       struct in_addr dst_addr;
+       struct in_addr group_addr;
+       int query_buf_size;
+
+       if (!igmp_ver)
+               igmp_ver = 2;
+
+       if (igmp_ver == 3)
+               query_buf_size = PIM_IGMP_BUFSIZE_WRITE;
+       else
+               query_buf_size = IGMP_V12_MSG_SIZE;
+
+       dst_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
+       group_addr.s_addr = PIM_NET_INADDR_ANY;
+
+       if (PIM_DEBUG_IGMP_TRACE)
+               zlog_debug("Issuing general query on request on %s",
+                               ifp->name);
+
+       for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
+
+               char query_buf[query_buf_size];
+
+               igmp_send_query(igmp_ver, 0 /* igmp_group */, igmp->fd,
+                               igmp->interface->name, query_buf,
+                               sizeof(query_buf), 0 /* num_sources */,
+                               dst_addr, group_addr,
+                               pim_ifp->igmp_query_max_response_time_dsec,
+                               1 /* s_flag: always set for general queries */,
+                               igmp->querier_robustness_variable,
+                               igmp->querier_query_interval);
+       }
+}
index 7db568dcfe21597b36766edcbb761c555b6f51d8..9231b0b41fb0128120122eb1c46bc8a8ca55e22b 100644 (file)
@@ -198,4 +198,6 @@ void igmp_send_query(int igmp_version, struct igmp_group *group, int fd,
                     uint8_t querier_robustness_variable,
                     uint16_t querier_query_interval);
 void igmp_group_delete(struct igmp_group *group);
+
+void igmp_send_query_on_intf(struct interface *ifp, int igmp_ver);
 #endif /* PIM_IGMP_H */
index bc0460fa0397072ae44198afc94dfbf3774b797b..d9b940bba7203a10107c5455bb2f15591bdaa358 100644 (file)
@@ -332,7 +332,8 @@ void igmp_source_free(struct igmp_source *source)
 static void source_channel_oil_detach(struct igmp_source *source)
 {
        if (source->source_channel_oil) {
-               pim_channel_oil_del(source->source_channel_oil);
+               pim_channel_oil_del(source->source_channel_oil,
+                                   __PRETTY_FUNCTION__);
                source->source_channel_oil = NULL;
        }
 }
index ca0582434768dfba7da251fac285be22ba26c896..b1c55c1f43438e9c54005dbf1c9a3e7c1d8d79fd 100644 (file)
@@ -201,9 +201,14 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
                 * Let's blackhole those packets for the moment
                 * As that they will be coming up to the cpu
                 * and causing us to consider them.
+                *
+                * This *will* create a dangling channel_oil
+                * that I see no way to get rid of.  Just noting
+                * this for future reference.
                 */
                c_oil = pim_channel_oil_add(pim_ifp->pim, &sg,
-                                           pim_ifp->mroute_vif_index);
+                                           pim_ifp->mroute_vif_index,
+                                           __PRETTY_FUNCTION__);
                pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
 
                return 0;
@@ -211,14 +216,6 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
 
        up = pim_upstream_find_or_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR,
                                      __PRETTY_FUNCTION__);
-       if (!up) {
-               if (PIM_DEBUG_MROUTE) {
-                       zlog_debug(
-                               "%s: Failure to add upstream information for %s",
-                               __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
-               }
-               return 0;
-       }
 
        /*
         * I moved this debug till after the actual add because
@@ -523,7 +520,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
                        if (!up->channel_oil)
                                up->channel_oil = pim_channel_oil_add(
                                        pim_ifp->pim, &sg,
-                                       pim_ifp->mroute_vif_index);
+                                       pim_ifp->mroute_vif_index,
+                                       __PRETTY_FUNCTION__);
                        pim_upstream_inherited_olist(pim_ifp->pim, up);
                        if (!up->channel_oil->installed)
                                pim_mroute_add(up->channel_oil,
@@ -548,7 +546,8 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
        }
 
        pim_ifp = ifp->info;
-       oil = pim_channel_oil_add(pim_ifp->pim, &sg, pim_ifp->mroute_vif_index);
+       oil = pim_channel_oil_add(pim_ifp->pim, &sg, pim_ifp->mroute_vif_index,
+                                 __PRETTY_FUNCTION__);
        if (!oil->installed)
                pim_mroute_add(oil, __PRETTY_FUNCTION__);
        if (pim_if_connected_to_source(ifp, sg.src)) {
index 5f5030396750cc4cb9b0a6694e4cfd0b965d8d27..b6e2cada1fab1b3336159816f78042aea4d5abef 100644 (file)
@@ -66,9 +66,19 @@ struct pim_encoded_ipv4_unicast {
        struct in_addr addr;
 } __attribute__((packed));
 
+/*
+ *  Encoded Group format. RFC 4601 Sec 4.9.1
+ *   0                   1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |  Addr Family  | Encoding Type |B| Reserved  |Z|  Mask Len     |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                Group multicast Address
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+...
+ */
 struct pim_encoded_group_ipv4 {
-       uint8_t ne;
        uint8_t family;
+       uint8_t ne;
        uint8_t bidir : 1;      /* Bidir bit */
        uint8_t reserved : 6;   /* Reserved */
        uint8_t sz : 1;         /* scope zone bit */
@@ -76,9 +86,20 @@ struct pim_encoded_group_ipv4 {
        struct in_addr addr;
 } __attribute__((packed));
 
+
+/*
+ *  Encoded Source format. RFC 4601 Sec 4.9.1
+ *   0                   1                   2                   3
+ *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  | Addr Family   | Encoding Type | Rsrvd   |S|W|R|  Mask Len     |
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *  |                        Source Address
+ *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...
+ */
 struct pim_encoded_source_ipv4 {
-       uint8_t ne;
        uint8_t family;
+       uint8_t ne;
        uint8_t bits;
        uint8_t mask;
        struct in_addr addr;
index 22045c2d337c99ac27aa2b60fa2a768e43959018..d4fc03e20c4ac5db111454534ee34d0b1b427419 100644 (file)
 char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
 {
        char *out;
+       struct interface *ifp;
        struct prefix_sg sg;
        int i;
 
        sg.src = c_oil->oil.mfcc_origin;
        sg.grp = c_oil->oil.mfcc_mcastgrp;
-       snprintf(buf, size, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
-                c_oil->oil.mfcc_parent);
+       ifp = pim_if_find_by_vif_index(c_oil->pim, c_oil->oil.mfcc_parent);
+       snprintf(buf, size, "%s IIF: %s, OIFS: ", pim_str_sg_dump(&sg),
+                ifp ? ifp->name : "(?)");
 
        out = buf + strlen(buf);
        for (i = 0; i < MAXVIFS; i++) {
                if (c_oil->oil.mfcc_ttls[i] != 0) {
-                       snprintf(out, buf + size - out, "%d ", i);
+                       ifp = pim_if_find_by_vif_index(c_oil->pim, i);
+                       snprintf(out, buf + size - out, "%s ",
+                                ifp ? ifp->name : "(?)");
                        out += strlen(out);
                }
        }
@@ -144,7 +148,7 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
 
 struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
                                        struct prefix_sg *sg,
-                                       int input_vif_index)
+                                       int input_vif_index, const char *name)
 {
        struct channel_oil *c_oil;
        struct interface *ifp;
@@ -153,18 +157,23 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
        if (c_oil) {
                if (c_oil->oil.mfcc_parent != input_vif_index) {
                        c_oil->oil_inherited_rescan = 1;
-                       if (PIM_DEBUG_MROUTE)
+                       if (PIM_DEBUG_MROUTE_DETAIL)
                                zlog_debug(
-                                       "%s: Existing channel oil %s points to %d, modifying to point at %d",
-                                       __PRETTY_FUNCTION__,
-                                       pim_str_sg_dump(sg),
+                                       "%s: Existing channel oil %pSG4 points to %d, modifying to point at %d",
+                                       __PRETTY_FUNCTION__, sg,
                                        c_oil->oil.mfcc_parent,
                                        input_vif_index);
                }
                c_oil->oil.mfcc_parent = input_vif_index;
                ++c_oil->oil_ref_count;
-               c_oil->up = pim_upstream_find(
-                       pim, sg); // channel might be present prior to upstream
+               /* channel might be present prior to upstream */
+               c_oil->up = pim_upstream_find(pim, sg);
+
+               if (PIM_DEBUG_MROUTE)
+                       zlog_debug(
+                               "%s(%s): Existing oil for %pSG4 Ref Count: %d (Post Increment)",
+                               __PRETTY_FUNCTION__, name, sg,
+                               c_oil->oil_ref_count);
                return c_oil;
        }
 
@@ -173,9 +182,8 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
                if (!ifp) {
                        /* warning only */
                        zlog_warn(
-                               "%s: (S,G)=%s could not find input interface for input_vif_index=%d",
-                               __PRETTY_FUNCTION__, pim_str_sg_dump(sg),
-                               input_vif_index);
+                               "%s:%s (S,G)=%pSG4 could not find input interface for input_vif_index=%d",
+                               __PRETTY_FUNCTION__, name, sg, input_vif_index);
                }
        }
 
@@ -193,11 +201,23 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
 
        listnode_add_sort(pim->channel_oil_list, c_oil);
 
+       if (PIM_DEBUG_MROUTE)
+               zlog_debug(
+                       "%s(%s): New oil for %pSG4 vif_index: %d Ref Count: 1 (Post Increment)",
+                       __PRETTY_FUNCTION__, name, sg, input_vif_index);
        return c_oil;
 }
 
-void pim_channel_oil_del(struct channel_oil *c_oil)
+void pim_channel_oil_del(struct channel_oil *c_oil, const char *name)
 {
+       if (PIM_DEBUG_MROUTE) {
+               struct prefix_sg sg = {.src = c_oil->oil.mfcc_mcastgrp,
+                                      .grp = c_oil->oil.mfcc_origin};
+
+               zlog_debug(
+                       "%s(%s): Del oil for %pSG4, Ref Count: %d (Predecrement)",
+                       __PRETTY_FUNCTION__, name, &sg, c_oil->oil_ref_count);
+       }
        --c_oil->oil_ref_count;
 
        if (c_oil->oil_ref_count < 1) {
@@ -344,10 +364,12 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
          IGMP must be protected against adding looped MFC entries created
          by both source and receiver attached to the same interface. See
          TODO T22.
+         We shall allow igmp to create upstream when it is DR for the intf.
+         Assume RP reachable via non DR.
        */
-       if (channel_oil->up &&
-                       PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(
-                               channel_oil->up->flags)) {
+       if ((channel_oil->up &&
+           PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(channel_oil->up->flags)) ||
+           ((proto_mask == PIM_OIF_FLAG_PROTO_IGMP) && PIM_I_am_DR(pim_ifp))) {
                allow_iif_in_oil = true;
        }
 
index d097da6b3eb761959bf521f000533b288c6eacd8..485299196db48e66a28c75f2c313a03e211c78c0 100644 (file)
@@ -113,8 +113,8 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
                                         struct prefix_sg *sg);
 struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
                                        struct prefix_sg *sg,
-                                       int input_vif_index);
-void pim_channel_oil_del(struct channel_oil *c_oil);
+                                       int input_vif_index, const char *name);
+void pim_channel_oil_del(struct channel_oil *c_oil, const char *name);
 
 int pim_channel_add_oif(struct channel_oil *c_oil, struct interface *oif,
                        uint32_t proto_mask);
index 442b22e06fc6c674a40ee62f9b65df0764d2381d..62c3216e864946756f22c4a189ac0689b3a6610e 100644 (file)
@@ -124,9 +124,6 @@ int pim_static_add(struct pim_instance *pim, struct interface *iif,
                         * back if it fails.
                         */
                        original_s_route = static_route_alloc();
-                       if (!original_s_route) {
-                               return -5;
-                       }
                        memcpy(original_s_route, s_route,
                               sizeof(struct static_route));
 
index 50c68c66bdc2cfdaa85b2727bed30d269e0633a9..194fb2cffdd02af5dc053d73b09b14784726e177 100644 (file)
@@ -146,7 +146,7 @@ static void upstream_channel_oil_detach(struct pim_upstream *up)
                   but upstream would not keep reference of it
                 */
                up->channel_oil->up = NULL;
-               pim_channel_oil_del(up->channel_oil);
+               pim_channel_oil_del(up->channel_oil, __PRETTY_FUNCTION__);
                up->channel_oil = NULL;
        }
 }
@@ -740,13 +740,15 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
                pim_upstream_fill_static_iif(up, incoming);
                pim_ifp = up->rpf.source_nexthop.interface->info;
                assert(pim_ifp);
-               up->channel_oil = pim_channel_oil_add(pim,
-                               &up->sg, pim_ifp->mroute_vif_index);
+               up->channel_oil = pim_channel_oil_add(pim, &up->sg,
+                                                     pim_ifp->mroute_vif_index,
+                                                     __PRETTY_FUNCTION__);
        } else if (up->upstream_addr.s_addr == INADDR_ANY) {
                /* Create a dummmy channel oil with incoming ineterface MAXVIFS,
                 * since RP is not configured
                 */
-               up->channel_oil = pim_channel_oil_add(pim, &up->sg, MAXVIFS);
+               up->channel_oil = pim_channel_oil_add(pim, &up->sg, MAXVIFS,
+                                                     __PRETTY_FUNCTION__);
 
        } else {
                rpf_result = pim_rpf_update(pim, up, NULL);
@@ -759,14 +761,27 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
                         * MAXVIFS, since RP is not reachable
                         */
                        up->channel_oil = pim_channel_oil_add(
-                               pim, &up->sg, MAXVIFS);
+                               pim, &up->sg, MAXVIFS, __PRETTY_FUNCTION__);
                }
 
                if (up->rpf.source_nexthop.interface) {
                        pim_ifp = up->rpf.source_nexthop.interface->info;
                        if (pim_ifp)
-                               up->channel_oil = pim_channel_oil_add(pim,
-                                       &up->sg, pim_ifp->mroute_vif_index);
+                               up->channel_oil = pim_channel_oil_add(
+                                       pim, &up->sg, pim_ifp->mroute_vif_index,
+                                       __PRETTY_FUNCTION__);
+                       else {
+                               /*
+                                * Yeah this should not happen
+                                * but let's be sure that we are not
+                                * doing something stupid, all paths
+                                * through upstream creation will
+                                * create a channel oil
+                                */
+                               up->channel_oil = pim_channel_oil_add(
+                                       pim, &up->sg, MAXVIFS,
+                                       __PRETTY_FUNCTION__);
+                       }
                }
        }
 
@@ -1524,8 +1539,9 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
                                   __PRETTY_FUNCTION__, up->sg_str);
        }
        if (pim_ifp && !up->channel_oil)
-               up->channel_oil = pim_channel_oil_add(
-                       pim, &up->sg, pim_ifp->mroute_vif_index);
+               up->channel_oil = pim_channel_oil_add(pim, &up->sg,
+                                                     pim_ifp->mroute_vif_index,
+                                                     __PRETTY_FUNCTION__);
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                if (!ifp->info)
index 468cd56ee55bf315726948b9433ba2b8ca065a99..d1935195df4855a037c5f162f3562aa5f7847247 100644 (file)
@@ -70,10 +70,6 @@ int pim_debug_config_write(struct vty *vty)
                vty_out(vty, "debug igmp trace\n");
                ++writes;
        }
-       if (PIM_DEBUG_IGMP_TRACE_DETAIL) {
-               vty_out(vty, "debug igmp trace detail\n");
-               ++writes;
-       }
 
        if (PIM_DEBUG_MROUTE) {
                vty_out(vty, "debug mroute\n");
index 25ac307ac43defc1b51e27ba89d169df7da729db..2c814d0fdcb09f6bbeab7ed48db856b598fecbdb 100644 (file)
@@ -974,18 +974,8 @@ void igmp_source_forward_start(struct pim_instance *pim,
                if (!pim_rp_set_upstream_addr(pim, &vif_source,
                                              source->source_addr, sg.grp)) {
                        /*Create a dummy channel oil */
-                       source->source_channel_oil =
-                           pim_channel_oil_add(pim, &sg, MAXVIFS);
-
-                       if (!source->source_channel_oil) {
-                               if (PIM_DEBUG_IGMP_TRACE) {
-                                       zlog_debug(
-                                       "%s %s: could not create OIL for channel (S,G)=%s",
-                                       __FILE__, __PRETTY_FUNCTION__,
-                                       pim_str_sg_dump(&sg));
-                               }
-                               return;
-                       }
+                       source->source_channel_oil = pim_channel_oil_add(
+                               pim, &sg, MAXVIFS, __PRETTY_FUNCTION__);
                }
 
                else {
@@ -1035,7 +1025,9 @@ void igmp_source_forward_start(struct pim_instance *pim,
                                            source_str);
                                }
                                source->source_channel_oil =
-                                   pim_channel_oil_add(pim, &sg, MAXVIFS);
+                                       pim_channel_oil_add(
+                                               pim, &sg, MAXVIFS,
+                                               __PRETTY_FUNCTION__);
                        }
 
                        else {
@@ -1043,10 +1035,12 @@ void igmp_source_forward_start(struct pim_instance *pim,
                                 * Protect IGMP against adding looped MFC
                                 * entries created by both source and receiver
                                 * attached to the same interface. See TODO
-                                * T22.
+                                * T22. Block only when the intf is non DR
+                                * DR must create upstream.
                                 */
-                               if (input_iface_vif_index ==
-                                   pim_oif->mroute_vif_index) {
+                               if ((input_iface_vif_index ==
+                                   pim_oif->mroute_vif_index) &&
+                                   !(PIM_I_am_DR(pim_oif))) {
                                        /* ignore request for looped MFC entry
                                         */
                                        if (PIM_DEBUG_IGMP_TRACE) {
@@ -1065,8 +1059,9 @@ void igmp_source_forward_start(struct pim_instance *pim,
                                }
 
                                source->source_channel_oil =
-                                   pim_channel_oil_add(pim, &sg,
-                                       input_iface_vif_index);
+                                       pim_channel_oil_add(
+                                               pim, &sg, input_iface_vif_index,
+                                               __PRETTY_FUNCTION__);
                                if (!source->source_channel_oil) {
                                        if (PIM_DEBUG_IGMP_TRACE) {
                                                zlog_debug(
@@ -1241,22 +1236,14 @@ void pim_forward_start(struct pim_ifchannel *ch)
                                        __FILE__, __PRETTY_FUNCTION__,
                                        source_str);
                        }
-                       up->channel_oil = pim_channel_oil_add(pim, &up->sg,
-                                                               MAXVIFS);
+                       up->channel_oil = pim_channel_oil_add(
+                               pim, &up->sg, MAXVIFS, __PRETTY_FUNCTION__);
                }
 
-               else {
-                       up->channel_oil = pim_channel_oil_add(pim, &up->sg,
-                                                       input_iface_vif_index);
-                       if (!up->channel_oil) {
-                               if (PIM_DEBUG_PIM_TRACE)
-                                       zlog_debug(
-                                           "%s %s: could not create OIL for channel (S,G)=%s",
-                                           __FILE__, __PRETTY_FUNCTION__,
-                                           up->sg_str);
-                               return;
-                       }
-               }
+               else
+                       up->channel_oil = pim_channel_oil_add(
+                               pim, &up->sg, input_iface_vif_index,
+                               __PRETTY_FUNCTION__);
 
                if (PIM_DEBUG_TRACE) {
                        struct interface *in_intf = pim_if_find_by_vif_index(
@@ -1268,16 +1255,9 @@ void pim_forward_start(struct pim_ifchannel *ch)
                                input_iface_vif_index, up->sg_str);
                }
 
-               up->channel_oil = pim_channel_oil_add(pim, &up->sg,
-                                                     input_iface_vif_index);
-               if (!up->channel_oil) {
-                       if (PIM_DEBUG_PIM_TRACE)
-                               zlog_debug(
-                                       "%s %s: could not create OIL for channel (S,G)=%s",
-                                       __FILE__, __PRETTY_FUNCTION__,
-                                       up->sg_str);
-                       return;
-               }
+               up->channel_oil =
+                       pim_channel_oil_add(pim, &up->sg, input_iface_vif_index,
+                                           __PRETTY_FUNCTION__);
        }
 
        if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
index 634fee0b3025ad57776ddfdcd230f8af57cbb94d..80561f350ba2abcf901d1873c5447f2477e80387 100644 (file)
@@ -43,6 +43,8 @@
 #include "ripd/rip_debug.h"
 #include "ripd/rip_interface.h"
 
+DEFINE_MTYPE_STATIC(RIPD, RIP_INTERFACE, "RIP interface")
+DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String")
 DEFINE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc))
 DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc))
 
index 6befda0e28606c883690ee6e880de9fdd3bef9c7..715daf2e503b63a60d5cc46cbfc21381ec4b2351 100644 (file)
 #ifndef _QUAGGA_RIP_INTERFACE_H
 #define _QUAGGA_RIP_INTERFACE_H
 
+#include "memory.h"
 #include "zclient.h"
 
+DECLARE_MTYPE(RIP_INTERFACE_STRING)
+
 extern int rip_interface_down(int, struct zclient *, zebra_size_t, vrf_id_t);
 extern int rip_interface_up(int, struct zclient *, zebra_size_t, vrf_id_t);
 extern int rip_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t);
diff --git a/ripd/rip_memory.c b/ripd/rip_memory.c
deleted file mode 100644 (file)
index 7d703a8..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* ripd memory type definitions
- *
- * Copyright (C) 2015  David Lamparter
- *
- * This file is part of Quagga.
- *
- * Quagga 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.
- *
- * Quagga is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "rip_memory.h"
-
-DEFINE_MGROUP(RIPD, "ripd")
-DEFINE_MTYPE(RIPD, RIP, "RIP structure")
-DEFINE_MTYPE(RIPD, RIP_VRF_NAME, "RIP VRF name")
-DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info")
-DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface")
-DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String")
-DEFINE_MTYPE(RIPD, RIP_PEER, "RIP peer")
-DEFINE_MTYPE(RIPD, RIP_OFFSET_LIST, "RIP offset list")
-DEFINE_MTYPE(RIPD, RIP_DISTANCE, "RIP distance")
diff --git a/ripd/rip_memory.h b/ripd/rip_memory.h
deleted file mode 100644 (file)
index 1f9d8f5..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* ripd memory type declarations
- *
- * Copyright (C) 2015  David Lamparter
- *
- * This file is part of Quagga.
- *
- * Quagga 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.
- *
- * Quagga is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _QUAGGA_RIP_MEMORY_H
-#define _QUAGGA_RIP_MEMORY_H
-
-#include "memory.h"
-
-DECLARE_MGROUP(RIPD)
-DECLARE_MTYPE(RIP)
-DECLARE_MTYPE(RIP_VRF_NAME)
-DECLARE_MTYPE(RIP_INFO)
-DECLARE_MTYPE(RIP_INTERFACE)
-DECLARE_MTYPE(RIP_INTERFACE_STRING)
-DECLARE_MTYPE(RIP_PEER)
-DECLARE_MTYPE(RIP_OFFSET_LIST)
-DECLARE_MTYPE(RIP_DISTANCE)
-
-#endif /* _QUAGGA_RIP_MEMORY_H */
index f8a7f5dc678d9ccd5da8c9a13c8a3f645bdb33fe..1238d0f0fc8b4ff50e85d78f8e4305767bd92a0a 100644 (file)
@@ -33,6 +33,7 @@
 #include "ripd/ripd.h"
 #include "ripd/rip_debug.h"
 #include "ripd/rip_cli.h"
+#include "ripd/rip_interface.h"
 
 /*
  * XPath: /frr-ripd:ripd/instance
index 8307a95d27b3b11a792297d8b82105b3e8247bf6..776f121d59dac59af71e64e0b6a7220243e97b2d 100644 (file)
@@ -29,6 +29,8 @@
 
 #include "ripd/ripd.h"
 
+DEFINE_MTYPE_STATIC(RIPD, RIP_OFFSET_LIST, "RIP offset list")
+
 #define OFFSET_LIST_IN_NAME(O)  ((O)->direct[RIP_OFFSET_LIST_IN].alist_name)
 #define OFFSET_LIST_IN_METRIC(O)  ((O)->direct[RIP_OFFSET_LIST_IN].metric)
 
index 08aa61257d2853e8cade46a696f3e4e238a1b117..4ad7309c41c3b30a0a3bc86a5982f6abde72c7e7 100644 (file)
@@ -29,6 +29,8 @@
 
 #include "ripd/ripd.h"
 
+DEFINE_MTYPE_STATIC(RIPD, RIP_PEER, "RIP peer")
+
 static struct rip_peer *rip_peer_new(void)
 {
        return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer));
index 3216b8f89fda9417eba84d1980cdc033d8e43378..85d83c61dc3ca00efea00b85f522ee721dd11bf8 100644 (file)
@@ -231,6 +231,40 @@ static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
        route_match_ip_next_hop_prefix_list_compile,
        route_match_ip_next_hop_prefix_list_free};
 
+/* `match ip next-hop type <blackhole>' */
+
+static route_map_result_t
+route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
+                            route_map_object_t type, void *object)
+{
+       struct rip_info *rinfo;
+
+       if (type == RMAP_RIP && prefix->family == AF_INET) {
+               rinfo = (struct rip_info *)object;
+               if (!rinfo)
+                       return RMAP_DENYMATCH;
+
+               if (rinfo->nh.type == NEXTHOP_TYPE_BLACKHOLE)
+                       return RMAP_MATCH;
+       }
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ip_next_hop_type_compile(const char *arg)
+{
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ip_next_hop_type_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
+       "ip next-hop type", route_match_ip_next_hop_type,
+       route_match_ip_next_hop_type_compile,
+       route_match_ip_next_hop_type_free};
+
 /* `match ip address IP_ACCESS_LIST' */
 
 /* Match function should return 1 if match is success else return
@@ -537,6 +571,9 @@ void rip_route_map_init(void)
        route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
        route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
 
+       route_map_match_ip_next_hop_type_hook(generic_match_add);
+       route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
+
        route_map_match_metric_hook(generic_match_add);
        route_map_no_match_metric_hook(generic_match_delete);
 
@@ -556,6 +593,7 @@ void rip_route_map_init(void)
        route_map_install_match(&route_match_interface_cmd);
        route_map_install_match(&route_match_ip_next_hop_cmd);
        route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
+       route_map_install_match(&route_match_ip_next_hop_type_cmd);
        route_map_install_match(&route_match_ip_address_cmd);
        route_map_install_match(&route_match_ip_address_prefix_list_cmd);
        route_map_install_match(&route_match_tag_cmd);
index 3a1ffd17a6f47561d7b54a1e40f4c71e77509602..e0ff0430f81a4728cbe5524754975a60bdd0ed45 100644 (file)
 /* UDP receive buffer size */
 #define RIP_UDP_RCV_BUF 41600
 
+DEFINE_MGROUP(RIPD, "ripd")
+DEFINE_MTYPE_STATIC(RIPD, RIP, "RIP structure")
+DEFINE_MTYPE_STATIC(RIPD, RIP_VRF_NAME, "RIP VRF name")
+DEFINE_MTYPE_STATIC(RIPD, RIP_INFO, "RIP route info")
+DEFINE_MTYPE_STATIC(RIPD, RIP_DISTANCE, "RIP distance")
+
 /* Prototypes. */
 static void rip_output_process(struct connected *, struct sockaddr_in *, int,
                               uint8_t);
index 44f5932fb69a2c99e0bfa27a506cac86b9ce978c..7f2c3fd068e9e3c4f771bd46db2c87cfb67791f0 100644 (file)
@@ -24,7 +24,7 @@
 #include "hook.h"
 #include "nexthop.h"
 #include "distribute.h"
-#include "rip_memory.h"
+#include "memory.h"
 
 /* RIP version number. */
 #define RIPv1                            1
@@ -97,6 +97,8 @@
 #define RIP_INSTANCE   "/frr-ripd:ripd/instance"
 #define RIP_IFACE      "/frr-interface:lib/interface/frr-ripd:rip"
 
+DECLARE_MGROUP(RIPD)
+
 /* RIP structure. */
 struct rip {
        RB_ENTRY(rip) entry;
index 2a63cc52296a2afaaf100b6b7f7fd4d0c845e0c8..312c1db6afd56c565f512922ab66605799fe0b36 100644 (file)
@@ -23,7 +23,6 @@ ripd_librip_a_SOURCES = \
        ripd/rip_debug.c \
        ripd/rip_errors.c \
        ripd/rip_interface.c \
-       ripd/rip_memory.c \
        ripd/rip_offset.c \
        ripd/rip_northbound.c \
        ripd/rip_peer.c \
@@ -40,7 +39,6 @@ noinst_HEADERS += \
        ripd/rip_debug.h \
        ripd/rip_errors.h \
        ripd/rip_interface.h \
-       ripd/rip_memory.h \
        ripd/ripd.h \
        # end
 
index d83f4d27914506a3f6644c6cf164bf4b0e669cc2..49ed13a2c29b416d67275f3f86704f8b6473baa5 100644 (file)
@@ -49,6 +49,8 @@
 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP 
 #endif
 
+DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_IF, "ripng interface")
+
 /* Static utility function. */
 static void ripng_enable_apply(struct interface *);
 static void ripng_passive_interface_apply(struct interface *);
@@ -913,7 +915,7 @@ static struct ripng_interface *ri_new(void)
 {
        struct ripng_interface *ri;
 
-       ri = XCALLOC(MTYPE_IF, sizeof(struct ripng_interface));
+       ri = XCALLOC(MTYPE_RIPNG_IF, sizeof(struct ripng_interface));
 
        /* Set default split-horizon behavior.  If the interface is Frame
           Relay or SMDS is enabled, the default value for split-horizon is
@@ -950,7 +952,7 @@ static int ripng_if_new_hook(struct interface *ifp)
 /* Called when interface structure deleted. */
 static int ripng_if_delete_hook(struct interface *ifp)
 {
-       XFREE(MTYPE_IF, ifp->info);
+       XFREE(MTYPE_RIPNG_IF, ifp->info);
        ifp->info = NULL;
        return 0;
 }
diff --git a/ripngd/ripng_memory.c b/ripngd/ripng_memory.c
deleted file mode 100644 (file)
index f459566..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* ripngd memory type definitions
- *
- * Copyright (C) 2015  David Lamparter
- *
- * This file is part of Quagga.
- *
- * Quagga 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.
- *
- * Quagga is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "ripng_memory.h"
-
-DEFINE_MGROUP(RIPNGD, "ripngd")
-DEFINE_MTYPE(RIPNGD, RIPNG, "RIPng structure")
-DEFINE_MTYPE(RIPNGD, RIPNG_VRF_NAME, "RIPng VRF name")
-DEFINE_MTYPE(RIPNGD, RIPNG_ROUTE, "RIPng route info")
-DEFINE_MTYPE(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate")
-DEFINE_MTYPE(RIPNGD, RIPNG_PEER, "RIPng peer")
-DEFINE_MTYPE(RIPNGD, RIPNG_OFFSET_LIST, "RIPng offset lst")
-DEFINE_MTYPE(RIPNGD, RIPNG_RTE_DATA, "RIPng rte data")
diff --git a/ripngd/ripng_memory.h b/ripngd/ripng_memory.h
deleted file mode 100644 (file)
index 3dfc57b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* ripngd memory type declarations
- *
- * Copyright (C) 2015  David Lamparter
- *
- * This file is part of Quagga.
- *
- * Quagga 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.
- *
- * Quagga is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef _QUAGGA_RIPNG_MEMORY_H
-#define _QUAGGA_RIPNG_MEMORY_H
-
-#include "memory.h"
-
-DECLARE_MGROUP(RIPNGD)
-DECLARE_MTYPE(RIPNG)
-DECLARE_MTYPE(RIPNG_VRF_NAME)
-DECLARE_MTYPE(RIPNG_ROUTE)
-DECLARE_MTYPE(RIPNG_AGGREGATE)
-DECLARE_MTYPE(RIPNG_PEER)
-DECLARE_MTYPE(RIPNG_OFFSET_LIST)
-DECLARE_MTYPE(RIPNG_RTE_DATA)
-
-#endif /* _QUAGGA_RIPNG_MEMORY_H */
index 882c2fbc8c56182ad4ad7bb3e9107b0a0320c3a0..ba6e52fdda0e7f290443d1b73efe655a54524e93 100644 (file)
@@ -39,6 +39,8 @@
 #include "ripngd/ripng_debug.h"
 #include "ripngd/ripng_nexthop.h"
 
+DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_RTE_DATA, "RIPng rte data")
+
 #define DEBUG 1
 
 #define min(a, b) ((a) < (b) ? (a) : (b))
index fe95ccfc2bdf18907fbf91fd6d2c10a58dbf20cc..0094c993add429f58a869e6b6d9eb920f93e9a55 100644 (file)
@@ -33,6 +33,8 @@
 
 #include "ripngd/ripngd.h"
 
+DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_OFFSET_LIST, "RIPng offset lst")
+
 #define OFFSET_LIST_IN_NAME(O)  ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
 #define OFFSET_LIST_IN_METRIC(O)  ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
 
index 5376007747cdc81c34ed6f7f673c6b8438f2d97c..109524e2129091f51c5977f07bffaadcd4be65f7 100644 (file)
@@ -34,6 +34,8 @@
 #include "ripngd/ripngd.h"
 #include "ripngd/ripng_nexthop.h"
 
+DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_PEER, "RIPng peer")
+
 static struct ripng_peer *ripng_peer_new(void)
 {
        return XCALLOC(MTYPE_RIPNG_PEER, sizeof(struct ripng_peer));
index 1bf1007fecd5a22bd635f17f1c5714802a27f8b4..ed9d77a3783de0f4e02b0c0c92178853d12e6e37 100644 (file)
@@ -30,6 +30,8 @@
 #include "ripngd/ripngd.h"
 #include "ripngd/ripng_route.h"
 
+DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_AGGREGATE, "RIPng aggregate")
+
 static struct ripng_aggregate *ripng_aggregate_new(void)
 {
        struct ripng_aggregate *new;
index 71bc43049ab039b3a565fb766718b8cb7d2cd37a..3314892e74afded39219148b8c4c4cf1823152e5 100644 (file)
 #include "ripngd/ripng_debug.h"
 #include "ripngd/ripng_nexthop.h"
 
+DEFINE_MGROUP(RIPNGD, "ripngd")
+DEFINE_MTYPE_STATIC(RIPNGD, RIPNG, "RIPng structure")
+DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_VRF_NAME, "RIPng VRF name")
+DEFINE_MTYPE_STATIC(RIPNGD, RIPNG_ROUTE, "RIPng route info")
+
 enum { ripng_all_route,
        ripng_changed_route,
 };
index a2686304fcfafd5b9f1d359bbb61b09f5be79104..5a0d350a84b1108c686d8b1f1e5c0d12c2ac6f0e 100644 (file)
@@ -26,8 +26,7 @@
 #include <vty.h>
 #include <distribute.h>
 #include <vector.h>
-
-#include "ripng_memory.h"
+#include <memory.h>
 
 /* RIPng version and port number. */
 #define RIPNG_V1                         1
@@ -87,6 +86,8 @@
 #define RIPNG_INSTANCE "/frr-ripngd:ripngd/instance"
 #define RIPNG_IFACE    "/frr-interface:lib/interface/frr-ripngd:ripng"
 
+DECLARE_MGROUP(RIPNGD)
+
 /* RIPng structure. */
 struct ripng {
        RB_ENTRY(ripng) entry;
index ea0ccf14827c52698bd5adbd7a1c14343ce243c8..eac0d673139a16b2149e810e2b0c153e00425b38 100644 (file)
@@ -17,7 +17,6 @@ ripngd_libripng_a_SOURCES = \
        ripngd/ripng_cli.c \
        ripngd/ripng_debug.c \
        ripngd/ripng_interface.c \
-       ripngd/ripng_memory.c \
        ripngd/ripng_nexthop.c \
        ripngd/ripng_offset.c \
        ripngd/ripng_northbound.c \
@@ -34,7 +33,6 @@ ripngd/ripng_cli.$(OBJEXT): ripngd/ripng_cli_clippy.c
 noinst_HEADERS += \
        ripngd/ripng_cli.h \
        ripngd/ripng_debug.h \
-       ripngd/ripng_memory.h \
        ripngd/ripng_nexthop.h \
        ripngd/ripng_route.h \
        ripngd/ripngd.h \
index 9af30a587a4a17b4d63baeec80cd6cb89c83dd65..2aa0db59f11c4a7d201758ea9396733374609f13 100644 (file)
@@ -37,8 +37,6 @@ static void static_nht_update_safi(struct prefix *p, uint32_t nh_num,
        struct static_route *si;
        struct static_vrf *svrf;
        struct route_node *rn;
-       bool orig;
-       bool reinstall;
 
        svrf = vrf->info;
        if (!svrf)
@@ -49,7 +47,6 @@ static void static_nht_update_safi(struct prefix *p, uint32_t nh_num,
                return;
 
        for (rn = route_top(stable); rn; rn = route_next(rn)) {
-               reinstall = false;
                for (si = rn->info; si; si = si->next) {
                        if (si->nh_vrf_id != nh_vrf_id)
                                continue;
@@ -60,7 +57,6 @@ static void static_nht_update_safi(struct prefix *p, uint32_t nh_num,
                            && si->type != STATIC_IPV6_GATEWAY_IFNAME)
                                continue;
 
-                       orig = si->nh_valid;
                        if (p->family == AF_INET
                            && p->u.prefix4.s_addr == si->addr.ipv4.s_addr)
                                si->nh_valid = !!nh_num;
@@ -69,14 +65,7 @@ static void static_nht_update_safi(struct prefix *p, uint32_t nh_num,
                            && memcmp(&p->u.prefix6, &si->addr.ipv6, 16) == 0)
                                si->nh_valid = !!nh_num;
 
-                       if (orig != si->nh_valid)
-                               reinstall = true;
-
-                       if (reinstall) {
-                               static_zebra_route_add(rn, si, vrf->vrf_id,
-                                                      safi, true);
-                               reinstall = false;
-                       }
+                       static_zebra_route_add(rn, si, vrf->vrf_id, safi, true);
                }
        }
 }
diff --git a/tests/topotests/bgp_instance_del_test/__init__.py b/tests/topotests/bgp_instance_del_test/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp_instance_del_test/ce1 b/tests/topotests/bgp_instance_del_test/ce1
new file mode 120000 (symlink)
index 0000000..0924eb5
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/ce1
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/ce2 b/tests/topotests/bgp_instance_del_test/ce2
new file mode 120000 (symlink)
index 0000000..8c7a677
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/ce2
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/ce3 b/tests/topotests/bgp_instance_del_test/ce3
new file mode 120000 (symlink)
index 0000000..0abb8e5
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/ce3
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/ce4 b/tests/topotests/bgp_instance_del_test/ce4
new file mode 120000 (symlink)
index 0000000..ddee1ef
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/ce4
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/customize.py b/tests/topotests/bgp_instance_del_test/customize.py
new file mode 120000 (symlink)
index 0000000..99fcf39
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/customize.py
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/r1 b/tests/topotests/bgp_instance_del_test/r1
new file mode 120000 (symlink)
index 0000000..16babfa
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/r1
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/r2 b/tests/topotests/bgp_instance_del_test/r2
new file mode 120000 (symlink)
index 0000000..e25b932
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/r2
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/r3 b/tests/topotests/bgp_instance_del_test/r3
new file mode 120000 (symlink)
index 0000000..0d7c189
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/r3
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/r4 b/tests/topotests/bgp_instance_del_test/r4
new file mode 120000 (symlink)
index 0000000..2d667d3
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/r4
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/scripts b/tests/topotests/bgp_instance_del_test/scripts
new file mode 120000 (symlink)
index 0000000..c46bf1f
--- /dev/null
@@ -0,0 +1 @@
+../bgp_l3vpn_to_bgp_vrf/scripts
\ No newline at end of file
diff --git a/tests/topotests/bgp_instance_del_test/test_bgp_instance_del_test.py b/tests/topotests/bgp_instance_del_test/test_bgp_instance_del_test.py
new file mode 100755 (executable)
index 0000000..115c779
--- /dev/null
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+
+#
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2018, LabN Consulting, L.L.C.
+# Authored by Lou Berger <lberger@labn.net>
+#
+# 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.
+#
+
+import os
+import sys
+import pytest
+
+sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../'))
+
+from lib.ltemplate import *
+
+def test_check_linux_vrf():
+    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/check_linux_vrf.py', False, CliOnFail, CheckFunc)
+
+def test_adjacencies():
+    CliOnFail = None
+    # For debugging, uncomment the next line
+    #CliOnFail = 'tgen.mininet_cli'
+    CheckFunc = 'ltemplateVersionCheck(\'4.1\')'
+    #uncomment next line to start cli *before* script is run
+    #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True)'
+    ltemplateTest('scripts/adjacencies.py', False, CliOnFail, CheckFunc)
+
+def SKIP_test_add_routes():
+    CliOnFail = None
+    # For debugging, uncomment the next line
+    #CliOnFail = 'tgen.mininet_cli'
+    CheckFunc = 'ltemplateVersionCheck(\'4.1\')'
+    #uncomment next line to start cli *before* script is run
+    #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True)'
+    ltemplateTest('scripts/add_routes.py', False, CliOnFail, CheckFunc)
+
+def test_check_routes():
+    CliOnFail = None
+    # For debugging, uncomment the next line
+    #CliOnFail = 'tgen.mininet_cli'
+    CheckFunc = 'ltemplateVersionCheck(\'4.1\')'
+    #uncomment next line to start cli *before* script is run
+    #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True)'
+    ltemplateTest('scripts/check_routes.py', False, CliOnFail, CheckFunc)
+
+#manual data path setup test - remove once have bgp/zebra vrf path working
+def test_check_linux_mpls():
+    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/check_linux_mpls.py', False, CliOnFail, CheckFunc)
+
+def test_del_bgp_instances():
+    CliOnFail = None
+    # For debugging, uncomment the next line
+    #CliOnFail = 'tgen.mininet_cli'
+    CheckFunc = 'ltemplateVersionCheck(\'4.1\')'
+    #uncomment next line to start cli *before* script is run
+    #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True)'
+    ltemplateTest('scripts/del_bgp_instances.py', False, CliOnFail, CheckFunc)
+
+if __name__ == '__main__':
+    retval = pytest.main(["-s"])
+    sys.exit(retval)
index ce542413ba2554671977c2ac7934a757c9c4cca6..02fba97316d438018afb8216b2667fd2b96bddde 100644 (file)
@@ -149,7 +149,9 @@ def ltemplatePreRouterStartHook():
     krel = platform.release()
     tgen = get_topogen()
     logger.info('pre router-start hook, kernel=' + krel)
-    if topotest.version_cmp(krel, '4.15') == 0:
+
+    if topotest.version_cmp(krel, '4.15') >= 0 and \
+       topotest.version_cmp(krel, '4.18') <= 0:
         l3mdev_accept = 1
     else:
         l3mdev_accept = 0
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/del_bgp_instances.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/del_bgp_instances.py
new file mode 100644 (file)
index 0000000..c25c2d9
--- /dev/null
@@ -0,0 +1,7 @@
+from lutil import luCommand
+
+luCommand('r1','/usr/lib/frr/vtysh -c "conf ter" -c "no router bgp 5227 vrf r1-cust1" -c "no router bgp 5226"','.','none','Cleared bgp instances')
+luCommand('r2','/usr/lib/frr/vtysh -c "conf ter" -c "no router bgp 5226"','.','none','Cleared bgp instances')
+luCommand('r3','/usr/lib/frr/vtysh -c "conf ter" -c "no router bgp 5227 vrf r3-cust1" -c "no router bgp 5226"','.','none','Cleared bgp instances')
+luCommand('r4','/usr/lib/frr/vtysh -c "conf ter" -c "no router bgp 5228 vrf r4-cust2" -c "no router bgp 5227 vrf r4-cust1"  -c "no router bgp 5226"','.','none','Cleared bgp instances')
+
index c17bf1168c763430b23d2b983626e5c235f4b3e6..db53c1aacde84a06b873b36fe90c14ad2db1b290 100644 (file)
@@ -6,14 +6,19 @@ if ret != False and found != None:
     luCommand('ce3', 'vtysh -c "show bgp sum"',
              '.', 'pass', 'See %s sharp routes' % num)
     if num > 0:
+        rtrs = ['ce1', 'ce2', 'ce3']
+        for rtr in rtrs:
+            luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep Display','.', 'none', 'BGP routes pre remove')
+            luCommand(rtr, 'ip route show | cat -n | tail','.', 'none', 'Linux routes pre remove')
         wait = 2*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)
+            luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep Display',' 10 route', 'wait', 'BGP routes removed', wait)
+            luCommand(rtr, 'vtysh -c "show bgp ipv4 uni"','.', 'none', 'BGP routes post remove')
         for rtr in rtrs:
             luCommand(rtr, 'ip route show | grep -c \\^10\\.','^0$', 'wait', 'Linux routes removed', wait)
+            luCommand(rtr, 'ip route show','.', 'none', 'Linux routes post remove')
         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)
index 7f114d10df78ebd0d91ba2ee323caa7b3963ef2b..3619cdf84fe7422f03c7369afd80ca822dc46090 100644 (file)
@@ -11,14 +11,17 @@ if c > 0:
 else:
     d = r
 wait = 2*num/1000
-mem = {}
+mem_z = {}
+mem_b = {}
 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')
+    mem_z[rtr] = {'value': 0, 'units': 'unknown'}
+    mem_b[rtr] = {'value': 0, 'units': 'unknown'}
+    ret = luCommand(rtr, 'vtysh -c "show memory"', 'zebra: System allocator statistics:   Total heap allocated: *(\d*) ([A-Za-z]*) .*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)}
+        mem_z[rtr] = {'value': int(found.group(1)), 'units': found.group(2)}
+        mem_b[rtr] = {'value': int(found.group(3)), 'units': found.group(4)}
 
 luCommand('ce1', 'vtysh -c "sharp data nexthop"', 'sharpd is not running', 'none','check if sharpd running')
 doSharp = True
@@ -54,13 +57,20 @@ if doSharp == True:
         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')
+        ret = luCommand(rtr, 'vtysh -c "show memory"', 'zebra: System allocator statistics:   Total heap allocated: *(\d*) ([A-Za-z]*) .*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)))
+            val_z = int(found.group(1))
+            if mem_z[rtr]['units'] != found.group(2):
+                val_z *= 1000
+            delta_z = val_z - int(mem_z[rtr]['value'])
+            ave_z = float(delta_z)/float(num)
+
+            val_b = int(found.group(3))
+            if mem_b[rtr]['units'] != found.group(4):
+                val_b *= 1000
+            delta_b = val_b - int(mem_b[rtr]['value'])
+            ave_b = float(delta_b)/float(num)
+            luCommand(rtr, 'vtysh -c "show thread cpu"', '.', 'pass', 'BGPd heap: {0} {1} --> {2} {3} ({4} {1}/vpn route)'.format(mem_b[rtr]['value'], mem_b[rtr]['units'], found.group(3), found.group(4), round(ave_b,4)))
+            luCommand(rtr, 'vtysh -c "show thread cpu"', '.', 'pass', 'Zebra heap: {0} {1} --> {2} {3} ({4} {1}/vpn route)'.format(mem_z[rtr]['value'], mem_z[rtr]['units'], found.group(1), found.group(2), round(ave_z,4)))
 #done
index b9982d4900f9f4230f386c8cdb4bdb3b9d9fde30..c5e615d25210230e4995ec644f15cb9aaf2311a7 100644 (file)
@@ -55,8 +55,6 @@ Simplified `R1` config:
         ip address 172.16.1.254/24
         no link-detect
        !
-       bgp multiple-instance
-       !
        router bgp 100 view 1
         bgp router-id 172.30.1.1
         network 172.20.0.0/28 route-map local1
index 0c24942f4304e826c0c8bd30d96ef770a7fbda16..71397a9942c5fcb82654b8331e4d844993404282 100644 (file)
@@ -11,8 +11,6 @@ log file bgpd.log
 !debug bgp filters
 !debug bgp zebra
 !
-bgp multiple-instance
-!
 router bgp 100 view 1
  bgp router-id 172.30.1.1
  network 172.20.0.0/28 route-map local1
index 3ae18018bfdd84a10ff54ce82334ddc367458306..e58b4725eb6756b3425ee4570bdfd3ae037848cc 100755 (executable)
@@ -37,7 +37,7 @@ class lUtil:
     base_log_dir = '.'
     fout_name = 'output.log'
     fsum_name = 'summary.txt'
-    l_level = 9
+    l_level = 6
     CallOnFail = False
 
     l_total = 0
@@ -53,12 +53,12 @@ class lUtil:
     fsum = ''
     net  = ''
 
-    def log(self, str):
+    def log(self, str, level=6):
         if self.l_level > 0:
             if self.fout == '':
                 self.fout = open(self.fout_name, 'w', 0)
             self.fout.write(str+'\n')
-        if self.l_level > 5:
+        if level <= self.l_level:
             print(str)
 
     def summary(self, str):
@@ -226,14 +226,16 @@ Total %-4d                                                           %-4d %d\n\
             ret = success
         else:
             ret = search.group()
-            self.log('found:%s:' % ret)
             if op != 'fail':
                 success = True
+                level = 7
             else:
                 success = False
+                level = 5
+            self.log('found:%s:' % ret, level)
            # Experiment: compare matched strings obtained each way
            if self.l_dotall_experiment and (group_nl_converted != ret):
-               self.log('DOTALL experiment: strings differ dotall=[%s] orig=[%s]' % (group_nl_converted, ret))
+               self.log('DOTALL experiment: strings differ dotall=[%s] orig=[%s]' % (group_nl_converted, ret), 9)
         if op == 'pass' or op == 'fail':
             self.result(target, success, result)
         if js != None:
@@ -265,7 +267,7 @@ LUtil=None
 
 #entry calls
 def luStart(baseScriptDir='.', baseLogDir='.', net='',
-            fout='output.log', fsum='summary.txt', level=9):
+            fout='output.log', fsum='summary.txt', level=None):
     global LUtil
     #init class
     LUtil=lUtil()
@@ -276,7 +278,8 @@ def luStart(baseScriptDir='.', baseLogDir='.', net='',
         LUtil.fout_name = baseLogDir + '/' + fout
     if fsum != None:
         LUtil.fsum_name = baseLogDir + '/' + fsum
-    LUtil.l_level = level
+    if level != None:
+        LUtil.l_level = level
     LUtil.l_dotall_experiment = False
     LUtil.l_dotall_experiment = True
 
@@ -289,11 +292,11 @@ def luCommand(target, command, regexp='.', op='none', result='', time=10, return
 def luLast(usenl=False):
     if usenl:
        if LUtil.l_last_nl != None:
-           LUtil.log('luLast:%s:' %  LUtil.l_last_nl.group())
+           LUtil.log('luLast:%s:' %  LUtil.l_last_nl.group(), 7)
        return LUtil.l_last_nl
     else:
        if LUtil.l_last != None:
-           LUtil.log('luLast:%s:' %  LUtil.l_last.group())
+           LUtil.log('luLast:%s:' %  LUtil.l_last.group(), 7)
        return LUtil.l_last
 
 def luInclude(filename, CallOnFail=None):
index a328f969d6e4c84d4a035b0cf7605e83b3491a78..57eec108cbc7263acad4fd19b5cbe4c49610ba7e 100644 (file)
@@ -14,7 +14,6 @@ vrrpd_libvrrp_a_SOURCES = \
        vrrpd/vrrp.c \
        vrrpd/vrrp_arp.c \
        vrrpd/vrrp_debug.c \
-       vrrpd/vrrp_memory.c \
        vrrpd/vrrp_ndisc.c \
        vrrpd/vrrp_packet.c \
        vrrpd/vrrp_vty.c \
@@ -25,7 +24,6 @@ noinst_HEADERS += \
        vrrpd/vrrp.h \
        vrrpd/vrrp_arp.h \
        vrrpd/vrrp_debug.h \
-       vrrpd/vrrp_memory.h \
        vrrpd/vrrp_ndisc.h \
        vrrpd/vrrp_packet.h \
        vrrpd/vrrp_vty.h \
index 3d535cbfba251557432251975f41bee5ac5a0d69..5213b27d32c21fdc624b5ecc2ef91c31cf66163d 100644 (file)
 #include "vrrp.h"
 #include "vrrp_arp.h"
 #include "vrrp_debug.h"
-#include "vrrp_memory.h"
 #include "vrrp_ndisc.h"
 #include "vrrp_packet.h"
 #include "vrrp_zebra.h"
 
 #define VRRP_LOGPFX "[CORE] "
 
+DEFINE_MTYPE_STATIC(VRRPD, VRRP_IP, "VRRP IP address")
+DEFINE_MTYPE_STATIC(VRRPD, VRRP_RTR, "VRRP Router")
+
 /* statics */
 struct hash *vrrp_vrouters_hash;
 bool vrrp_autoconfig_is_on;
@@ -768,7 +770,7 @@ static void vrrp_send_advertisement(struct vrrp_router *r)
        ssize_t sent = sendto(r->sock_tx, pkt, (size_t)pktsz, 0, &dest.sa,
                              sockunion_sizeof(&dest));
 
-       XFREE(MTYPE_VRRP_PKT, pkt);
+       vrrp_pkt_free(pkt);
 
        if (sent < 0) {
                zlog_warn(VRRP_LOGPFX VRRP_LOGPFX_VRID VRRP_LOGPFX_FAM
index fd4901fe22fed7c7cd4f1bb20089731942398bf5..5d355d04b5452e6d6adc4e75858fb73e5526a12e 100644 (file)
@@ -23,6 +23,7 @@
 #include <zebra.h>
 #include <netinet/ip.h>
 
+#include "lib/memory.h"
 #include "lib/hash.h"
 #include "lib/hook.h"
 #include "lib/if.h"
@@ -54,6 +55,8 @@
 /* User compatibility constant */
 #define CS2MS 10
 
+DECLARE_MGROUP(VRRPD)
+
 /* Configured defaults */
 struct vrrp_defaults {
        uint8_t priority;
index 46a92d936a32564b0ef6304cab3ce95d324dc121..6afb418ad0890351d589111e3e3320f97dcff81e 100644 (file)
@@ -39,6 +39,8 @@
 #include "vrrp_vty.h"
 #include "vrrp_zebra.h"
 
+DEFINE_MGROUP(VRRPD, "vrrpd")
+
 char backup_config_file[256];
 
 zebra_capabilities_t _caps_p[] = {
@@ -142,6 +144,7 @@ int main(int argc, char **argv, char **envp)
 
        master = frr_init();
 
+       access_list_init();
        vrrp_debug_init();
        vrrp_zebra_init();
        vrrp_vty_init();
diff --git a/vrrpd/vrrp_memory.c b/vrrpd/vrrp_memory.c
deleted file mode 100644 (file)
index 30eef52..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * VRRP memory types.
- * Copyright (C) 2018-2019 Cumulus Networks, Inc.
- * Quentin Young
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include <zebra.h>
-
-#include "lib/memory.h"
-
-#include "vrrp_memory.h"
-
-DEFINE_MGROUP(VRRPD, "vrrpd");
-DEFINE_MTYPE(VRRPD, VRRP_IP, "VRRP IP address");
-DEFINE_MTYPE(VRRPD, VRRP_PKT, "VRRP packet");
-DEFINE_MTYPE(VRRPD, VRRP_RTR, "VRRP Router");
diff --git a/vrrpd/vrrp_memory.h b/vrrpd/vrrp_memory.h
deleted file mode 100644 (file)
index c3025d1..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * VRRP memory types.
- * Copyright (C) 2018-2019 Cumulus Networks, Inc.
- * Quentin Young
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#ifndef __VRRP_MEMORY_H__
-#define __VRRP_MEMORY_H__
-
-#include <zebra.h>
-
-#include "lib/memory.h"
-
-DECLARE_MGROUP(VRRPD);
-DECLARE_MTYPE(VRRP_IP);
-DECLARE_MTYPE(VRRP_PKT);
-DECLARE_MTYPE(VRRP_RTR);
-
-#endif /* __VRRP_MEMORY_H__ */
index c3f2afba4cbfed4d9882adcb33d224d926e03c98..c6b7ac1a7fad25028d7c67b94d3634dd26caa752 100644 (file)
 
 #include "vrrp.h"
 #include "vrrp_debug.h"
-#include "vrrp_memory.h"
 #include "vrrp_packet.h"
 
+DEFINE_MTYPE_STATIC(VRRPD, VRRP_PKT, "VRRP packet")
+
 /* clang-format off */
 const char *vrrp_packet_names[16] = {
        [0] = "Unknown",
@@ -151,6 +152,11 @@ ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
        return pktsize;
 }
 
+void vrrp_pkt_free(struct vrrp_pkt *pkt)
+{
+       XFREE(MTYPE_VRRP_PKT, pkt);
+}
+
 size_t vrrp_pkt_adver_dump(char *buf, size_t buflen, struct vrrp_pkt *pkt)
 {
        if (buflen < 1)
index 475e4780d5d93bb687c963cb6ad909a0eca02d7b..c2ce22f00891aa2d377589a413bbe76cdfee724e 100644 (file)
@@ -135,6 +135,9 @@ ssize_t vrrp_pkt_adver_build(struct vrrp_pkt **pkt, struct ipaddr *src,
                             uint16_t max_adver_int, uint8_t numip,
                             struct ipaddr **ips);
 
+/* free memory allocated by vrrp_pkt_adver_build's pkt arg */
+void vrrp_pkt_free(struct vrrp_pkt *pkt);
+
 /*
  * Dumps a VRRP ADVERTISEMENT packet to a string.
  *
index 48d81b02582665e5395865a2866d8fde27c13fad..2dc3d3f8a393f30b325b2471828dc163303882cb 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "vrrp.h"
 #include "vrrp_debug.h"
-#include "vrrp_memory.h"
 #include "vrrp_vty.h"
 #ifndef VTYSH_EXTRACT_PL
 #include "vrrpd/vrrp_vty_clippy.c"
index 9c2de0f62b8cf72f23bcd0ad19111a45cc71d52d..b8957c2b00bbbab6d080810d08f79e7e8d27fb85 100644 (file)
@@ -373,6 +373,10 @@ void vtysh_config_parse_line(void *arg, const char *line)
                                 strlen("debug northbound"))
                         == 0)
                        config = config_get(NORTHBOUND_DEBUG_NODE, line);
+               else if (strncmp(line, "debug route-map",
+                                strlen("debug route-map"))
+                        == 0)
+                       config = config_get(RMAP_DEBUG_NODE, line);
                else if (strncmp(line, "debug", strlen("debug")) == 0)
                        config = config_get(DEBUG_NODE, line);
                else if (strncmp(line, "password", strlen("password")) == 0
@@ -418,7 +422,8 @@ void vtysh_config_parse_line(void *arg, const char *line)
         || (I) == ACCESS_IPV6_NODE || (I) == ACCESS_MAC_NODE                  \
         || (I) == PREFIX_IPV6_NODE || (I) == FORWARDING_NODE                  \
         || (I) == DEBUG_NODE || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE      \
-        || (I) == NORTHBOUND_DEBUG_NODE || (I) == MPLS_NODE)
+        || (I) == NORTHBOUND_DEBUG_NODE || (I) == RMAP_DEBUG_NODE             \
+        || (I) == MPLS_NODE)
 
 /* Display configuration to file pointer. */
 void vtysh_config_dump(void)
index aaf70ab08b1d9917854b5cfb5c0da197979cbb97..17e5a7331c26c71fe4a85db1d645790d13f5154d 100644 (file)
@@ -62,35 +62,20 @@ static int vtysh_pam(const char *user)
 
        /* Start PAM. */
        ret = pam_start(FRR_PAM_NAME, user, &conv, &pamh);
-       /* printf ("ret %d\n", ret); */
 
        /* Is user really user? */
        if (ret == PAM_SUCCESS)
                ret = pam_authenticate(pamh, 0);
-/* printf ("ret %d\n", ret); */
 
-#if 0
-  /* Permitted access? */
-  if (ret == PAM_SUCCESS)
-    ret = pam_acct_mgmt (pamh, 0);
-  printf ("ret %d\n", ret);
-
-  if (ret == PAM_AUTHINFO_UNAVAIL)
-    ret = PAM_SUCCESS;
-#endif /* 0 */
-
-/* This is where we have been authorized or not. */
-#ifdef DEBUG
-       if (ret == PAM_SUCCESS)
-               printf("Authenticated\n");
-       else
-               printf("Not Authenticated\n");
-#endif /* DEBUG */
+       if (ret != PAM_SUCCESS)
+               fprintf(stderr, "vtysh_pam: Failure to initialize pam: %s(%d)",
+                       pam_strerror(pamh, ret), ret);
 
        /* close Linux-PAM */
        if (pam_end(pamh, ret) != PAM_SUCCESS) {
                pamh = NULL;
-               fprintf(stderr, "vtysh_pam: failed to release authenticator\n");
+               fprintf(stderr, "vtysh_pam: failed to release authenticator: %s(%d)\n",
+                       pam_strerror(pamh, ret), ret);
                exit(1);
        }
 
index 4971994346432f8131d7dbad65c4cbee04d1bf1f..2c306434a36dca516e0736137c81ced52a7ada85 100644 (file)
@@ -129,8 +129,18 @@ static const struct message family_str[] = {{AF_INET, "ipv4"},
                                            {RTNL_FAMILY_IP6MR, "ipv6MR"},
                                            {0}};
 
-static const struct message rttype_str[] = {{RTN_UNICAST, "unicast"},
+static const struct message rttype_str[] = {{RTN_UNSPEC, "none"},
+                                           {RTN_UNICAST, "unicast"},
+                                           {RTN_LOCAL, "local"},
+                                           {RTN_BROADCAST, "broadcast"},
+                                           {RTN_ANYCAST, "anycast"},
                                            {RTN_MULTICAST, "multicast"},
+                                           {RTN_BLACKHOLE, "blackhole"},
+                                           {RTN_UNREACHABLE, "unreachable"},
+                                           {RTN_PROHIBIT, "prohibited"},
+                                           {RTN_THROW, "throw"},
+                                           {RTN_NAT, "nat"},
+                                           {RTN_XRESOLVE, "resolver"},
                                            {0}};
 
 extern struct thread_master *master;
index 5797a5846aa8ef6f398a4148636cc7aa0e030cc6..19471067509ea9cea815ec88751d2f0c415e268b 100644 (file)
@@ -55,6 +55,7 @@
 #include "zebra/zebra_netns_notify.h"
 #include "zebra/zebra_rnh.h"
 #include "zebra/zebra_pbr.h"
+#include "zebra/zebra_vxlan.h"
 
 #if defined(HANDLE_NETLINK_FUZZING)
 #include "zebra/kernel_netlink.h"
@@ -455,6 +456,9 @@ int main(int argc, char **argv)
        /* RNH init */
        zebra_rnh_init();
 
+       /* Config handler Init */
+       zebra_evpn_init();
+
        /* Error init */
        zebra_error_init();
 
index 92c78a4cbb144a4a7dbad1b06312ef1024407d2c..b05d037f960640d574524476d12c864fe2d3a62e 100644 (file)
@@ -330,6 +330,10 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
                bh_type = BLACKHOLE_ADMINPROHIB;
                break;
        default:
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("Route rtm_type: %s(%d) intentionally ignoring",
+                                  nl_rttype_to_str(rtm->rtm_type),
+                                  rtm->rtm_type);
                return 0;
        }
 
@@ -2344,7 +2348,8 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
  * 5549 support, re-install them.
  */
 static void netlink_handle_5549(struct ndmsg *ndm, struct zebra_if *zif,
-                               struct interface *ifp, struct ipaddr *ip)
+                               struct interface *ifp, struct ipaddr *ip,
+                               bool handle_failed)
 {
        if (ndm->ndm_family != AF_INET)
                return;
@@ -2355,6 +2360,12 @@ static void netlink_handle_5549(struct ndmsg *ndm, struct zebra_if *zif,
        if (ipv4_ll.s_addr != ip->ip._v4_addr.s_addr)
                return;
 
+       if (handle_failed && ndm->ndm_state & NUD_FAILED) {
+               zlog_info("Neighbor Entry for %s has entered a failed state, not reinstalling",
+                         ifp->name);
+               return;
+       }
+
        if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, &zif->v6_2_v4_ll_addr6, true);
 }
 
@@ -2405,7 +2416,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
 
        /* if kernel deletes our rfc5549 neighbor entry, re-install it */
        if (h->nlmsg_type == RTM_DELNEIGH && (ndm->ndm_state & NUD_PERMANENT)) {
-               netlink_handle_5549(ndm, zif, ifp, &ip);
+               netlink_handle_5549(ndm, zif, ifp, &ip, false);
                if (IS_ZEBRA_DEBUG_KERNEL)
                        zlog_debug(
                                "\tNeighbor Entry Received is a 5549 entry, finished");
@@ -2414,7 +2425,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
 
        /* if kernel marks our rfc5549 neighbor entry invalid, re-install it */
        if (h->nlmsg_type == RTM_NEWNEIGH && !(ndm->ndm_state & NUD_VALID))
-               netlink_handle_5549(ndm, zif, ifp, &ip);
+               netlink_handle_5549(ndm, zif, ifp, &ip, true);
 
        /* The neighbor is present on an SVI. From this, we locate the
         * underlying
index e181b495b8dde899e31847a09603fd4237f99600..5841c44b0334fa152735397c2b956cf933478802 100644 (file)
@@ -50,6 +50,8 @@ extern struct zebra_privs_t zserv_privs;
 
 #if defined(HAVE_RTADV)
 
+DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix")
+
 #ifdef OPEN_BSD
 #include <netinet/icmp6.h>
 #endif
index abe1879c2634edb628b66c70b47afa8283ba73b0..f93562b31b53a2263dc11d05b2455dc073b7efb5 100644 (file)
@@ -36,8 +36,8 @@
 #include "zebra/debug.h"
 
 /* Memory type for context blocks */
-DEFINE_MTYPE(ZEBRA, DP_CTX, "Zebra DPlane Ctx")
-DEFINE_MTYPE(ZEBRA, DP_PROV, "Zebra DPlane Provider")
+DEFINE_MTYPE_STATIC(ZEBRA, DP_CTX, "Zebra DPlane Ctx")
+DEFINE_MTYPE_STATIC(ZEBRA, DP_PROV, "Zebra DPlane Provider")
 
 #ifndef AOK
 #  define AOK 0
index 35a5d69ee3b53934826b7d6ae0c3bca452c91579..32b9763c56a5ac4da95d3681ae35a75df7842a54 100644 (file)
 #include "network.h"
 #include "command.h"
 #include "version.h"
+#include "jhash.h"
 
 #include "zebra/rib.h"
 #include "zebra/zserv.h"
 #include "zebra/zebra_ns.h"
 #include "zebra/zebra_vrf.h"
 #include "zebra/zebra_errors.h"
+#include "zebra/zebra_memory.h"
 
 #include "fpm/fpm.h"
 #include "zebra_fpm_private.h"
+#include "zebra/zebra_router.h"
+#include "zebra_vxlan_private.h"
+
+DEFINE_MTYPE_STATIC(ZEBRA, FPM_MAC_INFO, "FPM_MAC_INFO");
 
 /*
  * Interval at which we attempt to connect to the FPM.
@@ -62,6 +68,9 @@
  * Interval over which we collect statistics.
  */
 #define ZFPM_STATS_IVL_SECS        10
+#define FPM_MAX_MAC_MSG_LEN 512
+
+static void zfpm_iterate_rmac_table(struct hash_backet *backet, void *args);
 
 /*
  * Structure that holds state for iterating over all route_node
@@ -178,6 +187,25 @@ typedef struct zfpm_glob_t_ {
         */
        TAILQ_HEAD(zfpm_dest_q, rib_dest_t_) dest_q;
 
+       /*
+        * List of fpm_mac_info structures to be processed
+        */
+       TAILQ_HEAD(zfpm_mac_q, fpm_mac_info_t) mac_q;
+
+       /*
+        * Hash table of fpm_mac_info_t entries
+        *
+        * While adding fpm_mac_info_t for a MAC to the mac_q,
+        * it is possible that another fpm_mac_info_t node for the this MAC
+        * is already present in the queue.
+        * This is possible in the case of consecutive add->delete operations.
+        * To avoid such duplicate insertions in the mac_q,
+        * define a hash table for fpm_mac_info_t which can be looked up
+        * to see if an fpm_mac_info_t node for a MAC is already present
+        * in the mac_q.
+        */
+       struct hash *fpm_mac_info_table;
+
        /*
         * Stream socket to the FPM.
         */
@@ -259,6 +287,7 @@ static int zfpm_write_cb(struct thread *thread);
 static void zfpm_set_state(zfpm_state_t state, const char *reason);
 static void zfpm_start_connect_timer(const char *reason);
 static void zfpm_start_stats_timer(void);
+static void zfpm_mac_info_del(struct fpm_mac_info_t *fpm_mac);
 
 /*
  * zfpm_thread_should_yield
@@ -492,6 +521,9 @@ static int zfpm_conn_up_thread_cb(struct thread *thread)
                goto done;
        }
 
+       /* Enqueue FPM updates for all the RMAC entries */
+       hash_iterate(zrouter.l3vni_table, zfpm_iterate_rmac_table, NULL);
+
        while ((rnode = zfpm_rnodes_iter_next(iter))) {
                dest = rib_dest_from_rnode(rnode);
 
@@ -591,9 +623,17 @@ static int zfpm_conn_down_thread_cb(struct thread *thread)
        struct route_node *rnode;
        zfpm_rnodes_iter_t *iter;
        rib_dest_t *dest;
+       struct fpm_mac_info_t *mac = NULL;
 
        assert(zfpm_g->state == ZFPM_STATE_IDLE);
 
+       /*
+        * Delink and free all fpm_mac_info_t nodes
+        * in the mac_q and fpm_mac_info_hash
+        */
+       while ((mac = TAILQ_FIRST(&zfpm_g->mac_q)) != NULL)
+               zfpm_mac_info_del(mac);
+
        zfpm_g->t_conn_down = NULL;
 
        iter = &zfpm_g->t_conn_down_state.iter;
@@ -778,6 +818,14 @@ done:
        return 0;
 }
 
+static bool zfpm_updates_pending(void)
+{
+       if (!(TAILQ_EMPTY(&zfpm_g->dest_q)) || !(TAILQ_EMPTY(&zfpm_g->mac_q)))
+               return true;
+
+       return false;
+}
+
 /*
  * zfpm_writes_pending
  *
@@ -794,9 +842,9 @@ static int zfpm_writes_pending(void)
                return 1;
 
        /*
-        * Check if there are any prefixes on the outbound queue.
+        * Check if there are any updates scheduled on the outbound queues.
         */
-       if (!TAILQ_EMPTY(&zfpm_g->dest_q))
+       if (zfpm_updates_pending())
                return 1;
 
        return 0;
@@ -861,12 +909,29 @@ struct route_entry *zfpm_route_for_update(rib_dest_t *dest)
 }
 
 /*
- * zfpm_build_updates
+ * Define an enum for return codes for queue processing functions
  *
- * Process the outgoing queue and write messages to the outbound
- * buffer.
+ * FPM_WRITE_STOP: This return code indicates that the write buffer is full.
+ * Stop processing all the queues and empty the buffer by writing its content
+ * to the socket.
+ *
+ * FPM_GOTO_NEXT_Q: This return code indicates that either this queue is
+ * empty or we have processed enough updates from this queue.
+ * So, move on to the next queue.
  */
-static void zfpm_build_updates(void)
+enum {
+       FPM_WRITE_STOP = 0,
+       FPM_GOTO_NEXT_Q = 1
+};
+
+#define FPM_QUEUE_PROCESS_LIMIT 10000
+
+/*
+ * zfpm_build_route_updates
+ *
+ * Process the dest_q queue and write FPM messages to the outbound buffer.
+ */
+static int zfpm_build_route_updates(void)
 {
        struct stream *s;
        rib_dest_t *dest;
@@ -877,25 +942,27 @@ static void zfpm_build_updates(void)
        struct route_entry *re;
        int is_add, write_msg;
        fpm_msg_type_e msg_type;
+       uint16_t q_limit;
 
-       s = zfpm_g->obuf;
+       if (TAILQ_EMPTY(&zfpm_g->dest_q))
+               return FPM_GOTO_NEXT_Q;
 
-       assert(stream_empty(s));
-
-       do {
+       s = zfpm_g->obuf;
+       q_limit = FPM_QUEUE_PROCESS_LIMIT;
 
+       do  {
                /*
                 * Make sure there is enough space to write another message.
                 */
                if (STREAM_WRITEABLE(s) < FPM_MAX_MSG_LEN)
-                       break;
+                       return FPM_WRITE_STOP;
 
                buf = STREAM_DATA(s) + stream_get_endp(s);
                buf_end = buf + STREAM_WRITEABLE(s);
 
                dest = TAILQ_FIRST(&zfpm_g->dest_q);
                if (!dest)
-                       break;
+                       return FPM_GOTO_NEXT_Q;
 
                assert(CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM));
 
@@ -955,9 +1022,135 @@ static void zfpm_build_updates(void)
                if (rib_gc_dest(dest->rnode))
                        zfpm_g->stats.dests_del_after_update++;
 
+               q_limit--;
+               if (q_limit == 0) {
+                       /*
+                        * We have processed enough updates in this queue.
+                        * Now yield for other queues.
+                        */
+                       return FPM_GOTO_NEXT_Q;
+               }
+       } while (true);
+}
+
+/*
+ * zfpm_encode_mac
+ *
+ * Encode a message to FPM with information about the given MAC.
+ *
+ * Returns the number of bytes written to the buffer.
+ */
+static inline int zfpm_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
+                               size_t in_buf_len, fpm_msg_type_e *msg_type)
+{
+       size_t len = 0;
+
+       *msg_type = FPM_MSG_TYPE_NONE;
+
+       switch (zfpm_g->message_format) {
+
+       case ZFPM_MSG_FORMAT_NONE:
+               break;
+       case ZFPM_MSG_FORMAT_NETLINK:
+#ifdef HAVE_NETLINK
+               len = zfpm_netlink_encode_mac(mac, in_buf, in_buf_len);
+               assert(fpm_msg_align(len) == len);
+               *msg_type = FPM_MSG_TYPE_NETLINK;
+#endif /* HAVE_NETLINK */
+               break;
+       case ZFPM_MSG_FORMAT_PROTOBUF:
+               break;
+       }
+       return len;
+}
+
+static int zfpm_build_mac_updates(void)
+{
+       struct stream *s;
+       struct fpm_mac_info_t *mac;
+       unsigned char *buf, *data, *buf_end;
+       fpm_msg_hdr_t *hdr;
+       size_t data_len, msg_len;
+       fpm_msg_type_e msg_type;
+       uint16_t q_limit;
+
+       if (TAILQ_EMPTY(&zfpm_g->mac_q))
+               return FPM_GOTO_NEXT_Q;
+
+       s = zfpm_g->obuf;
+       q_limit = FPM_QUEUE_PROCESS_LIMIT;
+
+       do  {
+               /* Make sure there is enough space to write another message. */
+               if (STREAM_WRITEABLE(s) < FPM_MAX_MAC_MSG_LEN)
+                       return FPM_WRITE_STOP;
+
+               buf = STREAM_DATA(s) + stream_get_endp(s);
+               buf_end = buf + STREAM_WRITEABLE(s);
+
+               mac = TAILQ_FIRST(&zfpm_g->mac_q);
+               if (!mac)
+                       return FPM_GOTO_NEXT_Q;
+
+               /* Check for no-op */
+               if (!CHECK_FLAG(mac->fpm_flags, ZEBRA_MAC_UPDATE_FPM)) {
+                       zfpm_g->stats.nop_deletes_skipped++;
+                       zfpm_mac_info_del(mac);
+                       continue;
+               }
+
+               hdr = (fpm_msg_hdr_t *)buf;
+               hdr->version = FPM_PROTO_VERSION;
+
+               data = fpm_msg_data(hdr);
+               data_len = zfpm_encode_mac(mac, (char *)data, buf_end - data,
+                                               &msg_type);
+               assert(data_len);
+
+               hdr->msg_type = msg_type;
+               msg_len = fpm_data_len_to_msg_len(data_len);
+               hdr->msg_len = htons(msg_len);
+               stream_forward_endp(s, msg_len);
+
+               /* Remove the MAC from the queue, and delete it. */
+               zfpm_mac_info_del(mac);
+
+               q_limit--;
+               if (q_limit == 0) {
+                       /*
+                        * We have processed enough updates in this queue.
+                        * Now yield for other queues.
+                        */
+                       return FPM_GOTO_NEXT_Q;
+               }
        } while (1);
 }
 
+/*
+ * zfpm_build_updates
+ *
+ * Process the outgoing queues and write messages to the outbound
+ * buffer.
+ */
+static void zfpm_build_updates(void)
+{
+       struct stream *s;
+
+       s = zfpm_g->obuf;
+       assert(stream_empty(s));
+
+       do {
+               /*
+                * Stop processing the queues if zfpm_g->obuf is full
+                * or we do not have more updates to process
+                */
+               if (zfpm_build_mac_updates() == FPM_WRITE_STOP)
+                       break;
+               if (zfpm_build_route_updates() == FPM_WRITE_STOP)
+                       break;
+       } while (zfpm_updates_pending());
+}
+
 /*
  * zfpm_write_cb
  */
@@ -1276,6 +1469,207 @@ static int zfpm_trigger_update(struct route_node *rn, const char *reason)
        return 0;
 }
 
+/*
+ * Generate Key for FPM MAC info hash entry
+ * Key is generated using MAC address and VNI id which should be sufficient
+ * to provide uniqueness
+ */
+static unsigned int zfpm_mac_info_hash_keymake(const void *p)
+{
+       struct fpm_mac_info_t *fpm_mac = (struct fpm_mac_info_t *)p;
+       uint32_t mac_key;
+
+       mac_key = jhash(fpm_mac->macaddr.octet, ETH_ALEN, 0xa5a5a55a);
+
+       return jhash_2words(mac_key, fpm_mac->vni, 0);
+}
+
+/*
+ * Compare function for FPM MAC info hash lookup
+ */
+static bool zfpm_mac_info_cmp(const void *p1, const void *p2)
+{
+       const struct fpm_mac_info_t *fpm_mac1 = p1;
+       const struct fpm_mac_info_t *fpm_mac2 = p2;
+
+       if (memcmp(fpm_mac1->macaddr.octet, fpm_mac2->macaddr.octet, ETH_ALEN)
+                       != 0)
+               return false;
+       if (fpm_mac1->r_vtep_ip.s_addr != fpm_mac2->r_vtep_ip.s_addr)
+               return false;
+       if (fpm_mac1->vni != fpm_mac2->vni)
+               return false;
+
+       return true;
+}
+
+/*
+ * Lookup FPM MAC info hash entry.
+ */
+static struct fpm_mac_info_t *zfpm_mac_info_lookup(struct fpm_mac_info_t *key)
+{
+       return hash_lookup(zfpm_g->fpm_mac_info_table, key);
+}
+
+/*
+ * Callback to allocate fpm_mac_info_t structure.
+ */
+static void *zfpm_mac_info_alloc(void *p)
+{
+       const struct fpm_mac_info_t *key = p;
+       struct fpm_mac_info_t *fpm_mac;
+
+       fpm_mac = XCALLOC(MTYPE_FPM_MAC_INFO, sizeof(struct fpm_mac_info_t));
+
+       memcpy(&fpm_mac->macaddr, &key->macaddr, ETH_ALEN);
+       memcpy(&fpm_mac->r_vtep_ip, &key->r_vtep_ip, sizeof(struct in_addr));
+       fpm_mac->vni = key->vni;
+
+       return (void *)fpm_mac;
+}
+
+/*
+ * Delink and free fpm_mac_info_t.
+ */
+static void zfpm_mac_info_del(struct fpm_mac_info_t *fpm_mac)
+{
+       hash_release(zfpm_g->fpm_mac_info_table, fpm_mac);
+       TAILQ_REMOVE(&zfpm_g->mac_q, fpm_mac, fpm_mac_q_entries);
+       XFREE(MTYPE_FPM_MAC_INFO, fpm_mac);
+}
+
+/*
+ * zfpm_trigger_rmac_update
+ *
+ * Zebra code invokes this function to indicate that we should
+ * send an update to FPM for given MAC entry.
+ *
+ * This function checks if we already have enqueued an update for this RMAC,
+ * If yes, update the same fpm_mac_info_t. Else, create and enqueue an update.
+ */
+static int zfpm_trigger_rmac_update(zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
+                                       bool delete, const char *reason)
+{
+       char buf[ETHER_ADDR_STRLEN];
+       struct fpm_mac_info_t *fpm_mac, key;
+       struct interface *vxlan_if, *svi_if;
+
+       /*
+        * Ignore if the connection is down. We will update the FPM about
+        * all destinations once the connection comes up.
+        */
+       if (!zfpm_conn_is_up())
+               return 0;
+
+       if (reason) {
+               zfpm_debug("triggering update to FPM - Reason: %s - %s",
+                       reason,
+                       prefix_mac2str(&rmac->macaddr, buf, sizeof(buf)));
+       }
+
+       vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
+       svi_if = zl3vni_map_to_svi_if(zl3vni);
+
+       memset(&key, 0, sizeof(struct fpm_mac_info_t));
+
+       memcpy(&key.macaddr, &rmac->macaddr, ETH_ALEN);
+       key.r_vtep_ip.s_addr = rmac->fwd_info.r_vtep_ip.s_addr;
+       key.vni = zl3vni->vni;
+
+       /* Check if this MAC is already present in the queue. */
+       fpm_mac = zfpm_mac_info_lookup(&key);
+
+       if (fpm_mac) {
+               if (!!CHECK_FLAG(fpm_mac->fpm_flags, ZEBRA_MAC_DELETE_FPM)
+                       == delete) {
+                       /*
+                        * MAC is already present in the queue
+                        * with the same op as this one. Do nothing
+                        */
+                       zfpm_g->stats.redundant_triggers++;
+                       return 0;
+               }
+
+               /*
+                * A new op for an already existing fpm_mac_info_t node.
+                * Update the existing node for the new op.
+                */
+               if (!delete) {
+                       /*
+                        * New op is "add". Previous op is "delete".
+                        * Update the fpm_mac_info_t for the new add.
+                        */
+                       fpm_mac->zebra_flags = rmac->flags;
+
+                       fpm_mac->vxlan_if = vxlan_if ? vxlan_if->ifindex : 0;
+                       fpm_mac->svi_if = svi_if ? svi_if->ifindex : 0;
+
+                       UNSET_FLAG(fpm_mac->fpm_flags, ZEBRA_MAC_DELETE_FPM);
+                       SET_FLAG(fpm_mac->fpm_flags, ZEBRA_MAC_UPDATE_FPM);
+               } else {
+                       /*
+                        * New op is "delete". Previous op is "add".
+                        * Thus, no-op. Unset ZEBRA_MAC_UPDATE_FPM flag.
+                        */
+                       SET_FLAG(fpm_mac->fpm_flags, ZEBRA_MAC_DELETE_FPM);
+                       UNSET_FLAG(fpm_mac->fpm_flags, ZEBRA_MAC_UPDATE_FPM);
+               }
+
+               return 0;
+       }
+
+       fpm_mac = hash_get(zfpm_g->fpm_mac_info_table, &key,
+                          zfpm_mac_info_alloc);
+       if (!fpm_mac)
+               return 0;
+
+       fpm_mac->zebra_flags = rmac->flags;
+       fpm_mac->vxlan_if = vxlan_if ? vxlan_if->ifindex : 0;
+       fpm_mac->svi_if = svi_if ? svi_if->ifindex : 0;
+
+       SET_FLAG(fpm_mac->fpm_flags, ZEBRA_MAC_UPDATE_FPM);
+       if (delete)
+               SET_FLAG(fpm_mac->fpm_flags, ZEBRA_MAC_DELETE_FPM);
+
+       TAILQ_INSERT_TAIL(&zfpm_g->mac_q, fpm_mac, fpm_mac_q_entries);
+
+       zfpm_g->stats.updates_triggered++;
+
+       /* If writes are already enabled, return. */
+       if (zfpm_g->t_write)
+               return 0;
+
+       zfpm_write_on();
+       return 0;
+}
+
+/*
+ * This function is called when the FPM connections is established.
+ * Iterate over all the RMAC entries for the given L3VNI
+ * and enqueue the RMAC for FPM processing.
+ */
+static void zfpm_trigger_rmac_update_wrapper(struct hash_backet *backet,
+                                            void *args)
+{
+       zebra_mac_t *zrmac = (zebra_mac_t *)backet->data;
+       zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)args;
+
+       zfpm_trigger_rmac_update(zrmac, zl3vni, false, "RMAC added");
+}
+
+/*
+ * This function is called when the FPM connections is established.
+ * This function iterates over all the L3VNIs to trigger
+ * FPM updates for RMACs currently available.
+ */
+static void zfpm_iterate_rmac_table(struct hash_backet *backet, void *args)
+{
+       zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)backet->data;
+
+       hash_iterate(zl3vni->rmac_table, zfpm_trigger_rmac_update_wrapper,
+                    (void *)zl3vni);
+}
+
 /*
  * zfpm_stats_timer_cb
  */
@@ -1589,6 +1983,13 @@ static int zfpm_init(struct thread_master *master)
        memset(zfpm_g, 0, sizeof(*zfpm_g));
        zfpm_g->master = master;
        TAILQ_INIT(&zfpm_g->dest_q);
+       TAILQ_INIT(&zfpm_g->mac_q);
+
+       /* Create hash table for fpm_mac_info_t enties */
+       zfpm_g->fpm_mac_info_table = hash_create(zfpm_mac_info_hash_keymake,
+                                                zfpm_mac_info_cmp,
+                                                "FPM MAC info hash table");
+
        zfpm_g->sock = -1;
        zfpm_g->state = ZFPM_STATE_IDLE;
 
@@ -1631,6 +2032,7 @@ static int zfpm_init(struct thread_master *master)
 static int zebra_fpm_module_init(void)
 {
        hook_register(rib_update, zfpm_trigger_update);
+       hook_register(zebra_rmac_update, zfpm_trigger_rmac_update);
        hook_register(frr_late_init, zfpm_init);
        return 0;
 }
index 2ac79b100c3250669a3a0bba8d4dca8b5983b985..d5479bc627ae1ba777d636bf0ef166825995bec0 100644 (file)
@@ -580,4 +580,67 @@ int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, struct route_entry *re,
        return netlink_route_info_encode(ri, in_buf, in_buf_len);
 }
 
+/*
+ * zfpm_netlink_encode_mac
+ *
+ * Create a netlink message corresponding to the given MAC.
+ *
+ * Returns the number of bytes written to the buffer. 0 or a negative
+ * value indicates an error.
+ */
+int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
+                           size_t in_buf_len)
+{
+       char buf1[ETHER_ADDR_STRLEN];
+       size_t buf_offset;
+
+       struct macmsg {
+               struct nlmsghdr hdr;
+               struct ndmsg ndm;
+               char buf[0];
+       } *req;
+       req = (void *)in_buf;
+
+       buf_offset = offsetof(struct macmsg, buf);
+       if (in_buf_len < buf_offset)
+               return 0;
+       memset(req, 0, buf_offset);
+
+       /* Construct nlmsg header */
+       req->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+       req->hdr.nlmsg_type = CHECK_FLAG(mac->fpm_flags, ZEBRA_MAC_DELETE_FPM) ?
+                               RTM_DELNEIGH : RTM_NEWNEIGH;
+       req->hdr.nlmsg_flags = NLM_F_REQUEST;
+       if (req->hdr.nlmsg_type == RTM_NEWNEIGH)
+               req->hdr.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
+
+       /* Construct ndmsg */
+       req->ndm.ndm_family = AF_BRIDGE;
+       req->ndm.ndm_ifindex = mac->vxlan_if;
+
+       req->ndm.ndm_state = NUD_REACHABLE;
+       req->ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
+       if (CHECK_FLAG(mac->zebra_flags,
+               (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)))
+               req->ndm.ndm_state |= NUD_NOARP;
+       else
+               req->ndm.ndm_flags |= NTF_EXT_LEARNED;
+
+       /* Add attributes */
+       addattr_l(&req->hdr, in_buf_len, NDA_LLADDR, &mac->macaddr, 6);
+       addattr_l(&req->hdr, in_buf_len, NDA_DST, &mac->r_vtep_ip, 4);
+       addattr32(&req->hdr, in_buf_len, NDA_MASTER, mac->svi_if);
+       addattr32(&req->hdr, in_buf_len, NDA_VNI, mac->vni);
+
+       assert(req->hdr.nlmsg_len < in_buf_len);
+
+       zfpm_debug("Tx %s family %s ifindex %u MAC %s DEST %s",
+                  nl_msg_type_to_str(req->hdr.nlmsg_type),
+                  nl_family_to_str(req->ndm.ndm_family), req->ndm.ndm_ifindex,
+                  prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)),
+                  inet_ntoa(mac->r_vtep_ip));
+
+       return req->hdr.nlmsg_len;
+}
+
 #endif /* HAVE_NETLINK */
index 943aad98642c754537e5c2db2530d993fc6769ba..c169ee8c2219481a160e246919b2331fa7f919cd 100644 (file)
@@ -53,6 +53,34 @@ static inline void zfpm_debug(const char *format, ...)
 }
 #endif
 
+/* This structure contains the MAC addresses enqueued for FPM processing. */
+struct fpm_mac_info_t {
+       struct ethaddr macaddr;
+       uint32_t zebra_flags; /* Could be used to build FPM messages */
+       vni_t vni;
+       ifindex_t vxlan_if;
+       ifindex_t svi_if; /* L2 or L3 Bridge interface */
+       struct in_addr r_vtep_ip; /* Remote VTEP IP */
+
+       /* Linkage to put MAC on the FPM processing queue. */
+       TAILQ_ENTRY(fpm_mac_info_t) fpm_mac_q_entries;
+
+       uint8_t fpm_flags;
+
+#define ZEBRA_MAC_UPDATE_FPM 0x1 /* This flag indicates if we want to upadte
+                                 * data plane for this MAC. If a MAC is added
+                                 * and then deleted immediately, we do not want
+                                 * to update data plane for such operation.
+                                 * Unset the ZEBRA_MAC_UPDATE_FPM flag in this
+                                 * case. FPM thread while processing the queue
+                                 * node will check this flag and dequeue the
+                                 * node silently without sending any update to
+                                 * the data plane.
+                                 */
+#define ZEBRA_MAC_DELETE_FPM 0x2 /* This flag is set if it is a delete operation
+                                 * for the MAC.
+                                 */
+};
 
 /*
  * Externs
@@ -64,6 +92,9 @@ extern int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest,
 extern int zfpm_protobuf_encode_route(rib_dest_t *dest, struct route_entry *re,
                                      uint8_t *in_buf, size_t in_buf_len);
 
+extern int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
+                                  size_t in_buf_len);
+
 extern struct route_entry *zfpm_route_for_update(rib_dest_t *dest);
 
 #ifdef __cplusplus
index ee041b1c3dbd95009cb1a79b9a80083aaae9875c..a9c2c5fe58b7e2efbe61b67dc2e40e5ebe4baf8a 100644 (file)
 #include "zebra_memory.h"
 
 DEFINE_MGROUP(ZEBRA, "zebra")
-DEFINE_MTYPE(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix")
-DEFINE_MTYPE(ZEBRA, ZEBRA_VRF, "ZEBRA VRF")
 DEFINE_MTYPE(ZEBRA, RE, "Route Entry")
-DEFINE_MTYPE(ZEBRA, RIB_QUEUE, "RIB process work queue")
-DEFINE_MTYPE(ZEBRA, STATIC_ROUTE, "Static route")
 DEFINE_MTYPE(ZEBRA, RIB_DEST, "RIB destination")
-DEFINE_MTYPE(ZEBRA, RIB_TABLE_INFO, "RIB table info")
-DEFINE_MTYPE(ZEBRA, RNH, "Nexthop tracking object")
index 667c73b2270fd348ef6bf8886dc31085c3e0c05c..e15f972493269c63906728368a5fceb6c311bf2d 100644 (file)
@@ -29,17 +29,9 @@ extern "C" {
 #endif
 
 DECLARE_MGROUP(ZEBRA)
-DECLARE_MTYPE(RTADV_PREFIX)
 DECLARE_MTYPE(ZEBRA_NS)
-DECLARE_MTYPE(ZEBRA_VRF)
 DECLARE_MTYPE(RE)
-DECLARE_MTYPE(RIB_QUEUE)
-DECLARE_MTYPE(STATIC_ROUTE)
 DECLARE_MTYPE(RIB_DEST)
-DECLARE_MTYPE(RIB_TABLE_INFO)
-DECLARE_MTYPE(RNH)
-DECLARE_MTYPE(DP_CTX)
-DECLARE_MTYPE(DP_PROV)
 
 #ifdef __cplusplus
 }
index cc614abac54f7940dc46eba0ea7f3cce482b1975..2df24f75c5e1ed1b1d6a85c68218aeee94e2106e 100644 (file)
@@ -744,9 +744,10 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq)
                if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
                        char buf[PREFIX_STRLEN];
 
-                       zlog_debug("%s: %s Being examined for Nexthop Tracking",
+                       zlog_debug("%s: %s Being examined for Nexthop Tracking Count: %zd",
                                   __PRETTY_FUNCTION__,
-                                  srcdest_rnode2str(rn, buf, sizeof(buf)));
+                                  srcdest_rnode2str(rn, buf, sizeof(buf)),
+                                  dest ? rnh_list_count(&dest->nht) : 0);
                }
                if (!dest) {
                        rn = rn->parent;
@@ -760,7 +761,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
                 */
-               frr_each (rnh_list, &dest->nht, rnh) {
+               frr_each_safe(rnh_list, &dest->nht, rnh) {
                        struct zebra_vrf *zvrf =
                                zebra_vrf_lookup_by_id(rnh->vrf_id);
                        struct prefix *p = &rnh->node->p;
@@ -769,11 +770,12 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq)
                                char buf1[PREFIX_STRLEN];
                                char buf2[PREFIX_STRLEN];
 
-                               zlog_debug("%u:%s has Nexthop(%s) depending on it, evaluating %u:%u",
+                               zlog_debug("%u:%s has Nexthop(%s) Type: %s depending on it, evaluating %u:%u",
                                           zvrf->vrf->vrf_id,
                                           srcdest_rnode2str(rn, buf1,
                                                      sizeof(buf1)),
                                           prefix2str(p, buf2, sizeof(buf2)),
+                                          rnh_type2str(rnh->type),
                                           seq, rnh->seqno);
                        }
 
@@ -2442,6 +2444,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
        bool is_srcdst = src_p && src_p->prefixlen;
        char straddr[PREFIX_STRLEN];
        char srcaddr[PREFIX_STRLEN];
+       char nhname[PREFIX_STRLEN];
        struct nexthop *nexthop;
 
        zlog_debug("%s: dumping RE entry %p for %s%s%s vrf %u", func,
@@ -2451,12 +2454,12 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
                             : "",
                   re->vrf_id);
        zlog_debug("%s: uptime == %lu, type == %u, instance == %d, table == %d",
-                  func, (unsigned long)re->uptime, re->type, re->instance,
+                  straddr, (unsigned long)re->uptime, re->type, re->instance,
                   re->table);
        zlog_debug(
                "%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u",
-               func, re->metric, re->mtu, re->distance, re->flags, re->status);
-       zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", func,
+               straddr, re->metric, re->mtu, re->distance, re->flags, re->status);
+       zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr,
                   re->nexthop_num, re->nexthop_active_num);
 
        for (ALL_NEXTHOPS(re->ng, nexthop)) {
@@ -2465,27 +2468,27 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
 
                switch (nexthop->type) {
                case NEXTHOP_TYPE_BLACKHOLE:
-                       sprintf(straddr, "Blackhole");
+                       sprintf(nhname, "Blackhole");
                        break;
                case NEXTHOP_TYPE_IFINDEX:
                        ifp = if_lookup_by_index(nexthop->ifindex,
                                                 nexthop->vrf_id);
-                       sprintf(straddr, "%s", ifp ? ifp->name : "Unknown");
+                       sprintf(nhname, "%s", ifp ? ifp->name : "Unknown");
                        break;
                case NEXTHOP_TYPE_IPV4:
                        /* fallthrough */
                case NEXTHOP_TYPE_IPV4_IFINDEX:
-                       inet_ntop(AF_INET, &nexthop->gate, straddr,
+                       inet_ntop(AF_INET, &nexthop->gate, nhname,
                                  INET6_ADDRSTRLEN);
                        break;
                case NEXTHOP_TYPE_IPV6:
                case NEXTHOP_TYPE_IPV6_IFINDEX:
-                       inet_ntop(AF_INET6, &nexthop->gate, straddr,
+                       inet_ntop(AF_INET6, &nexthop->gate, nhname,
                                  INET6_ADDRSTRLEN);
                        break;
                }
                zlog_debug("%s: %s %s[%u] vrf %s(%u) with flags %s%s%s%s%s%s",
-                          func, (nexthop->rparent ? "  NH" : "NH"), straddr,
+                          straddr, (nexthop->rparent ? "  NH" : "NH"), nhname,
                           nexthop->ifindex, vrf ? vrf->name : "Unknown",
                           nexthop->vrf_id,
                           (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
@@ -2507,7 +2510,7 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
                                    ? "DUPLICATE "
                                    : ""));
        }
-       zlog_debug("%s: dump complete", func);
+       zlog_debug("%s: dump complete", straddr);
 }
 
 /* This is an exported helper to rtm_read() to dump the strange
index 1024f3a0525c425bbeb2d37f383f3d5d759ab7b0..6f65f8ab7a1d917b3b24a4fd2d72c5631d5fb8ad 100644 (file)
@@ -50,6 +50,8 @@
 #include "zebra/zebra_memory.h"
 #include "zebra/zebra_errors.h"
 
+DEFINE_MTYPE_STATIC(ZEBRA, RNH, "Nexthop tracking object")
+
 static void free_state(vrf_id_t vrf_id, struct route_entry *re,
                       struct route_node *rn);
 static void copy_state(struct rnh *rnh, struct route_entry *re,
@@ -160,14 +162,15 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
 
        if (IS_ZEBRA_DEBUG_NHT) {
                prefix2str(p, buf, sizeof(buf));
-               zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type);
+               zlog_debug("%u: Add RNH %s type %s", vrfid, buf,
+                          rnh_type2str(type));
        }
        table = get_rnh_table(vrfid, afi, type);
        if (!table) {
                prefix2str(p, buf, sizeof(buf));
                flog_warn(EC_ZEBRA_RNH_NO_TABLE,
-                         "%u: Add RNH %s type %d - table not found", vrfid,
-                         buf, type);
+                         "%u: Add RNH %s type %s - table not found", vrfid,
+                         buf, rnh_type2str(type));
                exists = false;
                return NULL;
        }
@@ -271,8 +274,8 @@ static void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
 
        if (IS_ZEBRA_DEBUG_NHT) {
                char buf[PREFIX2STR_BUFFER];
-               zlog_debug("%u: Del RNH %s type %d", rnh->vrf_id,
-                          rnh_str(rnh, buf, sizeof(buf)), type);
+               zlog_debug("%u: Del RNH %s type %s", rnh->vrf_id,
+                          rnh_str(rnh, buf, sizeof(buf)), rnh_type2str(type));
        }
 
        zebra_free_rnh(rnh);
@@ -293,9 +296,9 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
 {
        if (IS_ZEBRA_DEBUG_NHT) {
                char buf[PREFIX2STR_BUFFER];
-               zlog_debug("%u: Client %s registers for RNH %s type %d", vrf_id,
+               zlog_debug("%u: Client %s registers for RNH %s type %s", vrf_id,
                           zebra_route_string(client->proto),
-                          rnh_str(rnh, buf, sizeof(buf)), type);
+                          rnh_str(rnh, buf, sizeof(buf)), rnh_type2str(type));
        }
        if (!listnode_lookup(rnh->client_list, client))
                listnode_add(rnh->client_list, client);
@@ -312,9 +315,9 @@ void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
 {
        if (IS_ZEBRA_DEBUG_NHT) {
                char buf[PREFIX2STR_BUFFER];
-               zlog_debug("Client %s unregisters for RNH %s type %d",
+               zlog_debug("Client %s unregisters for RNH %s type %s",
                           zebra_route_string(client->proto),
-                          rnh_str(rnh, buf, sizeof(buf)), type);
+                          rnh_str(rnh, buf, sizeof(buf)), rnh_type2str(type));
        }
        listnode_delete(rnh->client_list, client);
        zebra_delete_rnh(rnh, type);
@@ -756,7 +759,7 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
         * change.
         */
        zebra_rnh_remove_from_routing_table(rnh);
-       if (!prefix_same(&rnh->resolved_route, prn ? NULL : &prn->p)) {
+       if (!prefix_same(&rnh->resolved_route, prn ? &prn->p : NULL)) {
                if (prn)
                        prefix_copy(&rnh->resolved_route, &prn->p);
                else {
@@ -803,8 +806,8 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi,
 
        if (IS_ZEBRA_DEBUG_NHT) {
                prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
-               zlog_debug("%u:%s: Evaluate RNH, type %d %s", zvrf->vrf->vrf_id,
-                          bufn, type, force ? "(force)" : "");
+               zlog_debug("%u:%s: Evaluate RNH, type %s %s", zvrf->vrf->vrf_id,
+                          bufn, rnh_type2str(type), force ? "(force)" : "");
        }
 
        rnh = nrn->info;
@@ -962,7 +965,6 @@ static void copy_state(struct rnh *rnh, struct route_entry *re,
 
 static int compare_state(struct route_entry *r1, struct route_entry *r2)
 {
-
        if (!r1 && !r2)
                return 0;
 
@@ -978,8 +980,7 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
        if (r1->nexthop_num != r2->nexthop_num)
                return 1;
 
-       if (CHECK_FLAG(r1->status, ROUTE_ENTRY_NEXTHOPS_CHANGED)
-           || CHECK_FLAG(r1->status, ROUTE_ENTRY_LABELS_CHANGED))
+       if (nexthop_group_hash(&r1->ng) != nexthop_group_hash(&r2->ng))
                return 1;
 
        return 0;
@@ -1156,9 +1157,9 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
        struct rnh *rnh;
 
        if (IS_ZEBRA_DEBUG_NHT)
-               zlog_debug("%u: Client %s RNH cleanup for family %s type %d",
+               zlog_debug("%u: Client %s RNH cleanup for family %s type %s",
                           vrf_id, zebra_route_string(client->proto),
-                          afi2str(afi), type);
+                          afi2str(afi), rnh_type2str(type));
 
        ntable = get_rnh_table(vrf_id, afi, type);
        if (!ntable) {
index 95a39411816ff4be7920f95c5934cd548deb2205..c7d2c0d2984a6fa7f26f812810ce0ec7ba5d6e8b 100644 (file)
@@ -43,6 +43,18 @@ static inline int rnh_resolve_via_default(int family)
                return 0;
 }
 
+static inline const char *rnh_type2str(rnh_type_t type)
+{
+       switch (type) {
+       case RNH_NEXTHOP_TYPE:
+               return "Nexthop";
+       case RNH_IMPORT_CHECK_TYPE:
+               return "Import";
+       }
+
+       return "ERROR";
+}
+
 extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
                                 rnh_type_t type, bool *exists);
 extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
index dbfe695a00ac0acae7ee1953b22c94da1d5f9683..2f7d50541ed2d3546f8d7232ab802ac65f85b700 100644 (file)
@@ -1254,6 +1254,40 @@ static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
        route_match_address_prefix_list_compile,
        route_match_address_prefix_list_free};
 
+/* `match ipv6 next-hop type <TYPE>' */
+
+static route_map_result_t
+route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
+                              route_map_object_t type, void *object)
+{
+       struct nh_rmap_obj *nh_data;
+
+       if (type == RMAP_ZEBRA && prefix->family == AF_INET6) {
+               nh_data = (struct nh_rmap_obj *)object;
+               if (!nh_data)
+                       return RMAP_DENYMATCH;
+
+               if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
+                       return RMAP_MATCH;
+       }
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv6_next_hop_type_compile(const char *arg)
+{
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ipv6_next_hop_type_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
+       "ipv6 next-hop type", route_match_ipv6_next_hop_type,
+       route_match_ipv6_next_hop_type_compile,
+       route_match_ipv6_next_hop_type_free};
+
 /* `match ip address prefix-len PREFIXLEN' */
 
 static route_map_result_t
@@ -1345,6 +1379,40 @@ static struct route_map_rule_cmd route_match_ip_nexthop_prefix_len_cmd = {
        route_match_address_prefix_len_free     /* reuse */
 };
 
+/* `match ip next-hop type <blackhole>' */
+
+static route_map_result_t
+route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
+                            route_map_object_t type, void *object)
+{
+       struct nh_rmap_obj *nh_data;
+
+       if (type == RMAP_ZEBRA && prefix->family == AF_INET) {
+               nh_data = (struct nh_rmap_obj *)object;
+               if (!nh_data)
+                       return RMAP_DENYMATCH;
+
+               if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
+                       return RMAP_MATCH;
+       }
+       return RMAP_NOMATCH;
+}
+
+static void *route_match_ip_next_hop_type_compile(const char *arg)
+{
+       return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+static void route_match_ip_next_hop_type_free(void *rule)
+{
+       XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
+       "ip next-hop type", route_match_ip_next_hop_type,
+       route_match_ip_next_hop_type_compile,
+       route_match_ip_next_hop_type_free};
+
 /* `match source-protocol PROTOCOL' */
 
 static route_map_result_t route_match_source_protocol(void *rule,
@@ -1927,6 +1995,9 @@ void zebra_route_map_init(void)
        route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
        route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
 
+       route_map_match_ip_next_hop_type_hook(generic_match_add);
+       route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
+
        route_map_match_tag_hook(generic_match_add);
        route_map_no_match_tag_hook(generic_match_delete);
 
@@ -1936,6 +2007,9 @@ void zebra_route_map_init(void)
        route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
        route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
 
+       route_map_match_ipv6_next_hop_type_hook(generic_match_add);
+       route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
+
        route_map_install_match(&route_match_tag_cmd);
        route_map_install_match(&route_match_interface_cmd);
        route_map_install_match(&route_match_ip_next_hop_cmd);
@@ -1947,6 +2021,8 @@ void zebra_route_map_init(void)
        route_map_install_match(&route_match_ip_address_prefix_len_cmd);
        route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
        route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
+       route_map_install_match(&route_match_ip_next_hop_type_cmd);
+       route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
        route_map_install_match(&route_match_source_protocol_cmd);
        route_map_install_match(&route_match_source_instance_cmd);
 
index 4352d688a1da7b04f552532ed5005ddeba95a6d3..1e9f9e4ec7d21401218246cb2dc9ea8d7e5b949b 100644 (file)
@@ -32,6 +32,8 @@
 #include "zebra_nhg.h"
 #include "debug.h"
 
+DEFINE_MTYPE_STATIC(ZEBRA, RIB_TABLE_INFO, "RIB table info")
+
 struct zebra_router zrouter = {
        .multipath_num = MULTIPATH_NUM,
        .ipv4_multicast_mode = MCAST_NO_CONFIG,
index fdf0cbc693fc282b4570c443333f0d639baee37e..fcc94a7be906827bbd0392f5077c6c66c90a58a0 100644 (file)
@@ -48,7 +48,8 @@ static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
 static void zebra_rnhtable_node_cleanup(struct route_table *table,
                                        struct route_node *node);
 
-DEFINE_MTYPE_STATIC(ZEBRA, OTHER_TABLE, "Other Table");
+DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_VRF, "ZEBRA VRF")
+DEFINE_MTYPE_STATIC(ZEBRA, OTHER_TABLE, "Other Table")
 
 /* VRF information update. */
 static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
index 077c1ff8f0262d2a25ec72f7b8b8e5e29c29518f..a3a630d53e53697956c9cd1e9e9a5995ce518cd3 100644 (file)
@@ -60,6 +60,9 @@ DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC");
 DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor");
 DEFINE_MTYPE_STATIC(ZEBRA, ZVXLAN_SG, "zebra VxLAN multicast group");
 
+DEFINE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
+           bool delete, const char *reason), (rmac, zl3vni, delete, reason))
+
 /* definitions */
 /* PMSI strings. */
 #define VXLAN_FLOOD_STR_NO_INFO "-"
@@ -143,8 +146,6 @@ static zebra_l3vni_t *zl3vni_lookup(vni_t vni);
 static void *zl3vni_alloc(void *p);
 static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id);
 static int zl3vni_del(zebra_l3vni_t *zl3vni);
-static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni);
-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);
 
@@ -224,6 +225,9 @@ static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
                                struct in_addr mcast_grp);
 static void zebra_vxlan_sg_cleanup(struct hash_backet *backet, void *arg);
 
+static void zvni_send_mac_to_client(zebra_vni_t *zvn);
+static void zvni_send_neigh_to_client(zebra_vni_t *zvni);
+
 /* Private functions */
 static int host_rb_entry_compare(const struct host_rb_entry *hle1,
                                 const struct host_rb_entry *hle2)
@@ -871,10 +875,10 @@ static void zvni_print_neigh_hash(struct hash_bucket *bucket, void *ctxt)
                if (json_vni == NULL) {
                        if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) &&
                            (wctx->count == 0))
-                               vty_out(vty,
-                                       "%*s %-6s %-8s %-17s %-21s\n",
+                               vty_out(vty, "%*s %-6s %-8s %-17s %-21s %s\n",
                                        -wctx->addr_width, "Neighbor", "Type",
-                                       "State", "MAC", "Remote VTEP");
+                                       "State", "MAC", "Remote VTEP",
+                                       "Seq #'s");
                        vty_out(vty, "%*s %-6s %-8s %-17s %-21s %u/%u\n",
                                -wctx->addr_width, buf2, "remote", state_str,
                                buf1, inet_ntoa(n->r_vtep_ip), n->loc_seq, n->rem_seq);
@@ -1386,8 +1390,11 @@ static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
                                vty_out(vty, " %-5u", vid);
                        else
                                json_object_int_add(json_mac, "vlan", vid);
-               }
+               } else /* No vid? fill out the space */
+                       if (json_mac_hdr == NULL)
+                               vty_out(vty, " %-5s", "");
                if (json_mac_hdr == NULL) {
+                       vty_out(vty, " %u/%u", mac->loc_seq, mac->rem_seq);
                        vty_out(vty, "\n");
                } else {
                        json_object_int_add(json_mac, "localSequence",
@@ -1418,11 +1425,13 @@ static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
                        if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) &&
                            (wctx->count == 0)) {
                                vty_out(vty, "\nVNI %u\n\n", wctx->zvni->vni);
-                               vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC",
-                                       "Type", "Intf/Remote VTEP", "VLAN");
+                               vty_out(vty, "%-17s %-6s %-21s %-5s %s\n",
+                                       "MAC", "Type", "Intf/Remote VTEP",
+                                       "VLAN", "Seq #'s");
                        }
-                       vty_out(vty, "%-17s %-6s %-21s\n", buf1, "remote",
-                               inet_ntoa(mac->fwd_info.r_vtep_ip));
+                       vty_out(vty, "%-17s %-6s %-21s %-5s %u/%u\n", buf1,
+                               "remote", inet_ntoa(mac->fwd_info.r_vtep_ip),
+                               "", mac->loc_seq, mac->rem_seq);
                } else {
                        json_object_string_add(json_mac, "type", "remote");
                        json_object_string_add(json_mac, "remoteVtep",
@@ -1536,8 +1545,8 @@ static void zvni_print_mac_hash_all_vni(struct hash_bucket *bucket, void *ctxt)
                if (json == NULL) {
                        vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
                                zvni->vni, num_macs);
-                       vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
-                               "Intf/Remote VTEP", "VLAN");
+                       vty_out(vty, "%-17s %-6s %-21s %-5s %s\n", "MAC",
+                               "Type", "Intf/Remote VTEP", "VLAN", "Seq #'s");
                } else
                        json_object_int_add(json_vni, "numMacs", num_macs);
        }
@@ -2869,6 +2878,16 @@ static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket *bucket,
        /* Add primary SVI MAC*/
        zvni = (zebra_vni_t *)bucket->data;
 
+       /* Global (Zvrf) advertise-default-gw is disabled,
+        * but zvni advertise-default-gw is enabled
+        */
+       if (zvni->advertise_gw_macip) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
+                                  zvni->vni);
+               return;
+       }
+
        ifp = zvni->vxlan_if;
        if (!ifp)
                return;
@@ -2950,6 +2969,16 @@ static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket *bucket,
        if (!zvni)
                return;
 
+       /* Global(vrf) advertise-svi-ip disabled, but zvni advertise-svi-ip
+        * enabled
+        */
+       if (zvni->advertise_svi_macip) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip",
+                                  zvni->vni);
+               return;
+       }
+
        ifp = zvni->vxlan_if;
        if (!ifp)
                return;
@@ -4056,46 +4085,67 @@ static void zvni_build_hash_table(void)
                                        ifp->name, ifp->ifindex, vni,
                                        inet_ntoa(vxl->vtep_ip));
 
-                       /* VNI hash entry is not expected to exist. */
+                       /* VNI hash entry is expected to exist, if the BGP process is killed */
                        zvni = zvni_lookup(vni);
                        if (zvni) {
                                zlog_debug(
                                        "VNI hash already present for IF %s(%u) L2-VNI %u",
                                        ifp->name, ifp->ifindex, vni);
-                               continue;
-                       }
 
-                       zvni = zvni_add(vni);
-                       if (!zvni) {
-                               zlog_debug(
-                                       "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
-                                       ifp->name, ifp->ifindex, vni);
-                               return;
-                       }
+                               /*
+                                * Inform BGP if intf is up and mapped to
+                                * bridge.
+                                */
+                               if (if_is_operative(ifp) &&
+                                       zif->brslave_info.br_if)
+                                       zvni_send_add_to_client(zvni);
 
-                       if (zvni->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr ||
-                               zvni->mcast_grp.s_addr != vxl->mcast_grp.s_addr) {
-                               zebra_vxlan_sg_deref(zvni->local_vtep_ip,
-                                       zvni->mcast_grp);
-                               zebra_vxlan_sg_ref(vxl->vtep_ip,
-                                       vxl->mcast_grp);
-                               zvni->local_vtep_ip = vxl->vtep_ip;
-                               zvni->mcast_grp = vxl->mcast_grp;
-                       }
-                       zvni->vxlan_if = ifp;
-                       vlan_if = zvni_map_to_svi(vxl->access_vlan,
-                                                 zif->brslave_info.br_if);
-                       if (vlan_if) {
-                               zvni->vrf_id = vlan_if->vrf_id;
-                               zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
-                               if (zl3vni)
-                                       listnode_add_sort(zl3vni->l2vnis, zvni);
-                       }
+                               /* Send Local MAC-entries to client */
+                               zvni_send_mac_to_client(zvni);
 
+                               /* Send Loval Neighbor entries to client */
+                               zvni_send_neigh_to_client(zvni);
+                       } else {
+                               zvni = zvni_add(vni);
+                               if (!zvni) {
+                                       zlog_debug(
+                                               "Failed to add VNI hash, IF %s(%u) L2-VNI %u",
+                                               ifp->name, ifp->ifindex, vni);
+                                       return;
+                               }
+
+                               if (zvni->local_vtep_ip.s_addr !=
+                                       vxl->vtep_ip.s_addr ||
+                                       zvni->mcast_grp.s_addr !=
+                                       vxl->mcast_grp.s_addr) {
+                                       zebra_vxlan_sg_deref(
+                                               zvni->local_vtep_ip,
+                                               zvni->mcast_grp);
+                                       zebra_vxlan_sg_ref(vxl->vtep_ip,
+                                               vxl->mcast_grp);
+                                       zvni->local_vtep_ip = vxl->vtep_ip;
+                                       zvni->mcast_grp = vxl->mcast_grp;
+                               }
+                               zvni->vxlan_if = ifp;
+                               vlan_if = zvni_map_to_svi(vxl->access_vlan,
+                                               zif->brslave_info.br_if);
+                               if (vlan_if) {
+                                       zvni->vrf_id = vlan_if->vrf_id;
+                                       zl3vni = zl3vni_from_vrf(
+                                                       vlan_if->vrf_id);
+                                       if (zl3vni)
+                                               listnode_add_sort(
+                                                       zl3vni->l2vnis, zvni);
+                               }
 
-                       /* Inform BGP if intf is up and mapped to bridge. */
-                       if (if_is_operative(ifp) && zif->brslave_info.br_if)
-                               zvni_send_add_to_client(zvni);
+                               /*
+                                * Inform BGP if intf is up and mapped to
+                                * bridge.
+                                */
+                               if (if_is_operative(ifp) &&
+                                       zif->brslave_info.br_if)
+                                       zvni_send_add_to_client(zvni);
+                       }
                }
        }
 }
@@ -4459,6 +4509,10 @@ static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
                memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
                zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
 
+               /* Send RMAC for FPM processing */
+               hook_call(zebra_rmac_update, zrmac, zl3vni, false,
+                         "new RMAC added");
+
                /* install rmac in kernel */
                zl3vni_rmac_install(zl3vni, zrmac);
        }
@@ -4479,6 +4533,10 @@ static void zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac,
                /* uninstall from kernel */
                zl3vni_rmac_uninstall(zl3vni, zrmac);
 
+               /* Send RMAC for FPM processing */
+               hook_call(zebra_rmac_update, zrmac, zl3vni, true,
+                         "RMAC deleted");
+
                /* del the rmac entry */
                zl3vni_rmac_del(zl3vni, zrmac);
        }
@@ -4790,7 +4848,7 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni)
        return 0;
 }
 
-static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
+struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
 {
        struct zebra_ns *zns = NULL;
        struct route_node *rn = NULL;
@@ -4821,7 +4879,7 @@ static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
        return NULL;
 }
 
-static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
+struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
 {
        struct zebra_if *zif = NULL;       /* zebra_if for vxlan_if */
        struct zebra_l2info_vxlan *vxl = NULL; /* l2 info for vxlan_if */
@@ -5089,6 +5147,10 @@ static void zl3vni_del_rmac_hash_entry(struct hash_bucket *bucket, void *ctx)
        zrmac = (zebra_mac_t *)bucket->data;
        zl3vni = (zebra_l3vni_t *)ctx;
        zl3vni_rmac_uninstall(zl3vni, zrmac);
+
+       /* Send RMAC for FPM processing */
+       hook_call(zebra_rmac_update, zrmac, zl3vni, true, "RMAC deleted");
+
        zl3vni_rmac_del(zl3vni, zrmac);
 }
 
@@ -6089,9 +6151,8 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
                vty_out(vty,
                        "Number of ARPs (local and remote) known for this VNI: %u\n",
                        num_neigh);
-               vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
-                       -wctx.addr_width, "IP", "Type",
-                       "State", "MAC", "Remote VTEP");
+               vty_out(vty, "%*s %-6s %-8s %-17s %-21s %s\n", -wctx.addr_width,
+                       "IP", "Type", "State", "MAC", "Remote VTEP", "Seq #'s");
        } else
                json_object_int_add(json, "numArpNd", num_neigh);
 
@@ -6353,8 +6414,8 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
                vty_out(vty,
                        "Number of MACs (local and remote) known for this VNI: %u\n",
                        num_macs);
-               vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
-                       "Intf/Remote VTEP", "VLAN");
+               vty_out(vty, "%-17s %-6s %-21s %-5s %s\n", "MAC", "Type",
+                       "Intf/Remote VTEP", "VLAN", "Seq #'s");
        } else
                json_object_int_add(json, "numMacs", num_macs);
 
@@ -8916,7 +8977,7 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
        struct interface *ifp = NULL;
 
        if (!EVPN_ENABLED(zvrf)) {
-               zlog_debug("EVPN GW-MACIP Adv for non-EVPN VRF %u",
+               zlog_debug("EVPN SVI-MACIP Adv for non-EVPN VRF %u",
                          zvrf_id(zvrf));
                return;
        }
@@ -8927,7 +8988,7 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
 
        if (!vni) {
                if (IS_ZEBRA_DEBUG_VXLAN)
-                       zlog_debug("EVPN gateway macip Adv %s, currently %s",
+                       zlog_debug("EVPN SVI-MACIP Adv %s, currently %s",
                                   advertise ? "enabled" : "disabled",
                                   advertise_gw_macip_enabled(NULL)
                                           ? "enabled"
@@ -9637,3 +9698,120 @@ static void zebra_vxlan_sg_cleanup(struct hash_backet *backet, void *arg)
 
        zebra_vxlan_sg_del(vxlan_sg);
 }
+
+/************************** EVPN BGP config management ************************/
+/* Notify Local MACs to the clienti, skips GW MAC */
+static void zvni_send_mac_hash_entry_to_client(struct hash_bucket *bucket,
+                                              void *arg)
+{
+       struct mac_walk_ctx *wctx = arg;
+       zebra_mac_t *zmac = bucket->data;
+
+       if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_DEF_GW))
+               return;
+
+       if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
+               zvni_mac_send_add_to_client(wctx->zvni->vni, &zmac->macaddr,
+                                               zmac->flags, zmac->loc_seq);
+}
+
+/* Iterator to Notify Local MACs of a L2VNI */
+static void zvni_send_mac_to_client(zebra_vni_t *zvni)
+{
+       struct mac_walk_ctx wctx;
+
+       if (!zvni->mac_table)
+               return;
+
+       memset(&wctx, 0, sizeof(struct mac_walk_ctx));
+       wctx.zvni = zvni;
+
+       hash_iterate(zvni->mac_table, zvni_send_mac_hash_entry_to_client,
+                       &wctx);
+}
+
+/* Notify Neighbor entries to the Client, skips the GW entry */
+static void zvni_send_neigh_hash_entry_to_client(struct hash_bucket *bucket,
+                                                void *arg)
+{
+       struct mac_walk_ctx *wctx = arg;
+       zebra_neigh_t *zn = bucket->data;
+       zebra_mac_t *zmac = NULL;
+
+       if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_DEF_GW))
+               return;
+
+       if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_LOCAL) &&
+               IS_ZEBRA_NEIGH_ACTIVE(zn)) {
+               zmac = zvni_mac_lookup(wctx->zvni, &zn->emac);
+               if (!zmac)
+                       return;
+
+               zvni_neigh_send_add_to_client(wctx->zvni->vni, &zn->ip,
+                                               &zn->emac, zn->flags,
+                                               zn->loc_seq);
+       }
+}
+
+/* Iterator of a specific L2VNI */
+static void zvni_send_neigh_to_client(zebra_vni_t *zvni)
+{
+       struct neigh_walk_ctx wctx;
+
+       memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
+       wctx.zvni = zvni;
+
+       hash_iterate(zvni->neigh_table, zvni_send_neigh_hash_entry_to_client,
+                       &wctx);
+}
+
+static void zvni_evpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt)
+{
+       zebra_vni_t *zvni = NULL;
+
+       zvni = (zebra_vni_t *)bucket->data;
+       zvni->advertise_gw_macip = 0;
+       zvni->advertise_svi_macip = 0;
+       zvni->advertise_subnet = 0;
+
+       zvni_neigh_del_all(zvni, 0, 0,
+                          DEL_REMOTE_NEIGH | DEL_REMOTE_NEIGH_FROM_VTEP);
+       zvni_mac_del_all(zvni, 0, 0,
+                        DEL_REMOTE_MAC | DEL_REMOTE_MAC_FROM_VTEP);
+       zvni_vtep_del_all(zvni, 0);
+}
+
+/* Cleanup EVPN configuration of a specific VRF */
+static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf)
+{
+       zvrf->advertise_all_vni = 0;
+       zvrf->advertise_gw_macip = 0;
+       zvrf->advertise_svi_macip = 0;
+       zvrf->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
+
+       hash_iterate(zvrf->vni_table, zvni_evpn_cfg_cleanup, NULL);
+}
+
+/* Cleanup BGP EVPN configuration upon client disconnect */
+static int zebra_evpn_cfg_clean_up(struct zserv *client)
+{
+       struct vrf *vrf;
+       struct zebra_vrf *zvrf;
+
+       if (client->proto != ZEBRA_ROUTE_BGP)
+               return 0;
+
+       RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
+               zvrf = vrf->info;
+               if (zvrf)
+                       zebra_evpn_vrf_cfg_cleanup(zvrf);
+       }
+
+       return 0;
+}
+
+/* Cleanup BGP EVPN configuration upon client disconnect */
+extern void zebra_evpn_init(void)
+{
+       hook_register(zserv_client_close, zebra_evpn_cfg_clean_up);
+}
index f752bdd690d27995d23f375e787899a357180596..6117567bc165e7ad4c9a820ac62aac9e6d9f0a60 100644 (file)
@@ -212,6 +212,7 @@ extern int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
 extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
                                            struct zebra_vrf *zvrf,
                                            vni_t vni);
+extern void zebra_evpn_init(void);
 
 #ifdef __cplusplus
 }
index 1dd42b7083d717aa962a79d4bf3f1965d806f264..8e7804264633b3d3ae19e0c6d100ec05605442b8 100644 (file)
@@ -431,6 +431,12 @@ struct nh_walk_ctx {
 };
 
 extern zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id);
+extern struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni);
+extern struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni);
+
+DECLARE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
+            bool delete, const char *reason), (rmac, zl3vni, delete, reason))
+
 
 #ifdef __cplusplus
 }