#include "zebra/zebra_l2.h"
#include "lib/json.h"
+DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP");
static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt);
static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
void **args);
+static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
+ json_object *json);
+static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty,
+ json_object *json);
static void zvni_print_mac(zebra_mac_t *mac, void *ctxt);
static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt);
static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt);
/* l3-vni rmac related APIs */
static void zl3vni_print_rmac_hash(struct hash_backet *, void *);
-static void zl3vni_print_rmac_hash_all_vni(struct hash_backet *, void *);
static zebra_mac_t *zl3vni_rmac_lookup(zebra_l3vni_t *zl3vni,
struct ethaddr *rmac);
static void *zl3vni_rmac_alloc(void *p);
static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id);
static int zl3vni_del(zebra_l3vni_t *zl3vni);
static zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t);
-static vni_t zvni_get_l3vni(zebra_vni_t *zvni);
static struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni);
static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni);
-static void zvni_get_rmac(zebra_vni_t *zvni, struct ethaddr *rmac);
static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni);
static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni);
json_object_object_add(json, vni_str, json_vni);
}
+/* print a specific next hop for an l3vni */
+static void zl3vni_print_nh(zebra_neigh_t *n,
+ struct vty *vty,
+ json_object *json)
+{
+ char buf1[ETHER_ADDR_STRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+ struct listnode *node = NULL;
+ struct prefix *p = NULL;
+ json_object *json_hosts = NULL;
+
+ if (!json) {
+ vty_out(vty, "Ip: %s\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");
+ for (ALL_LIST_ELEMENTS_RO(n->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, "ip",
+ ipaddr2str(&(n->ip), buf2,
+ sizeof(buf2)));
+ json_object_string_add(json, "rmac",
+ prefix_mac2str(&n->emac, buf2,
+ sizeof(buf2)));
+ 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);
+ }
+}
+
+/* Print a specific RMAC entry */
+static void zl3vni_print_rmac(zebra_mac_t *zrmac,
+ struct vty *vty,
+ json_object *json)
+{
+ char buf1[ETHER_ADDR_STRLEN];
+ char buf2[PREFIX_STRLEN];
+ struct listnode *node = NULL;
+ struct prefix *p = NULL;
+ json_object *json_hosts = NULL;
+
+ if (!json) {
+ vty_out(vty, "MAC: %s\n",
+ 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");
+ 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",
+ prefix_mac2str(&zrmac->macaddr,
+ buf1,
+ sizeof(buf1)));
+ json_object_string_add(json, "vtep-ip",
+ inet_ntoa(zrmac->fwd_info.r_vtep_ip));
+ 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);
+ }
+}
+
/*
* Print a specific MAC entry.
*/
{
struct nh_walk_ctx *wctx = NULL;
struct vty *vty = NULL;
- struct json_object *json = NULL;
+ struct json_object *json_vni = NULL;
struct json_object *json_nh = NULL;
zebra_neigh_t *n = NULL;
char buf1[ETHER_ADDR_STRLEN];
wctx = (struct nh_walk_ctx *)ctx;
vty = wctx->vty;
- json = wctx->json;
- if (json)
+ json_vni = wctx->json;
+ if (json_vni)
json_nh = json_object_new_object();
n = (zebra_neigh_t *)backet->data;
if (!n)
return;
- if (!json) {
+ if (!json_vni) {
vty_out(vty, "%-15s %-17s %6d\n",
ipaddr2str(&(n->ip), buf2, sizeof(buf2)),
prefix_mac2str(&n->emac, buf1, sizeof(buf1)),
- n->nh_refcnt);
+ listcount(n->host_list));
} else {
- json_object_string_add(json_nh, "vtep-ip",
- inet_ntoa(n->r_vtep_ip));
+ json_object_string_add(json_nh, "nexthop-ip",
+ ipaddr2str(&n->ip, buf2, sizeof(buf2)));
json_object_string_add(json_nh, "rmac",
prefix_mac2str(&n->emac, buf1,
sizeof(buf1)));
- json_object_int_add(json_nh, "refCnt", n->nh_refcnt);
+ 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);
}
}
static void zl3vni_print_nh_hash_all_vni(struct hash_backet *backet,
- void *ctx)
+ void **args)
{
struct vty *vty = NULL;
json_object *json = NULL;
json_object *json_vni = NULL;
- json_object *json_nh = NULL;
zebra_l3vni_t *zl3vni = NULL;
uint32_t num_nh = 0;
- struct nh_walk_ctx *wctx = NULL;
+ struct nh_walk_ctx wctx;
char vni_str[VNI_STR_LEN];
- wctx = (struct nh_walk_ctx *)ctx;
- vty = (struct vty *)wctx->vty;
- json = (struct json_object *)wctx->json;
+ vty = (struct vty *)args[0];
+ json = (struct json_object *)args[1];
zl3vni = (zebra_l3vni_t *)backet->data;
if (!zl3vni) {
if (json) {
json_vni = json_object_new_object();
- json_nh = json_object_new_array();
snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
}
if (json == NULL) {
- vty_out(vty, "\nVNI %u #Next-Hopss %u\n\n",
+ vty_out(vty, "\nVNI %u #Next-Hops %u\n\n",
zl3vni->vni, num_nh);
- vty_out(vty, "%-17s %-21s %-6s\n", "MAC",
- "Remote VTEP", "Refcnt");
vty_out(vty, "%-15s %-17s %6s\n", "IP",
"RMAC", "Refcnt");
} else
json_object_int_add(json_vni, "numNh", num_nh);
- wctx->json = json_nh;
- hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, wctx);
- wctx->json = json;
- if (json) {
- json_object_object_add(json_vni, "nh", json_nh);
+ memset(&wctx, 0, sizeof(struct nh_walk_ctx));
+ wctx.vty = vty;
+ wctx.json = json_vni;
+ hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
+ if (json)
json_object_object_add(json, vni_str, json_vni);
- }
}
static void zl3vni_print_rmac_hash_all_vni(struct hash_backet *backet,
- void *ctx)
+ void **args)
{
struct vty *vty = NULL;
json_object *json = NULL;
json_object *json_vni = NULL;
- json_object *json_mac = NULL;
zebra_l3vni_t *zl3vni = NULL;
u_int32_t num_rmacs;
- struct rmac_walk_ctx *wctx = NULL;
+ struct rmac_walk_ctx wctx;
char vni_str[VNI_STR_LEN];
- wctx = (struct rmac_walk_ctx *)ctx;
- vty = (struct vty *)wctx->vty;
- json = (struct json_object *)wctx->json;
+ vty = (struct vty *)args[0];
+ json = (struct json_object *)args[1];
zl3vni = (zebra_l3vni_t *)backet->data;
if (!zl3vni) {
if (json) {
json_vni = json_object_new_object();
- json_mac = json_object_new_array();
snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni);
}
* under the vni. Re-assign primary json object to fill
* next vni information.
*/
- wctx->json = json_mac;
- hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, wctx);
- wctx->json = json;
- if (json) {
- json_object_object_add(json_vni, "rmacs", json_mac);
+ memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
+ wctx.vty = vty;
+ wctx.json = json_vni;
+ hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
+ if (json)
json_object_object_add(json, vni_str, json_vni);
- }
}
static void zl3vni_print_rmac_hash(struct hash_backet *backet,
vty_out(vty, "%-17s %-21s %-6d\n",
prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
inet_ntoa(zrmac->fwd_info.r_vtep_ip),
- zrmac->rmac_refcnt);
+ listcount(zrmac->host_list));
} else {
json_object_string_add(json_rmac, "rmac",
prefix_mac2str(&zrmac->macaddr, buf,
sizeof(buf)));
json_object_string_add(json_rmac, "vtep-ip",
inet_ntoa(zrmac->fwd_info.r_vtep_ip));
- json_object_int_add(json_rmac, "refcnt", zrmac->rmac_refcnt);
- json_object_array_add(json, json_rmac);
+ json_object_int_add(json_rmac, "refcnt",
+ listcount(zrmac->host_list));
+ json_object_object_add(json,
+ prefix_mac2str(&zrmac->macaddr, buf,
+ sizeof(buf)),
+ json_rmac);
}
}
if (!json) {
vty_out(vty, "VNI: %u\n", zl3vni->vni);
+ vty_out(vty, " Local Vtep Ip: %s",
+ inet_ntoa(zl3vni->local_vtep_ip));
vty_out(vty, " Vxlan-Intf: %s\n",
zl3vni_vxlan_if_name(zl3vni));
vty_out(vty, " SVI-If: %s\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",
+ inet_ntoa(zl3vni->local_vtep_ip));
json_object_string_add(json, "vxlan-intf",
zl3vni_vxlan_if_name(zl3vni));
json_object_string_add(json, "svi-if",
char buf[ETHER_ADDR_STRLEN];
struct vty *vty = NULL;
json_object *json = NULL;
+ json_object *json_vni = NULL;
zebra_l3vni_t *zl3vni = NULL;
- vty = ctx[0];
- json = ctx[1];
+ vty = (struct vty *)ctx[0];
+ json = (json_object *)ctx[1];
zl3vni = (zebra_l3vni_t *)backet->data;
if (!zl3vni)
return;
if (!json) {
- vty_out(vty, "%-10u %-20s %-20s %-5s %-37s %-18s\n",
+ vty_out(vty, "%-10u %-15s %-20s %-20s %-5s %-37s %-18s\n",
zl3vni->vni,
+ inet_ntoa(zl3vni->local_vtep_ip),
zl3vni_vxlan_if_name(zl3vni),
zl3vni_svi_if_name(zl3vni),
zl3vni_state2str(zl3vni),
zl3vni_vrf_name(zl3vni),
zl3vni_rmac2str(zl3vni, buf, sizeof(buf)));
} else {
- json_object_int_add(json, "vni", zl3vni->vni);
- json_object_string_add(json, "vxlan-if",
+ 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",
zl3vni_vxlan_if_name(zl3vni));
- json_object_string_add(json, "svi-if",
+ json_object_string_add(json_vni, "svi-if",
zl3vni_svi_if_name(zl3vni));
- json_object_string_add(json, "state",
+ json_object_string_add(json_vni, "state",
zl3vni_state2str(zl3vni));
- json_object_string_add(json, "vrf",
+ json_object_string_add(json_vni, "vrf",
zl3vni_vrf_name(zl3vni));
- json_object_string_add(json, "rmac",
+ json_object_string_add(json_vni, "rmac",
zl3vni_rmac2str(zl3vni, buf,
sizeof(buf)));
+ json_object_object_add(json, vni_str, json_vni);
}
}
s = client->obuf;
stream_reset(s);
- zserv_create_header(s, cmd, VRF_DEFAULT);
+ zclient_create_header(s, cmd, VRF_DEFAULT);
stream_putl(s, vni);
stream_put(s, macaddr->octet, ETH_ALEN);
if (ip) {
static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
struct ethaddr *macaddr, struct ipaddr *ip)
{
- vni_t l3vni = 0;
- struct ethaddr rmac;
char buf[ETHER_ADDR_STRLEN];
- char buf1[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
zebra_neigh_t *n = NULL;
zebra_mac_t *mac = NULL;
struct zebra_if *zif = NULL;
struct zebra_l2info_vxlan *vxl = NULL;
- memset(&rmac, 0, sizeof(struct ethaddr));
-
zif = zvni->vxlan_if->info;
if (!zif)
return -1;
vxl = &zif->l2info.vxl;
- /* get the l3-vni */
- l3vni = zvni_get_l3vni(zvni);
-
- /* get the rmac */
- zvni_get_rmac(zvni, &rmac);
-
mac = zvni_mac_lookup(zvni, macaddr);
if (!mac) {
mac = zvni_mac_add(zvni, macaddr);
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "SVI %s(%u) L2-VNI %u L3-VNI %u RMAC %s , sending GW MAC %s IP %s add to BGP",
+ "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP",
ifp->name, ifp->ifindex, zvni->vni,
- l3vni,
- prefix_mac2str(&rmac, buf1, sizeof(buf1)),
prefix_mac2str(macaddr, buf, sizeof(buf)),
ipaddr2str(ip, buf2, sizeof(buf2)));
static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
struct ipaddr *ip)
{
- vni_t l3vni = 0;
- struct ethaddr rmac;
- char buf[ETHER_ADDR_STRLEN];
char buf1[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
zebra_neigh_t *n = NULL;
zebra_mac_t *mac = NULL;
- memset(&rmac, 0, sizeof(struct ethaddr));
-
- /* get the l30vni */
- l3vni = zvni_get_l3vni(zvni);
-
- /* get the rmac */
- zvni_get_rmac(zvni, &rmac);
-
/* If the neigh entry is not present nothing to do*/
n = zvni_neigh_lookup(zvni, ip);
if (!n)
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "SVI %s(%u) L2-VNI %u, L3-VNI %u RMAC %s sending GW MAC %s IP %s del to BGP",
- ifp->name, ifp->ifindex, zvni->vni, l3vni,
- prefix_mac2str(&rmac, buf, sizeof(buf)),
+ "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)));
s = client->obuf;
stream_reset(s);
- zserv_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
+ zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
stream_putl(s, zvni->vni);
stream_put_in_addr(s, &zvni->local_vtep_ip);
stream_put(s, &zvni->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */
s = client->obuf;
stream_reset(s);
- zserv_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
+ zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
stream_putl(s, vni);
/* Write packet size. */
}
/* associate with vxlan_if */
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
zl3vni->vxlan_if = ifp;
- /* we need to associate with SVI.
+ /*
+ * we need to associate with SVI.
* we can associate with svi-if only after association
- * with vxlan-intf is complete */
+ * with vxlan-intf is complete
+ */
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
if (is_l3vni_oper_up(zl3vni))
zvni_del(zvni);
}
+/* cleanup L3VNI */
+static void zl3vni_cleanup_all(struct hash_backet *backet,
+ void *args)
+{
+ zebra_l3vni_t *zl3vni = NULL;
+
+ zl3vni = (zebra_l3vni_t *)backet->data;
+ if (!zl3vni)
+ return;
+
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+}
+
+static int is_host_present_in_host_list(struct list *list,
+ struct prefix *host)
+{
+ struct listnode *node = NULL;
+ struct prefix *p = NULL;
+
+ for (ALL_LIST_ELEMENTS_RO(list, node, p)) {
+ if (prefix_same(p, host))
+ return 1;
+ }
+ return 0;
+}
+
+static void host_list_add_host(struct list *list,
+ struct prefix *host)
+{
+ struct prefix *p = NULL;
+
+ p = XCALLOC(MTYPE_HOST_PREFIX, sizeof(struct prefix));
+ memcpy(p, host, sizeof(struct prefix));
+
+ listnode_add_sort(list, p);
+}
+
+static void host_list_delete_host(struct list *list,
+ struct prefix *host)
+{
+ struct listnode *node = NULL, *nnode = NULL, *node_to_del = NULL;
+ struct prefix *p = NULL;
+
+ for (ALL_LIST_ELEMENTS(list, node, nnode, p)) {
+ if (prefix_same(p, host)) {
+ XFREE(MTYPE_HOST_PREFIX, p);
+ node_to_del = node;
+ }
+ }
+
+ if (node_to_del)
+ list_delete_node(list, node_to_del);
+}
+
/*
* Look up MAC hash entry.
*/
zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
assert(zrmac);
- zrmac->neigh_list = list_new();
- zrmac->neigh_list->cmp = (int (*)(void *, void *))neigh_cmp;
+ zrmac->host_list = list_new();
+ zrmac->host_list->cmp = (int (*)(void *, void *))prefix_cmp;
SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
{
zebra_mac_t *tmp_rmac;
- list_delete(zrmac->neigh_list);
+ if (zrmac->host_list)
+ list_delete_and_null(&zrmac->host_list);
+ zrmac->host_list = NULL;
tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
if (tmp_rmac)
return 0;
if (!zl3vni->vxlan_if) {
- zlog_err("RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
+ zlog_err(
+ "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
prefix_mac2str(&zrmac->macaddr, buf, sizeof(buf)),
zl3vni->vni, zl3vni);
return -1;
}
/* handle rmac add */
-static int zebra_vxlan_l3vni_remote_rmac_add(zebra_l3vni_t *zl3vni,
- struct ethaddr *rmac,
- struct ipaddr *vtep_ip)
+static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni,
+ struct ethaddr *rmac,
+ struct ipaddr *vtep_ip,
+ struct prefix *host_prefix)
{
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
/* install rmac in kernel */
zl3vni_rmac_install(zl3vni, zrmac);
}
- zrmac->rmac_refcnt++;
+
+ if (!is_host_present_in_host_list(zrmac->host_list, host_prefix))
+ host_list_add_host(zrmac->host_list, host_prefix);
return 0;
}
/* handle rmac delete */
-static int zebra_vxlan_l3vni_remote_rmac_del(zebra_l3vni_t *zl3vni,
- struct ethaddr *rmac)
+static int zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni,
+ struct ethaddr *rmac,
+ struct prefix *host_prefix)
{
zebra_mac_t *zrmac = NULL;
if (!zrmac)
return -1;
- zrmac->rmac_refcnt--;
- if (!zrmac->rmac_refcnt) {
+ host_list_delete_host(zrmac->host_list, host_prefix);
+ if (list_isempty(zrmac->host_list)) {
/* uninstall from kernel */
zl3vni_rmac_uninstall(zl3vni, zrmac);
n = hash_get(zl3vni->nh_table, &tmp_n, zl3vni_nh_alloc);
assert(n);
+ n->host_list = list_new();
+ n->host_list->cmp = (int (*)(void *, void *))prefix_cmp;
+
memcpy(&n->emac, mac, ETH_ALEN);
SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE_NH);
{
zebra_neigh_t *tmp_n;
+ if (n->host_list)
+ list_delete_and_null(&n->host_list);
+ n->host_list = NULL;
+
tmp_n = hash_release(zl3vni->nh_table, n);
if (tmp_n)
XFREE(MTYPE_NEIGH, tmp_n);
}
/* add remote vtep as a neigh entry */
-static int zebra_vxlan_l3vni_remote_nh_add(zebra_l3vni_t *zl3vni,
- struct ipaddr *vtep_ip,
- struct ethaddr *rmac)
+static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni,
+ struct ipaddr *vtep_ip,
+ struct ethaddr *rmac,
+ struct prefix *host_prefix)
{
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
/* install the nh neigh in kernel */
zl3vni_nh_install(zl3vni, nh);
}
- nh->nh_refcnt++;
+
+ if (!is_host_present_in_host_list(nh->host_list, host_prefix))
+ host_list_add_host(nh->host_list, host_prefix);
+
return 0;
}
/* handle nh neigh delete */
-static int zebra_vxlan_l3vni_remote_nh_del(zebra_l3vni_t *zl3vni,
- struct ipaddr *vtep_ip)
+static int zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni,
+ struct ipaddr *vtep_ip,
+ struct prefix *host_prefix)
{
zebra_neigh_t *nh = NULL;
if (!nh)
return -1;
- nh->nh_refcnt--;
- if (!nh->nh_refcnt) {
+ host_list_delete_host(nh->host_list, host_prefix);
+ if (list_isempty(nh->host_list)) {
/* uninstall from kernel */
zl3vni_nh_uninstall(zl3vni, nh);
return 0;
}
+/* handle neigh update from kernel - the only thing of interest is to
+ * readd stale entries.
+ */
+static int zl3vni_local_nh_add_update(zebra_l3vni_t *zl3vni,
+ struct ipaddr *ip, u_int16_t state)
+{
+#ifdef GNU_LINUX
+ zebra_neigh_t *n = NULL;
+
+ n = zl3vni_nh_lookup(zl3vni, ip);
+ if (!n)
+ return 0;
+
+ /* all next hop neigh are remote and installed by frr.
+ * If the kernel has aged this entry, re-install.
+ */
+ if (state & NUD_STALE)
+ zl3vni_nh_install(zl3vni, n);
+#endif
+ return 0;
+}
+
+/* handle neigh delete from kernel */
+static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni,
+ struct ipaddr *ip)
+{
+ zebra_neigh_t *n = NULL;
+
+ n = zl3vni_nh_lookup(zl3vni, ip);
+ if (!n)
+ return 0;
+
+ /* all next hop neigh are remote and installed by frr.
+ * If we get an age out notification for these neigh entries, we have to
+ * install it back
+ */
+ zl3vni_nh_install(zl3vni, n);
+
+ return 0;
+}
+
/*
* Hash function for L3 VNI.
*/
continue;
vxl = &zif->l2info.vxl;
- if (vxl->vni == zl3vni->vni)
+ if (vxl->vni == zl3vni->vni) {
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
return ifp;
+ }
}
return NULL;
struct ethaddr rmac;
char buf[ETHER_ADDR_STRLEN];
- client = zebra_find_client(ZEBRA_ROUTE_BGP);
+ client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
/* BGP may not be running. */
if (!client)
return 0;
s = client->obuf;
stream_reset(s);
- zserv_create_header(s, ZEBRA_L3VNI_ADD,
+ zclient_create_header(s, ZEBRA_L3VNI_ADD,
zl3vni_vrf_id(zl3vni));
stream_putl(s, zl3vni->vni);
stream_put(s, &rmac, sizeof(struct ethaddr));
+ stream_put_in_addr(s, &zl3vni->local_vtep_ip);
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Send L3_VNI_ADD %u VRF %s RMAC %s to %s",
+ zlog_debug("Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s to %s",
zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
prefix_mac2str(&rmac, buf, sizeof(buf)),
+ inet_ntoa(zl3vni->local_vtep_ip),
zebra_route_string(client->proto));
client->l3vniadd_cnt++;
struct stream *s = NULL;
struct zserv *client = NULL;
- client = zebra_find_client(ZEBRA_ROUTE_BGP);
+ client = zebra_find_client(ZEBRA_ROUTE_BGP, 0);
/* BGP may not be running. */
if (!client)
return 0;
s = client->obuf;
stream_reset(s);
- zserv_create_header(s, ZEBRA_L3VNI_DEL,
+ zclient_create_header(s, ZEBRA_L3VNI_DEL,
zl3vni_vrf_id(zl3vni));
stream_putl(s, zl3vni->vni);
static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni)
{
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("L3-VNI %u is UP - send add to BGP and update all neigh enries",
+ zlog_debug("L3-VNI %u is UP - send add to BGP",
zl3vni->vni);
/* send l3vni add to BGP */
static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni)
{
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("L3-VNI %u is Down - send del to BGP and update all neigh enries",
+ zlog_debug("L3-VNI %u is Down - Send del to BGP",
zl3vni->vni);
/* send l3-vni del to BGP*/
listnode_add_sort(zl3vni->l2vnis, zvni);
}
-/* l3vni from zvni */
-static vni_t zvni_get_l3vni(zebra_vni_t *zvni)
-{
- zebra_l3vni_t *zl3vni = NULL;
-
- zl3vni = zl3vni_from_vrf(zvni->vrf_id);
- if (!zl3vni || !is_l3vni_oper_up(zl3vni))
- return 0;
-
- return zl3vni->vni;
-}
-
-/* rmac from l3vni */
-static void zvni_get_rmac(zebra_vni_t *zvni,
- struct ethaddr *rmac)
-{
- zebra_l3vni_t *zl3vni = NULL;
-
- zl3vni = zl3vni_from_vrf(zvni->vrf_id);
- if (!zl3vni || !is_l3vni_oper_up(zl3vni))
- return;
-
- if (zl3vni->svi_if)
- memcpy(rmac->octet, zl3vni->svi_if->hw_addr, ETH_ALEN);
-}
-
/*
* handle transition of vni from l2 to l3 and vice versa
*/
* that it can be reprogrammed as L3-VNI in the system. It is also
* possible that the vrf-vni mapping is removed from FRR while the vxlan
* interface is still present in kernel. In this case to keep it
- * symmetric, we will delete the l3-vni and reprogram it as l2-vni */
+ * symmetric, we will delete the l3-vni and reprogram it as l2-vni
+ */
if (add) {
/* Locate hash entry */
zvni = zvni_lookup(vni);
/* TODO_MITESH: This needs to be thought through. We don't have
* enough information at this point to reprogram the vni as
* l2-vni. One way is to store the required info in l3-vni and
- * used it solely for this purpose */
+ * used it solely for this purpose
+ */
}
return 0;
}
+/* delete and uninstall rmac hash entry */
+static void zl3vni_del_rmac_hash_entry(struct hash_backet *backet,
+ void *ctx)
+{
+ zebra_mac_t *zrmac = NULL;
+ zebra_l3vni_t *zl3vni = NULL;
+
+ zrmac = (zebra_mac_t *)backet->data;
+ zl3vni = (zebra_l3vni_t *)ctx;
+ zl3vni_rmac_uninstall(zl3vni, zrmac);
+ zl3vni_rmac_del(zl3vni, zrmac);
+}
+
+/* delete and uninstall nh hash entry */
+static void zl3vni_del_nh_hash_entry(struct hash_backet *backet,
+ void *ctx)
+{
+ zebra_neigh_t *n = NULL;
+ zebra_l3vni_t *zl3vni = NULL;
+
+ n = (zebra_neigh_t *)backet->data;
+ zl3vni = (zebra_l3vni_t *)ctx;
+ zl3vni_nh_uninstall(zl3vni, n);
+ zl3vni_nh_del(zl3vni, n);
+}
+
/* Public functions */
/* handle evpn route in vrf table */
void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
struct ethaddr *rmac,
- struct ipaddr *ip)
+ struct ipaddr *vtep_ip,
+ struct prefix *host_prefix)
{
zebra_l3vni_t *zl3vni = NULL;
return;
/* add the next hop neighbor */
- zebra_vxlan_l3vni_remote_nh_add(zl3vni, ip, rmac);
+ zl3vni_remote_nh_add(zl3vni, vtep_ip, rmac, host_prefix);
/* add the rmac */
- zebra_vxlan_l3vni_remote_rmac_add(zl3vni, rmac, ip);
+ zl3vni_remote_rmac_add(zl3vni, rmac, vtep_ip, host_prefix);
}
/* handle evpn vrf route delete */
void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
struct ethaddr *rmac,
- struct ipaddr *ip)
+ struct ipaddr *vtep_ip,
+ struct prefix *host_prefix)
{
zebra_l3vni_t *zl3vni = NULL;
zl3vni = zl3vni_from_vrf(vrf_id);
- if (!zl3vni || !is_l3vni_oper_up(zl3vni))
+ if (!zl3vni)
return;
/* delete the next hop entry */
- zebra_vxlan_l3vni_remote_nh_del(zl3vni, ip);
+ zl3vni_remote_nh_del(zl3vni, vtep_ip, host_prefix);
/* delete the rmac entry */
- zebra_vxlan_l3vni_remote_rmac_del(zl3vni, rmac);
+ zl3vni_remote_rmac_del(zl3vni, rmac, host_prefix);
}
+void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty,
+ vni_t l3vni,
+ struct ethaddr *rmac,
+ u_char use_json)
+{
+ zebra_l3vni_t *zl3vni = NULL;
+ zebra_mac_t *zrmac = NULL;
+ json_object *json = NULL;
+
+ if (!is_evpn_enabled()) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ return;
+ }
+
+ if (use_json)
+ json = json_object_new_object();
+
+ zl3vni = zl3vni_lookup(l3vni);
+ if (!zl3vni) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty, "%% L3-VNI %u doesnt exist\n",
+ l3vni);
+ return;
+ }
+
+ zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
+ if (!zrmac) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty,
+ "%% Requested RMAC doesnt exist in L3-VNI %u",
+ l3vni);
+ return;
+ }
+
+ zl3vni_print_rmac(zrmac, vty, json);
+
+ if (use_json) {
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+}
void zebra_vxlan_print_rmacs_l3vni(struct vty *vty,
vni_t l3vni,
u_int32_t num_rmacs;
struct rmac_walk_ctx wctx;
json_object *json = NULL;
- json_object *json_rmac = NULL;
if (!is_evpn_enabled())
return;
if (!num_rmacs)
return;
- if (use_json) {
+ if (use_json)
json = json_object_new_object();
- json_rmac = json_object_new_array();
- }
memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
wctx.vty = vty;
- wctx.json = json_rmac;
-
+ wctx.json = json;
if (!use_json) {
vty_out(vty,
"Number of Remote RMACs known for this VNI: %u\n",
hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx);
if (use_json) {
- json_object_object_add(json, "rmacs", json_rmac);
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
u_char use_json)
{
struct zebra_ns *zns = NULL;
- struct rmac_walk_ctx wctx;
json_object *json = NULL;
+ void *args[2];
if (!is_evpn_enabled()) {
if (use_json)
}
zns = zebra_ns_lookup(NS_DEFAULT);
- if (!zns)
+ if (!zns) {
+ if (use_json)
+ vty_out(vty, "{}\n");
return;
+ }
if (use_json)
json = json_object_new_object();
- memset(&wctx, 0, sizeof(struct rmac_walk_ctx));
- wctx.vty = vty;
- wctx.json = json;
+ args[0] = vty;
+ args[1] = json;
+ hash_iterate(zns->l3vni_table,
+ (void (*)(struct hash_backet *,
+ void *))zl3vni_print_rmac_hash_all_vni,
+ 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);
+ }
+}
+
+void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty,
+ vni_t l3vni,
+ struct ipaddr *ip,
+ u_char use_json)
+{
+ zebra_l3vni_t *zl3vni = NULL;
+ zebra_neigh_t *n = NULL;
+ json_object *json = NULL;
+
+ if (!is_evpn_enabled()) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ return;
+ }
+
+ if (use_json)
+ json = json_object_new_object();
- hash_iterate(zns->l3vni_table, zl3vni_print_rmac_hash_all_vni, &wctx);
+ zl3vni = zl3vni_lookup(l3vni);
+ if (!zl3vni) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
+ return;
+ }
+
+ n = zl3vni_nh_lookup(zl3vni, ip);
+ if (!n) {
+ if (use_json)
+ vty_out(vty, "{}\n");
+ else
+ vty_out(vty,
+ "%% Requested next-hop not present for L3-VNI %u",
+ l3vni);
+ return;
+ }
+
+ zl3vni_print_nh(n, vty, json);
if (use_json) {
vty_out(vty, "%s\n", json_object_to_json_string_ext(
u_int32_t num_nh;
struct nh_walk_ctx wctx;
json_object *json = NULL;
- json_object *json_nh = NULL;
zebra_l3vni_t *zl3vni = NULL;
if (!is_evpn_enabled())
if (!num_nh)
return;
- if (use_json) {
+ if (use_json)
json = json_object_new_object();
- json_nh = json_object_new_array();
- }
wctx.vty = vty;
- wctx.json = json_nh;
-
+ wctx.json = json;
if (!use_json) {
vty_out(vty,
"Number of NH Neighbors known for this VNI: %u\n",
hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx);
if (use_json) {
- json_object_object_add(json, "next-hop-neighbors", json_nh);
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
u_char use_json)
{
struct zebra_ns *zns = NULL;
- struct nh_walk_ctx wctx;
json_object *json = NULL;
+ void *args[2];
if (!is_evpn_enabled()) {
if (use_json)
if (use_json)
json = json_object_new_object();
- memset(&wctx, 0, sizeof(struct nh_walk_ctx));
- wctx.vty = vty;
- wctx.json = json;
-
- hash_iterate(zns->l3vni_table, zl3vni_print_nh_hash_all_vni, &wctx);
+ args[0] = vty;
+ args[1] = json;
+ hash_iterate(zns->l3vni_table,
+ (void (*)(struct hash_backet *,
+ void *))zl3vni_print_nh_hash_all_vni,
+ args);
if (use_json) {
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json_object *json = NULL;
zebra_l3vni_t *zl3vni = NULL;
- args[0] = vty;
- args[1] = json;
-
- if (!is_evpn_enabled())
+ if (!is_evpn_enabled()) {
+ if (use_json)
+ vty_out(vty, "{}\n");
return;
+ }
zl3vni = zl3vni_lookup(vni);
if (!zl3vni) {
if (use_json)
json = json_object_new_object();
+ args[0] = vty;
+ args[1] = json;
zl3vni_print(zl3vni, (void *)args);
if (use_json) {
json_object *json = NULL;
struct zebra_ns *zns = NULL;
- args[0] = vty;
- args[1] = json;
-
- if (!is_evpn_enabled())
+ if (!is_evpn_enabled()) {
+ if (use_json)
+ vty_out(vty, "{}\n");
return;
+ }
zns = zebra_ns_lookup(NS_DEFAULT);
assert(zns);
json_object_int_add(json, "numVnis", num_vnis);
} else {
vty_out(vty, "Number of L3 VNIs: %u\n", num_vnis);
- vty_out(vty, "%-10s %-20s %-20s %-5s %-37s %-18s\n", "VNI",
- "Vx-intf", "L3-SVI", "State", "VRF", "Rmac");
+ 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);
int zebra_vxlan_local_neigh_del(struct interface *ifp,
struct interface *link_if, struct ipaddr *ip)
{
- vni_t l3vni = 0;
- struct ethaddr rmac;
char buf[INET6_ADDRSTRLEN];
- char buf1[INET6_ADDRSTRLEN];
char buf2[ETHER_ADDR_STRLEN];
zebra_neigh_t *n = NULL;
zebra_vni_t *zvni = NULL;
zebra_mac_t *zmac = NULL;
+ zebra_l3vni_t *zl3vni = NULL;
- memset(&rmac, 0, sizeof(struct ethaddr));
+ /* check if this is a remote neigh entry corresponding to remote
+ * next-hop
+ */
+ zl3vni = zl3vni_from_svi(ifp, link_if);
+ if (zl3vni)
+ return zl3vni_local_nh_del(zl3vni, ip);
/* We are only interested in neighbors on an SVI that resides on top
* of a VxLAN bridge.
zvni = zvni_from_svi(ifp, link_if);
if (!zvni)
return 0;
+
if (!zvni->vxlan_if) {
zlog_err(
"VNI %u hash %p doesn't have intf upon local neighbor DEL",
return -1;
}
- /* get the l3-vni */
- l3vni = zvni_get_l3vni(zvni);
-
- /* get the rmac */
- zvni_get_rmac(zvni, &rmac);
-
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u L3-VNI %u RMAC %s",
+ zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
ipaddr2str(ip, buf, sizeof(buf)),
- ifp->name, ifp->ifindex, zvni->vni,
- l3vni, prefix_mac2str(&rmac, buf1, sizeof(buf1)));
+ ifp->name, ifp->ifindex, zvni->vni);
/* If entry doesn't exist, nothing to do. */
n = zvni_neigh_lookup(zvni, ip);
struct ethaddr *macaddr, u_int16_t state,
u_char ext_learned)
{
- vni_t l3vni = 0;
- struct ethaddr rmac;
char buf[ETHER_ADDR_STRLEN];
- char buf1[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
zebra_vni_t *zvni = NULL;
zebra_neigh_t *n = NULL;
zebra_mac_t *zmac = NULL, *old_zmac = NULL;
+ zebra_l3vni_t *zl3vni = NULL;
- memset(&rmac, 0, sizeof(struct ethaddr));
+ /* check if this is a remote neigh entry corresponding to remote
+ * next-hop
+ */
+ zl3vni = zl3vni_from_svi(ifp, link_if);
+ if (zl3vni)
+ return zl3vni_local_nh_add_update(zl3vni, ip, state);
/* We are only interested in neighbors on an SVI that resides on top
* of a VxLAN bridge.
if (!zvni)
return 0;
- /* get the l3-vni */
- l3vni = zvni_get_l3vni(zvni);
-
- /* get the rmac */
- zvni_get_rmac(zvni, &rmac);
-
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u L3-VNI %u RMAC %s",
+ "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u",
ipaddr2str(ip, buf2, sizeof(buf2)),
prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
ifp->ifindex, state, ext_learned ? "ext-learned " : "",
- zvni->vni, l3vni,
- prefix_mac2str(&rmac, buf1, sizeof(buf1)));
+ zvni->vni);
/* create a dummy MAC if the MAC is not already present */
zmac = zvni_mac_lookup(zvni, macaddr);
/* Inform BGP. */
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("neigh %s (MAC %s) is now ACTIVE on L2-VNI %u L3-VNI %u with RMAC %s",
+ zlog_debug("neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
ipaddr2str(ip, buf2, sizeof(buf2)),
prefix_mac2str(macaddr, buf, sizeof(buf)),
- zvni->vni,
- l3vni,
- prefix_mac2str(&rmac, buf1, sizeof(buf1)));
-
+ zvni->vni);
ZEBRA_NEIGH_SET_ACTIVE(n);
return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0);
}
/* we need to associate with SVI, if any, we can associate with
- * svi-if only after association with vxlan-intf is complete */
+ * svi-if only after association with vxlan-intf is complete
+ */
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
if (is_l3vni_oper_up(zl3vni))
zebra_vxlan_process_l3vni_oper_down(zl3vni);
/* remove the association with vxlan_if */
+ memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
zl3vni->vxlan_if = NULL;
} else {
}
/* access-vlan change - process oper down, associate with new
- * svi_if and then process oper up again */
+ * svi_if and then process oper up again
+ */
if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
if (if_is_operative(ifp)) {
zebra_vxlan_process_l3vni_oper_down(zl3vni);
}
/* associate with vxlan_if */
+ zl3vni->local_vtep_ip = vxl->vtep_ip;
zl3vni->vxlan_if = ifp;
/* Associate with SVI, if any. We can associate with svi-if only
}
int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf,
- vni_t vni, char *err,
+ vni_t vni,
+ char *err, int err_str_sz,
int add)
{
zebra_l3vni_t *zl3vni = NULL;
/* check if the vni is already present under zvrf */
if (zvrf->l3vni) {
- snprintf(err, ERR_STR_SZ,
+ snprintf(err, err_str_sz,
"VNI is already configured under the vrf");
return -1;
}
/* check if this VNI is already present in the system */
zl3vni = zl3vni_lookup(vni);
if (zl3vni) {
- snprintf(err, ERR_STR_SZ,
+ snprintf(err, err_str_sz,
"VNI is already configured as L3-VNI");
return -1;
}
/* add the L3-VNI to the global table */
zl3vni = zl3vni_add(vni, zvrf_id(zvrf));
if (!zl3vni) {
- snprintf(err, ERR_STR_SZ,
+ snprintf(err, err_str_sz,
"Could not add L3-VNI");
return -1;
}
zvrf->l3vni = vni;
/* associate with vxlan-intf;
- * we need to associate with the vxlan-intf first */
+ * we need to associate with the vxlan-intf first
+ */
zl3vni->vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
/* associate with corresponding SVI interface, we can associate
* with svi-if only after vxlan interface association is
- * complete */
+ * complete
+ */
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
/* formulate l2vni list */
} else {
zl3vni = zl3vni_lookup(vni);
if (!zl3vni) {
- snprintf(err, ERR_STR_SZ, "VNI doesn't exist");
+ snprintf(err, err_str_sz, "VNI doesn't exist");
return -1;
}
zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ /* delete and uninstall all rmacs */
+ hash_iterate(zl3vni->rmac_table,
+ zl3vni_del_rmac_hash_entry,
+ zl3vni);
+
+ /* delete and uninstall all next-hops */
+ hash_iterate(zl3vni->nh_table,
+ zl3vni_del_nh_hash_entry,
+ zl3vni);
+
zvrf->l3vni = 0;
zl3vni_del(zl3vni);
int zebra_vxlan_advertise_all_vni(struct zserv *client,
u_short length, struct zebra_vrf *zvrf)
{
- struct stream *s;
- int advertise;
+ struct stream *s = NULL;
+ int advertise = 0;
+ struct zebra_ns *zns = NULL;
if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("EVPN VNI Adv for non-default VRF %u",
* kernel and free entries.
*/
hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf);
+
+ /* cleanup all l3vnis */
+ zns = zebra_ns_lookup(NS_DEFAULT);
+ if (!zns)
+ return -1;
+
+ hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL);
}
stream_failure: