diff options
author | Anuradha Karuppiah <anuradhak@nvidia.com> | 2021-12-18 20:28:49 +0100 |
---|---|---|
committer | Donald Sharp <sharpd@nvidia.com> | 2022-06-27 13:56:55 +0200 |
commit | 4cf4fad15307fab9e21dd228fc7f80be4da801c2 (patch) | |
tree | ad69f25ba188879ec685b91c84239e8685287f67 | |
parent | Merge pull request #11426 from error2407/open_policy (diff) | |
download | frr-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.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 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); |