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);
-static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty);
+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);
/* print a specific next hop for an l3vni */
static void zl3vni_print_nh(zebra_neigh_t *n,
- struct vty *vty)
+ 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;
- vty_out(vty, "Ip: %s\n",
- ipaddr2str(&n->ip, buf1, sizeof(buf1)));
- 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)));
+ 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)
+ 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;
- 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)));
+ 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);
+ }
}
/*
}
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,
inet_ntoa(zrmac->fwd_info.r_vtep_ip));
json_object_int_add(json_rmac, "refcnt",
listcount(zrmac->host_list));
- json_object_array_add(json, json_rmac);
+ 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",
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),
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_vni, "svi-if",
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)
{
zebra_mac_t *tmp_rmac;
if (zrmac->host_list)
- list_delete(zrmac->host_list);
+ list_delete_and_null(&zrmac->host_list);
zrmac->host_list = NULL;
tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
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;
zebra_neigh_t *tmp_n;
if (n->host_list)
- list_delete(n->host_list);
+ list_delete_and_null(&n->host_list);
n->host_list = NULL;
tmp_n = hash_release(zl3vni->nh_table, n);
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 */
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 */
void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty,
vni_t l3vni,
- struct ethaddr *rmac)
+ 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 (!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) {
- vty_out(vty, "%% L3-VNI %u doesnt exist\n",
- l3vni);
+ 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) {
- vty_out(vty, "%% Requested RMAC doesnt exist in L3-VNI %u",
- l3vni);
+ 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);
+ 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,
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;
-
- hash_iterate(zns->l3vni_table, zl3vni_print_rmac_hash_all_vni, &wctx);
+ 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(
void zebra_vxlan_print_specific_nh_l3vni(struct vty *vty,
vni_t l3vni,
- struct ipaddr *ip)
+ 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 (!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) {
- vty_out(vty, "%% L3-VNI %u does not exist\n", l3vni);
+ 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) {
- vty_out(vty, "%% Requested next-hop not present for L3-VNI %u",
- l3vni);
+ 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);
+ zl3vni_print_nh(n, 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_nh_l3vni(struct vty *vty,
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;
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: