]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_vxlan.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / zebra / zebra_vxlan.c
index 34bae8dc605d505e52c131e97122ed628e7d4642..20dc64b0bc95f68ff9ec5b9f466fa9e16c356afb 100644 (file)
@@ -187,6 +187,18 @@ static int remote_neigh_count(zebra_mac_t *zmac);
 static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac);
 static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t);
 static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t);
+static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
+                                                 zebra_neigh_t *nbr,
+                                                 struct in_addr vtep_ip,
+                                                 bool do_dad,
+                                                 bool *is_dup_detect,
+                                                 bool is_local);
+static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
+                                               zebra_mac_t *mac,
+                                               struct in_addr vtep_ip,
+                                               bool do_dad,
+                                               bool *is_dup_detect,
+                                               bool is_local);
 
 /* Private functions */
 static int host_rb_entry_compare(const struct host_rb_entry *hle1,
@@ -364,6 +376,287 @@ static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
        return 0;
 }
 
+static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
+                                               zebra_mac_t *mac,
+                                               struct in_addr vtep_ip,
+                                               bool do_dad,
+                                               bool *is_dup_detect,
+                                               bool is_local)
+{
+       zebra_neigh_t *nbr;
+       struct listnode *node = NULL;
+       struct timeval elapsed = {0, 0};
+       char buf[ETHER_ADDR_STRLEN];
+       char buf1[INET6_ADDRSTRLEN];
+       bool reset_params = false;
+
+       if (!(zvrf->dup_addr_detect && do_dad))
+               return;
+
+       /* MAC is detected as duplicate,
+        * Local MAC event -> hold on advertising to BGP.
+        * Remote MAC event -> hold on installing it.
+        */
+       if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug(
+                                  "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u",
+                                  __PRETTY_FUNCTION__,
+                                  prefix_mac2str(&mac->macaddr, buf,
+                                                 sizeof(buf)),
+                                  mac->flags, mac->dad_count,
+                                  zvrf->dad_freeze_time);
+
+               /* For duplicate MAC do not update
+                * client but update neigh due to
+                * this MAC update.
+                */
+               if (zvrf->dad_freeze)
+                       *is_dup_detect = false;
+
+               return;
+       }
+
+       /* Check if detection time (M-secs) expired.
+        * Reset learn count and detection start time.
+        */
+       monotime_since(&mac->detect_start_time, &elapsed);
+       reset_params = (elapsed.tv_sec > zvrf->dad_time);
+       if (is_local && !reset_params) {
+               /* RFC-7432: A PE/VTEP that detects a MAC mobility
+                * event via LOCAL learning starts an M-second timer.
+                *
+                * NOTE: This is the START of the probe with count is
+                * 0 during LOCAL learn event.
+                * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time)
+                */
+               reset_params = !mac->dad_count;
+       }
+
+       if (reset_params) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug(
+                                  "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u"
+                                  , __PRETTY_FUNCTION__,
+                                  prefix_mac2str(&mac->macaddr, buf,
+                                                 sizeof(buf)),
+                                  mac->flags, mac->dad_count);
+
+               mac->dad_count = 0;
+               /* Start dup. addr detection (DAD) start time,
+                * ONLY during LOCAL learn.
+                */
+               if (is_local)
+                       monotime(&mac->detect_start_time);
+
+       } else if (!is_local) {
+               /* For REMOTE MAC, increment detection count
+                * ONLY while in probe window, once window passed,
+                * next local learn event should trigger DAD.
+                */
+               mac->dad_count++;
+       }
+
+       /* For LOCAL MAC learn event, once count is reset above via either
+        * initial/start detection time or passed the probe time, the count
+        * needs to be incremented.
+        */
+       if (is_local)
+               mac->dad_count++;
+
+       zlog_debug("%s: MAC DAD %s dad_count %u ",
+                  __PRETTY_FUNCTION__,
+                  prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+                  mac->dad_count);
+
+       if (mac->dad_count >= zvrf->dad_max_moves) {
+               flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
+                         "VNI %u: MAC %s detected as duplicate during %s VTEP %s",
+                         mac->zvni->vni,
+                         prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+                         is_local ? "local update, last" :
+                         "remote update, from", inet_ntoa(vtep_ip));
+
+               SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
+
+               /* Capture Duplicate detection time */
+               mac->dad_dup_detect_time = monotime(NULL);
+
+               /* Mark all IPs/Neighs as duplicate
+                * associcated with this MAC
+                */
+               for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
+
+                       /* Ony Mark IPs which are Local */
+                       if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
+                               continue;
+
+                       SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
+
+                       nbr->dad_dup_detect_time = monotime(NULL);
+
+                       flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
+                                 "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
+                                 mac->zvni->vni,
+                                 prefix_mac2str(&mac->macaddr,
+                                                buf, sizeof(buf)),
+                                 ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+                                 is_local ? "local" : "remote");
+               }
+
+               /* Start auto recovery timer for this MAC */
+               THREAD_OFF(mac->dad_mac_auto_recovery_timer);
+               if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
+                       if (IS_ZEBRA_DEBUG_VXLAN)
+                               zlog_debug(
+                                       "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start"
+                                       , __PRETTY_FUNCTION__,
+                                       prefix_mac2str(&mac->macaddr, buf,
+                                                      sizeof(buf)),
+                                       mac->flags, zvrf->dad_freeze_time);
+
+                       thread_add_timer(zebrad.master,
+                                        zebra_vxlan_dad_mac_auto_recovery_exp,
+                                        mac, zvrf->dad_freeze_time,
+                                        &mac->dad_mac_auto_recovery_timer);
+               }
+
+               /* Do not inform to client (BGPd),
+                * upd_neigh for neigh sequence change.
+                */
+               if (zvrf->dad_freeze)
+                       *is_dup_detect = false;
+       }
+}
+
+static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
+                                                 zebra_neigh_t *nbr,
+                                                 struct in_addr vtep_ip,
+                                                 bool do_dad,
+                                                 bool *is_dup_detect,
+                                                 bool is_local)
+{
+
+       struct timeval elapsed = {0, 0};
+       char buf[ETHER_ADDR_STRLEN];
+       char buf1[INET6_ADDRSTRLEN];
+       bool reset_params = false;
+
+       if (!zvrf->dup_addr_detect)
+               return;
+
+       /* IP is detected as duplicate or inherit dup
+        * state, hold on to install as remote entry
+        * only if freeze is enabled.
+        */
+       if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug(
+                                  "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
+                                          __PRETTY_FUNCTION__,
+                               prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
+                               ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+                               nbr->flags, nbr->dad_count,
+                               zvrf->dad_freeze_time);
+
+               if (zvrf->dad_freeze)
+                       *is_dup_detect = true;
+               /* warn-only action, neigh will be installed.
+                * freeze action, it wil not be installed.
+                */
+               return;
+       }
+
+       if (!do_dad)
+               return;
+
+       /* Check if detection time (M-secs) expired.
+        * Reset learn count and detection start time.
+        * During remote mac add, count should already be 1
+        * via local learning.
+        */
+       monotime_since(&nbr->detect_start_time, &elapsed);
+       reset_params = (elapsed.tv_sec > zvrf->dad_time);
+
+       if (is_local && !reset_params) {
+               /* RFC-7432: A PE/VTEP that detects a MAC mobility
+                * event via LOCAL learning starts an M-second timer.
+                *
+                * NOTE: This is the START of the probe with count is
+                * 0 during LOCAL learn event.
+                */
+               reset_params = !nbr->dad_count;
+       }
+
+       if (reset_params) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug(
+                               "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
+                               __PRETTY_FUNCTION__,
+                               prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
+                               ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+                               nbr->flags, nbr->dad_count);
+               /* Reset learn count but do not start detection
+                * during REMOTE learn event.
+                */
+               nbr->dad_count = 0;
+               /* Start dup. addr detection (DAD) start time,
+                * ONLY during LOCAL learn.
+                */
+               if (is_local)
+                       monotime(&nbr->detect_start_time);
+
+       } else if (!is_local) {
+               /* For REMOTE IP/Neigh, increment detection count
+                * ONLY while in probe window, once window passed,
+                * next local learn event should trigger DAD.
+                */
+               nbr->dad_count++;
+       }
+
+       /* For LOCAL IP/Neigh learn event, once count is reset above via either
+        * initial/start detection time or passed the probe time, the count
+        * needs to be incremented.
+        */
+       if (is_local)
+               nbr->dad_count++;
+
+       if (nbr->dad_count >= zvrf->dad_max_moves) {
+               flog_warn(EC_ZEBRA_DUP_IP_DETECTED,
+                         "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s",
+                         nbr->zvni->vni,
+                         prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
+                         ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+                         is_local ? "local update, last" :
+                         "remote update, from",
+                         inet_ntoa(vtep_ip));
+
+               SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
+
+               /* Capture Duplicate detection time */
+               nbr->dad_dup_detect_time = monotime(NULL);
+
+               /* Start auto recovery timer for this IP */
+               THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
+               if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
+                       if (IS_ZEBRA_DEBUG_VXLAN)
+                               zlog_debug(
+                                       "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
+                                  __PRETTY_FUNCTION__,
+                                  prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
+                                  ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+                                  nbr->flags, zvrf->dad_freeze_time);
+
+                       thread_add_timer(zebrad.master,
+                               zebra_vxlan_dad_ip_auto_recovery_exp,
+                               nbr, zvrf->dad_freeze_time,
+                               &nbr->dad_ip_auto_recovery_timer);
+               }
+               if (zvrf->dad_freeze)
+                       *is_dup_detect = true;
+       }
+}
+
 /*
  * Helper function to determine maximum width of neighbor IP address for
  * display - just because we're dealing with IPv6 addresses that can
@@ -578,6 +871,33 @@ static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt)
                json_object_object_add(json_vni, buf2, json_row);
 }
 
+/*
+ * Print neighbor hash entry in detail - called for display of all neighbors.
+ */
+static void zvni_print_neigh_hash_detail(struct hash_backet *backet, void *ctxt)
+{
+       struct vty *vty;
+       json_object *json_vni = NULL, *json_row = NULL;
+       zebra_neigh_t *n;
+       char buf[INET6_ADDRSTRLEN];
+       struct neigh_walk_ctx *wctx = ctxt;
+
+       vty = wctx->vty;
+       json_vni = wctx->json;
+       n = (zebra_neigh_t *)backet->data;
+       if (!n)
+               return;
+
+       ipaddr2str(&n->ip, buf, sizeof(buf));
+       if (json_vni)
+               json_row = json_object_new_object();
+
+       zvni_print_neigh(n, vty, json_row);
+
+       if (json_vni)
+               json_object_object_add(json_vni, buf, json_row);
+}
+
 /*
  * Print neighbors for all VNI.
  */
@@ -657,6 +977,80 @@ static void zvni_print_dad_neigh_hash(struct hash_backet *backet, void *ctxt)
                zvni_print_neigh_hash(backet, ctxt);
 }
 
+static void zvni_print_dad_neigh_hash_detail(struct hash_backet *backet,
+                                            void *ctxt)
+{
+       zebra_neigh_t *nbr;
+
+       nbr = (zebra_neigh_t *)backet->data;
+       if (!nbr)
+               return;
+
+       if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
+               zvni_print_neigh_hash_detail(backet, ctxt);
+}
+
+/*
+ * Print neighbors for all VNIs in detail.
+ */
+static void zvni_print_neigh_hash_all_vni_detail(struct hash_backet *backet,
+                                                void **args)
+{
+       struct vty *vty;
+       json_object *json = NULL, *json_vni = NULL;
+       zebra_vni_t *zvni;
+       uint32_t num_neigh;
+       struct neigh_walk_ctx wctx;
+       char vni_str[VNI_STR_LEN];
+       uint32_t print_dup;
+
+       vty = (struct vty *)args[0];
+       json = (json_object *)args[1];
+       print_dup = (uint32_t)(uintptr_t)args[2];
+
+       zvni = (zebra_vni_t *)backet->data;
+       if (!zvni) {
+               if (json)
+                       vty_out(vty, "{}\n");
+               return;
+       }
+       num_neigh = hashcount(zvni->neigh_table);
+
+       if (print_dup && num_dup_detected_neighs(zvni) == 0)
+               return;
+
+       if (json == NULL) {
+               vty_out(vty,
+                       "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
+                       zvni->vni, num_neigh);
+       } else {
+               json_vni = json_object_new_object();
+               json_object_int_add(json_vni, "numArpNd", num_neigh);
+               snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
+       }
+       if (!num_neigh) {
+               if (json)
+                       json_object_object_add(json, vni_str, json_vni);
+               return;
+       }
+
+       memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
+       wctx.zvni = zvni;
+       wctx.vty = vty;
+       wctx.addr_width = 15;
+       wctx.json = json_vni;
+
+       if (print_dup)
+               hash_iterate(zvni->neigh_table,
+                            zvni_print_dad_neigh_hash_detail, &wctx);
+       else
+               hash_iterate(zvni->neigh_table, zvni_print_neigh_hash_detail,
+                            &wctx);
+
+       if (json)
+               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)
@@ -833,10 +1227,6 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
                }
 
                json_object_object_add(json, buf1, json_mac);
-               vty_out(vty, "%s\n",
-                       json_object_to_json_string_ext(
-                               json, JSON_C_TO_STRING_PRETTY));
-               json_object_free(json);
        } else {
                vty_out(vty, "MAC: %s\n", buf1);
 
@@ -1033,6 +1423,43 @@ static void zvni_print_dad_mac_hash(struct hash_backet *backet, void *ctxt)
                zvni_print_mac_hash(backet, ctxt);
 }
 
+/*
+ * Print MAC hash entry in detail - called for display of all MACs.
+ */
+static void zvni_print_mac_hash_detail(struct hash_backet *backet, void *ctxt)
+{
+       struct vty *vty;
+       json_object *json_mac_hdr = NULL;
+       zebra_mac_t *mac;
+       struct mac_walk_ctx *wctx = ctxt;
+       char buf1[20];
+
+       vty = wctx->vty;
+       json_mac_hdr = wctx->json;
+       mac = (zebra_mac_t *)backet->data;
+       if (!mac)
+               return;
+
+       wctx->count++;
+       prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
+
+       zvni_print_mac(mac, vty, json_mac_hdr);
+}
+
+/* Print Duplicate MAC in detail */
+static void zvni_print_dad_mac_hash_detail(struct hash_backet *backet,
+                                          void *ctxt)
+{
+       zebra_mac_t *mac;
+
+       mac = (zebra_mac_t *)backet->data;
+       if (!mac)
+               return;
+
+       if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
+               zvni_print_mac_hash_detail(backet, ctxt);
+}
+
 /*
  * Print MACs for all VNI.
  */
@@ -1103,6 +1530,72 @@ static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt)
        }
 }
 
+/*
+ * Print MACs in detail for all VNI.
+ */
+static void zvni_print_mac_hash_all_vni_detail(struct hash_backet *backet,
+                                              void *ctxt)
+{
+       struct vty *vty;
+       json_object *json = NULL, *json_vni = NULL;
+       json_object *json_mac = NULL;
+       zebra_vni_t *zvni;
+       uint32_t num_macs;
+       struct mac_walk_ctx *wctx = ctxt;
+       char vni_str[VNI_STR_LEN];
+
+       vty = (struct vty *)wctx->vty;
+       json = (struct json_object *)wctx->json;
+
+       zvni = (zebra_vni_t *)backet->data;
+       if (!zvni) {
+               if (json)
+                       vty_out(vty, "{}\n");
+               return;
+       }
+       wctx->zvni = zvni;
+
+       /*We are iterating over a new VNI, set the count to 0*/
+       wctx->count = 0;
+
+       num_macs = num_valid_macs(zvni);
+       if (!num_macs)
+               return;
+
+       if (wctx->print_dup && (num_dup_detected_macs(zvni) == 0))
+               return;
+
+       if (json) {
+               json_vni = json_object_new_object();
+               json_mac = json_object_new_object();
+               snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
+       }
+
+       if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) {
+               if (json == NULL) {
+                       vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n",
+                               zvni->vni, num_macs);
+               } else
+                       json_object_int_add(json_vni, "numMacs", num_macs);
+       }
+       /* assign per-vni to wctx->json object to fill macs
+        * under the vni. Re-assign primary json object to fill
+        * next vni information.
+        */
+       wctx->json = json_mac;
+       if (wctx->print_dup)
+               hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash_detail,
+                            wctx);
+       else
+               hash_iterate(zvni->mac_table, zvni_print_mac_hash_detail, wctx);
+       wctx->json = json;
+       if (json) {
+               if (wctx->count)
+                       json_object_object_add(json_vni, "macs", json_mac);
+               json_object_object_add(json, vni_str, json_vni);
+       }
+}
+
 static void zl3vni_print_nh_hash(struct hash_backet *backet, void *ctx)
 {
        struct nh_walk_ctx *wctx = NULL;
@@ -1436,6 +1929,35 @@ static void zl3vni_print_hash(struct hash_backet *backet, void *ctx[])
        }
 }
 
+/* Private Structure to pass callback data for hash iterator */
+struct zvni_evpn_show {
+       struct vty *vty;
+       json_object *json;
+       struct zebra_vrf *zvrf;
+};
+
+/* print a L3 VNI hash entry in detail*/
+static void zl3vni_print_hash_detail(struct hash_backet *backet, void *data)
+{
+       struct vty *vty = NULL;
+       zebra_l3vni_t *zl3vni = NULL;
+       json_object *json = NULL;
+       bool use_json = false;
+       struct zvni_evpn_show *zes = data;
+
+       vty = zes->vty;
+       json = zes->json;
+
+       if (json)
+               use_json = true;
+
+       zl3vni = (zebra_l3vni_t *)backet->data;
+
+       zebra_vxlan_print_vni(vty, zes->zvrf, zl3vni->vni, use_json);
+       vty_out(vty, "\n");
+}
+
+
 /*
  * Print a VNI hash entry - called for display of all VNIs.
  */
@@ -1500,6 +2022,29 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[])
        }
 }
 
+/*
+ * Print a VNI hash entry in detail - called for display of all VNIs.
+ */
+static void zvni_print_hash_detail(struct hash_backet *backet, void *data)
+{
+       struct vty *vty;
+       zebra_vni_t *zvni;
+       json_object *json = NULL;
+       bool use_json = false;
+       struct zvni_evpn_show *zes = data;
+
+       vty = zes->vty;
+       json = zes->json;
+
+       if (json)
+               use_json = true;
+
+       zvni = (zebra_vni_t *)backet->data;
+
+       zebra_vxlan_print_vni(vty, zes->zvrf, zvni->vni, use_json);
+       vty_out(vty, "\n");
+}
+
 /*
  * Inform BGP about local MACIP.
  */
@@ -2314,8 +2859,8 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
        bool neigh_mac_change = false;
        bool neigh_on_hold = false;
        bool neigh_was_remote = false;
+       bool do_dad = false;
        struct in_addr vtep_ip = {.s_addr = 0};
-       struct timeval elapsed = {0, 0};
 
        /* Check if the MAC exists. */
        zmac = zvni_mac_lookup(zvni, macaddr);
@@ -2507,102 +3052,16 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                        ipaddr2str(&n->ip, buf2, sizeof(buf2)));
        }
 
-       /* Duplicate Address Detection (DAD) is enabled.
-        * Based on Mobility event Scenario-B from the
-        * draft, IP/Neigh's MAC binding changed and
-        * neigh's previous state was remote, trigger DAD.
+       /* For IP Duplicate Address Detection (DAD) is trigger,
+        * when the event is extended mobility based on scenario-B
+        * from the draft, IP/Neigh's MAC binding changed and
+        * neigh's previous state was remote.
         */
-       if (zvrf->dup_addr_detect) {
-               /* Neigh could have inherit dup flag or IP DAD
-                * detected earlier
-                */
-               if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) {
-                       if (IS_ZEBRA_DEBUG_VXLAN)
-                               zlog_debug(
-                                          "%s: duplicate addr MAC %s IP %s skip update to client, learn count %u recover time %u",
-                                          __PRETTY_FUNCTION__,
-                                          prefix_mac2str(macaddr,
-                                                         buf, sizeof(buf)),
-                                          ipaddr2str(ip, buf2, sizeof(buf2)),
-                                          n->dad_count,
-                                          zvrf->dad_freeze_time);
-
-                       /* In case of warn-only, inform client and update neigh
-                        */
-                       if (zvrf->dad_freeze)
-                               neigh_on_hold = true;
-
-                       goto send_notif;
-               }
-
-               /* MAC binding changed and previous state was remote */
-               if (!(neigh_mac_change && neigh_was_remote))
-                       goto send_notif;
-
-               /* First check if neigh is already marked duplicate via
-                * MAC dup detection, before firing M Seconds
-                * duplicate detection.
-                * RFC-7432: A PE/VTEP that detects a MAC mobility
-                * event via local learning starts an M-second timer.
-                *
-                * Check if detection time (M-secs) expired.
-                * Reset learn count and detection start time.
-                */
-               monotime_since(&n->detect_start_time, &elapsed);
-               if (n->dad_count == 0 || elapsed.tv_sec > zvrf->dad_time) {
-                       if (IS_ZEBRA_DEBUG_VXLAN)
-                               zlog_debug("%s: duplicate addr MAC %s detection time passed, reset learn count %u",
-                                          __PRETTY_FUNCTION__,
-                                          prefix_mac2str(macaddr, buf,
-                                                         sizeof(buf)),
-                                          n->dad_count);
-                       n->dad_count = 0;
-                       /* Start dup. detection time */
-                       monotime(&n->detect_start_time);
-               }
-
-               n->dad_count++;
-
-               if (n->dad_count >= zvrf->dad_max_moves) {
-                       flog_warn(EC_ZEBRA_DUP_IP_DETECTED,
-                                 "VNI %u: MAC %s IP %s detected as duplicate during local update, last VTEP %s",
-                                 zvni->vni,
-                                 prefix_mac2str(&n->emac, buf, sizeof(buf)),
-                                 ipaddr2str(ip, buf2, sizeof(buf2)),
-                                 inet_ntoa(vtep_ip));
-
-                       /* Mark Duplicate */
-                       SET_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE);
-
-                       /* Capture Duplicate detection time */
-                       n->dad_dup_detect_time = monotime(NULL);
-
-                       /* Start auto recovery timer for this IP */
-                       THREAD_OFF(n->dad_ip_auto_recovery_timer);
-                       if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
-                               if (IS_ZEBRA_DEBUG_VXLAN)
-                                       zlog_debug(
-                                               "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
-                                       __PRETTY_FUNCTION__,
-                                       prefix_mac2str(macaddr, buf,
-                                                      sizeof(buf)),
-                                       ipaddr2str(ip, buf2, sizeof(buf2)),
-                                       n->flags,
-                                       zvrf->dad_freeze_time);
-
-                               thread_add_timer(zebrad.master,
-                                       zebra_vxlan_dad_ip_auto_recovery_exp,
-                                       n,
-                                       zvrf->dad_freeze_time,
-                                       &n->dad_ip_auto_recovery_timer);
-                       }
-
-                       if (zvrf->dad_freeze)
-                               neigh_on_hold = true;
-               }
-       }
+       if (neigh_mac_change && neigh_was_remote)
+               do_dad = true;
 
-send_notif:
+       zebra_vxlan_dup_addr_detect_for_neigh(zvrf, n, vtep_ip, do_dad,
+                                             &neigh_on_hold, true);
 
        /* Before we program this in BGP, we need to check if MAC is locally
         * learnt. If not, force neighbor to be inactive and reset its seq.
@@ -4557,8 +5016,6 @@ static void process_remote_macip_add(vni_t vni,
        bool is_router;
        bool do_dad = false;
        bool is_dup_detect = false;
-       struct listnode *node = NULL;
-       struct timeval elapsed = {0, 0};
 
        /* Locate VNI hash entry - expected to exist. */
        zvni = zvni_lookup(vni);
@@ -4714,114 +5171,11 @@ static void process_remote_macip_add(vni_t vni,
                else
                        UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
 
-               if (zvrf->dup_addr_detect && do_dad) {
-                       /* MAC is detected as duplicate, hold on to
-                        * install as remote entry.
-                        */
-                       if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
-                               if (IS_ZEBRA_DEBUG_VXLAN)
-                                       zlog_debug(
-                                                  "%s: duplicate addr MAC %s skip installing, learn count %u recover time %u",
-                                                          __PRETTY_FUNCTION__,
-                                               prefix_mac2str(macaddr,
-                                                       buf, sizeof(buf)),
-                                               mac->dad_count,
-                                               zvrf->dad_freeze_time);
-                               /* Do not install MAC but process neigh
-                                * due to the remote MAC add.
-                                */
-                               goto process_neigh;
-                       }
-
-                       /* Check if detection time (M-secs) expired.
-                        * Reset learn count and detection start time.
-                        */
-                       monotime_since(&mac->detect_start_time, &elapsed);
-                       if (elapsed.tv_sec > zvrf->dad_time) {
-                               if (IS_ZEBRA_DEBUG_VXLAN)
-                                       zlog_debug("%s: duplicate addr MAC %s flags 0%x detection time passed, reset learn count %u",
-                                                  __PRETTY_FUNCTION__,
-                                                  prefix_mac2str(macaddr, buf,
-                                                                 sizeof(buf)),
-                                                  mac->flags, mac->dad_count);
-                               /* Reset learn count but do not start detection
-                                * during remote learn.
-                                * Next local learn event start time wil be
-                                * resetted.
-                                */
-                               mac->dad_count = 0;
-                       } else {
-                               /* Increment detection count while in probe
-                                * window
-                                */
-                               mac->dad_count++;
-                       }
-
-                       if (mac->dad_count >= zvrf->dad_max_moves) {
-                               flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
-                                       "VNI %u: MAC %s detected as duplicate during remote update, from VTEP %s",
-                                       zvni->vni,
-                                       prefix_mac2str(&mac->macaddr,
-                                                      buf, sizeof(buf)),
-                                       inet_ntoa(mac->fwd_info.r_vtep_ip));
-
-                               SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
-
-                               /* Capture Duplicate detection time */
-                               mac->dad_dup_detect_time = monotime(NULL);
-
-                               /* Mark all IPs/Neighs as duplicate associcated
-                                * with this MAC
-                                */
-                               for (ALL_LIST_ELEMENTS_RO(mac->neigh_list,
-                                                         node, n)) {
-                                       /* Ony Mark IPs which are Remote */
-                                       if (!CHECK_FLAG(n->flags,
-                                                      ZEBRA_NEIGH_REMOTE))
-                                               continue;
-
-                                       SET_FLAG(n->flags,
-                                                ZEBRA_NEIGH_DUPLICATE);
-
-                                       /* Capture Duplicate detection time */
-                                       n->dad_dup_detect_time = monotime(NULL);
-
-                                       flog_warn(
-                                       EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
-                                                 "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
-                                                 zvni->vni,
-                                                 prefix_mac2str(&mac->macaddr,
-                                                       buf, sizeof(buf)),
-                                                 ipaddr2str(&n->ip, buf1,
-                                                            sizeof(buf1)));
-                               }
-
-                               /* Start auto recovery timer for this
-                                * MAC
-                                */
-                               THREAD_OFF(mac->dad_mac_auto_recovery_timer);
-                               if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
-                                       if (IS_ZEBRA_DEBUG_VXLAN)
-                                               zlog_debug("%s: duplicate addr MAC %s flags 0%x auto recovery time %u start",
-                                                  __PRETTY_FUNCTION__,
-                                                  prefix_mac2str(&mac->macaddr,
-                                                       buf, sizeof(buf)),
-                                                  mac->flags,
-                                                  zvrf->dad_freeze_time);
-
-                                       thread_add_timer(zebrad.master,
-                                       zebra_vxlan_dad_mac_auto_recovery_exp,
-                                       mac,
-                                       zvrf->dad_freeze_time,
-                                       &mac->dad_mac_auto_recovery_timer);
-                               }
-
-                               if (zvrf->dad_freeze)
-                                       is_dup_detect = true;
-                       }
+               zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac,
+                                                   mac->fwd_info.r_vtep_ip,
+                                                   do_dad, &is_dup_detect,
+                                                   false);
 
-               }
-process_neigh:
                zvni_process_neigh_on_remote_mac_add(zvni, mac);
 
                /* Install the entry. */
@@ -4960,102 +5314,12 @@ process_neigh:
                                ipaddr2str(&n->ip, buf1, sizeof(buf1)));
                }
 
-               if (zvrf->dup_addr_detect) {
-                       /* IP is detected as duplicate or inherit dup
-                        * state, hold on to install as remote entry
-                        * only if freeze is enabled.
-                        */
-                       if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) {
-                               if (IS_ZEBRA_DEBUG_VXLAN)
-                                       zlog_debug(
-                                                  "%s: duplicate addr MAC %s IP %s skip installing, learn count %u recover time %u",
-                                                          __PRETTY_FUNCTION__,
-                                               prefix_mac2str(macaddr,
-                                                       buf, sizeof(buf)),
-                                               ipaddr2str(ipaddr, buf1,
-                                                          sizeof(buf1)),
-                                               n->dad_count,
-                                               zvrf->dad_freeze_time);
-
-                               if (zvrf->dad_freeze)
-                                       is_dup_detect = true;
-                               /* warn-only action, neigh will be installed.
-                                * freeze action, it wil not be installed.
-                                */
-                               goto install_neigh;
-                       }
-
-                       if (!do_dad)
-                               goto install_neigh;
-
-                       /* Check if detection time (M-secs) expired.
-                        * Reset learn count and detection start time.
-                        * During remote mac add, count should already be 1
-                        * via local learning.
-                        */
-                       monotime_since(&n->detect_start_time, &elapsed);
-                       if (elapsed.tv_sec > zvrf->dad_time) {
-                               if (IS_ZEBRA_DEBUG_VXLAN)
-                                       zlog_debug("%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
-                                                  __PRETTY_FUNCTION__,
-                                                  prefix_mac2str(macaddr, buf,
-                                                                 sizeof(buf)),
-                                                  ipaddr2str(ipaddr, buf1,
-                                                             sizeof(buf1)),
-                                                  n->flags,
-                                                  n->dad_count);
-                               /* Reset learn count but do not start detection
-                                * during remote learn event.
-                                */
-                               n->dad_count = 0;
-                       } else {
-                               /* Increment detection count while in probe
-                                * window
-                                */
-                               n->dad_count++;
-                       }
-
-                       if (n->dad_count >= zvrf->dad_max_moves) {
-                               flog_warn(EC_ZEBRA_DUP_IP_DETECTED,
-                                         "VNI %u: MAC %s IP %s detected as duplicate during remote update, from VTEP %s",
-                                         zvni->vni,
-                                         prefix_mac2str(&mac->macaddr,
-                                                       buf, sizeof(buf)),
-                                         ipaddr2str(ipaddr, buf1,
-                                                          sizeof(buf1)),
-                                         inet_ntoa(n->r_vtep_ip));
-
-                               SET_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE);
-
-                               /* Capture Duplicate detection time */
-                               n->dad_dup_detect_time = monotime(NULL);
-
-                               /* Start auto recovery timer for this IP */
-                               THREAD_OFF(n->dad_ip_auto_recovery_timer);
-                               if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
-                                       if (IS_ZEBRA_DEBUG_VXLAN)
-                                               zlog_debug(
-                                                       "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
-                                                  __PRETTY_FUNCTION__,
-                                                  prefix_mac2str(&mac->macaddr,
-                                                                 buf,
-                                                                 sizeof(buf)),
-                                                  ipaddr2str(ipaddr, buf1,
-                                                             sizeof(buf1)),
-                                                  mac->flags,
-                                                  zvrf->dad_freeze_time);
-
-                                       thread_add_timer(zebrad.master,
-                                       zebra_vxlan_dad_ip_auto_recovery_exp,
-                                       n,
-                                       zvrf->dad_freeze_time,
-                                       &n->dad_ip_auto_recovery_timer);
-                               }
-                               if (zvrf->dad_freeze)
-                                       is_dup_detect = true;
-                       }
-               }
-install_neigh:
+               /* Check duplicate address detection for IP */
+               zebra_vxlan_dup_addr_detect_for_neigh(zvrf, n,
+                                                     n->r_vtep_ip,
+                                                     do_dad,
+                                                     &is_dup_detect,
+                                                     false);
                /* Install the entry. */
                if (!is_dup_detect)
                        zvni_neigh_install(zvni, n);
@@ -5654,6 +5918,37 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
        }
 }
 
+/*
+ * Display neighbors across all VNIs in detail(VTY command handler).
+ */
+void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty,
+                                           struct zebra_vrf *zvrf,
+                                           bool print_dup, bool use_json)
+{
+       json_object *json = NULL;
+       void *args[3];
+
+       if (!is_evpn_enabled())
+               return;
+
+       if (use_json)
+               json = json_object_new_object();
+
+       args[0] = vty;
+       args[1] = json;
+       args[2] = (void *)(ptrdiff_t)print_dup;
+
+       hash_iterate(zvrf->vni_table,
+                    (void (*)(struct hash_backet *,
+                              void *))zvni_print_neigh_hash_all_vni_detail,
+                    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);
+       }
+}
+
 /*
  * Display specific neighbor for a VNI, if present (VTY command handler).
  */
@@ -5888,6 +6183,38 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
        }
 }
 
+/*
+ * Display MACs in detail for all VNIs (VTY command handler).
+ */
+void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty,
+                                          struct zebra_vrf *zvrf,
+                                          bool print_dup, bool use_json)
+{
+       struct mac_walk_ctx wctx;
+       json_object *json = NULL;
+
+       if (!is_evpn_enabled()) {
+               if (use_json)
+                       vty_out(vty, "{}\n");
+               return;
+       }
+       if (use_json)
+               json = json_object_new_object();
+
+       memset(&wctx, 0, sizeof(struct mac_walk_ctx));
+       wctx.vty = vty;
+       wctx.json = json;
+       wctx.print_dup = print_dup;
+       hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni_detail,
+                    &wctx);
+
+       if (use_json) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
 /*
  * Display MACs for all VNIs (VTY command handler).
  */
@@ -5955,6 +6282,11 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
                json = json_object_new_object();
 
        zvni_print_mac(mac, 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);
+       }
 }
 
 /* Print Duplicate MACs per VNI */
@@ -6015,9 +6347,9 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
 
 }
 
-void zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
-                                         struct zebra_vrf *zvrf,
-                                         vni_t vni, struct ethaddr *macaddr)
+int zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
+                                        struct zebra_vrf *zvrf,
+                                        vni_t vni, struct ethaddr *macaddr)
 {
        zebra_vni_t *zvni;
        zebra_mac_t *mac;
@@ -6025,23 +6357,24 @@ void zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
        zebra_neigh_t *nbr = NULL;
 
        if (!is_evpn_enabled())
-               return;
+               return CMD_SUCCESS;
+
        zvni = zvni_lookup(vni);
        if (!zvni) {
                vty_out(vty, "%% VNI %u does not exist\n", vni);
-               return;
+               return CMD_WARNING;
        }
 
        mac = zvni_mac_lookup(zvni, macaddr);
        if (!mac) {
                vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
                        vni);
-               return;
+               return CMD_WARNING;
        }
 
        if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
                vty_out(vty, "%% Requested MAC is not duplicate detected\n");
-               return;
+               return CMD_WARNING;
        }
 
        /* Remove all IPs as duplicate associcated with this MAC */
@@ -6080,7 +6413,7 @@ void zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
                                        &mac->macaddr,
                                        mac->flags,
                                        mac->loc_seq))
-                       return;
+                       return CMD_SUCCESS;
 
                /* Process all neighbors associated with this MAC. */
                zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
@@ -6092,11 +6425,12 @@ void zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
                zvni_mac_install(zvni, mac);
        }
 
+       return CMD_SUCCESS;
 }
 
-void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
-                                        struct zebra_vrf *zvrf,
-                                        vni_t vni, struct ipaddr *ip)
+int zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
+                                       struct zebra_vrf *zvrf,
+                                       vni_t vni, struct ipaddr *ip)
 {
        zebra_vni_t *zvni;
        zebra_neigh_t *nbr;
@@ -6105,12 +6439,12 @@ void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
        char buf2[ETHER_ADDR_STRLEN];
 
        if (!is_evpn_enabled())
-               return;
+               return CMD_SUCCESS;
 
        zvni = zvni_lookup(vni);
        if (!zvni) {
                vty_out(vty, "%% VNI %u does not exist\n", vni);
-               return;
+               return CMD_WARNING;
        }
 
        nbr = zvni_neigh_lookup(zvni, ip);
@@ -6118,7 +6452,7 @@ void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
                vty_out(vty,
                        "%% Requested host IP does not exist in VNI %u\n",
                        vni);
-               return;
+               return CMD_WARNING;
        }
 
        ipaddr2str(&nbr->ip, buf, sizeof(buf));
@@ -6127,7 +6461,7 @@ void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
                vty_out(vty,
                        "%% Requsted host IP %s is not duplicate detected\n",
                        buf);
-               return;
+               return CMD_WARNING;
        }
 
        mac = zvni_mac_lookup(zvni, &nbr->emac);
@@ -6136,7 +6470,7 @@ void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
                vty_out(vty,
                        "%% Requested IP's associated MAC %s is still in duplicate state\n",
                        prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)));
-               return;
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
        if (IS_ZEBRA_DEBUG_VXLAN)
@@ -6159,6 +6493,7 @@ void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
                zvni_neigh_install(zvni, nbr);
        }
 
+       return CMD_SUCCESS;
 }
 
 static void zvni_clear_dup_mac_hash(struct hash_backet *backet, void *ctxt)
@@ -6291,13 +6626,13 @@ static void zvni_clear_dup_detect_hash_vni_all(struct hash_backet *backet,
 
 }
 
-void zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
+int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
                                          struct zebra_vrf *zvrf)
 {
        void *args[2];
 
        if (!is_evpn_enabled())
-               return;
+               return CMD_SUCCESS;
 
        args[0] = vty;
        args[1] = zvrf;
@@ -6306,9 +6641,10 @@ void zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
                     (void (*)(struct hash_backet *, void *))
                     zvni_clear_dup_detect_hash_vni_all, args);
 
+       return CMD_SUCCESS;
 }
 
-void zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
+int  zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
                                      struct zebra_vrf *zvrf,
                                      vni_t vni)
 {
@@ -6317,12 +6653,12 @@ void zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
        struct neigh_walk_ctx n_wctx;
 
        if (!is_evpn_enabled())
-               return;
+               return CMD_SUCCESS;
 
        zvni = zvni_lookup(vni);
        if (!zvni) {
                vty_out(vty, "%% VNI %u does not exist\n", vni);
-               return;
+               return CMD_WARNING;
        }
 
        if (hashcount(zvni->neigh_table)) {
@@ -6342,6 +6678,7 @@ void zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
                hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx);
        }
 
+       return CMD_SUCCESS;
 }
 
 /*
@@ -6582,6 +6919,49 @@ stream_failure:
        return;
 }
 
+/*
+ * Display VNI hash table in detail(VTY command handler).
+ */
+void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
+                                  bool use_json)
+{
+       json_object *json = NULL;
+       struct zebra_ns *zns = NULL;
+       struct zvni_evpn_show zes;
+
+       if (!is_evpn_enabled())
+               return;
+
+       zns = zebra_ns_lookup(NS_DEFAULT);
+       if (!zns)
+               return;
+
+
+       if (use_json)
+               json = json_object_new_object();
+
+       zes.vty = vty;
+       zes.json = json;
+       zes.zvrf = zvrf;
+
+       /* Display all L2-VNIs */
+       hash_iterate(zvrf->vni_table, (void (*)(struct hash_backet *,
+                                               void *))zvni_print_hash_detail,
+                    &zes);
+
+       /* Display all L3-VNIs */
+       hash_iterate(zrouter.l3vni_table,
+                    (void (*)(struct hash_backet *,
+                              void *))zl3vni_print_hash_detail,
+                    &zes);
+
+       if (use_json) {
+               vty_out(vty, "%s\n", json_object_to_json_string_ext(
+                                            json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+}
+
 /*
  * Handle neighbor delete notification from the kernel (on a VLAN device
  * / L3 interface). This may result in either the neighbor getting deleted
@@ -7032,11 +7412,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
        bool mac_sticky = false;
        bool inform_client = false;
        bool upd_neigh = false;
-       zebra_neigh_t *n = NULL;
-       struct listnode *node = NULL;
        struct in_addr vtep_ip = {.s_addr = 0};
-       struct timeval elapsed = {0, 0};
-       char buf2[INET6_ADDRSTRLEN];
 
        /* We are interested in MACs only on ports or (port, VLAN) that
         * map to a VNI.
@@ -7181,136 +7557,13 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
                        inform_client = true;
                        upd_neigh = true;
 
-                       if (zvrf->dup_addr_detect && do_dad) {
-                               /* MAC is detected as duplicate, hold on
-                                * advertising to BGP.
-                                */
-                               if (CHECK_FLAG(mac->flags,
-                                              ZEBRA_MAC_DUPLICATE)) {
-                                       if (IS_ZEBRA_DEBUG_VXLAN)
-                                               zlog_debug(
-                                                          "%s: duplicate addr MAC %s skip update to client, learn count %u recover time %u",
-                                                          __PRETTY_FUNCTION__,
-                                                       prefix_mac2str(macaddr,
-                                                       buf, sizeof(buf)),
-                                                       mac->dad_count,
-                                                       zvrf->dad_freeze_time);
-                                       /* For duplicate MAC do not update
-                                        * client but update neigh due to
-                                        * this MAC update.
-                                        */
-                                       if (zvrf->dad_freeze)
-                                               inform_client = false;
-
-                                       goto send_notif;
-                               }
-
-                               /* Check if detection time (M-secs) expired.
-                                * Reset learn count and detection start time.
-                                */
-                               monotime_since(&mac->detect_start_time,
-                                              &elapsed);
-                               if (mac->dad_count == 0 ||
-                                   elapsed.tv_sec >= zvrf->dad_time) {
-
-                                       if (IS_ZEBRA_DEBUG_VXLAN)
-                                               zlog_debug("%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u",
-                                                  __PRETTY_FUNCTION__,
-                                                  prefix_mac2str(
-                                                       macaddr, buf,
-                                                       sizeof(buf)),
-                                                  mac->flags,
-                                                  mac->dad_count);
-
-                                       mac->dad_count = 0;
-                                       /* Capture start dup. detection time */
-                                       monotime(&mac->detect_start_time);
-                               }
-
-                               /* Increment move count */
-                               mac->dad_count++;
-
-                               if (mac->dad_count >= zvrf->dad_max_moves) {
-                                       flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
-                                                 "VNI %u: MAC %s detected as duplicate during local update, last VTEP %s",
-                                                 zvni->vni,
-                                                 prefix_mac2str(&mac->macaddr,
-                                                       buf, sizeof(buf)),
-                                                 inet_ntoa(vtep_ip));
-
-                                       SET_FLAG(mac->flags,
-                                                ZEBRA_MAC_DUPLICATE);
-
-                                       /* Capture Duplicate detection time */
-                                       mac->dad_dup_detect_time =
-                                               monotime(NULL);
-
-                                       /* Mark all IPs/Neighs as duplicate
-                                        * associcated with this MAC
-                                        */
-                                       for (ALL_LIST_ELEMENTS_RO(
-                                                       mac->neigh_list,
-                                                       node, n)) {
-
-                                               /* Ony Mark IPs which are Local
-                                                */
-                                               if (!CHECK_FLAG(n->flags,
-                                                       ZEBRA_NEIGH_LOCAL))
-                                                       continue;
-
-                                               SET_FLAG(n->flags,
-                                                        ZEBRA_NEIGH_DUPLICATE);
-
-                                               n->dad_dup_detect_time =
-                                                       monotime(NULL);
-
-                                               flog_warn(
-                                               EC_ZEBRA_DUP_IP_INHERIT_DETECTED
-                                               ,
-                                                 "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
-                                                 zvni->vni,
-                                                 prefix_mac2str(&mac->macaddr,
-                                                       buf, sizeof(buf)),
-                                                 ipaddr2str(&n->ip, buf2,
-                                                            sizeof(buf2)));
-                                       }
-
-                                       /* Start auto recovery timer for this
-                                        * MAC
-                                        */
-                                       THREAD_OFF(
-                                       mac->dad_mac_auto_recovery_timer);
-                                       if (zvrf->dad_freeze &&
-                                           zvrf->dad_freeze_time) {
-                                               if (IS_ZEBRA_DEBUG_VXLAN)
-                                                       zlog_debug("%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start",
-                                                       __PRETTY_FUNCTION__,
-                                                       prefix_mac2str(
-                                                               &mac->macaddr,
-                                                               buf,
-                                                               sizeof(buf)),
-                                                       mac->flags,
-                                                       zvrf->dad_freeze_time);
-
-                                               thread_add_timer(zebrad.master,
-                                               zebra_vxlan_dad_mac_auto_recovery_exp,
-                                               mac,
-                                               zvrf->dad_freeze_time,
-                                               &mac->dad_mac_auto_recovery_timer);
-                                       }
-
-                                       /* Do not inform to client (BGPd),
-                                        * upd_neigh for neigh sequence change.
-                                        */
-                                       if (zvrf->dad_freeze)
-                                               inform_client = false;
-                               }
-                       }
+                       zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac, vtep_ip,
+                                                           do_dad,
+                                                           &inform_client,
+                                                           true);
                }
        }
 
-send_notif:
-
        /* Inform BGP if required. */
        if (inform_client) {
                if (zvni_mac_send_add_to_client(zvni->vni, macaddr,
@@ -8142,7 +8395,7 @@ int zebra_vxlan_if_add(struct interface *ifp)
                                "Add L2-VNI %u VRF %s intf %s(%u) VLAN %u local IP %s master %u",
                                vni,
                                vlan_if ? vrf_id_to_name(vlan_if->vrf_id)
-                                       : "Default",
+                                       : VRF_DEFAULT_NAME,
                                ifp->name, ifp->ifindex, vxl->access_vlan,
                                inet_ntoa(vxl->vtep_ip),
                                zif->brslave_info.bridge_ifindex);
@@ -8611,14 +8864,14 @@ void zebra_vxlan_close_tables(struct zebra_vrf *zvrf)
 }
 
 /* init the l3vni table */
-void zebra_vxlan_ns_init(struct zebra_ns *zns)
+void zebra_vxlan_init(void)
 {
        zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp,
                                          "Zebra VRF L3 VNI table");
 }
 
 /* free l3vni table */
-void zebra_vxlan_ns_disable(struct zebra_ns *zns)
+void zebra_vxlan_disable(void)
 {
        hash_free(zrouter.l3vni_table);
 }