summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/zebra_mpls.c10
-rw-r--r--zebra/zebra_mpls.h7
-rw-r--r--zebra/zebra_ns.c9
-rw-r--r--zebra/zebra_vrf.c233
-rw-r--r--zebra/zebra_vrf.h1
-rw-r--r--zebra/zebra_vty.c232
-rw-r--r--zebra/zebra_vxlan.c726
-rw-r--r--zebra/zebra_vxlan.h13
-rw-r--r--zebra/zebra_vxlan_null.c12
-rw-r--r--zebra/zebra_vxlan_private.h5
-rw-r--r--zebra/zserv.c3
-rw-r--r--zebra/zserv.h2
12 files changed, 889 insertions, 364 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 61051ba87e..22c81b5784 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -2876,6 +2876,16 @@ int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *zvrf)
}
/*
+ * Called when VRF becomes inactive, cleans up information but keeps
+ * the table itself.
+ * NOTE: Currently supported only for default VRF.
+ */
+void zebra_mpls_cleanup_tables(struct zebra_vrf *zvrf)
+{
+ hash_iterate(zvrf->lsp_table, lsp_uninstall_from_kernel, NULL);
+}
+
+/*
* Called upon process exiting, need to delete LSP forwarding
* entries from the kernel.
* NOTE: Currently supported only for default VRF.
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index 9d8ca34f82..27a4971691 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -385,6 +385,13 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf);
/*
+ * Called when VRF becomes inactive, cleans up information but keeps
+ * the table itself.
+ * NOTE: Currently supported only for default VRF.
+ */
+void zebra_mpls_cleanup_tables(struct zebra_vrf *zvrf);
+
+/*
* Called upon process exiting, need to delete LSP forwarding
* entries from the kernel.
* NOTE: Currently supported only for default VRF.
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index b3b9c6d18a..c48a6f7bd8 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -41,6 +41,7 @@ struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id)
return dzns;
}
+/* Do global enable actions - open sockets, read kernel config etc. */
int zebra_ns_enable(ns_id_t ns_id, void **info)
{
struct zebra_ns *zns = (struct zebra_ns *)(*info);
@@ -49,8 +50,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
rtadv_init(zns);
#endif
- zns->if_table = route_table_init();
- zebra_vxlan_ns_init(zns);
kernel_init(zns);
interface_list(zns);
route_read(zns);
@@ -79,8 +78,14 @@ int zebra_ns_init(void)
ns_init();
+ /* Do any needed per-NS data structure allocation. */
+ dzns->if_table = route_table_init();
+ zebra_vxlan_ns_init(dzns);
+
+ /* Register zebra VRF callbacks, create and activate default VRF. */
zebra_vrf_init();
+ /* Default NS is activated */
zebra_ns_enable(NS_DEFAULT, (void **)&dzns);
return 0;
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 246a7e7e4c..b9b3048486 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -41,6 +41,11 @@
extern struct zebra_t zebrad;
+static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
+ safi_t safi);
+static void zebra_rnhtable_node_cleanup(struct route_table *table,
+ struct route_node *node);
+
/* VRF information update. */
static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
{
@@ -82,7 +87,7 @@ static int zebra_vrf_new(struct vrf *vrf)
struct zebra_vrf *zvrf;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_info("ZVRF %s with id %u", vrf->name, vrf->vrf_id);
+ zlog_info("VRF %s created, id %u", vrf->name, vrf->vrf_id);
zvrf = zebra_vrf_alloc();
zvrf->zns = zebra_ns_lookup(
@@ -101,14 +106,36 @@ static int zebra_vrf_enable(struct vrf *vrf)
struct route_table *stable;
struct route_node *rn;
struct static_route *si;
+ struct route_table *table;
struct interface *ifp;
afi_t afi;
safi_t safi;
assert(zvrf);
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("VRF %s id %u is now active",
+ zvrf_name(zvrf), zvrf_id(zvrf));
+ /* Inform clients that the VRF is now active. This is an
+ * add for the clients.
+ */
zebra_vrf_add_update(zvrf);
+ /* Allocate tables */
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+ zebra_vrf_table_create(zvrf, afi, safi);
+
+ table = route_table_init();
+ table->cleanup = zebra_rnhtable_node_cleanup;
+ zvrf->rnh_table[afi] = table;
+
+ table = route_table_init();
+ table->cleanup = zebra_rnhtable_node_cleanup;
+ zvrf->import_check_table[afi] = table;
+ }
+
+ /* Install any static routes configured for this VRF. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
stable = zvrf->stable[afi][safi];
@@ -132,6 +159,9 @@ static int zebra_vrf_enable(struct vrf *vrf)
}
}
+ /* Kick off any VxLAN-EVPN processing. */
+ zebra_vxlan_vrf_enable(zvrf);
+
return 0;
}
@@ -142,13 +172,19 @@ static int zebra_vrf_disable(struct vrf *vrf)
struct route_table *stable;
struct route_node *rn;
struct static_route *si;
+ struct route_table *table;
+ struct interface *ifp;
+ u_int32_t table_id;
afi_t afi;
safi_t safi;
+ unsigned i;
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("VRF %s id %u is now disabled.", zvrf_name(zvrf),
- zvrf_id(zvrf));
+ assert(zvrf);
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("VRF %s id %u is now inactive",
+ zvrf_name(zvrf), zvrf_id(zvrf));
+ /* Uninstall any static routes configured for this VRF. */
for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
stable = zvrf->stable[afi][safi];
@@ -161,6 +197,84 @@ static int zebra_vrf_disable(struct vrf *vrf)
afi, safi, &rn->p, NULL, si);
}
+ /* Stop any VxLAN-EVPN processing. */
+ zebra_vxlan_vrf_disable(zvrf);
+
+ /* Inform clients that the VRF is now inactive. This is a
+ * delete for the clients.
+ */
+ zebra_vrf_delete_update(zvrf);
+
+ /* If asked to retain routes, there's nothing more to do. */
+ if (CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN))
+ return 0;
+
+ /* Remove all routes. */
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+ rib_close_table(zvrf->table[afi][safi]);
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
+ table_id++)
+ if (zvrf->other_table[afi][table_id])
+ rib_close_table(zvrf->other_table[afi][table_id]);
+ }
+
+ /* Cleanup Vxlan, MPLS and PW tables. */
+ zebra_vxlan_cleanup_tables(zvrf);
+ zebra_mpls_cleanup_tables(zvrf);
+ zebra_pw_exit(zvrf);
+
+ /* Remove link-local IPv4 addresses created for BGP unnumbered peering. */
+ FOR_ALL_INTERFACES (vrf, ifp)
+ if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
+
+ /* clean-up work queues */
+ for (i = 0; i < MQ_SIZE; i++) {
+ struct listnode *lnode, *nnode;
+ struct route_node *rnode;
+ rib_dest_t *dest;
+
+ for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, rnode)) {
+ dest = rib_dest_from_rnode(rnode);
+ if (dest && rib_dest_vrf(dest) == zvrf) {
+ route_unlock_node(rnode);
+ list_delete_node(zebrad.mq->subq[i], lnode);
+ zebrad.mq->size--;
+ }
+ }
+ }
+
+ /* Cleanup (free) routing tables and NHT tables. */
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
+ void *table_info;
+
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
+ table = zvrf->table[afi][safi];
+ table_info = table->info;
+ route_table_finish(table);
+ XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ zvrf->table[afi][safi] = NULL;
+ }
+
+ if (vrf->vrf_id == VRF_DEFAULT)
+ for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
+ table_id++)
+ if (zvrf->other_table[afi][table_id]) {
+ table = zvrf->other_table[afi][table_id];
+ table_info = table->info;
+ route_table_finish(table);
+ XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ zvrf->other_table[afi][table_id] = NULL;
+ }
+
+ route_table_finish(zvrf->rnh_table[afi]);
+ zvrf->rnh_table[afi] = NULL;
+ route_table_finish(zvrf->import_check_table[afi]);
+ zvrf->import_check_table[afi] = NULL;
+ }
+
return 0;
}
@@ -174,38 +288,9 @@ static int zebra_vrf_delete(struct vrf *vrf)
unsigned i;
assert(zvrf);
-
- zebra_vrf_delete_update(zvrf);
-
- /* uninstall everything */
- if (!CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN)) {
- struct interface *ifp;
-
- for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
- for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST;
- safi++)
- rib_close_table(zvrf->table[afi][safi]);
-
- if (vrf->vrf_id == VRF_DEFAULT)
- for (table_id = 0;
- table_id < ZEBRA_KERNEL_TABLE_MAX;
- table_id++)
- if (zvrf->other_table[afi][table_id])
- rib_close_table(
- zvrf->other_table
- [afi]
- [table_id]);
- }
-
- /* Cleanup Vxlan table and update kernel */
- zebra_vxlan_close_tables(zvrf);
-
- zebra_mpls_close_tables(zvrf);
- zebra_pw_exit(zvrf);
-
- FOR_ALL_INTERFACES (vrf, ifp)
- if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
- }
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("VRF %s id %u deleted",
+ zvrf_name(zvrf), zvrf_id(zvrf));
/* clean-up work queues */
for (i = 0; i < MQ_SIZE; i++) {
@@ -213,8 +298,7 @@ static int zebra_vrf_delete(struct vrf *vrf)
struct route_node *rnode;
rib_dest_t *dest;
- for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode,
- rnode)) {
+ for (ALL_LIST_ELEMENTS(zebrad.mq->subq[i], lnode, nnode, rnode)) {
dest = rib_dest_from_rnode(rnode);
if (dest && rib_dest_vrf(dest) == zvrf) {
route_unlock_node(rnode);
@@ -224,22 +308,27 @@ static int zebra_vrf_delete(struct vrf *vrf)
}
}
+ /* Free Vxlan and MPLS. */
+ zebra_vxlan_close_tables(zvrf);
+ zebra_mpls_close_tables(zvrf);
+
/* release allocated memory */
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
void *table_info;
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
table = zvrf->table[afi][safi];
- table_info = table->info;
- route_table_finish(table);
- XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ if (table) {
+ table_info = table->info;
+ route_table_finish(table);
+ XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ }
table = zvrf->stable[afi][safi];
route_table_finish(table);
}
- for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX;
- table_id++)
+ for (table_id = 0; table_id < ZEBRA_KERNEL_TABLE_MAX; table_id++)
if (zvrf->other_table[afi][table_id]) {
table = zvrf->other_table[afi][table_id];
table_info = table->info;
@@ -251,7 +340,7 @@ static int zebra_vrf_delete(struct vrf *vrf)
route_table_finish(zvrf->import_check_table[afi]);
}
- /* cleanup evpn states for vrf */
+ /* Cleanup EVPN states for vrf */
zebra_vxlan_vrf_delete(zvrf);
list_delete_all_node(zvrf->rid_all_sorted_list);
@@ -262,6 +351,37 @@ static int zebra_vrf_delete(struct vrf *vrf)
return 0;
}
+/* Return if this VRF has any FRR configuration or not.
+ * IMPORTANT: This function needs to be updated when additional configuration
+ * is added for a VRF.
+ */
+int zebra_vrf_has_config(struct zebra_vrf *zvrf)
+{
+ afi_t afi;
+ safi_t safi;
+ struct route_table *stable;
+
+ /* NOTE: This is a don't care for the default VRF, but we go through
+ * the motions to keep things consistent.
+ */
+ /* Any static routes? */
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+ stable = zvrf->stable[afi][safi];
+ if (!stable)
+ continue;
+ if (route_table_count(stable))
+ return 1;
+ }
+ }
+
+ /* EVPN L3-VNI? */
+ if (zvrf->l3vni)
+ return 1;
+
+ return 0;
+}
+
/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
* NOTE: Table-id is relevant only in the Default VRF.
*/
@@ -354,9 +474,9 @@ struct zebra_vrf *zebra_vrf_alloc(void)
zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf));
+ /* Allocate table for static route configuration. */
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
- zebra_vrf_table_create(zvrf, afi, safi);
if (afi == AFI_IP6)
table = srcdest_table_init();
else
@@ -364,14 +484,6 @@ struct zebra_vrf *zebra_vrf_alloc(void)
table->cleanup = zebra_stable_node_cleanup;
zvrf->stable[afi][safi] = table;
}
-
- table = route_table_init();
- table->cleanup = zebra_rnhtable_node_cleanup;
- zvrf->rnh_table[afi] = table;
-
- table = route_table_init();
- table->cleanup = zebra_rnhtable_node_cleanup;
- zvrf->import_check_table[afi] = table;
}
zebra_vxlan_init_tables(zvrf);
@@ -477,16 +589,23 @@ static int vrf_config_write(struct vty *vty)
if (!zvrf)
continue;
- if (vrf->vrf_id != VRF_DEFAULT)
+ if (zvrf_id(zvrf) == VRF_DEFAULT) {
+ if (zvrf->l3vni)
+ vty_out(vty, "vni %u\n", zvrf->l3vni);
+ vty_out(vty, "!\n");
+ }
+
+ if (vrf_is_user_cfged(vrf)) {
vty_out(vty, "vrf %s\n", zvrf_name(zvrf));
+ if (zvrf->l3vni)
+ vty_out(vty, " vni %u\n", zvrf->l3vni);
+ vty_out(vty, "!\n");
+ }
static_config(vty, zvrf, AFI_IP, SAFI_UNICAST, "ip route");
static_config(vty, zvrf, AFI_IP, SAFI_MULTICAST, "ip mroute");
static_config(vty, zvrf, AFI_IP6, SAFI_UNICAST, "ipv6 route");
- if (vrf->vrf_id != VRF_DEFAULT && zvrf->l3vni)
- vty_out(vty, " vni %u\n", zvrf->l3vni);
-
if (vrf->vrf_id != VRF_DEFAULT)
vty_out(vty, "!\n");
}
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index c7a0717ee8..fe7e77e8be 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -149,5 +149,6 @@ extern struct route_table *zebra_vrf_static_table(afi_t, safi_t,
struct zebra_vrf *zvrf);
extern struct route_table *
zebra_vrf_other_route_table(afi_t afi, u_int32_t table_id, vrf_id_t vrf_id);
+extern int zebra_vrf_has_config(struct zebra_vrf *zvrf);
extern void zebra_vrf_init(void);
#endif
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 62869b7eec..f8c9833854 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -231,13 +231,19 @@ static int zebra_static_route_leak(struct vty *vty,
type = STATIC_IPV6_GATEWAY;
}
- if (!negate)
+ if (!negate) {
static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
bh_type, tag, distance, zvrf, nh_zvrf,
&snh_label);
- else
+ /* Mark as having FRR configuration */
+ vrf_set_user_cfged(zvrf->vrf);
+ } else {
static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
tag, distance, zvrf, &snh_label);
+ /* If no other FRR config for this VRF, mark accordingly. */
+ if (!zebra_vrf_has_config(zvrf))
+ vrf_reset_user_cfged(zvrf->vrf);
+ }
return CMD_SUCCESS;
}
@@ -247,19 +253,39 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
const char *mask_str, const char *src_str,
const char *gate_str, const char *ifname,
const char *flag_str, const char *tag_str,
- const char *distance_str, const char *vrf_id_str,
+ const char *distance_str, const char *vrf_name,
const char *label_str)
{
struct zebra_vrf *zvrf;
+ struct vrf *vrf;
/* VRF id */
- zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
+ zvrf = zebra_vrf_lookup_by_name(vrf_name);
- if (!zvrf) {
- vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
+ /* When trying to delete, the VRF must exist. */
+ if (negate && !zvrf) {
+ vty_out(vty, "%% vrf %s is not defined\n", vrf_name);
return CMD_WARNING_CONFIG_FAILED;
}
+ /* When trying to create, create the VRF if it doesn't exist.
+ * Note: The VRF isn't active until we hear about it from the kernel.
+ */
+ if (!zvrf) {
+ vrf = vrf_get(VRF_UNKNOWN, vrf_name);
+ if (!vrf) {
+ vty_out(vty, "%% Could not create vrf %s\n", vrf_name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ zvrf = vrf->info;
+ if (!zvrf) {
+ vty_out(vty, "%% Could not create vrf-info %s\n",
+ vrf_name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ /* Mark as having FRR configuration */
+ vrf_set_user_cfged(vrf);
+ }
return zebra_static_route_leak(vty, zvrf, zvrf, afi, safi,
negate, dest_str, mask_str, src_str,
gate_str, ifname, flag_str, tag_str,
@@ -2286,16 +2312,67 @@ DEFUN (show_vrf,
else
vty_out(vty, "id %u table %u", zvrf_id(zvrf),
zvrf->table_id);
+ if (vrf_is_user_cfged(vrf))
+ vty_out(vty, " (configured)");
vty_out(vty, "\n");
}
return CMD_SUCCESS;
}
+DEFUN (default_vrf_vni_mapping,
+ default_vrf_vni_mapping_cmd,
+ "vni " CMD_VNI_RANGE,
+ "VNI corresponding to the DEFAULT VRF\n"
+ "VNI-ID\n")
+{
+ int ret = 0;
+ char err[ERR_STR_SZ];
+ struct zebra_vrf *zvrf = NULL;
+ vni_t vni = strtoul(argv[1]->arg, NULL, 10);
+
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (!zvrf)
+ return CMD_WARNING;
+
+ ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 1);
+ if (ret != 0) {
+ vty_out(vty, "%s\n", err);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_default_vrf_vni_mapping,
+ no_default_vrf_vni_mapping_cmd,
+ "no vni " CMD_VNI_RANGE,
+ NO_STR
+ "VNI corresponding to DEFAULT VRF\n"
+ "VNI-ID")
+{
+ int ret = 0;
+ char err[ERR_STR_SZ];
+ vni_t vni = strtoul(argv[2]->arg, NULL, 10);
+ struct zebra_vrf *zvrf = NULL;
+
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (!zvrf)
+ return CMD_WARNING;
+
+ ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0);
+ if (ret != 0) {
+ vty_out(vty, "%s\n", err);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN (vrf_vni_mapping,
vrf_vni_mapping_cmd,
"vni " CMD_VNI_RANGE,
- "VNI\n"
+ "VNI corresponding to tenant VRF\n"
"VNI-ID\n")
{
int ret = 0;
@@ -2307,6 +2384,8 @@ DEFUN (vrf_vni_mapping,
assert(vrf);
assert(zvrf);
+ /* Mark as having FRR configuration */
+ vrf_set_user_cfged(vrf);
ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 1);
if (ret != 0) {
vty_out(vty, "%s\n", err);
@@ -2320,7 +2399,7 @@ DEFUN (no_vrf_vni_mapping,
no_vrf_vni_mapping_cmd,
"no vni " CMD_VNI_RANGE,
NO_STR
- "VNI\n"
+ "VNI corresponding to tenant VRF\n"
"VNI-ID")
{
int ret = 0;
@@ -2338,6 +2417,10 @@ DEFUN (no_vrf_vni_mapping,
return CMD_WARNING;
}
+ /* If no other FRR config for this VRF, mark accordingly. */
+ if (!zebra_vrf_has_config(zvrf))
+ vrf_reset_user_cfged(vrf);
+
return CMD_SUCCESS;
}
@@ -2361,29 +2444,16 @@ DEFUN (show_vrf_vni,
json_vrfs = json_object_new_array();
}
+ if (!uj)
+ vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
+ "VRF", "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
+
RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
zvrf = vrf->info;
if (!zvrf)
continue;
- if (!zvrf->l3vni)
- continue;
-
- if (!uj) {
- vty_out(vty, "vrf: %s VNI: %u",
- zvrf_name(zvrf),
- zvrf->l3vni);
- vty_out(vty, "\n");
- } else {
- json_object *json_vrf = NULL;
-
- json_vrf = json_object_new_object();
- json_object_string_add(json_vrf, "vrf",
- zvrf_name(zvrf));
- json_object_int_add(json_vrf, "l3vni",
- zvrf->l3vni);
- json_object_array_add(json_vrfs, json_vrf);
- }
+ zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
}
if (uj) {
@@ -2396,6 +2466,19 @@ DEFUN (show_vrf_vni,
return CMD_SUCCESS;
}
+DEFUN (show_evpn_global,
+ show_evpn_global_cmd,
+ "show evpn [json]",
+ SHOW_STR
+ "EVPN\n"
+ JSON_STR)
+{
+ u_char uj = use_json(argc, argv);
+
+ zebra_vxlan_print_evpn(vty, uj);
+ return CMD_SUCCESS;
+}
+
DEFUN (show_evpn_vni,
show_evpn_vni_cmd,
"show evpn vni [json]",
@@ -2431,44 +2514,13 @@ DEFUN (show_evpn_vni_vni,
return CMD_SUCCESS;
}
-DEFUN (show_evpn_l3vni,
- show_evpn_l3vni_cmd,
- "show evpn l3vni [json]",
- SHOW_STR
- "EVPN\n"
- "L3 VNI\n"
- JSON_STR)
-{
- u_char uj = use_json(argc, argv);
-
- zebra_vxlan_print_l3vnis(vty, uj);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_evpn_l3vni_vni,
- show_evpn_l3vni_vni_cmd,
- "show evpn l3vni " CMD_VNI_RANGE "[json]",
- SHOW_STR
- "EVPN\n"
- "L3 VxLAN Network Identifier\n"
- "VNI number\n"
- JSON_STR)
-{
- vni_t vni;
- u_char uj = use_json(argc, argv);
-
- vni = strtoul(argv[3]->arg, NULL, 10);
- zebra_vxlan_print_l3vni(vty, vni, uj);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_evpn_rmac_l3vni_mac,
- show_evpn_rmac_l3vni_mac_cmd,
- "show evpn rmac l3vni " CMD_VNI_RANGE " mac WORD [json]",
+DEFUN (show_evpn_rmac_vni_mac,
+ show_evpn_rmac_vni_mac_cmd,
+ "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
SHOW_STR
"EVPN\n"
"RMAC\n"
- "L3-VNI\n"
+ "L3 VNI\n"
"VNI number\n"
"MAC\n"
"mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
@@ -2487,13 +2539,13 @@ DEFUN (show_evpn_rmac_l3vni_mac,
return CMD_SUCCESS;
}
-DEFUN (show_evpn_rmac_l3vni,
- show_evpn_rmac_l3vni_cmd,
- "show evpn rmac l3vni " CMD_VNI_RANGE "[json]",
+DEFUN (show_evpn_rmac_vni,
+ show_evpn_rmac_vni_cmd,
+ "show evpn rmac vni " CMD_VNI_RANGE "[json]",
SHOW_STR
"EVPN\n"
"RMAC\n"
- "L3-VNI\n"
+ "L3 VNI\n"
"VNI number\n"
JSON_STR)
{
@@ -2506,13 +2558,13 @@ DEFUN (show_evpn_rmac_l3vni,
return CMD_SUCCESS;
}
-DEFUN (show_evpn_rmac_l3vni_all,
- show_evpn_rmac_l3vni_all_cmd,
- "show evpn rmac l3vni all [json]",
+DEFUN (show_evpn_rmac_vni_all,
+ show_evpn_rmac_vni_all_cmd,
+ "show evpn rmac vni all [json]",
SHOW_STR
"EVPN\n"
"RMAC addresses\n"
- "L3-VNI\n"
+ "L3 VNI\n"
"All VNIs\n"
JSON_STR)
{
@@ -2523,13 +2575,13 @@ DEFUN (show_evpn_rmac_l3vni_all,
return CMD_SUCCESS;
}
-DEFUN (show_evpn_nh_l3vni_ip,
- show_evpn_nh_l3vni_ip_cmd,
- "show evpn next-hops l3vni " CMD_VNI_RANGE " ip WORD [json]",
+DEFUN (show_evpn_nh_vni_ip,
+ show_evpn_nh_vni_ip_cmd,
+ "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
SHOW_STR
"EVPN\n"
"Remote Vteps\n"
- "L3-VNI\n"
+ "L3 VNI\n"
"VNI number\n"
"Ip address\n"
"Host address (ipv4 or ipv6)\n"
@@ -2550,13 +2602,13 @@ DEFUN (show_evpn_nh_l3vni_ip,
return CMD_SUCCESS;
}
-DEFUN (show_evpn_nh_l3vni,
- show_evpn_nh_l3vni_cmd,
- "show evpn next-hops l3vni " CMD_VNI_RANGE "[json]",
+DEFUN (show_evpn_nh_vni,
+ show_evpn_nh_vni_cmd,
+ "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
SHOW_STR
"EVPN\n"
"Remote Vteps\n"
- "L3-VNI\n"
+ "L3 VNI\n"
"VNI number\n"
JSON_STR)
{
@@ -2569,13 +2621,13 @@ DEFUN (show_evpn_nh_l3vni,
return CMD_SUCCESS;
}
-DEFUN (show_evpn_nh_l3vni_all,
- show_evpn_nh_l3vni_all_cmd,
- "show evpn next-hops l3vni all [json]",
+DEFUN (show_evpn_nh_vni_all,
+ show_evpn_nh_vni_all_cmd,
+ "show evpn next-hops vni all [json]",
SHOW_STR
"EVPN\n"
"Remote VTEPs\n"
- "L3-VNI\n"
+ "L3 VNI\n"
"All VNIs\n"
JSON_STR)
{
@@ -3283,16 +3335,15 @@ void zebra_vty_init(void)
/* Commands for VRF */
install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
+ install_element(VIEW_NODE, &show_evpn_global_cmd);
install_element(VIEW_NODE, &show_evpn_vni_cmd);
install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
- install_element(VIEW_NODE, &show_evpn_l3vni_cmd);
- install_element(VIEW_NODE, &show_evpn_l3vni_vni_cmd);
- install_element(VIEW_NODE, &show_evpn_rmac_l3vni_mac_cmd);
- install_element(VIEW_NODE, &show_evpn_rmac_l3vni_cmd);
- install_element(VIEW_NODE, &show_evpn_rmac_l3vni_all_cmd);
- install_element(VIEW_NODE, &show_evpn_nh_l3vni_ip_cmd);
- install_element(VIEW_NODE, &show_evpn_nh_l3vni_cmd);
- install_element(VIEW_NODE, &show_evpn_nh_l3vni_all_cmd);
+ install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
+ install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
+ install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
+ install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
+ install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
+ install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
@@ -3303,7 +3354,8 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
- install_element(CONFIG_NODE, &no_vrf_vni_mapping_cmd);
+ install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
+ install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
install_element(VRF_NODE, &vrf_vni_mapping_cmd);
install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 1690079f68..fb1aebecc3 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -46,7 +46,6 @@
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_memory.h"
#include "zebra/zebra_l2.h"
-#include "lib/json.h"
DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
@@ -59,6 +58,9 @@ DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor");
/* static function declarations */
+static int ip_prefix_send_to_client(vrf_id_t vrf_id,
+ struct prefix *p,
+ uint16_t cmd);
static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json);
static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt);
static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
@@ -286,6 +288,12 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
: "Inactive");
}
}
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) {
+ if (!json)
+ vty_out(vty, " Default-gateway");
+ else
+ json_object_boolean_true_add(json, "defaultGateway");
+ }
if (json == NULL)
vty_out(vty, "\n");
}
@@ -442,7 +450,8 @@ static void zl3vni_print_nh(zebra_neigh_t *n,
ipaddr2str(&n->ip, buf2, sizeof(buf2)));
vty_out(vty, " RMAC: %s\n",
prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
- vty_out(vty, " Host-List:\n");
+ vty_out(vty, " Refcount: %d\n", listcount(n->host_list));
+ vty_out(vty, " Prefixes:\n");
for (ALL_LIST_ELEMENTS_RO(n->host_list, node, p))
vty_out(vty, " %s\n",
prefix2str(p, buf2, sizeof(buf2)));
@@ -451,15 +460,16 @@ static void zl3vni_print_nh(zebra_neigh_t *n,
json_object_string_add(json, "ip",
ipaddr2str(&(n->ip), buf2,
sizeof(buf2)));
- json_object_string_add(json, "rmac",
+ json_object_string_add(json, "routerMac",
prefix_mac2str(&n->emac, buf2,
sizeof(buf2)));
+ json_object_int_add(json, "refCount", listcount(n->host_list));
for (ALL_LIST_ELEMENTS_RO(n->host_list, node, p))
json_object_array_add(json_hosts,
json_object_new_string(
prefix2str(p, buf2,
sizeof(buf2))));
- json_object_object_add(json, "hosts", json_hosts);
+ json_object_object_add(json, "prefixList", json_hosts);
}
}
@@ -479,24 +489,27 @@ static void zl3vni_print_rmac(zebra_mac_t *zrmac,
prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
vty_out(vty, " Remote VTEP: %s\n",
inet_ntoa(zrmac->fwd_info.r_vtep_ip));
- vty_out(vty, " Host-List:\n");
+ vty_out(vty, " Refcount: %d\n", listcount(zrmac->host_list));
+ vty_out(vty, " Prefixes:\n");
for (ALL_LIST_ELEMENTS_RO(zrmac->host_list, node, p))
vty_out(vty, " %s\n",
prefix2str(p, buf2, sizeof(buf2)));
} else {
json_hosts = json_object_new_array();
- json_object_string_add(json, "Rmac",
+ json_object_string_add(json, "routerMac",
prefix_mac2str(&zrmac->macaddr,
buf1,
sizeof(buf1)));
- json_object_string_add(json, "vtep-ip",
+ json_object_string_add(json, "vtepIp",
inet_ntoa(zrmac->fwd_info.r_vtep_ip));
+ json_object_int_add(json, "refCount",
+ listcount(zrmac->host_list));
for (ALL_LIST_ELEMENTS_RO(zrmac->host_list, node, p))
json_object_array_add(json_hosts,
json_object_new_string(
prefix2str(p, buf2,
sizeof(buf2))));
- json_object_object_add(json, "hosts", json_hosts);
+ json_object_object_add(json, "prefixList", json_hosts);
}
}
@@ -534,6 +547,12 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
vty_out(vty, " Auto Mac ");
}
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
+ vty_out(vty, " Sticky Mac ");
+
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
+ vty_out(vty, " Default-gateway Mac ");
+
vty_out(vty, "\n");
/* print all the associated neigh */
vty_out(vty, " Neighbors:\n");
@@ -739,17 +758,15 @@ static void zl3vni_print_nh_hash(struct hash_backet *backet,
return;
if (!json_vni) {
- vty_out(vty, "%-15s %-17s %6d\n",
+ vty_out(vty, "%-15s %-17s\n",
ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
- prefix_mac2str(&n->emac, buf1, sizeof(buf1)),
- listcount(n->host_list));
+ prefix_mac2str(&n->emac, buf1, sizeof(buf1)));
} else {
- json_object_string_add(json_nh, "nexthop-ip",
+ json_object_string_add(json_nh, "nexthopIp",
ipaddr2str(&n->ip, buf2, sizeof(buf2)));
- json_object_string_add(json_nh, "rmac",
+ json_object_string_add(json_nh, "routerMac",
prefix_mac2str(&n->emac, buf1,
sizeof(buf1)));
- json_object_int_add(json_nh, "refCnt", listcount(n->host_list));
json_object_object_add(json_vni,
ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
json_nh);
@@ -789,10 +806,9 @@ static void zl3vni_print_nh_hash_all_vni(struct hash_backet *backet,
if (json == NULL) {
vty_out(vty, "\nVNI %u #Next-Hops %u\n\n",
zl3vni->vni, num_nh);
- vty_out(vty, "%-15s %-17s %6s\n", "IP",
- "RMAC", "Refcnt");
+ vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
} else
- json_object_int_add(json_vni, "numNh", num_nh);
+ json_object_int_add(json_vni, "numNextHops", num_nh);
memset(&wctx, 0, sizeof(struct nh_walk_ctx));
wctx.vty = vty;
@@ -833,10 +849,9 @@ static void zl3vni_print_rmac_hash_all_vni(struct hash_backet *backet,
}
if (json == NULL) {
- vty_out(vty, "\nVNI %u #MACs %u\n\n",
+ vty_out(vty, "\nVNI %u #RMACs %u\n\n",
zl3vni->vni, num_rmacs);
- vty_out(vty, "%-17s %-21s %-6s\n", "MAC",
- "Remote VTEP", "Refcnt");
+ vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP");
} else
json_object_int_add(json_vni, "numRmacs", num_rmacs);
@@ -872,18 +887,15 @@ static void zl3vni_print_rmac_hash(struct hash_backet *backet,
return;
if (!json) {
- vty_out(vty, "%-17s %-21s %-6d\n",
+ vty_out(vty, "%-17s %-21s\n",
prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
- inet_ntoa(zrmac->fwd_info.r_vtep_ip),
- listcount(zrmac->host_list));
+ inet_ntoa(zrmac->fwd_info.r_vtep_ip));
} else {
- json_object_string_add(json_rmac, "rmac",
+ json_object_string_add(json_rmac, "routerMac",
prefix_mac2str(&zrmac->macaddr, buf,
sizeof(buf)));
- json_object_string_add(json_rmac, "vtep-ip",
+ json_object_string_add(json_rmac, "vtepIp",
inet_ntoa(zrmac->fwd_info.r_vtep_ip));
- json_object_int_add(json_rmac, "refcnt",
- listcount(zrmac->host_list));
json_object_object_add(json,
prefix_mac2str(&zrmac->macaddr, buf,
sizeof(buf)),
@@ -906,7 +918,10 @@ static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx)
if (!json) {
vty_out(vty, "VNI: %u\n", zl3vni->vni);
- vty_out(vty, " Local Vtep Ip: %s",
+ vty_out(vty, " Type: %s\n", "L3");
+ vty_out(vty, " Tenant VRF: %s\n",
+ zl3vni_vrf_name(zl3vni));
+ vty_out(vty, " Local Vtep Ip: %s\n",
inet_ntoa(zl3vni->local_vtep_ip));
vty_out(vty, " Vxlan-Intf: %s\n",
zl3vni_vxlan_if_name(zl3vni));
@@ -914,35 +929,34 @@ static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx)
zl3vni_svi_if_name(zl3vni));
vty_out(vty, " State: %s\n",
zl3vni_state2str(zl3vni));
- vty_out(vty, " Vrf: %s\n",
- zl3vni_vrf_name(zl3vni));
- vty_out(vty, " Rmac: %s\n",
+ vty_out(vty, " Router MAC: %s\n",
zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
- vty_out(vty, " L2-VNIs: ");
+ vty_out(vty, " L2 VNIs: ");
for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni))
vty_out(vty, "%u ", zvni->vni);
vty_out(vty, "\n");
} else {
json_vni_list = json_object_new_array();
json_object_int_add(json, "vni", zl3vni->vni);
- json_object_string_add(json, "local-vtep-ip",
+ json_object_string_add(json, "type", "L3");
+ json_object_string_add(json, "localVtepIp",
inet_ntoa(zl3vni->local_vtep_ip));
- json_object_string_add(json, "vxlan-intf",
+ json_object_string_add(json, "vxlanIntf",
zl3vni_vxlan_if_name(zl3vni));
- json_object_string_add(json, "svi-if",
+ json_object_string_add(json, "sviIntf",
zl3vni_svi_if_name(zl3vni));
json_object_string_add(json, "state",
zl3vni_state2str(zl3vni));
json_object_string_add(json, "vrf",
zl3vni_vrf_name(zl3vni));
- json_object_string_add(json, "rmac",
+ json_object_string_add(json, "routerMac",
zl3vni_rmac2str(zl3vni, buf,
sizeof(buf)));
for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni)) {
json_object_array_add(json_vni_list,
json_object_new_int(zvni->vni));
}
- json_object_object_add(json, "l2-vnis", json_vni_list);
+ json_object_object_add(json, "l2Vnis", json_vni_list);
}
}
@@ -964,9 +978,11 @@ static void zvni_print(zebra_vni_t *zvni, void **ctxt)
if (json == NULL) {
vty_out(vty, "VNI: %u\n", zvni->vni);
- vty_out(vty, " VRF: %s\n", vrf_id_to_name(zvni->vrf_id));
+ vty_out(vty, " Type: %s\n", "L2");
+ vty_out(vty, " Tenant VRF: %s\n", vrf_id_to_name(zvni->vrf_id));
} else {
json_object_int_add(json, "vni", zvni->vni);
+ json_object_string_add(json, "type", "L2");
json_object_string_add(json, "vrf",
vrf_id_to_name(zvni->vrf_id));
}
@@ -978,11 +994,13 @@ static void zvni_print(zebra_vni_t *zvni, void **ctxt)
}
num_macs = num_valid_macs(zvni);
num_neigh = hashcount(zvni->neigh_table);
- if (json == NULL)
- vty_out(vty, " VxLAN interface: %s ifIndex: %u VTEP IP: %s\n",
- zvni->vxlan_if->name, zvni->vxlan_if->ifindex,
+ if (json == NULL) {
+ vty_out(vty, " VxLAN interface: %s\n",
+ zvni->vxlan_if->name);
+ vty_out(vty, " VxLAN ifIndex: %u\n", zvni->vxlan_if->ifindex);
+ vty_out(vty," Local VTEP IP: %s\n",
inet_ntoa(zvni->local_vtep_ip));
- else {
+ } else {
json_object_string_add(json, "vxlanInterface",
zvni->vxlan_if->name);
json_object_int_add(json, "ifindex", zvni->vxlan_if->ifindex);
@@ -1033,7 +1051,6 @@ static void zvni_print(zebra_vni_t *zvni, void **ctxt)
static void zl3vni_print_hash(struct hash_backet *backet,
void *ctx[])
{
- char buf[ETHER_ADDR_STRLEN];
struct vty *vty = NULL;
json_object *json = NULL;
json_object *json_vni = NULL;
@@ -1047,33 +1064,30 @@ static void zl3vni_print_hash(struct hash_backet *backet,
return;
if (!json) {
- vty_out(vty, "%-10u %-15s %-20s %-20s %-5s %-37s %-18s\n",
- zl3vni->vni,
- inet_ntoa(zl3vni->local_vtep_ip),
+ vty_out(vty,
+ "%-10u %-4s %-21s %-8lu %-8lu %-15s %-37s\n",
+ zl3vni->vni, "L3",
zl3vni_vxlan_if_name(zl3vni),
- zl3vni_svi_if_name(zl3vni),
- zl3vni_state2str(zl3vni),
- zl3vni_vrf_name(zl3vni),
- zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
+ hashcount(zl3vni->rmac_table),
+ hashcount(zl3vni->nh_table),
+ "n/a",
+ zl3vni_vrf_name(zl3vni));
} else {
char vni_str[VNI_STR_LEN];
snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
json_vni = json_object_new_object();
json_object_int_add(json_vni, "vni", zl3vni->vni);
- json_object_string_add(json_vni, "local-ip",
- inet_ntoa(zl3vni->local_vtep_ip));
- json_object_string_add(json_vni, "vxlan-if",
+ json_object_string_add(json_vni, "vxlanIf",
zl3vni_vxlan_if_name(zl3vni));
- json_object_string_add(json_vni, "svi-if",
- zl3vni_svi_if_name(zl3vni));
- json_object_string_add(json_vni, "state",
- zl3vni_state2str(zl3vni));
- json_object_string_add(json_vni, "vrf",
+ json_object_int_add(json_vni, "numMacs",
+ hashcount(zl3vni->rmac_table));
+ json_object_int_add(json_vni, "numArpNd",
+ hashcount(zl3vni->nh_table));
+ json_object_string_add(json_vni, "numRemoteVteps", "n/a");
+ json_object_string_add(json_vni, "type", "L3");
+ json_object_string_add(json_vni, "tenantVrf",
zl3vni_vrf_name(zl3vni));
- json_object_string_add(json_vni, "rmac",
- zl3vni_rmac2str(zl3vni, buf,
- sizeof(buf)));
json_object_object_add(json, vni_str, json_vni);
}
@@ -1111,24 +1125,26 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[])
num_macs = num_valid_macs(zvni);
num_neigh = hashcount(zvni->neigh_table);
if (json == NULL)
- vty_out(vty, "%-10u %-21s %-15s %-8u %-8u %-15u %-37s\n",
- zvni->vni,
+ vty_out(vty,
+ "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n",
+ zvni->vni, "L2",
zvni->vxlan_if ? zvni->vxlan_if->name : "unknown",
- inet_ntoa(zvni->local_vtep_ip), num_macs, num_neigh,
- num_vteps,
+ num_macs, num_neigh, num_vteps,
vrf_id_to_name(zvni->vrf_id));
else {
char vni_str[VNI_STR_LEN];
snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
json_vni = json_object_new_object();
+ json_object_int_add(json_vni, "vni", zvni->vni);
+ json_object_string_add(json_vni, "type", "L2");
json_object_string_add(json_vni, "vxlanIf",
zvni->vxlan_if ? zvni->vxlan_if->name
: "unknown");
- json_object_string_add(json_vni, "vtepIp",
- inet_ntoa(zvni->local_vtep_ip));
json_object_int_add(json_vni, "numMacs", num_macs);
json_object_int_add(json_vni, "numArpNd", num_neigh);
json_object_int_add(json_vni, "numRemoteVteps", num_vteps);
+ json_object_string_add(json_vni, "tenantVrf",
+ vrf_id_to_name(zvni->vrf_id));
if (num_vteps) {
json_vtep_list = json_object_new_array();
for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) {
@@ -1409,7 +1425,7 @@ static void zvni_process_neigh_on_local_mac_add(zebra_vni_t *zvni,
ZEBRA_NEIGH_SET_ACTIVE(n);
zvni_neigh_send_add_to_client(
- zvni->vni, &n->ip, &n->emac, 0);
+ zvni->vni, &n->ip, &n->emac, n->flags);
} else {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
@@ -1519,8 +1535,14 @@ static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni,
*/
static int zvni_neigh_send_add_to_client(vni_t vni,
struct ipaddr *ip,
- struct ethaddr *macaddr, u_char flags)
+ struct ethaddr *macaddr,
+ u_char neigh_flags)
{
+ u_char flags = 0;
+
+ if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW))
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
ZEBRA_MACIP_ADD);
}
@@ -1692,7 +1714,37 @@ static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni)
zvni_gw_macip_add(ifp, zvni, &macaddr, &ip);
}
+ return 0;
+}
+
+
+static int zvni_advertise_subnet(zebra_vni_t *zvni,
+ struct interface *ifp,
+ int advertise)
+{
+ struct listnode *cnode = NULL, *cnnode = NULL;
+ struct connected *c = NULL;
+ struct ethaddr macaddr;
+
+ memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
+
+ for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) {
+ struct prefix p;
+ memcpy(&p, c->address, sizeof(struct prefix));
+
+ /* skip link local address */
+ if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6))
+ continue;
+
+ apply_mask(&p);
+ if (advertise)
+ ip_prefix_send_to_client(ifp->vrf_id, &p,
+ ZEBRA_IP_PREFIX_ROUTE_ADD);
+ else
+ ip_prefix_send_to_client(ifp->vrf_id, &p,
+ ZEBRA_IP_PREFIX_ROUTE_DEL);
+ }
return 0;
}
@@ -1729,6 +1781,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
/* Set "local" forwarding info. */
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
+ SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.vid = vxl->access_vlan;
@@ -1748,9 +1801,14 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
/* Set "local" forwarding info. */
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+ SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW);
memcpy(&n->emac, macaddr, ETH_ALEN);
n->ifindex = ifp->ifindex;
+ /* Only advertise in BGP if the knob is enabled */
+ if (!advertise_gw_macip_enabled(zvni))
+ return 0;
+
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
@@ -1759,7 +1817,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
ipaddr2str(ip, buf2, sizeof(buf2)));
zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr,
- ZEBRA_MAC_TYPE_GW);
+ n->flags);
return 0;
}
@@ -1793,16 +1851,21 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
return -1;
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s del to BGP",
- ifp->name, ifp->ifindex, zvni->vni,
- prefix_mac2str(&(n->emac), buf1, sizeof(buf1)),
- ipaddr2str(ip, buf2, sizeof(buf2)));
-
- /* Remove neighbor from BGP. */
- zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
- ZEBRA_MAC_TYPE_GW);
+ /* only need to delete the entry from bgp if we sent it before */
+ if (advertise_gw_macip_enabled(zvni)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
+ ifp->vrf_id, ifp->name,
+ ifp->ifindex, zvni->vni,
+ prefix_mac2str(&(n->emac),
+ NULL,
+ ETHER_ADDR_STRLEN),
+ ipaddr2str(ip, buf2, sizeof(buf2)));
+
+ /* Remove neighbor from BGP. */
+ zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
+ ZEBRA_MACIP_TYPE_GW);
+ }
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);
@@ -1869,9 +1932,6 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
if (!zvni)
return;
- if (!advertise_gw_macip_enabled(zvni))
- return;
-
ifp = zvni->vxlan_if;
if (!ifp)
return;
@@ -1985,7 +2045,6 @@ static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
{
struct mac_walk_ctx *wctx = arg;
zebra_mac_t *mac = backet->data;
- u_char sticky = 0;
if (((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
|| ((wctx->flags & DEL_REMOTE_MAC)
@@ -1995,11 +2054,9 @@ static int zvni_mac_del_hash_entry(struct hash_backet *backet, void *arg)
&& IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
&wctx->r_vtep_ip))) {
if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
- sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1
- : 0;
zvni_mac_send_del_to_client(
wctx->zvni->vni, &mac->macaddr,
- (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
+ mac->flags);
}
if (wctx->uninstall)
@@ -2074,8 +2131,16 @@ static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac)
* Inform BGP about local MAC addition.
*/
static int zvni_mac_send_add_to_client(vni_t vni,
- struct ethaddr *macaddr, u_char flags)
+ struct ethaddr *macaddr,
+ u_char mac_flags)
{
+ u_char flags = 0;
+
+ if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
+ if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
ZEBRA_MACIP_ADD);
}
@@ -2084,8 +2149,16 @@ static int zvni_mac_send_add_to_client(vni_t vni,
* Inform BGP about local MAC deletion.
*/
static int zvni_mac_send_del_to_client(vni_t vni,
- struct ethaddr *macaddr, u_char flags)
+ struct ethaddr *macaddr,
+ u_char mac_flags)
{
+ u_char flags = 0;
+
+ if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY))
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
+ if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW))
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
ZEBRA_MACIP_DEL);
}
@@ -2393,15 +2466,13 @@ static void zvni_read_mac_neigh(zebra_vni_t *zvni,
vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
if (vlan_if) {
- if (advertise_gw_macip_enabled(zvni)) {
- /* Add SVI MAC-IP */
- zvni_add_macip_for_intf(vlan_if, zvni);
+ /* Add SVI MAC-IP */
+ zvni_add_macip_for_intf(vlan_if, zvni);
- /* Add VRR MAC-IP - if any*/
- vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
- if (vrr_if)
- zvni_add_macip_for_intf(vrr_if, zvni);
- }
+ /* Add VRR MAC-IP - if any*/
+ vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
+ if (vrr_if)
+ zvni_add_macip_for_intf(vrr_if, zvni);
neigh_read_for_vlan(zns, vlan_if);
}
@@ -2795,17 +2866,19 @@ static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip)
/*
* Cleanup VNI/VTEP and update kernel
*/
-static void zvni_cleanup_all(struct hash_backet *backet, void *zvrf)
+static void zvni_cleanup_all(struct hash_backet *backet, void *arg)
{
zebra_vni_t *zvni = NULL;
zebra_l3vni_t *zl3vni = NULL;
+ struct zebra_vrf *zvrf = (struct zebra_vrf *)arg;
zvni = (zebra_vni_t *)backet->data;
if (!zvni)
return;
/* remove from l3-vni list */
- zl3vni = zl3vni_from_vrf(zvni->vrf_id);
+ if (zvrf->l3vni)
+ zl3vni = zl3vni_lookup(zvrf->l3vni);
if (zl3vni)
listnode_delete(zl3vni->l2vnis, zvni);
@@ -3158,13 +3231,13 @@ static int zl3vni_nh_install(zebra_l3vni_t *zl3vni,
static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni,
zebra_neigh_t *n)
{
- if (!is_l3vni_oper_up(zl3vni))
- return -1;
-
if (!(n->flags & ZEBRA_NEIGH_REMOTE) ||
!(n->flags & ZEBRA_NEIGH_REMOTE_NH))
return 0;
+ if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if))
+ return 0;
+
return kernel_del_neigh(zl3vni->svi_if, &n->ip);
}
@@ -3712,6 +3785,63 @@ static void zl3vni_del_nh_hash_entry(struct hash_backet *backet,
zl3vni_nh_del(zl3vni, n);
}
+static int ip_prefix_send_to_client(vrf_id_t vrf_id,
+ struct prefix *p,
+ uint16_t cmd)
+{
+ struct zserv *client = NULL;
+ struct stream *s = NULL;
+ char buf[PREFIX_STRLEN];
+
+ client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
+ /* BGP may not be running. */
+ if (!client)
+ return 0;
+
+ s = client->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, cmd, vrf_id);
+ stream_put(s, p, sizeof(struct prefix));
+
+ /* Write packet size. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Send ip prefix %s %s on vrf %s",
+ prefix2str(p, buf, sizeof(buf)),
+ (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL",
+ vrf_id_to_name(vrf_id));
+
+ if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD)
+ client->prefixadd_cnt++;
+ else
+ client->prefixdel_cnt++;
+
+ return zebra_server_send_message(client);
+}
+
+/* re-add remote rmac if needed */
+static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,
+ struct ethaddr *rmac)
+{
+ char buf[ETHER_ADDR_STRLEN];
+ zebra_mac_t *zrmac = NULL;
+
+ zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
+ if (!zrmac)
+ return 0;
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Del remote RMAC %s L3VNI %u - readd",
+ prefix_mac2str(rmac, buf, sizeof(buf)),
+ zl3vni->vni);
+
+ zl3vni_rmac_install(zl3vni, zrmac);
+ return 0;
+}
+
/* Public functions */
/* handle evpn route in vrf table */
@@ -3834,8 +3964,7 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty,
vty_out(vty,
"Number of Remote RMACs known for this VNI: %u\n",
num_rmacs);
- vty_out(vty, "%-17s %-21s %-6s\n", "MAC",
- "Remote VTEP", "Refcnt");
+ vty_out(vty, "%-17s %-21s\n", "MAC", "Remote VTEP");
} else
json_object_int_add(json, "numRmacs", num_rmacs);
@@ -3966,10 +4095,9 @@ void zebra_vxlan_print_nh_l3vni(struct vty *vty,
vty_out(vty,
"Number of NH Neighbors known for this VNI: %u\n",
num_nh);
- vty_out(vty, "%-15s %-17s %6s\n", "IP",
- "RMAC", "Refcnt");
+ vty_out(vty, "%-15s %-17s\n", "IP", "RMAC");
} else
- json_object_int_add(json, "numNh", num_nh);
+ json_object_int_add(json, "numNextHops", num_nh);
hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
@@ -4053,52 +4181,40 @@ void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni, u_char use_json)
}
}
-/*
- * Display L3 VNI hash table (VTY command handler).
- */
-void zebra_vxlan_print_l3vnis(struct vty *vty, u_char use_json)
+void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
+ json_object *json_vrfs)
{
- u_int32_t num_vnis;
- void *args[2];
- json_object *json = NULL;
- struct zebra_ns *zns = NULL;
-
- if (!is_evpn_enabled()) {
- if (use_json)
- vty_out(vty, "{}\n");
- return;
- }
-
- zns = zebra_ns_lookup(NS_DEFAULT);
- assert(zns);
+ char buf[ETHER_ADDR_STRLEN];
+ zebra_l3vni_t *zl3vni = NULL;
- num_vnis = hashcount(zns->l3vni_table);
- if (!num_vnis) {
- if (use_json)
- vty_out(vty, "{}\n");
+ zl3vni = zl3vni_lookup(zvrf->l3vni);
+ if (!zl3vni)
return;
- }
- if (use_json) {
- json = json_object_new_object();
- json_object_int_add(json, "numVnis", num_vnis);
+ if (!json_vrfs) {
+ vty_out(vty, "%-37s %-10u %-20s %-20s %-5s %-18s\n",
+ zvrf_name(zvrf),
+ zl3vni->vni,
+ zl3vni_vxlan_if_name(zl3vni),
+ zl3vni_svi_if_name(zl3vni),
+ zl3vni_state2str(zl3vni),
+ zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
} else {
- vty_out(vty, "Number of L3 VNIs: %u\n", num_vnis);
- vty_out(vty, "%-10s %-15s %-20s %-20s %-5s %-37s %-18s\n",
- "VNI", "Local-ip", "Vx-intf", "L3-SVI", "State",
- "VRF", "Rmac");
- }
-
- args[0] = vty;
- args[1] = json;
- hash_iterate(zns->l3vni_table,
- (void (*)(struct hash_backet *, void *))zl3vni_print_hash,
- args);
-
- if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
+ json_object *json_vrf = NULL;
+ json_vrf = json_object_new_object();
+ json_object_string_add(json_vrf, "vrf",
+ zvrf_name(zvrf));
+ json_object_int_add(json_vrf, "vni", zl3vni->vni);
+ json_object_string_add(json_vrf, "vxlanIntf",
+ zl3vni_vxlan_if_name(zl3vni));
+ json_object_string_add(json_vrf, "sviIntf",
+ zl3vni_svi_if_name(zl3vni));
+ json_object_string_add(json_vrf, "state",
+ zl3vni_state2str(zl3vni));
+ json_object_string_add(json_vrf, "routerMac",
+ zl3vni_rmac2str(zl3vni, buf,
+ sizeof(buf)));
+ json_object_array_add(json_vrfs, json_vrf);
}
}
@@ -4467,25 +4583,45 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
u_char use_json)
{
- zebra_vni_t *zvni;
json_object *json = NULL;
void *args[2];
if (!is_evpn_enabled())
return;
- zvni = zvni_lookup(vni);
- if (!zvni) {
- if (use_json)
- vty_out(vty, "{}\n");
- else
- vty_out(vty, "%% VNI %u does not exist\n", vni);
- return;
- }
+
if (use_json)
json = json_object_new_object();
args[0] = vty;
args[1] = json;
- zvni_print(zvni, (void *)args);
+
+ if (is_vni_l3(vni)) {
+ zebra_l3vni_t *zl3vni = NULL;
+
+ zl3vni = zl3vni_lookup(vni);
+ if (!zl3vni) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty, "%% VNI %u does not exist\n", vni);
+ return;
+ }
+
+ zl3vni_print(zl3vni, (void *)args);
+ } else {
+ zebra_vni_t *zvni;
+
+ zvni = zvni_lookup(vni);
+ if (!zvni) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty, "%% VNI %u does not exist\n", vni);
+ return;
+ }
+
+ zvni_print(zvni, (void *)args);
+ }
+
if (use_json) {
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
@@ -4493,44 +4629,91 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni,
}
}
-/*
- * Display VNI hash table (VTY command handler).
- */
-void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
- u_char use_json)
+/* Display all global details for EVPN */
+void zebra_vxlan_print_evpn(struct vty *vty, u_char uj)
{
- u_int32_t num_vnis;
+ int num_l2vnis = 0;
+ int num_l3vnis = 0;
+ int num_vnis = 0;
json_object *json = NULL;
- void *args[2];
+ struct zebra_ns *zns = NULL;
+ struct zebra_vrf *zvrf = NULL;
if (!is_evpn_enabled())
return;
- num_vnis = hashcount(zvrf->vni_table);
- if (!num_vnis) {
- if (use_json)
- vty_out(vty, "{}\n");
+
+ zns = zebra_ns_lookup(NS_DEFAULT);
+ if (!zns)
return;
- }
- if (use_json) {
+
+ zvrf = vrf_info_lookup(VRF_DEFAULT);
+ if (!zvrf)
+ return;
+
+ num_l3vnis = hashcount(zns->l3vni_table);
+ num_l2vnis = hashcount(zvrf->vni_table);
+ num_vnis = num_l2vnis + num_l3vnis;
+
+ if (uj) {
json = json_object_new_object();
json_object_string_add(json, "advertiseGatewayMacip",
zvrf->advertise_gw_macip ? "Yes" : "No");
json_object_int_add(json, "numVnis", num_vnis);
+ json_object_int_add(json, "numL2Vnis", num_l2vnis);
+ json_object_int_add(json, "numL3Vnis", num_l3vnis);
} else {
+ vty_out(vty, "L2 VNIs: %u\n", num_l2vnis);
+ vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
vty_out(vty, "Advertise gateway mac-ip: %s\n",
zvrf->advertise_gw_macip ? "Yes" : "No");
- vty_out(vty, "Number of VNIs: %u\n", num_vnis);
- vty_out(vty, "%-10s %-21s %-15s %-8s %-8s %-15s %-37s\n", "VNI",
- "VxLAN IF", "VTEP IP", "# MACs", "# ARPs",
- "# Remote VTEPs", "VRF");
}
+
+ if (uj) {
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+}
+
+/*
+ * Display VNI hash table (VTY command handler).
+ */
+void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
+ u_char use_json)
+{
+ json_object *json = NULL;
+ struct zebra_ns *zns = NULL;
+ void *args[2];
+
+ if (!is_evpn_enabled())
+ return;
+
+ zns = zebra_ns_lookup(NS_DEFAULT);
+ if (!zns)
+ return;
+
+
+ if (use_json)
+ json = json_object_new_object();
+ else
+ vty_out(vty,
+ "%-10s %-4s %-21s %-8s %-8s %-15s %-37s\n",
+ "VNI", "Type", "VxLAN IF", "# MACs",
+ "# ARPs", "# Remote VTEPs", "Tenant VRF");
+
args[0] = vty;
args[1] = json;
+ /* Display all L2-VNIs */
hash_iterate(zvrf->vni_table,
(void (*)(struct hash_backet *, void *))zvni_print_hash,
args);
+ /* Display all L3-VNIs */
+ hash_iterate(zns->l3vni_table,
+ (void (*)(struct hash_backet *, void *))zl3vni_print_hash,
+ args);
+
if (use_json) {
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
@@ -4768,7 +4951,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
zvni->vni);
ZEBRA_NEIGH_SET_ACTIVE(n);
- return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0);
+ return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
}
@@ -4879,6 +5062,17 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
if (!mac && !n)
continue;
+ /* Ignore the delete if this mac is a gateway mac-ip */
+ if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) &&
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
+ zlog_err("%u: Ignore Del for MAC %s neigh %s on VNI %u as it is configured as a default gateway",
+ zvrf_id(zvrf),
+ prefix_mac2str(&macaddr, buf, sizeof(buf)),
+ ipaddr2str(&ip, buf1, sizeof(buf1)),
+ vni);
+ continue;
+ }
+
/* Uninstall remote neighbor or MAC. */
if (n) {
/* When the MAC changes for an IP, it is possible the
@@ -4936,7 +5130,8 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
int update_mac = 0, update_neigh = 0;
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
- u_char sticky;
+ u_char sticky = 0;
+ u_char flags = 0;
struct interface *ifp = NULL;
struct zebra_if *zif = NULL;
@@ -4973,17 +5168,17 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
STREAM_GET(&vtep_ip.s_addr, s, IPV4_MAX_BYTELEN);
l += IPV4_MAX_BYTELEN;
- /* Get 'sticky' flag. */
- STREAM_GETC(s, sticky);
+ /* Get flags - sticky mac and/or gateway mac */
+ flags = stream_getc(s);
+ sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
l++;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Recv MACIP Add %sMAC %s IP %s VNI %u Remote VTEP %s from %s",
- sticky ? "sticky " : "",
+ "Recv MACIP Add MAC %s IP %s VNI %u Remote VTEP %s with flags 0x%x from %s",
prefix_mac2str(&macaddr, buf, sizeof(buf)),
ipaddr2str(&ip, buf1, sizeof(buf1)), vni,
- inet_ntoa(vtep_ip),
+ inet_ntoa(vtep_ip), flags,
zebra_route_string(client->proto));
/* Locate VNI hash entry - expected to exist. */
@@ -5025,13 +5220,26 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
zvni_vtep_install(zvni, &vtep_ip);
}
- /* First, check if the remote MAC is unknown or has a change. If
- * so,
- * that needs to be updated first. Note that client could
- * install
- * MAC and MACIP separately or just install the latter.
- */
mac = zvni_mac_lookup(zvni, &macaddr);
+
+ /* Ignore the update if the mac is already present
+ as a gateway mac */
+ if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) &&
+ CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%u:Ignore MAC %s IP %s on VNI %u as MAC is already configured as gateway mac",
+ zvrf_id(zvrf),
+ prefix_mac2str(&macaddr,
+ buf, sizeof(buf)),
+ ipaddr2str(&ip, buf1,
+ sizeof(buf1)), vni);
+ continue;
+ }
+
+ /* check if the remote MAC is unknown or has a change.
+ * If so, that needs to be updated first. Note that client could
+ * install MAC and MACIP separately or just install the latter.
+ */
if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
|| (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0)
!= sticky
@@ -5146,7 +5354,6 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
zebra_vni_t *zvni;
zebra_mac_t *mac;
char buf[ETHER_ADDR_STRLEN];
- u_char sticky;
zif = ifp->info;
assert(zif);
@@ -5178,9 +5385,7 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
ifp->name, ifp->ifindex, vni);
/* Remove MAC from BGP. */
- sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
- zvni_mac_send_del_to_client(zvni->vni, macaddr,
- (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
+ zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
/*
* If there are no neigh associated with the mac delete the mac
@@ -5205,11 +5410,12 @@ int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
struct interface *br_if,
struct ethaddr *macaddr, vlanid_t vid)
{
- struct zebra_if *zif;
- struct zebra_l2info_vxlan *vxl;
+ struct zebra_if *zif = NULL;
+ struct zebra_l2info_vxlan *vxl = NULL;
vni_t vni;
- zebra_vni_t *zvni;
- zebra_mac_t *mac;
+ zebra_vni_t *zvni = NULL;
+ zebra_l3vni_t *zl3vni = NULL;
+ zebra_mac_t *mac = NULL;
char buf[ETHER_ADDR_STRLEN];
zif = ifp->info;
@@ -5221,6 +5427,11 @@ int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
if (!is_evpn_enabled())
return 0;
+ /* check if this is a remote RMAC and readd simillar to remote macs */
+ zl3vni = zl3vni_lookup(vni);
+ if (zl3vni)
+ return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr);
+
/* Locate hash entry; it is expected to exist. */
zvni = zvni_lookup(vni);
if (!zvni)
@@ -5253,7 +5464,6 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
zebra_vni_t *zvni;
zebra_mac_t *mac;
char buf[ETHER_ADDR_STRLEN];
- u_char sticky;
/* We are interested in MACs only on ports or (port, VLAN) that
* map to a VNI.
@@ -5282,9 +5492,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
return 0;
/* Remove MAC from BGP. */
- sticky = CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? 1 : 0;
- zvni_mac_send_del_to_client(zvni->vni, macaddr,
- (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
+ zvni_mac_send_del_to_client(zvni->vni, macaddr, mac->flags);
/* Update all the neigh entries associated with this mac */
zvni_process_neigh_on_local_mac_del(zvni, mac);
@@ -5423,7 +5631,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
if (add) {
zvni_process_neigh_on_local_mac_add(zvni, mac);
return zvni_mac_send_add_to_client(zvni->vni, macaddr,
- sticky);
+ mac->flags);
}
return 0;
@@ -5687,10 +5895,6 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
}
- /* check if we are advertising gw macip routes */
- if (!advertise_gw_macip_enabled(zvni))
- return 0;
-
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
if (p->family == AF_INET) {
@@ -6394,17 +6598,115 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf,
return 0;
}
-int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
+int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf)
{
zebra_l3vni_t *zl3vni = NULL;
- zl3vni = zl3vni_from_vrf(zvrf_id(zvrf));
+ if (zvrf->l3vni)
+ zl3vni = zl3vni_lookup(zvrf->l3vni);
if (!zl3vni)
return 0;
+ zl3vni->vrf_id = zvrf_id(zvrf);
+ if (is_l3vni_oper_up(zl3vni))
+ zebra_vxlan_process_l3vni_oper_up(zl3vni);
+ return 0;
+}
+
+int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf)
+{
+ zebra_l3vni_t *zl3vni = NULL;
+
+ if (zvrf->l3vni)
+ zl3vni = zl3vni_lookup(zvrf->l3vni);
+ if (!zl3vni)
+ return 0;
+
+ zl3vni->vrf_id = VRF_UNKNOWN;
zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ return 0;
+}
+
+int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
+{
+ zebra_l3vni_t *zl3vni = NULL;
+ vni_t vni;
+
+ if (zvrf->l3vni)
+ zl3vni = zl3vni_lookup(zvrf->l3vni);
+ if (!zl3vni)
+ return 0;
+
+ vni = zl3vni->vni;
zl3vni_del(zl3vni);
- zebra_vxlan_handle_vni_transition(zvrf, zl3vni->vni, 0);
+ zebra_vxlan_handle_vni_transition(zvrf, vni, 0);
+
+ return 0;
+}
+
+/*
+ * Handle message from client to enable/disable advertisement of g/w macip
+ * routes
+ */
+int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
+ struct zebra_vrf *zvrf)
+{
+ struct stream *s;
+ int advertise;
+ vni_t vni = 0;
+ zebra_vni_t *zvni = NULL;
+ struct interface *ifp = NULL;
+ struct zebra_if *zif = NULL;
+ struct zebra_l2info_vxlan zl2_info;
+ struct interface *vlan_if = NULL;
+
+ if (zvrf_id(zvrf) != VRF_DEFAULT) {
+ zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
+ zvrf_id(zvrf));
+ return -1;
+ }
+
+ s = client->ibuf;
+ advertise = stream_getc(s);
+ vni = stream_get3(s);
+
+ zvni = zvni_lookup(vni);
+ if (!zvni)
+ return 0;
+
+ if (zvni->advertise_subnet == advertise)
+ return 0;
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "EVPN subnet Adv %s on VNI %d , currently %s",
+ advertise ? "enabled" : "disabled", vni,
+ zvni->advertise_subnet ? "enabled" : "disabled");
+
+
+ zvni->advertise_subnet = advertise;
+
+ ifp = zvni->vxlan_if;
+ if (!ifp)
+ return 0;
+
+ zif = ifp->info;
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ return 0;
+
+ zl2_info = zif->l2info.vxl;
+
+ vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
+ zif->brslave_info.br_if);
+ if (!vlan_if)
+ return 0;
+
+ if (zvni->advertise_subnet)
+ zvni_advertise_subnet(zvni, vlan_if, 1);
+ else
+ zvni_advertise_subnet(zvni, vlan_if, 0);
return 0;
}
@@ -6590,6 +6892,14 @@ void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
"Zebra VRF VNI Table");
}
+/* Cleanup VNI info, but don't free the table. */
+void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
+{
+ if (!zvrf)
+ return;
+ hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
+}
+
/* Close all VNI handling */
void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
{
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index b7def6acf8..d9801a8b60 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -31,6 +31,7 @@
#include "vlan.h"
#include "vxlan.h"
+#include "lib/json.h"
#include "zebra/zebra_vrf.h"
/* Is EVPN enabled? */
@@ -53,8 +54,12 @@ is_evpn_enabled()
extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf);
+extern int zebra_vxlan_vrf_enable(struct zebra_vrf *zvrf);
+extern int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf);
+extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf);
extern void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty, vni_t l3vni,
struct ipaddr *ip, u_char uj);
+extern void zebra_vxlan_print_evpn(struct vty *vty, u_char uj);
extern void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
struct ethaddr *rmac,
u_char use_json);
@@ -99,9 +104,8 @@ extern void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t vni, u_char
extern void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, u_char use_json);
extern void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni,
u_char use_json);
-extern void zebra_vxlan_print_l3vnis(struct vty *vty,
- u_char use_json);
-
+extern void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf,
+ json_object *json_vrfs);
extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
int add);
extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if);
@@ -140,6 +144,8 @@ extern int zebra_vxlan_remote_vtep_add(struct zserv *client,
u_short length, struct zebra_vrf *zvrf);
extern int zebra_vxlan_remote_vtep_del(struct zserv *client,
u_short length, struct zebra_vrf *zvrf);
+extern int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
+ struct zebra_vrf *zvrf);
extern int zebra_vxlan_advertise_gw_macip(struct zserv *client,
u_short length,
struct zebra_vrf *zvrf);
@@ -151,6 +157,7 @@ extern int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
int err_str_sz, int add);
extern void zebra_vxlan_init_tables(struct zebra_vrf *zvrf);
extern void zebra_vxlan_close_tables(struct zebra_vrf *);
+extern void zebra_vxlan_cleanup_tables(struct zebra_vrf *);
extern void zebra_vxlan_ns_init(struct zebra_ns *zns);
extern void zebra_vxlan_ns_disable(struct zebra_ns *zns);
extern void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
diff --git a/zebra/zebra_vxlan_null.c b/zebra/zebra_vxlan_null.c
index db828c337e..0eb880e848 100644
--- a/zebra/zebra_vxlan_null.c
+++ b/zebra/zebra_vxlan_null.c
@@ -83,6 +83,10 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf)
{
}
+void zebra_vxlan_print_evpn(struct vty *vty, u_char uj)
+{
+}
+
void zebra_vxlan_print_rmacs_l3vni(struct vty*, vni_t, u_char)
{
}
@@ -103,10 +107,6 @@ void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni)
{
}
-void zebra_vxlan_print_l3vnis(struct vty *vty)
-{
-}
-
int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
{
return 0;
@@ -207,3 +207,7 @@ void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
{
}
+
+void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf)
+{
+}
diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h
index ef6f9b99cb..8d34b3e2f1 100644
--- a/zebra/zebra_vxlan_private.h
+++ b/zebra/zebra_vxlan_private.h
@@ -70,6 +70,9 @@ struct zebra_vni_t_ {
/* Flag for advertising gw macip */
u_int8_t advertise_gw_macip;
+ /* Flag for advertising gw macip */
+ u_int8_t advertise_subnet;
+
/* Corresponding VxLAN interface. */
struct interface *vxlan_if;
@@ -233,6 +236,7 @@ struct zebra_mac_t_ {
#define ZEBRA_MAC_AUTO 0x04 /* Auto created for neighbor. */
#define ZEBRA_MAC_STICKY 0x08 /* Static MAC */
#define ZEBRA_MAC_REMOTE_RMAC 0x10 /* remote router mac */
+#define ZEBRA_MAC_DEF_GW 0x20
/* Local or remote info. */
union {
@@ -314,6 +318,7 @@ struct zebra_neigh_t_ {
#define ZEBRA_NEIGH_LOCAL 0x01
#define ZEBRA_NEIGH_REMOTE 0x02
#define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */
+#define ZEBRA_NEIGH_DEF_GW 0x08
enum zebra_neigh_state state;
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 3ee2bb59ec..71437bab15 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -2603,6 +2603,9 @@ static inline void zserv_handle_commands(struct zserv *client,
case ZEBRA_ADVERTISE_DEFAULT_GW:
zebra_vxlan_advertise_gw_macip(client, length, zvrf);
break;
+ case ZEBRA_ADVERTISE_SUBNET:
+ zebra_vxlan_advertise_subnet(client, length, zvrf);
+ break;
case ZEBRA_ADVERTISE_ALL_VNI:
zebra_vxlan_advertise_all_vni(client, length, zvrf);
break;
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 4b3b0041b8..7d5f6b4543 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -114,6 +114,8 @@ struct zserv {
u_int32_t l3vnidel_cnt;
u_int32_t macipadd_cnt;
u_int32_t macipdel_cnt;
+ u_int32_t prefixadd_cnt;
+ u_int32_t prefixdel_cnt;
time_t connect_time;
time_t last_read_time;