diff options
| author | Anuradha Karuppiah <anuradhak@nvidia.com> | 2021-12-18 11:28:49 -0800 | 
|---|---|---|
| committer | Donald Sharp <sharpd@nvidia.com> | 2022-06-27 07:56:55 -0400 | 
| commit | 4cf4fad15307fab9e21dd228fc7f80be4da801c2 (patch) | |
| tree | ad69f25ba188879ec685b91c84239e8685287f67 | |
| parent | f646c17a4349a2439230980bdae70b58b34b862c (diff) | |
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.c | 25 | ||||
| -rw-r--r-- | zebra/debug.h | 5 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 30 | ||||
| -rw-r--r-- | zebra/subdir.am | 2 | ||||
| -rw-r--r-- | zebra/zebra_neigh.c | 279 | ||||
| -rw-r--r-- | zebra/zebra_neigh.h | 64 | ||||
| -rw-r--r-- | zebra/zebra_pbr.h | 17 | ||||
| -rw-r--r-- | zebra/zebra_router.c | 3 | ||||
| -rw-r--r-- | zebra/zebra_router.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 12 | 
10 files changed, 433 insertions, 6 deletions
diff --git a/zebra/debug.c b/zebra/debug.c index 525180d4ee..98e25af857 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 dc44367d01..e761e5e3e3 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 ad9e13a0f8..21c991c7db 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 a09b895cee..e895ffa65f 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 0000000000..2fca2a0615 --- /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 0000000000..953f2e300a --- /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 33b8162a88..64f0193876 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 92d519bad1..9fccda9e08 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 c96c8e5f46..2ae2482487 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 011fa2a1e5..0725d19677 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);  | 
