]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_vxlan.c
Merge pull request #3851 from donaldsharp/bgp_routemap_fix
[mirror_frr.git] / zebra / zebra_vxlan.c
index b55ca60c00270b08f325c7fbf812051286413348..560cd89abd781dde7fbaa1d3890d6855c232df92 100644 (file)
@@ -50,7 +50,7 @@
 #include "zebra/zebra_vrf.h"
 #include "zebra/zebra_vxlan.h"
 #include "zebra/zebra_vxlan_private.h"
-#include "zebra/zserv.h"
+#include "zebra/zebra_router.h"
 
 DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix");
 DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash");
@@ -81,7 +81,7 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[]);
 
 static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
                                         struct ipaddr *ip, uint8_t flags,
-                                        uint32_t seq, uint16_t cmd);
+                                        uint32_t seq, int state, uint16_t cmd);
 static unsigned int neigh_hash_keymake(void *p);
 static void *zvni_neigh_alloc(void *p);
 static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
@@ -97,9 +97,10 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
                                         uint8_t flags, uint32_t seq);
 static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
                                         struct ethaddr *macaddr,
-                                        uint8_t flags);
+                                        uint8_t flags, int state);
 static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
 static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
+static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n);
 static zebra_vni_t *zvni_from_svi(struct interface *ifp,
                                  struct interface *br_if);
 static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if);
@@ -163,7 +164,7 @@ static zebra_vni_t *zvni_add(vni_t vni);
 static int zvni_del(zebra_vni_t *zvni);
 static int zvni_send_add_to_client(zebra_vni_t *zvni);
 static int zvni_send_del_to_client(vni_t vni);
-static void zvni_build_hash_table();
+static void zvni_build_hash_table(void);
 static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep);
 static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip);
 static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip);
@@ -179,6 +180,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
                             struct ipaddr *ip);
 struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp);
 static int advertise_gw_macip_enabled(zebra_vni_t *zvni);
+static int advertise_svi_macip_enabled(zebra_vni_t *zvni);
 static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf,
                                               zebra_mac_t *old_zmac,
                                               zebra_mac_t *new_zmac,
@@ -332,6 +334,20 @@ static int advertise_gw_macip_enabled(zebra_vni_t *zvni)
        return 0;
 }
 
+static int advertise_svi_macip_enabled(zebra_vni_t *zvni)
+{
+       struct zebra_vrf *zvrf;
+
+       zvrf = vrf_info_lookup(VRF_DEFAULT);
+       if (zvrf && zvrf->advertise_svi_macip)
+               return 1;
+
+       if (zvni && zvni->advertise_svi_macip)
+               return 1;
+
+       return 0;
+}
+
 /* As part Duplicate Address Detection (DAD) for IP mobility
  * MAC binding changes, ensure to inherit duplicate flag
  * from MAC.
@@ -510,7 +526,7 @@ static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
                                                       sizeof(buf)),
                                        mac->flags, zvrf->dad_freeze_time);
 
-                       thread_add_timer(zebrad.master,
+                       thread_add_timer(zrouter.master,
                                         zebra_vxlan_dad_mac_auto_recovery_exp,
                                         mac, zvrf->dad_freeze_time,
                                         &mac->dad_mac_auto_recovery_timer);
@@ -556,6 +572,7 @@ static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
 
                if (zvrf->dad_freeze)
                        *is_dup_detect = true;
+
                /* warn-only action, neigh will be installed.
                 * freeze action, it wil not be installed.
                 */
@@ -642,7 +659,7 @@ static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf,
                                   ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
                                   nbr->flags, zvrf->dad_freeze_time);
 
-                       thread_add_timer(zebrad.master,
+                       thread_add_timer(zrouter.master,
                                zebra_vxlan_dad_ip_auto_recovery_exp,
                                nbr, zvrf->dad_freeze_time,
                                &nbr->dad_ip_auto_recovery_timer);
@@ -687,10 +704,11 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
        struct zebra_vrf *zvrf = NULL;
        struct timeval detect_start_time = {0, 0};
 
-       zvrf = zebra_vrf_lookup_by_id(n->zvni->vrf_id);
+       zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
        if (!zvrf)
                return;
 
+       zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
        ipaddr2str(&n->ip, buf2, sizeof(buf2));
        prefix_mac2str(&n->emac, buf1, sizeof(buf1));
        type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ?
@@ -1135,7 +1153,7 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
        struct zebra_vrf *zvrf;
        struct timeval detect_start_time = {0, 0};
 
-       zvrf = zebra_vrf_lookup_by_id(mac->zvni->vrf_id);
+       zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
 
        vty = (struct vty *)ctxt;
        prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1));
@@ -2045,7 +2063,7 @@ static void zvni_print_hash_detail(struct hash_backet *backet, void *data)
  */
 static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
                                         struct ipaddr *ip, uint8_t flags,
-                                        uint32_t seq, uint16_t cmd)
+                                        uint32_t seq, int state, uint16_t cmd)
 {
        char buf[ETHER_ADDR_STRLEN];
        char buf2[INET6_ADDRSTRLEN];
@@ -2079,6 +2097,8 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
        if (cmd == ZEBRA_MACIP_ADD) {
                stream_putc(s, flags); /* sticky mac/gateway mac */
                stream_putl(s, seq); /* sequence number */
+       } else {
+               stream_putl(s, state); /* state - active/inactive */
        }
 
 
@@ -2217,7 +2237,7 @@ static void zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg)
                && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
                if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
                        zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip,
-                                                     &n->emac, 0);
+                                                     &n->emac, 0, n->state);
 
                if (wctx->uninstall)
                        zvni_neigh_uninstall(wctx->zvni, n);
@@ -2296,7 +2316,7 @@ static void zvni_process_neigh_on_local_mac_change(zebra_vni_t *zvni,
        struct zebra_vrf *zvrf = NULL;
        char buf[ETHER_ADDR_STRLEN];
 
-       zvrf = vrf_info_lookup(zvni->vrf_id);
+       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
 
        if (IS_ZEBRA_DEBUG_VXLAN)
                zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
@@ -2353,7 +2373,7 @@ static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni,
                                ZEBRA_NEIGH_SET_INACTIVE(n);
                                n->loc_seq = 0;
                                zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
-                                                             &n->emac, 0);
+                                     &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
                        }
                }
        }
@@ -2384,7 +2404,7 @@ static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni,
                                ZEBRA_NEIGH_SET_INACTIVE(n);
                                n->loc_seq = 0;
                                zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
-                                                             &n->emac, 0);
+                                             &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
                        }
                }
        }
@@ -2400,6 +2420,18 @@ static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni,
        /* NOTE: Currently a NO-OP. */
 }
 
+static void zvni_probe_neigh_on_mac_add(zebra_vni_t *zvni, zebra_mac_t *zmac)
+{
+       zebra_neigh_t *nbr = NULL;
+       struct listnode *node = NULL;
+
+       for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, nbr)) {
+               if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL) &&
+                   IS_ZEBRA_NEIGH_INACTIVE(nbr))
+                       zvni_neigh_probe(zvni, nbr);
+       }
+}
+
 /*
  * Inform BGP about local neighbor addition.
  */
@@ -2417,17 +2449,18 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
                SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
 
        return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
-                                            seq, ZEBRA_MACIP_ADD);
+                            seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
 }
 
 /*
  * Inform BGP about local neighbor deletion.
  */
 static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
-                                        struct ethaddr *macaddr, uint8_t flags)
+                                        struct ethaddr *macaddr, uint8_t flags,
+                                        int state)
 {
        return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
-                                            0, ZEBRA_MACIP_DEL);
+                                            0, state, ZEBRA_MACIP_DEL);
 }
 
 /*
@@ -2495,6 +2528,32 @@ static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n)
        return kernel_del_neigh(vlan_if, &n->ip);
 }
 
+/*
+ * Probe neighbor from the kernel.
+ */
+static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n)
+{
+       struct zebra_if *zif;
+       struct zebra_l2info_vxlan *vxl;
+       struct interface *vlan_if;
+
+       zif = zvni->vxlan_if->info;
+       if (!zif)
+               return -1;
+       vxl = &zif->l2info.vxl;
+
+       vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
+       if (!vlan_if)
+               return -1;
+
+#ifdef GNU_LINUX
+       return kernel_upd_neigh(vlan_if, &n->ip, &n->emac,
+                               0, NUD_PROBE);
+#else
+       return 0;
+#endif
+}
+
 /*
  * Install neighbor hash entry - called upon access VLAN change.
  */
@@ -2748,7 +2807,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
 
        /* Remove neighbor from BGP. */
        zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
-                                     ZEBRA_MACIP_TYPE_GW);
+                                     ZEBRA_MACIP_TYPE_GW, ZEBRA_NEIGH_ACTIVE);
 
        /* Delete this neighbor entry. */
        zvni_neigh_del(zvni, n);
@@ -2830,10 +2889,48 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
        /* Add primary SVI MAC-IP */
        zvni_add_macip_for_intf(vlan_if, zvni);
 
-       /* Add VRR MAC-IP - if any*/
-       vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
-       if (vrr_if)
-               zvni_add_macip_for_intf(vrr_if, zvni);
+       if (advertise_gw_macip_enabled(zvni)) {
+               /* Add VRR MAC-IP - if any*/
+               vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
+               if (vrr_if)
+                       zvni_add_macip_for_intf(vrr_if, zvni);
+       }
+
+       return;
+}
+
+static void zvni_svi_macip_del_for_vni_hash(struct hash_backet *backet,
+                                          void *ctxt)
+{
+       zebra_vni_t *zvni = NULL;
+       struct zebra_if *zif = NULL;
+       struct zebra_l2info_vxlan zl2_info;
+       struct interface *vlan_if = NULL;
+       struct interface *ifp;
+
+       /* Add primary SVI MAC*/
+       zvni = (zebra_vni_t *)backet->data;
+       if (!zvni)
+               return;
+
+       ifp = zvni->vxlan_if;
+       if (!ifp)
+               return;
+       zif = ifp->info;
+
+       /* If down or not mapped to a bridge, we're done. */
+       if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+               return;
+
+       zl2_info = zif->l2info.vxl;
+
+       vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
+                                 zif->brslave_info.br_if);
+       if (!vlan_if)
+               return;
+
+       /* Del primary MAC-IP */
+       zvni_del_macip_for_intf(vlan_if, zvni);
 
        return;
 }
@@ -2891,7 +2988,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                }
        }
 
-       zvrf = vrf_info_lookup(zvni->vrf_id);
+       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
        if (!zvrf)
                return -1;
 
@@ -2962,7 +3059,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
                         */
                        if (IS_ZEBRA_NEIGH_ACTIVE(n))
                                zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
-                                                             &n->emac, 0);
+                                             &n->emac, 0, n->state);
                        old_zmac = zvni_mac_lookup(zvni, &n->emac);
                        if (old_zmac) {
                                old_mac_seq = CHECK_FLAG(old_zmac->flags,
@@ -3318,7 +3415,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
                SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
 
        return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
-                                            seq, ZEBRA_MACIP_ADD);
+                            seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
 }
 
 /*
@@ -3327,7 +3424,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
 static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr)
 {
        return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */,
-                                            0 /* seq */, ZEBRA_MACIP_DEL);
+                            0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL);
 }
 
 /*
@@ -3840,7 +3937,7 @@ static int zvni_send_del_to_client(vni_t vni)
  * Build the VNI hash table by going over the VxLAN interfaces. This
  * is called when EVPN (advertise-all-vni) is enabled.
  */
-static void zvni_build_hash_table()
+static void zvni_build_hash_table(void)
 {
        struct zebra_ns *zns;
        struct route_node *rn;
@@ -5139,11 +5236,15 @@ static void process_remote_macip_add(vni_t vni,
                 * RFC-7432: A PE/VTEP that detects a MAC mobility
                 * event via local learning starts an M-second timer.
                 *
-                * VTEP-IP or seq. change along is not considered
+                * VTEP-IP or seq. change alone is not considered
                 * for dup. detection.
+                *
+                * MAC is already marked duplicate set dad, then
+                * is_dup_detect will be set to not install the entry.
                 */
-               if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) &&
-                   mac->dad_count)
+               if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) &&
+                   mac->dad_count) ||
+                   CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
                        do_dad = true;
 
                /* Remove local MAC from BGP. */
@@ -5254,7 +5355,7 @@ static void process_remote_macip_add(vni_t vni,
                                    IS_ZEBRA_NEIGH_ACTIVE(n))
                                        zvni_neigh_send_del_to_client(
                                                zvni->vni, &n->ip,
-                                               &n->emac, 0);
+                                               &n->emac, 0, n->state);
 
                                /* update neigh list for macs */
                                old_mac = zvni_mac_lookup(zvni, &n->emac);
@@ -5320,6 +5421,8 @@ static void process_remote_macip_add(vni_t vni,
                        zvni_neigh_install(zvni, n);
        }
 
+       zvni_probe_neigh_on_mac_add(zvni, mac);
+
        /* Update seq number. */
        n->rem_seq = seq;
 }
@@ -5336,6 +5439,9 @@ static void process_remote_macip_del(vni_t vni,
        zebra_neigh_t *n = NULL;
        struct interface *ifp = NULL;
        struct zebra_if *zif = NULL;
+       struct zebra_ns *zns;
+       struct zebra_l2info_vxlan *vxl;
+       struct zebra_vrf *zvrf;
        char buf[ETHER_ADDR_STRLEN];
        char buf1[INET6_ADDRSTRLEN];
 
@@ -5359,6 +5465,8 @@ static void process_remote_macip_del(vni_t vni,
                                   vni);
                return;
        }
+       zns = zebra_ns_lookup(NS_DEFAULT);
+       vxl = &zif->l2info.vxl;
 
        /* The remote VTEP specified is normally expected to exist, but
         * it is possible that the peer may delete the VTEP before deleting
@@ -5385,9 +5493,10 @@ static void process_remote_macip_del(vni_t vni,
        if (!mac && !n)
                return;
 
+       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+
        /* Ignore the delete if this mac is a gateway mac-ip */
-       if (mac
-           && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
+       if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
            && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
                zlog_warn(
                        "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
@@ -5401,6 +5510,23 @@ static void process_remote_macip_del(vni_t vni,
 
        /* Uninstall remote neighbor or MAC. */
        if (n) {
+               if (zvrf->dad_freeze &&
+                   CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE) &&
+                   CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) &&
+                   (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) {
+                       struct interface *vlan_if;
+
+                       vlan_if = zvni_map_to_svi(vxl->access_vlan,
+                                       zif->brslave_info.br_if);
+                       if (IS_ZEBRA_DEBUG_VXLAN)
+                               zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
+                                          __PRETTY_FUNCTION__,
+                                          ipaddr2str(ipaddr, buf1,
+                                                     sizeof(buf1)), n->flags,
+                                          vlan_if->name);
+                       neigh_read_specific_ip(ipaddr, vlan_if);
+               }
+
                /* When the MAC changes for an IP, it is possible the
                 * client may update the new MAC before trying to delete the
                 * "old" neighbor (as these are two different MACIP routes).
@@ -5413,6 +5539,25 @@ static void process_remote_macip_del(vni_t vni,
                        zvni_deref_ip2mac(zvni, mac);
                }
        } else {
+               /* DAD: when MAC is freeze state as remote learn event,
+                * remote mac-ip delete event is received will result in freeze
+                * entry removal, first fetch kernel for the same entry present
+                * as LOCAL and reachable, avoid deleting this entry instead
+                * use kerenel local entry to update during unfreeze time.
+                */
+               if (zvrf->dad_freeze &&
+                   CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) &&
+                   CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
+                       if (IS_ZEBRA_DEBUG_VXLAN)
+                               zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
+                                          __PRETTY_FUNCTION__,
+                                          prefix_mac2str(macaddr, buf,
+                                                         sizeof(buf)),
+                                          mac->flags);
+                       macfdb_read_specific_mac(zns, zif->brslave_info.br_if,
+                                                macaddr, vxl->access_vlan);
+               }
+
                if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
                        zvni_process_neigh_on_remote_mac_del(zvni, mac);
                        /*
@@ -6817,6 +6962,8 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
                vty_out(vty, "L3 VNIs: %u\n", num_l3vnis);
                vty_out(vty, "Advertise gateway mac-ip: %s\n",
                        zvrf->advertise_gw_macip ? "Yes" : "No");
+               vty_out(vty, "Advertise svi mac-ip: %s\n",
+                       zvrf->advertise_svi_macip ? "Yes" : "No");
                vty_out(vty, "Duplicate address detection: %s\n",
                        zvrf->dup_addr_detect ? "Enable" : "Disable");
                vty_out(vty, "  Detection max-moves %u, time %d\n",
@@ -6907,8 +7054,8 @@ void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
 
        if (IS_ZEBRA_DEBUG_VXLAN)
                zlog_debug(
-                       "%s: duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
-                       __PRETTY_FUNCTION__,
+                       "VRF %s duplicate detect %s max_moves %u timeout %u freeze %s freeze_time %u",
+                       vrf_id_to_name(zvrf->vrf->vrf_id),
                        zvrf->dup_addr_detect ? "enable" : "disable",
                        zvrf->dad_max_moves,
                        zvrf->dad_time,
@@ -6978,6 +7125,7 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
        zebra_vni_t *zvni = NULL;
        zebra_mac_t *zmac = NULL;
        zebra_l3vni_t *zl3vni = NULL;
+       struct zebra_vrf *zvrf;
 
        /* check if this is a remote neigh entry corresponding to remote
         * next-hop
@@ -7030,9 +7178,23 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
                return 0;
        }
 
+       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+       if (!zvrf) {
+               zlog_debug("%s: VNI %u vrf lookup failed.",
+                                  __PRETTY_FUNCTION__, zvni->vni);
+               return -1;
+       }
+
+       /* In case of feeze action, if local neigh is in duplicate state,
+        * Mark the Neigh as inactive before sending delete request to BGPd,
+        * If BGPd has remote entry, it will re-install
+        */
+       if (zvrf->dad_freeze &&
+           CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE))
+           ZEBRA_NEIGH_SET_INACTIVE(n);
+
        /* Remove neighbor from BGP. */
-       if (IS_ZEBRA_NEIGH_ACTIVE(n))
-               zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0);
+       zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0, n->state);
 
        /* Delete this neighbor entry. */
        zvni_neigh_del(zvni, n);
@@ -8604,6 +8766,102 @@ stream_failure:
        return;
 }
 
+/*
+ * Handle message from client to enable/disable advertisement of svi macip
+ * routes
+ */
+void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       int advertise;
+       vni_t vni = 0;
+       zebra_vni_t *zvni = NULL;
+       struct interface *ifp = NULL;
+
+       if (zvrf_id(zvrf) != VRF_DEFAULT) {
+               zlog_debug("EVPN GW-MACIP Adv for non-default VRF %u",
+                          zvrf_id(zvrf));
+               return;
+       }
+
+       s = msg;
+       STREAM_GETC(s, advertise);
+       STREAM_GETL(s, vni);
+
+       if (!vni) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("EVPN gateway macip Adv %s, currently %s",
+                                  advertise ? "enabled" : "disabled",
+                                  advertise_gw_macip_enabled(NULL)
+                                          ? "enabled"
+                                          : "disabled");
+
+               if (zvrf->advertise_svi_macip == advertise)
+                       return;
+
+
+               if (advertise) {
+                       zvrf->advertise_svi_macip = advertise;
+                       hash_iterate(zvrf->vni_table,
+                                    zvni_gw_macip_add_for_vni_hash, NULL);
+               } else {
+                       hash_iterate(zvrf->vni_table,
+                                    zvni_svi_macip_del_for_vni_hash, NULL);
+                       zvrf->advertise_svi_macip = advertise;
+               }
+
+       } else {
+               struct zebra_if *zif = NULL;
+               struct zebra_l2info_vxlan zl2_info;
+               struct interface *vlan_if = NULL;
+
+               zvni = zvni_lookup(vni);
+               if (!zvni)
+                       return;
+
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug(
+                               "EVPN SVI macip Adv %s on VNI %d , currently %s",
+                               advertise ? "enabled" : "disabled", vni,
+                               advertise_svi_macip_enabled(zvni)
+                                       ? "enabled"
+                                       : "disabled");
+
+               if (zvni->advertise_svi_macip == advertise)
+                       return;
+
+               ifp = zvni->vxlan_if;
+               if (!ifp)
+                       return;
+
+               zif = ifp->info;
+
+               /* If down or not mapped to a bridge, we're done. */
+               if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+                       return;
+
+               zl2_info = zif->l2info.vxl;
+
+               vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
+                                         zif->brslave_info.br_if);
+               if (!vlan_if)
+                       return;
+
+               if (advertise) {
+                       zvni->advertise_svi_macip = advertise;
+                       /* Add primary SVI MAC-IP */
+                       zvni_add_macip_for_intf(vlan_if, zvni);
+               } else {
+                       /* Del primary MAC-IP */
+                       zvni_del_macip_for_intf(vlan_if, zvni);
+                       zvni->advertise_svi_macip = advertise;
+               }
+       }
+
+stream_failure:
+       return;
+}
+
 /*
  * Handle message from client to enable/disable advertisement of g/w macip
  * routes
@@ -8904,16 +9162,16 @@ static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t)
        nbr = THREAD_ARG(t);
 
        /* since this is asynchronous we need sanity checks*/
-       zvrf = vrf_info_lookup(nbr->zvni->vrf_id);
-       if (!zvrf)
+       nbr = zvni_neigh_lookup(zvni, &nbr->ip);
+       if (!nbr)
                return 0;
 
        zvni = zvni_lookup(nbr->zvni->vni);
        if (!zvni)
                return 0;
 
-       nbr = zvni_neigh_lookup(zvni, &nbr->ip);
-       if (!nbr)
+       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+       if (!zvrf)
                return 0;
 
        if (IS_ZEBRA_DEBUG_VXLAN)
@@ -8954,16 +9212,16 @@ static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t)
        mac = THREAD_ARG(t);
 
        /* since this is asynchronous we need sanity checks*/
-       zvrf = vrf_info_lookup(mac->zvni->vrf_id);
-       if (!zvrf)
+       mac = zvni_mac_lookup(zvni, &mac->macaddr);
+       if (!mac)
                return 0;
 
        zvni = zvni_lookup(mac->zvni->vni);
        if (!zvni)
                return 0;
 
-       mac = zvni_mac_lookup(zvni, &mac->macaddr);
-       if (!mac)
+       zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+       if (!zvrf)
                return 0;
 
        if (IS_ZEBRA_DEBUG_VXLAN)