diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c
index 0fd83ae..71d80e0 100644
--- a/ovn/controller/physical.c
+++ b/ovn/controller/physical.c
@@ -21,6 +21,7 @@
 #include "lflow.h"
 #include "lport.h"
 #include "chassis.h"
+#include "pinctrl.h"
 #include "lib/bundle.h"
 #include "openvswitch/poll-loop.h"
 #include "lib/uuid.h"
@@ -235,8 +236,14 @@ get_zone_ids(const struct sbrec_port_binding *binding,
 }
 
 static void
-put_replace_router_port_mac_flows(const struct sbrec_port_binding *localnet_port,
+put_replace_router_port_mac_flows(struct ovsdb_idl_index
+                                  *sbrec_chassis_by_name,
+                                  struct ovsdb_idl_index
+                                  *sbrec_port_binding_by_name,
+                                  const struct sbrec_port_binding
+                                  *localnet_port,
                                   const struct sbrec_chassis *chassis,
+                                  const struct sset *active_tunnels,
                                   const struct hmap *local_datapaths,
                                   struct ofpbuf *ofpacts_p,
                                   ofp_port_t ofport,
@@ -277,8 +284,22 @@ put_replace_router_port_mac_flows(const struct sbrec_port_binding *localnet_port
         char *err_str = NULL;
         struct match match;
         struct ofpact_mac *replace_mac;
+        char *cr_peer_name = xasprintf("cr-%s", rport_binding->logical_port);
 
-        /* Table 65, priority 150.
+
+        if (pinctrl_is_chassis_resident(sbrec_chassis_by_name,
+                                        sbrec_port_binding_by_name,
+                                        chassis, active_tunnels,
+                                        cr_peer_name)) {
+           /* If a router port's chassisredirect port is resident on this chassis,
+            * then we need not do mac replace. */
+           free(cr_peer_name);
+           continue;
+        }
+
+        free(cr_peer_name);
+
+       /* Table 65, priority 150.
          * =======================
          *
          * Implements output to localnet port.
@@ -793,7 +814,10 @@ consider_port_binding(struct ovsdb_idl_index *sbrec_chassis_by_name,
                         &match, ofpacts_p);
 
         if (!strcmp(binding->type, "localnet")) {
-            put_replace_router_port_mac_flows(binding, chassis, local_datapaths,
+            put_replace_router_port_mac_flows(sbrec_chassis_by_name,
+                                              sbrec_port_binding_by_name,
+                                              binding, chassis,
+                                              active_tunnels, local_datapaths,
                                               ofpacts_p, ofport, flow_table);
         }
 
diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c
index 2a10d1a..72a3d96 100644
--- a/ovn/controller/pinctrl.c
+++ b/ovn/controller/pinctrl.c
@@ -67,13 +67,6 @@ 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(
@@ -134,6 +127,31 @@ pinctrl_init(void)
     init_buffered_packets_map();
 }
 
+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)
+{
+    const struct sbrec_port_binding *pb
+        = lport_lookup_by_name(sbrec_port_binding_by_name, port_name);
+    if (!pb || !pb->chassis) {
+        return false;
+    }
+    if (strcmp(pb->type, "chassisredirect")) {
+        return pb->chassis == chassis;
+    } else {
+        struct ovs_list *gateway_chassis =
+            gateway_chassis_get_ordered(sbrec_chassis_by_name, pb);
+        bool active = gateway_chassis_is_active(gateway_chassis,
+                                                chassis,
+                                                active_tunnels);
+        gateway_chassis_destroy(gateway_chassis);
+        return active;
+    }
+}
+
 static ovs_be32
 queue_msg(struct ofpbuf *msg)
 {
@@ -2405,31 +2423,6 @@ get_localnet_vifs_l3gwports(
     sbrec_port_binding_index_destroy_row(target);
 }
 
-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)
-{
-    const struct sbrec_port_binding *pb
-        = lport_lookup_by_name(sbrec_port_binding_by_name, port_name);
-    if (!pb || !pb->chassis) {
-        return false;
-    }
-    if (strcmp(pb->type, "chassisredirect")) {
-        return pb->chassis == chassis;
-    } else {
-        struct ovs_list *gateway_chassis =
-            gateway_chassis_get_ordered(sbrec_chassis_by_name, pb);
-        bool active = gateway_chassis_is_active(gateway_chassis,
-                                                chassis,
-                                                active_tunnels);
-        gateway_chassis_destroy(gateway_chassis);
-        return active;
-    }
-}
-
 /* Extracts the mac, IPv4 and IPv6 addresses, and logical port from
  * 'addresses' which should be of the format 'MAC [IP1 IP2 ..]
  * [is_chassis_resident("LPORT_NAME")]', where IPn should be a valid IPv4
diff --git a/ovn/controller/pinctrl.h b/ovn/controller/pinctrl.h
index 697d024..7d0b726 100644
--- a/ovn/controller/pinctrl.h
+++ b/ovn/controller/pinctrl.h
@@ -45,4 +45,10 @@ void pinctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
 void pinctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn);
 void pinctrl_destroy(void);
 
+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);
 #endif /* ovn/pinctrl.h */
diff --git a/tests/ovn.at b/tests/ovn.at
index 6af746e..6fce847 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -12282,7 +12282,7 @@ ovn-nbctl list logical_router_port
 
 AT_CLEANUP
 
-AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR chassis mac])
+AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR E-W chassis mac])
 ovn_start
 
 
@@ -12292,6 +12292,8 @@ ovn_start
 # of VIF port name indicates the hypervisor it is bound to, e.g.
 # lp23 means VIF 3 on hv2.
 #
+# Both the switches are connected to a logical router "router".
+#
 # Each switch's VLAN tag and their logical switch ports are:
 #   - ls1:
 #       - tagged with VLAN 101
@@ -12475,6 +12477,105 @@ as hv2 ovs-appctl fdb/show br-phys
 
 OVN_CHECK_PACKETS([hv2/vif22-tx.pcap], [vif22.expected])
 
+
+# Associate a chassis as gateway chassis and validate garp.
+
+OVN_CLEANUP([hv1],[hv2])
+
+AT_CLEANUP
+
+
+AT_SETUP([ovn -- 2 HVs, 2 lports/HV, localnet ports, DVR N-S GARP])
+ovn_start
+
+
+# In this test cases we create 2 switches, all connected to same
+# physical network (through br-phys on each HV). Each switch has
+# 1 VIF. Each HV has 1 VIF port. The first digit
+# of VIF port name indicates the hypervisor it is bound to, e.g.
+# lp23 means VIF 3 on hv2.
+#
+# Both the switches are connected to a logical router "router".
+#
+# Additionally, we create a logical switch (ls-underlay) for N-S traffic.
+#
+# Each switch's VLAN tag and their logical switch ports are:
+#   - ls1:
+#       - tagged with VLAN 101
+#       - ports: lp11
+#   - ls2:
+#       - tagged with VLAN 201
+#       - ports: lp22
+#   - ls-underlay:
+#       - tagged with VLAN 1000
+#
+# Note: a localnet port is created for each switch to connect to
+# physical network.
+# lsp_to_ls LSP
+#
+# Prints the name of the logical switch that contains LSP.
+
+net_add n1
+for i in 1 2; do
+    sim_add hv$i
+    as hv$i
+    ovs-vsctl add-br br-phys
+    ovs-vsctl set open . external-ids:ovn-bridge-mappings=phys:br-phys
+    ovs-vsctl set open . external-ids:ovn-chassis-mac-mappings="phys:aa:bb:cc:dd:ee:$i$i"
+    ovs-vsctl set open . external-ids:system-id="HV$i"
+    ovn_attach n1 br-phys 192.168.0.$i
+    ovs-vsctl set-controller br-int ptcp:
+done
+
+ovn-nbctl ls-add ls-underlay vlan
+ovn-nbctl lsp-add ls-underlay ln3 "" 1000
+ovn-nbctl lsp-set-addresses ln3 unknown
+ovn-nbctl lsp-set-type ln3 localnet
+ovn-nbctl lsp-set-options ln3 network_name=phys
+
+ovn-nbctl lr-add router
+ovn-nbctl lrp-add router router-to-underlay 00:00:01:01:02:07 172.31.0.1/24
+
+ovn-nbctl lsp-add ls-underlay underlay-to-router -- set Logical_Switch_Port \
+                              underlay-to-router type=router \
+                              options:router-port=router-to-underlay \
+                              -- lsp-set-addresses underlay-to-router router
+
+ovn-nbctl --wait=sb sync
+
+# Associate hv2 as gateway chassis
+ovn-nbctl lrp-set-gateway-chassis router-to-underlay hv2
+
+ovn-nbctl show
+ovn-sbctl show
+
+# Dump a bunch of info helpful for debugging if there's a failure.
+
+echo "------ OVN dump ------"
+ovn-nbctl show
+ovn-sbctl show
+
+echo "------ hv1 dump ------"
+as hv1 ovs-vsctl show
+as hv1 ovs-vsctl list Open_Vswitch
+
+echo "------ hv2 dump ------"
+as hv2 ovs-vsctl show
+as hv2 ovs-vsctl list Open_Vswitch
+
+sleep 1
+
+echo "----------- Post Traffic hv1 dump -----------"
+as hv1 ovs-ofctl -O OpenFlow13 dump-flows br-int
+as hv1 ovs-appctl fdb/show br-phys
+
+echo "----------- Post Traffic hv2 dump -----------"
+as hv2 ovs-ofctl -O OpenFlow13 dump-flows br-int
+as hv2 ovs-appctl fdb/show br-phys
+
+AT_CHECK([as hv2 ovs-appctl fdb/show br-phys | grep 00:00:01:01:02:07 | grep 1000 | wc -l], [0], [[1
+]])
+
 OVN_CLEANUP([hv1],[hv2])
 
 AT_CLEANUP
