summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@nvidia.com>2021-12-18 20:28:49 +0100
committerDonald Sharp <sharpd@nvidia.com>2022-06-27 13:56:55 +0200
commit4cf4fad15307fab9e21dd228fc7f80be4da801c2 (patch)
treead69f25ba188879ec685b91c84239e8685287f67
parentMerge pull request #11426 from error2407/open_policy (diff)
downloadfrr-4cf4fad15307fab9e21dd228fc7f80be4da801c2.tar.xz
frr-4cf4fad15307fab9e21dd228fc7f80be4da801c2.zip
zebra: add support for maintaining local neigh entries
Currently specific local neighbors (attached to SVIs) are maintatined in an EVPN specific database. There is a need to maintain L3 neighbors for other purposes including MAC resolution for PBR nexthops. Signed-off-by: Donald Sharp <sharpd@nvidia.com> Cleanup compile and fix crash Signed-off-by: Anuradha Karuppiah <anuradhak@nvidia.com>
-rw-r--r--zebra/debug.c25
-rw-r--r--zebra/debug.h5
-rw-r--r--zebra/rt_netlink.c30
-rw-r--r--zebra/subdir.am2
-rw-r--r--zebra/zebra_neigh.c279
-rw-r--r--zebra/zebra_neigh.h64
-rw-r--r--zebra/zebra_pbr.h17
-rw-r--r--zebra/zebra_router.c3
-rw-r--r--zebra/zebra_router.h2
-rw-r--r--zebra/zebra_vty.c12
10 files changed, 433 insertions, 6 deletions
diff --git a/zebra/debug.c b/zebra/debug.c
index 525180d4e..98e25af85 100644
--- a/zebra/debug.c
+++ b/zebra/debug.c
@@ -42,6 +42,7 @@ unsigned long zebra_debug_mlag;
unsigned long zebra_debug_nexthop;
unsigned long zebra_debug_evpn_mh;
unsigned long zebra_debug_pbr;
+unsigned long zebra_debug_neigh;
DEFINE_HOOK(zebra_debug_show_debugging, (struct vty *vty), (vty));
@@ -327,6 +328,22 @@ DEFUN (debug_zebra_pbr,
return CMD_SUCCESS;
}
+DEFPY (debug_zebra_neigh,
+ debug_zebra_neigh_cmd,
+ "[no$no] debug zebra neigh",
+ NO_STR
+ DEBUG_STR
+ "Zebra configuration\n"
+ "Debug zebra neigh events\n")
+{
+ if (no)
+ UNSET_FLAG(zebra_debug_neigh, ZEBRA_DEBUG_NEIGH);
+ else
+ SET_FLAG(zebra_debug_neigh, ZEBRA_DEBUG_NEIGH);
+
+ return CMD_SUCCESS;
+}
+
DEFPY (debug_zebra_mlag,
debug_zebra_mlag_cmd,
"[no$no] debug zebra mlag",
@@ -694,6 +711,11 @@ static int config_write_debug(struct vty *vty)
write++;
}
+ if (IS_ZEBRA_DEBUG_NEIGH) {
+ vty_out(vty, "debug zebra neigh\n");
+ write++;
+ }
+
return write;
}
@@ -713,6 +735,7 @@ void zebra_debug_init(void)
zebra_debug_nht = 0;
zebra_debug_nexthop = 0;
zebra_debug_pbr = 0;
+ zebra_debug_neigh = 0;
install_node(&debug_node);
@@ -734,6 +757,7 @@ void zebra_debug_init(void)
install_element(ENABLE_NODE, &debug_zebra_mlag_cmd);
install_element(ENABLE_NODE, &debug_zebra_nexthop_cmd);
install_element(ENABLE_NODE, &debug_zebra_pbr_cmd);
+ install_element(ENABLE_NODE, &debug_zebra_neigh_cmd);
install_element(ENABLE_NODE, &no_debug_zebra_events_cmd);
install_element(ENABLE_NODE, &no_debug_zebra_nht_cmd);
install_element(ENABLE_NODE, &no_debug_zebra_mpls_cmd);
@@ -764,6 +788,7 @@ void zebra_debug_init(void)
install_element(CONFIG_NODE, &debug_zebra_dplane_cmd);
install_element(CONFIG_NODE, &debug_zebra_nexthop_cmd);
install_element(CONFIG_NODE, &debug_zebra_pbr_cmd);
+ install_element(CONFIG_NODE, &debug_zebra_neigh_cmd);
install_element(CONFIG_NODE, &no_debug_zebra_events_cmd);
install_element(CONFIG_NODE, &no_debug_zebra_nht_cmd);
diff --git a/zebra/debug.h b/zebra/debug.h
index dc44367d0..e761e5e3e 100644
--- a/zebra/debug.h
+++ b/zebra/debug.h
@@ -70,6 +70,8 @@ extern "C" {
#define ZEBRA_DEBUG_PBR 0x01
+#define ZEBRA_DEBUG_NEIGH 0x01
+
/* Debug related macro. */
#define IS_ZEBRA_DEBUG_EVENT (zebra_debug_event & ZEBRA_DEBUG_EVENT)
@@ -121,6 +123,8 @@ extern "C" {
#define IS_ZEBRA_DEBUG_PBR (zebra_debug_pbr & ZEBRA_DEBUG_PBR)
+#define IS_ZEBRA_DEBUG_NEIGH (zebra_debug_neigh & ZEBRA_DEBUG_NEIGH)
+
extern unsigned long zebra_debug_event;
extern unsigned long zebra_debug_packet;
extern unsigned long zebra_debug_kernel;
@@ -135,6 +139,7 @@ extern unsigned long zebra_debug_mlag;
extern unsigned long zebra_debug_nexthop;
extern unsigned long zebra_debug_evpn_mh;
extern unsigned long zebra_debug_pbr;
+extern unsigned long zebra_debug_neigh;
extern void zebra_debug_init(void);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index ad9e13a0f..21c991c7d 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -80,6 +80,7 @@
#include "zebra/zebra_errors.h"
#include "zebra/zebra_evpn_mh.h"
#include "zebra/zebra_trace.h"
+#include "zebra/zebra_neigh.h"
#ifndef AF_MPLS
#define AF_MPLS 28
@@ -3882,10 +3883,10 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
} else if (IS_ZEBRA_IF_BRIDGE(ifp))
link_if = ifp;
else {
+ link_if = NULL;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
" Neighbor Entry received is not on a VLAN or a BRIDGE, ignoring");
- return 0;
}
memset(&mac, 0, sizeof(mac));
@@ -3949,12 +3950,25 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
*/
local_inactive = false;
- return zebra_vxlan_handle_kernel_neigh_update(
- ifp, link_if, &ip, &mac, ndm->ndm_state, is_ext,
- is_router, local_inactive, dp_static);
+ /* Add local neighbors to the l3 interface database */
+ if (is_ext)
+ zebra_neigh_del(ifp, &ip);
+ else
+ zebra_neigh_add(ifp, &ip, &mac);
+
+ if (link_if)
+ zebra_vxlan_handle_kernel_neigh_update(
+ ifp, link_if, &ip, &mac, ndm->ndm_state,
+ is_ext, is_router, local_inactive,
+ dp_static);
+ return 0;
}
- return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
+
+ zebra_neigh_del(ifp, &ip);
+ if (link_if)
+ zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
+ return 0;
}
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -3967,7 +3981,11 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
/* Process the delete - it may result in re-adding the neighbor if it is
* a valid "remote" neighbor.
*/
- return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
+ zebra_neigh_del(ifp, &ip);
+ if (link_if)
+ zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
+
+ return 0;
}
static int netlink_neigh_table(struct nlmsghdr *h, ns_id_t ns_id, int startup)
diff --git a/zebra/subdir.am b/zebra/subdir.am
index a09b895ce..e895ffa65 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -125,6 +125,7 @@ zebra_zebra_SOURCES = \
zebra/zebra_vty.c \
zebra/zebra_vxlan.c \
zebra/zebra_evpn_mh.c \
+ zebra/zebra_neigh.c \
zebra/zserv.c \
# end
@@ -197,6 +198,7 @@ noinst_HEADERS += \
zebra/zebra_vxlan.h \
zebra/zebra_vxlan_private.h \
zebra/zebra_evpn_mh.h \
+ zebra/zebra_neigh.h \
zebra/zserv.h \
# end
diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c
new file mode 100644
index 000000000..2fca2a061
--- /dev/null
+++ b/zebra/zebra_neigh.c
@@ -0,0 +1,279 @@
+/*
+ * Zebra neighbor table management
+ *
+ * Copyright (C) 2021 Nvidia
+ * Anuradha Karuppiah
+ *
+ * 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.
+ */
+
+#include <zebra.h>
+
+#include "command.h"
+#include "hash.h"
+#include "if.h"
+#include "jhash.h"
+#include "linklist.h"
+#include "log.h"
+#include "memory.h"
+#include "prefix.h"
+#include "stream.h"
+#include "table.h"
+
+#include "zebra/zebra_router.h"
+#include "zebra/debug.h"
+#include "zebra/interface.h"
+#include "zebra/rib.h"
+#include "zebra/rt.h"
+#include "zebra/rt_netlink.h"
+#include "zebra/zebra_errors.h"
+#include "zebra/interface.h"
+#include "zebra/zebra_neigh.h"
+#include "zebra/zebra_pbr.h"
+
+DEFINE_MTYPE_STATIC(ZEBRA, ZNEIGH_INFO, "Zebra neigh table");
+DEFINE_MTYPE_STATIC(ZEBRA, ZNEIGH_ENT, "Zebra neigh entry");
+
+static int zebra_neigh_rb_cmp(const struct zebra_neigh_ent *n1,
+ const struct zebra_neigh_ent *n2)
+{
+ if (n1->ifindex < n2->ifindex)
+ return -1;
+
+ if (n1->ifindex > n2->ifindex)
+ return 1;
+
+ if (n1->ip.ipa_type < n2->ip.ipa_type)
+ return -1;
+
+ if (n1->ip.ipa_type > n2->ip.ipa_type)
+ return 1;
+
+ if (n1->ip.ipa_type == AF_INET) {
+ if (n1->ip.ipaddr_v4.s_addr < n2->ip.ipaddr_v4.s_addr)
+ return -1;
+
+ if (n1->ip.ipaddr_v4.s_addr > n2->ip.ipaddr_v4.s_addr)
+ return 1;
+
+ return 0;
+ }
+
+ return memcmp(&n1->ip.ipaddr_v6, &n2->ip.ipaddr_v6, IPV6_MAX_BYTELEN);
+}
+RB_GENERATE(zebra_neigh_rb_head, zebra_neigh_ent, rb_node, zebra_neigh_rb_cmp);
+
+static struct zebra_neigh_ent *zebra_neigh_find(ifindex_t ifindex,
+ struct ipaddr *ip)
+{
+ struct zebra_neigh_ent tmp;
+
+ tmp.ifindex = ifindex;
+ memcpy(&tmp.ip, ip, sizeof(*ip));
+ return RB_FIND(zebra_neigh_rb_head, &zneigh_info->neigh_rb_tree, &tmp);
+}
+
+static struct zebra_neigh_ent *
+zebra_neigh_new(ifindex_t ifindex, struct ipaddr *ip, struct ethaddr *mac)
+{
+ struct zebra_neigh_ent *n;
+
+ n = XCALLOC(MTYPE_ZNEIGH_ENT, sizeof(struct zebra_neigh_ent));
+
+ memcpy(&n->ip, ip, sizeof(*ip));
+ n->ifindex = ifindex;
+ if (mac) {
+ memcpy(&n->mac, mac, sizeof(*mac));
+ n->flags |= ZEBRA_NEIGH_ENT_ACTIVE;
+ }
+
+ /* Add to rb_tree */
+ if (RB_INSERT(zebra_neigh_rb_head, &zneigh_info->neigh_rb_tree, n)) {
+ XFREE(MTYPE_ZNEIGH_ENT, n);
+ return NULL;
+ }
+
+ /* Initialise the pbr rule list */
+ n->pbr_rule_list = list_new();
+ listset_app_node_mem(n->pbr_rule_list);
+
+ if (IS_ZEBRA_DEBUG_NEIGH)
+ zlog_debug("zebra neigh new if %d %pIA %pEA", n->ifindex,
+ &n->ip, &n->mac);
+
+ return n;
+}
+
+static void zebra_neigh_pbr_rules_update(struct zebra_neigh_ent *n)
+{
+ struct zebra_pbr_rule *rule;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(n->pbr_rule_list, node, rule))
+ dplane_pbr_rule_update(rule, rule);
+}
+
+static void zebra_neigh_free(struct zebra_neigh_ent *n)
+{
+ if (listcount(n->pbr_rule_list)) {
+ /* if rules are still using the neigh mark it as inactive and
+ * update the dataplane
+ */
+ if (n->flags & ZEBRA_NEIGH_ENT_ACTIVE) {
+ n->flags &= ~ZEBRA_NEIGH_ENT_ACTIVE;
+ memset(&n->mac, 0, sizeof(n->mac));
+ }
+ zebra_neigh_pbr_rules_update(n);
+ return;
+ }
+ if (IS_ZEBRA_DEBUG_NEIGH)
+ zlog_debug("zebra neigh free if %d %pIA %pEA", n->ifindex,
+ &n->ip, &n->mac);
+
+ /* cleanup resources maintained against the neigh */
+ list_delete(&n->pbr_rule_list);
+
+ RB_REMOVE(zebra_neigh_rb_head, &zneigh_info->neigh_rb_tree, n);
+
+ XFREE(MTYPE_ZNEIGH_ENT, n);
+}
+
+/* kernel neigh del */
+void zebra_neigh_del(struct interface *ifp, struct ipaddr *ip)
+{
+ struct zebra_neigh_ent *n;
+
+ if (IS_ZEBRA_DEBUG_NEIGH)
+ zlog_debug("zebra neigh del if %s/%d %pIA", ifp->name,
+ ifp->ifindex, ip);
+
+ n = zebra_neigh_find(ifp->ifindex, ip);
+ if (!n)
+ return;
+ zebra_neigh_free(n);
+}
+
+/* kernel neigh add */
+void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip,
+ struct ethaddr *mac)
+{
+ struct zebra_neigh_ent *n;
+
+ if (IS_ZEBRA_DEBUG_NEIGH)
+ zlog_debug("zebra neigh add if %s/%d %pIA %pEA", ifp->name,
+ ifp->ifindex, ip, mac);
+
+ n = zebra_neigh_find(ifp->ifindex, ip);
+ if (n) {
+ if (!memcmp(&n->mac, mac, sizeof(*mac)))
+ return;
+
+ memcpy(&n->mac, mac, sizeof(*mac));
+ n->flags |= ZEBRA_NEIGH_ENT_ACTIVE;
+
+ /* update rules linked to the neigh */
+ zebra_neigh_pbr_rules_update(n);
+ } else {
+ zebra_neigh_new(ifp->ifindex, ip, mac);
+ }
+}
+
+void zebra_neigh_deref(struct zebra_pbr_rule *rule)
+{
+ struct zebra_neigh_ent *n = rule->action.neigh;
+
+ if (IS_ZEBRA_DEBUG_NEIGH)
+ zlog_debug("zebra neigh deref if %d %pIA by pbr rule %u",
+ n->ifindex, &n->ip, rule->rule.seq);
+
+ rule->action.neigh = NULL;
+ /* remove rule from the list and free if it is inactive */
+ list_delete_node(n->pbr_rule_list, &rule->action.neigh_listnode);
+ if (!(n->flags & ZEBRA_NEIGH_ENT_ACTIVE))
+ zebra_neigh_free(n);
+}
+
+/* XXX - this needs to work with evpn's neigh read */
+static void zebra_neigh_read_on_first_ref(void)
+{
+ static bool neigh_read_done;
+
+ if (!neigh_read_done) {
+ neigh_read(zebra_ns_lookup(NS_DEFAULT));
+ neigh_read_done = true;
+ }
+}
+
+void zebra_neigh_ref(int ifindex, struct ipaddr *ip,
+ struct zebra_pbr_rule *rule)
+{
+ struct zebra_neigh_ent *n;
+
+ if (IS_ZEBRA_DEBUG_NEIGH)
+ zlog_debug("zebra neigh ref if %d %pIA by pbr rule %u", ifindex,
+ ip, rule->rule.seq);
+
+ zebra_neigh_read_on_first_ref();
+ n = zebra_neigh_find(ifindex, ip);
+ if (!n)
+ n = zebra_neigh_new(ifindex, ip, NULL);
+
+ /* link the pbr entry to the neigh */
+ if (rule->action.neigh == n)
+ return;
+
+ if (rule->action.neigh)
+ zebra_neigh_deref(rule);
+
+ rule->action.neigh = n;
+ listnode_init(&rule->action.neigh_listnode, rule);
+ listnode_add(n->pbr_rule_list, &rule->action.neigh_listnode);
+}
+
+static void zebra_neigh_show_one(struct vty *vty, struct zebra_neigh_ent *n)
+{
+ char mac_buf[ETHER_ADDR_STRLEN];
+ char ip_buf[INET6_ADDRSTRLEN];
+ struct interface *ifp;
+
+ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+ n->ifindex);
+ ipaddr2str(&n->ip, ip_buf, sizeof(ip_buf));
+ prefix_mac2str(&n->mac, mac_buf, sizeof(mac_buf));
+ vty_out(vty, "%-20s %-30s %-18s %u\n", ifp ? ifp->name : "-", ip_buf,
+ mac_buf, listcount(n->pbr_rule_list));
+}
+
+void zebra_neigh_show(struct vty *vty)
+{
+ struct zebra_neigh_ent *n;
+
+ vty_out(vty, "%-20s %-30s %-18s %s\n", "Interface", "Neighbor", "MAC",
+ "#Rules");
+ RB_FOREACH (n, zebra_neigh_rb_head, &zneigh_info->neigh_rb_tree)
+ zebra_neigh_show_one(vty, n);
+}
+
+void zebra_neigh_init(void)
+{
+ zneigh_info = XCALLOC(MTYPE_ZNEIGH_INFO, sizeof(*zrouter.neigh_info));
+ RB_INIT(zebra_neigh_rb_head, &zneigh_info->neigh_rb_tree);
+}
+
+void zebra_neigh_terminate(void)
+{
+ if (!zrouter.neigh_info)
+ return;
+
+ XFREE(MTYPE_ZNEIGH_INFO, zneigh_info);
+}
diff --git a/zebra/zebra_neigh.h b/zebra/zebra_neigh.h
new file mode 100644
index 000000000..953f2e300
--- /dev/null
+++ b/zebra/zebra_neigh.h
@@ -0,0 +1,64 @@
+/*
+ * Zebra neighbor table management
+ *
+ * Copyright (C) 2021 Nvidia
+ * Anuradha Karuppiah
+ *
+ * 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.
+ */
+
+#ifndef _ZEBRA_NEIGH_H
+#define _ZEBRA_NEIGH_H
+
+#include <zebra.h>
+
+#include "if.h"
+
+#define zneigh_info zrouter.neigh_info
+
+struct zebra_neigh_ent {
+ ifindex_t ifindex;
+ struct ipaddr ip;
+
+ struct ethaddr mac;
+
+ uint32_t flags;
+#define ZEBRA_NEIGH_ENT_ACTIVE (1 << 0) /* can be used for traffic */
+
+ /* memory used for adding the neigt entry to zneigh_info->es_rb_tree */
+ RB_ENTRY(zebra_neigh_ent) rb_node;
+
+ /* list of pbr rules associated with this neigh */
+ struct list *pbr_rule_list;
+};
+RB_HEAD(zebra_neigh_rb_head, zebra_neigh_ent);
+RB_PROTOTYPE(zebra_neigh_rb_head, zebra_neigh_ent, rb_node, zebra_es_rb_cmp);
+
+struct zebra_neigh_info {
+ /* RB tree of neighbor entries */
+ struct zebra_neigh_rb_head neigh_rb_tree;
+};
+
+
+/****************************************************************************/
+extern void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip,
+ struct ethaddr *mac);
+extern void zebra_neigh_del(struct interface *ifp, struct ipaddr *ip);
+extern void zebra_neigh_show(struct vty *vty);
+extern void zebra_neigh_init(void);
+extern void zebra_neigh_terminate(void);
+extern void zebra_neigh_deref(struct zebra_pbr_rule *rule);
+extern void zebra_neigh_ref(int ifindex, struct ipaddr *ip,
+ struct zebra_pbr_rule *rule);
+
+#endif /* _ZEBRA_NEIGH_H */
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index 33b8162a8..64f019387 100644
--- a/zebra/zebra_pbr.h
+++ b/zebra/zebra_pbr.h
@@ -36,6 +36,21 @@
extern "C" {
#endif
+struct zebra_pbr_action {
+ afi_t afi;
+
+ /* currently only one nexthop is supported */
+ union g_addr gate;
+
+ /* dest-interface */
+ ifindex_t ifindex;
+
+ /* neigh */
+ struct zebra_neigh_ent *neigh;
+ /* zebr_pbr_rule is linked to neigh via neigh_listnode */
+ struct listnode neigh_listnode;
+};
+
struct zebra_pbr_rule {
int sock;
@@ -43,6 +58,8 @@ struct zebra_pbr_rule {
char ifname[INTERFACE_NAMSIZ];
+ struct zebra_pbr_action action;
+
vrf_id_t vrf_id;
};
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 92d519bad..9fccda9e0 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -29,6 +29,7 @@
#include "zebra_vxlan.h"
#include "zebra_mlag.h"
#include "zebra_nhg.h"
+#include "zebra_neigh.h"
#include "debug.h"
#include "zebra_script.h"
@@ -242,6 +243,7 @@ void zebra_router_terminate(void)
zebra_vxlan_disable();
zebra_mlag_terminate();
+ zebra_neigh_terminate();
/* Free NHE in ID table only since it has unhashable entries as well */
hash_clean(zrouter.nhgs_id, zebra_nhg_hash_free);
@@ -282,6 +284,7 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zebra_vxlan_init();
zebra_mlag_init();
+ zebra_neigh_init();
zrouter.rules_hash = hash_create_size(8, zebra_pbr_rules_hash_key,
zebra_pbr_rules_hash_equal,
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index c96c8e5f4..2ae248248 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -159,6 +159,8 @@ struct zebra_router {
/* Tables and other global info maintained for EVPN multihoming */
struct zebra_evpn_mh_info *mh_info;
+ struct zebra_neigh_info *neigh_info;
+
/* EVPN MH broadcast domains indexed by the VID */
struct hash *evpn_vlan_table;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 011fa2a1e..0725d1967 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -64,6 +64,7 @@
#include "zebra/table_manager.h"
#include "zebra/zebra_script.h"
#include "zebra/rtadv.h"
+#include "zebra/zebra_neigh.h"
extern int allow_delete;
@@ -3005,6 +3006,15 @@ DEFUN (show_evpn_global,
return CMD_SUCCESS;
}
+DEFPY(show_evpn_neigh, show_neigh_cmd, "show ip neigh",
+ SHOW_STR IP_STR "neighbors\n")
+
+{
+ zebra_neigh_show(vty);
+
+ return CMD_SUCCESS;
+}
+
DEFPY(show_evpn_l2_nh,
show_evpn_l2_nh_cmd,
"show evpn l2-nh [json$json]",
@@ -4529,6 +4539,8 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
+ install_element(VIEW_NODE, &show_neigh_cmd);
+
install_element(VIEW_NODE, &show_pbr_ipset_cmd);
install_element(VIEW_NODE, &show_pbr_iptable_cmd);
install_element(VIEW_NODE, &show_route_zebra_dump_cmd);