diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
index 5aebbfc..77d28ac 100644
--- a/ovn/controller/pinctrl.c
+++ b/ovn/controller/pinctrl.c
@@ -67,6 +67,13 @@ static void destroy_buffered_packets_map(void);
 static void pinctrl_handle_put_mac_binding(const struct flow *md,
                                            const struct flow *headers,
                                            bool is_arp);
+static bool
+pinctrl_is_chassis_resident(struct ovsdb_idl_index *sbrec_chassis_by_name,
+                            struct ovsdb_idl_index *sbrec_port_binding_by_name,
+                            const struct sbrec_chassis *chassis,
+                            const struct sset *active_tunnels,
+                            const char *port_name);
+
 static void init_put_mac_bindings(void);
 static void destroy_put_mac_bindings(void);
 static void run_put_mac_bindings(
@@ -114,6 +121,8 @@ static void send_ipv6_ras(
 COVERAGE_DEFINE(pinctrl_drop_put_mac_binding);
 COVERAGE_DEFINE(pinctrl_drop_buffered_packets_map);
 
+#define GARP_DEF_REPEAT_INTERVAL_MS   (3 * 60 * 1000) // 3 mins
+
 void
 pinctrl_init(void)
 {
@@ -2089,6 +2098,8 @@ struct garp_data {
     int backoff;                 /* Backoff for the next announcement. */
     uint32_t dp_key;             /* Datapath used to output this GARP. */
     uint32_t port_key;           /* Port to inject the GARP into. */
+    bool is_repeat;              /* Send GARPs continously */
+    long long int repeat_interval; /* Interval between GARP bursts in ms */
 };
 
 /* Contains GARPs to be sent. */
@@ -2112,7 +2123,8 @@ destroy_send_garps(void)
 
 static void
 add_garp(const char *name, const struct eth_addr ea, ovs_be32 ip,
-         uint32_t dp_key, uint32_t port_key)
+         uint32_t dp_key, uint32_t port_key, bool is_repeat,
+         long long int repeat_interval)
 {
     struct garp_data *garp = xmalloc(sizeof *garp);
     garp->ea = ea;
@@ -2121,15 +2133,19 @@ add_garp(const char *name, const struct eth_addr ea, ovs_be32 ip,
     garp->backoff = 1;
     garp->dp_key = dp_key;
     garp->port_key = port_key;
+    garp->is_repeat = is_repeat;
+    garp->repeat_interval = repeat_interval;
     shash_add(&send_garp_data, name, garp);
 }
 
 /* Add or update a vif for which GARPs need to be announced. */
 static void
-send_garp_update(const struct sbrec_port_binding *binding_rec,
+send_garp_update(struct ovsdb_idl_index *sbrec_port_binding_by_name,
+                 const struct sbrec_port_binding *binding_rec,
                  struct shash *nat_addresses)
 {
     volatile struct garp_data *garp = NULL;
+
     /* Update GARP for NAT IP if it exists.  Consider port bindings with type
      * "l3gateway" for logical switch ports attached to gateway routers, and
      * port bindings with type "patch" for logical switch ports attached to
@@ -2151,7 +2167,7 @@ send_garp_update(const struct sbrec_port_binding *binding_rec,
                     add_garp(name, laddrs->ea,
                              laddrs->ipv4_addrs[i].addr,
                              binding_rec->datapath->tunnel_key,
-                             binding_rec->tunnel_key);
+                             binding_rec->tunnel_key, false, 0);
                 }
                 free(name);
             }
@@ -2161,6 +2177,60 @@ send_garp_update(const struct sbrec_port_binding *binding_rec,
         return;
     }
 
+    /* Update GARPs for local chassisredirect port, if the peer
+     * layer 2 switch is of type vlan.
+     */
+    if (!strcmp(binding_rec->type, "chassisredirect")) {
+       struct eth_addr mac;
+       ovs_be32 ip, mask;
+       uint32_t dp_key = 0;
+       uint32_t port_key = 0;
+       const struct sbrec_port_binding *peer_port = NULL;
+       const struct sbrec_port_binding *distributed_port = NULL;
+
+       if (!ovn_sbrec_get_port_binding_ip_mac(binding_rec, &mac,
+                                              &ip, &mask)) {
+          // Router Port binding without ip and mac configured.
+          static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+          VLOG_WARN_RL(&rl, "cannot send garp, router port binding: %s, "
+                       "does not have proper ip,mac values: %s",
+                       binding_rec->logical_port, *binding_rec->mac);
+          return;
+       }
+
+       const char *lrp_name = smap_get(&binding_rec->options, "distributed-port");
+       ovs_assert(lrp_name);
+
+       distributed_port = lport_lookup_by_name(sbrec_port_binding_by_name, lrp_name);
+       ovs_assert(distributed_port);
+
+       const char *peer_name = smap_get(&distributed_port->options, "peer");
+       ovs_assert(peer_name);
+
+       peer_port = lport_lookup_by_name(sbrec_port_binding_by_name, peer_name);
+       ovs_assert(peer_port);
+
+       const char *network_type = smap_get(&peer_port->datapath->external_ids, "network-type");
+
+       // Advertise GARP only of logical switch is of type vlan.
+       if (!network_type || strcmp(network_type, "vlan")) {
+          return;
+       }
+
+       dp_key = peer_port->datapath->tunnel_key;
+       port_key = peer_port->tunnel_key;
+
+       garp = shash_find_data(&send_garp_data, binding_rec->logical_port);
+       if (garp) {
+          garp->dp_key = dp_key;
+          garp->port_key = port_key;
+       } else {
+          add_garp(binding_rec->logical_port, mac, ip,
+                   dp_key, port_key, true, GARP_DEF_REPEAT_INTERVAL_MS);
+       }
+       return;
+    }
+
     /* Update GARP for vif if it exists. */
     garp = shash_find_data(&send_garp_data, binding_rec->logical_port);
     if (garp) {
@@ -2180,7 +2250,8 @@ send_garp_update(const struct sbrec_port_binding *binding_rec,
 
         add_garp(binding_rec->logical_port,
                  laddrs.ea, laddrs.ipv4_addrs[0].addr,
-                 binding_rec->datapath->tunnel_key, binding_rec->tunnel_key);
+                 binding_rec->datapath->tunnel_key, binding_rec->tunnel_key,
+                 false, 0);
 
         destroy_lport_addresses(&laddrs);
         break;
@@ -2238,7 +2309,13 @@ send_garp(struct garp_data *garp, long long int current_time)
         garp->backoff *= 2;
         garp->announce_time = current_time + garp->backoff * 1000;
     } else {
-        garp->announce_time = LLONG_MAX;
+       if (garp->is_repeat) {
+          garp->backoff = 1;
+          garp->announce_time = current_time + garp->repeat_interval;
+
+       } else {
+          garp->announce_time = LLONG_MAX;
+       }
     }
     return garp->announce_time;
 }
@@ -2492,6 +2569,65 @@ get_nat_addresses_and_keys(struct ovsdb_idl_index *sbrec_chassis_by_name,
 }
 
 static void
+get_local_cr_ports(struct ovsdb_idl_index *sbrec_chassis_by_name,
+                   struct ovsdb_idl_index *sbrec_port_binding_by_name,
+                   struct sset *local_cr_ports,
+                   struct sset *local_l3gw_ports,
+                   const struct sbrec_chassis *chassis,
+                   const struct sset *active_tunnels)
+{
+   const char *gw_port;
+   SSET_FOR_EACH(gw_port, local_l3gw_ports) {
+      const struct sbrec_port_binding *binding_rec;
+
+      binding_rec = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port);
+      if (!binding_rec) {
+         continue;
+      }
+
+      /* For the patch port we will add send garp for peer's ip and mac. */
+      if (!strcmp(binding_rec->type, "patch")) {
+         const struct sbrec_port_binding *cr_port = NULL;
+
+         bool is_cr_resident;
+         struct eth_addr mac;
+         ovs_be32 ip, mask;
+
+         const char *peer_name = smap_get(&binding_rec->options, "peer");
+         ovs_assert(peer_name);
+
+         char *cr_peer_name = xasprintf("cr-%s", peer_name);
+         cr_port = lport_lookup_by_name(sbrec_port_binding_by_name, cr_peer_name);
+         free(cr_peer_name);
+
+         if (!cr_port) {
+            continue;
+         }
+
+         is_cr_resident = pinctrl_is_chassis_resident(sbrec_chassis_by_name,
+                                                      sbrec_port_binding_by_name,
+                                                      chassis,
+                                                      active_tunnels,
+                                                      cr_port->logical_port);
+         if (!is_cr_resident) {
+            continue;
+         }
+
+         if (!ovn_sbrec_get_port_binding_ip_mac(cr_port, &mac, &ip, &mask)) {
+            // Router Port binding without ip and mac configured.
+            static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
+            VLOG_WARN_RL(&rl, "cannot send garp, router port binding: %s, "
+                         "does not have proper ip,mac values: %s",
+                         cr_port->logical_port, *cr_port->mac);
+            return;
+         }
+
+         sset_add(local_cr_ports, cr_port->logical_port);
+      }
+   }
+}
+
+static void
 send_garp_wait(void)
 {
     poll_timer_wait_until(send_garp_time);
@@ -2508,6 +2644,8 @@ send_garp_run(struct ovsdb_idl_index *sbrec_chassis_by_name,
 {
     struct sset localnet_vifs = SSET_INITIALIZER(&localnet_vifs);
     struct sset local_l3gw_ports = SSET_INITIALIZER(&local_l3gw_ports);
+    struct sset local_cr_ports = SSET_INITIALIZER(&local_cr_ports);
+
     struct sset nat_ip_keys = SSET_INITIALIZER(&nat_ip_keys);
     struct shash nat_addresses;
 
@@ -2523,12 +2661,19 @@ send_garp_run(struct ovsdb_idl_index *sbrec_chassis_by_name,
                                &nat_ip_keys, &local_l3gw_ports,
                                chassis, active_tunnels,
                                &nat_addresses);
+
+    get_local_cr_ports(sbrec_chassis_by_name,
+                       sbrec_port_binding_by_name,
+                       &local_cr_ports, &local_l3gw_ports,
+                       chassis, active_tunnels);
+
     /* For deleted ports and deleted nat ips, remove from send_garp_data. */
     struct shash_node *iter, *next;
     SHASH_FOR_EACH_SAFE (iter, next, &send_garp_data) {
         if (!sset_contains(&localnet_vifs, iter->name) &&
-            !sset_contains(&nat_ip_keys, iter->name)) {
-            send_garp_delete(iter->name);
+            !sset_contains(&nat_ip_keys, iter->name) &&
+            !sset_contains(&local_cr_ports, iter->name)) {
+           send_garp_delete(iter->name);
         }
     }
 
@@ -2538,7 +2683,7 @@ send_garp_run(struct ovsdb_idl_index *sbrec_chassis_by_name,
         const struct sbrec_port_binding *pb = lport_lookup_by_name(
             sbrec_port_binding_by_name, iface_id);
         if (pb) {
-            send_garp_update(pb, &nat_addresses);
+            send_garp_update(sbrec_port_binding_by_name, pb, &nat_addresses);
         }
     }
 
@@ -2548,7 +2693,17 @@ send_garp_run(struct ovsdb_idl_index *sbrec_chassis_by_name,
         const struct sbrec_port_binding *pb
             = lport_lookup_by_name(sbrec_port_binding_by_name, gw_port);
         if (pb) {
-            send_garp_update(pb, &nat_addresses);
+            send_garp_update(sbrec_port_binding_by_name, pb, &nat_addresses);
+        }
+    }
+
+    /* Update send_garp_data for nat-addresses. */
+    const char *cr_port;
+    SSET_FOR_EACH (cr_port, &local_cr_ports) {
+        const struct sbrec_port_binding *pb
+            = lport_lookup_by_name(sbrec_port_binding_by_name, cr_port);
+        if (pb) {
+            send_garp_update(sbrec_port_binding_by_name, pb, &nat_addresses);
         }
     }
 
diff --git a/ovn/lib/ovn-util.c b/ovn/lib/ovn-util.c
index aa03919..ae08261 100644
--- a/ovn/lib/ovn-util.c
+++ b/ovn/lib/ovn-util.c
@@ -16,6 +16,7 @@
 #include "ovn-util.h"
 #include "dirs.h"
 #include "openvswitch/vlog.h"
+#include "openvswitch/ofp-parse.h"
 #include "ovn/lib/ovn-nb-idl.h"
 #include "ovn/lib/ovn-sb-idl.h"
 
@@ -364,3 +365,33 @@ ovn_logical_flow_hash(const struct uuid *logical_datapath,
     hash = hash_string(match, hash);
     return hash_string(actions, hash);
 }
+
+/*  Extracts the mac, ip and mask for a sbrec_port_binding.
+ *
+ *  Expects following format:
+ *  "MAC_ADDRESS IP/MASK"
+ *
+ *  Return true if MAC, IP and MASK are found, false otherwise.
+ */
+bool
+ovn_sbrec_get_port_binding_ip_mac(const struct sbrec_port_binding *binding,
+                                  struct eth_addr *mac,
+                                  ovs_be32 *ip, ovs_be32 *mask)
+{
+    char *err_str = NULL;
+
+    err_str = str_to_mac(binding->mac[0], mac);
+    if (err_str) {
+        free(err_str);
+        return false;
+    }
+
+    err_str = ip_parse_masked(binding->mac[0] + ETH_ADDR_STRLEN + 1,
+                              ip, mask);
+    if (err_str) {
+        free(err_str);
+        return false;
+    }
+
+    return true;
+}
diff --git a/ovn/lib/ovn-util.h b/ovn/lib/ovn-util.h
index 6d5e1df..c01595a 100644
--- a/ovn/lib/ovn-util.h
+++ b/ovn/lib/ovn-util.h
@@ -19,6 +19,7 @@
 #include "lib/packets.h"
 
 struct nbrec_logical_router_port;
+struct sbrec_port_binding;
 struct sbrec_logical_flow;
 struct uuid;
 
@@ -81,4 +82,9 @@ uint32_t ovn_logical_flow_hash(const struct uuid *logical_datapath,
                                uint16_t priority,
                                const char *match, const char *actions);
 
+bool
+ovn_sbrec_get_port_binding_ip_mac(const struct sbrec_port_binding *binding,
+                                  struct eth_addr *mac, ovs_be32 *ip,
+                                  ovs_be32 *mask);
+
 #endif
