EVPN-learned MAC bindings (Type-2 routes from FRR via
the kernel neighbor table) were only installed as local
OpenFlow flows on the chassis running FRR.  When a VM on
a different chassis routed traffic through a logical
router that needed to resolve an EVPN-learned next-hop,
the MAC binding lookup failed because the flow only
existed on the FRR chassis.

Add a new engine node, en_evpn_mac_binding_sync, that
writes EVPN-learned MAC bindings to the SB MAC_Binding
table.  Once in SB, every chassis consumes them through
the existing lflow MAC_Binding pipeline at the same
priority as regular ARP/ND-learned entries.

The sync node tracks which (logical_port, ip, mac)
tuples it has written so it only deletes its own entries
without interfering with pinctrl-written dynamic
bindings, and skips SB writes when the MAC has not
changed.  A companion waker node periodically triggers
timestamp refreshes on synced entries to prevent northd
aging from removing entries that are still present in
the kernel neighbor table but not actively carrying
traffic.

The router-side consider_neighbor_flow() call is removed
from physical_consider_evpn_arp() since those flows now
come from the SB path.  The switch-side EVPN ARP lookup
flows (table 113, used for ARP/ND suppression) remain
local-only.

Note: the dynamic-routing-arp-prefer-local option no
longer affects the router MAC_Binding table priority for
EVPN entries (they are now always at the same priority
as dynamic entries).  It still controls the EVPN ARP
lookup side table (table 113) priority.  Removal of the
option is planned as a follow-up.

Fixes: 93ae6396e225 ("controller, northd: Add support for learning IP neighbors 
through EVPN.")
Reported-at: https://redhat.atlassian.net/browse/FDP-3587
Reported-at: https://redhat.atlassian.net/browse/FDP-4001
Assisted-by: Claude Opus 4.6, OpenCode
Signed-off-by: Ales Musil <[email protected]>
---
 NEWS                               |   5 +
 TODO.rst                           |   3 -
 controller/automake.mk             |   2 +
 controller/evpn-mac-binding-sync.c | 243 +++++++++++++++++++++
 controller/evpn-mac-binding-sync.h |  68 ++++++
 controller/garp_rarp.c             |   2 +-
 controller/ovn-controller.c        | 133 +++++++++++-
 controller/physical.c              |  29 +--
 controller/physical.h              |   3 +-
 controller/pinctrl.c               |   2 +-
 lib/mac-binding-index.c            |  25 ++-
 lib/mac-binding-index.h            |   5 +-
 ovn-sb.xml                         |   8 +
 tests/ovn-inc-proc-graph-dump.at   |   9 +
 tests/system-ovn.at                | 336 +++++++++++++++++++----------
 15 files changed, 710 insertions(+), 163 deletions(-)
 create mode 100644 controller/evpn-mac-binding-sync.c
 create mode 100644 controller/evpn-mac-binding-sync.h

diff --git a/NEWS b/NEWS
index fcee8b8c2..385e35590 100644
--- a/NEWS
+++ b/NEWS
@@ -65,6 +65,11 @@ Post v26.03.0
        "external_ids:dynamic-routing-port-mapping" for veth-based routing
        daemon integrations.  This feature is Linux-only and requires
        OVS version >= 4.0.
+     * EVPN-learned MAC bindings (Type-2 routes from FRR) are now stored
+       in the SB MAC_Binding table so they are distributed to all chassis.
+       Previously these bindings were local-only OpenFlow flows on the
+       chassis running FRR, causing MAC resolution failures for traffic
+       originating on other chassis.
    - Added "override-connected" option to Logical Router Static Routes to mark
      static routes as higher-priority than connected routes, which in turn led
      to changes in administrative distance for specific route types. Please see
diff --git a/TODO.rst b/TODO.rst
index beca38daf..25ac01ee9 100644
--- a/TODO.rst
+++ b/TODO.rst
@@ -156,9 +156,6 @@ OVN To-do List
     Otherwise we could try to add duplicated Learned_Routes and the ovnsb
     commit would fail.
 
-  * Add support for EVPN L3, that involves MAC Binding learning and
-    advertisement.
-
 * Datapath sync nodes
 
   * Migrate data stored in the ovn\_datapath structure to
diff --git a/controller/automake.mk b/controller/automake.mk
index a779250cb..bf126d257 100644
--- a/controller/automake.mk
+++ b/controller/automake.mk
@@ -16,6 +16,8 @@ controller_ovn_controller_SOURCES = \
        controller/evpn-binding.h \
        controller/evpn-fdb.c \
        controller/evpn-fdb.h \
+       controller/evpn-mac-binding-sync.c \
+       controller/evpn-mac-binding-sync.h \
        controller/ha-chassis.c \
        controller/ha-chassis.h \
        controller/if-status.c \
diff --git a/controller/evpn-mac-binding-sync.c 
b/controller/evpn-mac-binding-sync.c
new file mode 100644
index 000000000..8d927d2ce
--- /dev/null
+++ b/controller/evpn-mac-binding-sync.c
@@ -0,0 +1,243 @@
+/* Copyright (c) 2026, Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "openvswitch/poll-loop.h"
+#include "packets.h"
+#include "timeval.h"
+
+#include "evpn-arp.h"
+#include "evpn-mac-binding-sync.h"
+#include "lib/mac-binding-index.h"
+#include "local_data.h"
+#include "mac-cache.h"
+#include "ovn-sb-idl.h"
+#include "ovn-util.h"
+#include "vec.h"
+
+/* Hash a (logical_port, ip) pair. */
+static uint32_t
+evpn_mb_hash(const char *logical_port, const char *ip)
+{
+    uint32_t hash = hash_string(logical_port, 0);
+    return hash_string(ip, hash);
+}
+
+static struct evpn_mb_synced_entry *
+evpn_mb_synced_find(const struct hmap *synced, const char *logical_port,
+                    const char *ip)
+{
+    uint32_t hash = evpn_mb_hash(logical_port, ip);
+
+    struct evpn_mb_synced_entry *entry;
+    HMAP_FOR_EACH_WITH_HASH (entry, hmap_node, hash, synced) {
+        if (!strcmp(entry->logical_port, logical_port) &&
+            !strcmp(entry->ip, ip)) {
+            return entry;
+        }
+    }
+
+    return NULL;
+}
+
+static struct evpn_mb_synced_entry *
+evpn_mb_synced_add(struct hmap *synced, const char *logical_port,
+                   const char *ip)
+{
+    struct evpn_mb_synced_entry *entry = xmalloc(sizeof *entry);
+    entry->logical_port = xstrdup(logical_port);
+    entry->ip = xstrdup(ip);
+    hmap_insert(synced, &entry->hmap_node,
+                evpn_mb_hash(logical_port, ip));
+    return entry;
+}
+
+static void
+evpn_mb_synced_remove(struct hmap *synced, struct evpn_mb_synced_entry *entry)
+{
+    hmap_remove(synced, &entry->hmap_node);
+    free(entry->logical_port);
+    free(entry->ip);
+    free(entry);
+}
+
+/* Schedule the waker to fire after 'delay_ms' milliseconds. */
+static void
+evpn_mb_sync_waker_schedule(struct evpn_mb_sync_waker *waker,
+                            int64_t delay_ms)
+{
+    if (delay_ms < INT64_MAX) {
+        waker->should_schedule = true;
+        waker->next_wake_msec = time_msec() + delay_ms;
+        poll_timer_wait_until(waker->next_wake_msec);
+    }
+}
+
+/* Sync a single EVPN ARP entry to the SB MAC_Binding table for one
+ * router port.  Caller must ensure 'ovnsb_idl_txn' is valid.
+ * Returns the remaining time (in ms) until the next timestamp
+ * refresh is needed, or INT64_MAX if none. */
+static int64_t
+sync_evpn_mb_for_router_port(
+    struct ovsdb_idl_txn *ovnsb_idl_txn,
+    struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
+    const struct sbrec_mac_binding_table *mb_table,
+    const struct sbrec_port_binding *router_pb,
+    const struct evpn_arp *arp,
+    struct mac_cache_data *mac_cache_data,
+    struct ed_type_evpn_mac_binding_sync *data,
+    long long timewall_now)
+{
+    char *ip_s = normalize_v46(&arp->ip);
+    struct evpn_mb_synced_entry *existing =
+        evpn_mb_synced_find(&data->synced_entries,
+                            router_pb->logical_port, ip_s);
+
+    /* Resolve the cached UUID to a row pointer.  This is a cheap
+     * single-key hash lookup that avoids the heavier two-column
+     * index lookup inside mac_binding_add_to_sb(). */
+    const struct sbrec_mac_binding *sb_mb = existing
+        ? sbrec_mac_binding_table_get_for_uuid(mb_table, &existing->mb_uuid)
+        : NULL;
+
+    /* Insert or update the SB MAC_Binding row. */
+    const struct sbrec_mac_binding *b =
+        mac_binding_add_to_sb(ovnsb_idl_txn,
+                              sbrec_mac_binding_by_lport_ip,
+                              router_pb->logical_port,
+                              router_pb->datapath,
+                              arp->mac, ip_s, false,
+                              sb_mb);
+
+    if (!existing) {
+        existing = evpn_mb_synced_add(&data->synced_entries,
+                                      router_pb->logical_port, ip_s);
+    }
+
+    free(ip_s);
+    existing->mb_uuid = b->header_.uuid;
+    existing->stale = false;
+
+    /* Refresh timestamp to prevent aging. */
+    struct mac_cache_threshold *threshold =
+        mac_cache_threshold_find(mac_cache_data,
+                                 router_pb->datapath->tunnel_key);
+    if (!threshold) {
+        return INT64_MAX;
+    }
+
+    uint64_t since_updated = timewall_now - b->timestamp;
+    if (since_updated >= threshold->cooldown_period) {
+        sbrec_mac_binding_set_timestamp(b, timewall_now);
+        return threshold->cooldown_period;
+    }
+
+    return threshold->cooldown_period - since_updated;
+}
+
+void
+evpn_mac_binding_sync_run(
+    struct ovsdb_idl_txn *ovnsb_idl_txn,
+    struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
+    const struct sbrec_mac_binding_table *mb_table,
+    const struct hmap *local_datapaths,
+    const struct hmap *evpn_arps,
+    struct mac_cache_data *mac_cache_data,
+    struct ed_type_evpn_mac_binding_sync *data,
+    struct evpn_mb_sync_waker *waker)
+{
+    if (!ovnsb_idl_txn) {
+        data->sb_changes_pending = true;
+        return;
+    }
+
+    long long timewall_now = time_wall_msec();
+    int64_t min_next_refresh_ms = INT64_MAX;
+
+    /* Mark all synced entries as stale.  SB row pointers are resolved
+     * lazily by UUID only where needed (insert/update, timestamp
+     * refresh, delete), avoiding a per-entry index lookup here. */
+    struct evpn_mb_synced_entry *synced_entry;
+    HMAP_FOR_EACH (synced_entry, hmap_node, &data->synced_entries) {
+        synced_entry->stale = true;
+    }
+
+    /* Walk current EVPN ARPs and sync to SB. */
+    const struct evpn_arp *arp;
+    HMAP_FOR_EACH (arp, hmap_node, evpn_arps) {
+        const struct peer_ports *peers;
+        VECTOR_FOR_EACH_PTR (&arp->ldp->peer_ports, peers) {
+            const struct sbrec_port_binding *remote_pb = peers->remote;
+            struct local_datapath *peer_ld =
+                get_local_datapath(local_datapaths,
+                                   remote_pb->datapath->tunnel_key);
+            if (!peer_ld || peer_ld->is_switch) {
+                continue;
+            }
+
+            int64_t remaining =
+                sync_evpn_mb_for_router_port(ovnsb_idl_txn,
+                                             sbrec_mac_binding_by_lport_ip,
+                                             mb_table,
+                                             remote_pb, arp,
+                                             mac_cache_data, data,
+                                             timewall_now);
+            if (remaining < min_next_refresh_ms) {
+                min_next_refresh_ms = remaining;
+            }
+        }
+    }
+
+    /* Delete stale entries from SB. */
+    HMAP_FOR_EACH_SAFE (synced_entry, hmap_node, &data->synced_entries) {
+        if (!synced_entry->stale) {
+            continue;
+        }
+
+        const struct sbrec_mac_binding *sb_mb =
+            sbrec_mac_binding_table_get_for_uuid(
+                mb_table, &synced_entry->mb_uuid);
+        if (sb_mb) {
+            sbrec_mac_binding_delete(sb_mb);
+        }
+
+        evpn_mb_synced_remove(&data->synced_entries, synced_entry);
+    }
+
+    /* Schedule the waker for the next timestamp refresh. */
+    if (min_next_refresh_ms < INT64_MAX) {
+        evpn_mb_sync_waker_schedule(waker, min_next_refresh_ms);
+    }
+}
+
+void
+evpn_mac_binding_sync_init(struct ed_type_evpn_mac_binding_sync *data)
+{
+    hmap_init(&data->synced_entries);
+    data->sb_changes_pending = false;
+}
+
+void
+evpn_mac_binding_sync_cleanup(struct ed_type_evpn_mac_binding_sync *data)
+{
+    struct evpn_mb_synced_entry *entry;
+    HMAP_FOR_EACH_POP (entry, hmap_node, &data->synced_entries) {
+        free(entry->logical_port);
+        free(entry->ip);
+        free(entry);
+    }
+    hmap_destroy(&data->synced_entries);
+}
diff --git a/controller/evpn-mac-binding-sync.h 
b/controller/evpn-mac-binding-sync.h
new file mode 100644
index 000000000..dc1e63a6a
--- /dev/null
+++ b/controller/evpn-mac-binding-sync.h
@@ -0,0 +1,68 @@
+/* Copyright (c) 2026, Red Hat, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EVPN_MAC_BINDING_SYNC_H
+#define EVPN_MAC_BINDING_SYNC_H 1
+
+#include "openvswitch/hmap.h"
+#include "openvswitch/uuid.h"
+
+struct mac_cache_data;
+struct ovsdb_idl_index;
+struct ovsdb_idl_txn;
+struct sbrec_mac_binding_table;
+
+/* Tracks a MAC_Binding row that was written to SB by the EVPN sync. */
+struct evpn_mb_synced_entry {
+    struct hmap_node hmap_node;
+    char *logical_port;                  /* Router port name. */
+    char *ip;                            /* Normalized IP string. */
+    struct uuid mb_uuid;                 /* UUID of the SB MAC_Binding row.
+                                          * All-zeros when not yet synced. */
+    bool stale;                          /* Marked true at start of sync,
+                                          * cleared when still desired. */
+};
+
+/* Persistent state for the en_evpn_mac_binding_sync engine node. */
+struct ed_type_evpn_mac_binding_sync {
+    /* Contains 'struct evpn_mb_synced_entry'.  Tracks which
+     * (logical_port, ip) pairs we have written to SB. */
+    struct hmap synced_entries;
+
+    /* True when an SB write was skipped because ovnsb_idl_txn was NULL. */
+    bool sb_changes_pending;
+};
+
+/* Timer that periodically wakes the sync node so it can refresh
+ * timestamps on SB MAC_Binding rows it owns. */
+struct evpn_mb_sync_waker {
+    bool should_schedule;         /* Whether a wake is pending. */
+    long long next_wake_msec;     /* Absolute time of next wake. */
+};
+
+void evpn_mac_binding_sync_run(
+    struct ovsdb_idl_txn *ovnsb_idl_txn,
+    struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
+    const struct sbrec_mac_binding_table *mb_table,
+    const struct hmap *local_datapaths,
+    const struct hmap *evpn_arps,
+    struct mac_cache_data *mac_cache_data,
+    struct ed_type_evpn_mac_binding_sync *data,
+    struct evpn_mb_sync_waker *waker);
+
+void evpn_mac_binding_sync_init(struct ed_type_evpn_mac_binding_sync *);
+void evpn_mac_binding_sync_cleanup(struct ed_type_evpn_mac_binding_sync *);
+
+#endif /* EVPN_MAC_BINDING_SYNC_H */
diff --git a/controller/garp_rarp.c b/controller/garp_rarp.c
index 1cf415a9f..9de8345c7 100644
--- a/controller/garp_rarp.c
+++ b/controller/garp_rarp.c
@@ -365,7 +365,7 @@ send_garp_locally(const struct garp_rarp_ctx_in *r_ctx_in,
         mac_binding_add_to_sb(r_ctx_in->ovnsb_idl_txn,
                               r_ctx_in->sbrec_mac_binding_by_lport_ip,
                               remote->logical_port, remote->datapath,
-                              ea, ds_cstr(&ip_s), update_only);
+                              ea, ds_cstr(&ip_s), update_only, NULL);
         ds_destroy(&ip_s);
     }
 }
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 6551a4e30..c57695ec1 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -104,6 +104,7 @@
 #include "evpn-arp.h"
 #include "evpn-binding.h"
 #include "evpn-fdb.h"
+#include "evpn-mac-binding-sync.h"
 
 VLOG_DEFINE_THIS_MODULE(main);
 
@@ -5157,13 +5158,10 @@ static enum engine_input_handler_result
 pflow_output_arp_handler(struct engine_node *node, void *data)
 {
     struct ed_type_pflow_output *pfo = data;
-    struct ed_type_runtime_data *rt_data =
-        engine_get_input_data("runtime_data", node);
     struct ed_type_evpn_arp *ea_data =
         engine_get_input_data("evpn_arp", node);
 
-    physical_handle_evpn_arp_changes(&rt_data->local_datapaths,
-                                     &pfo->flow_table,
+    physical_handle_evpn_arp_changes(&pfo->flow_table,
                                      &ea_data->updated_arps,
                                      &ea_data->removed_arps);
     return EN_HANDLED_UPDATED;
@@ -5238,6 +5236,14 @@ controller_output_garp_rarp_handler(struct engine_node 
*node OVS_UNUSED,
     return EN_HANDLED_UPDATED;
 }
 
+static enum engine_input_handler_result
+controller_output_evpn_mac_binding_sync_handler(
+    struct engine_node *node OVS_UNUSED,
+    void *data OVS_UNUSED)
+{
+    return EN_HANDLED_UPDATED;
+}
+
 static enum engine_input_handler_result
 controller_output_datapaths_updated_handler(
     struct engine_node *node OVS_UNUSED,
@@ -7189,6 +7195,106 @@ evpn_arp_vtep_binding_handler(struct engine_node *node, 
void *data OVS_UNUSED)
     return EN_UNHANDLED;
 }
 
+/* EVPN MAC binding sync waker: a timer-based input node that
+ * periodically fires EN_UPDATED to trigger the sync node so it
+ * can refresh timestamps on SB MAC_Binding rows. */
+static void *
+en_evpn_mac_binding_sync_waker_init(struct engine_node *node OVS_UNUSED,
+                                    struct engine_arg *arg OVS_UNUSED)
+{
+    struct evpn_mb_sync_waker *waker = xzalloc(sizeof *waker);
+    return waker;
+}
+
+static enum engine_node_state
+en_evpn_mac_binding_sync_waker_run(struct engine_node *node OVS_UNUSED,
+                                   void *data)
+{
+    struct evpn_mb_sync_waker *waker = data;
+
+    if (!waker->should_schedule) {
+        return EN_UNCHANGED;
+    }
+
+    if (time_msec() >= waker->next_wake_msec) {
+        waker->should_schedule = false;
+        return EN_UPDATED;
+    }
+
+    poll_timer_wait_until(waker->next_wake_msec);
+    return EN_UNCHANGED;
+}
+
+static void
+en_evpn_mac_binding_sync_waker_cleanup(void *data OVS_UNUSED)
+{
+}
+
+/* EVPN MAC binding sync node: syncs EVPN-learned MAC bindings
+ * to the SB MAC_Binding table so they are distributed to all
+ * chassis. */
+static void *
+en_evpn_mac_binding_sync_init(struct engine_node *node OVS_UNUSED,
+                              struct engine_arg *arg OVS_UNUSED)
+{
+    struct ed_type_evpn_mac_binding_sync *data = xmalloc(sizeof *data);
+    evpn_mac_binding_sync_init(data);
+    return data;
+}
+
+static enum engine_node_state
+en_evpn_mac_binding_sync_run(struct engine_node *node, void *data_)
+{
+    struct ed_type_evpn_mac_binding_sync *data = data_;
+
+    struct ed_type_evpn_arp *earp_data =
+        engine_get_input_data("evpn_arp", node);
+    struct ed_type_runtime_data *rt_data =
+        engine_get_input_data("runtime_data", node);
+    struct mac_cache_data *mac_cache_data =
+        engine_get_input_data("mac_cache", node);
+    struct engine_node *sb_mb_node =
+        engine_get_input("SB_mac_binding", node);
+    struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip =
+        engine_ovsdb_node_get_index(sb_mb_node, "lport_ip");
+    const struct sbrec_mac_binding_table *mb_table =
+        EN_OVSDB_GET(sb_mb_node);
+
+    struct evpn_mb_sync_waker *waker =
+        engine_get_input_data("evpn_mac_binding_sync_waker", node);
+
+    data->sb_changes_pending = false;
+
+    evpn_mac_binding_sync_run(engine_get_context()->ovnsb_idl_txn,
+                              sbrec_mac_binding_by_lport_ip,
+                              mb_table,
+                              &rt_data->local_datapaths,
+                              &earp_data->arps,
+                              mac_cache_data,
+                              data, waker);
+
+    return EN_UPDATED;
+}
+
+static void
+en_evpn_mac_binding_sync_cleanup(void *data_)
+{
+    struct ed_type_evpn_mac_binding_sync *data = data_;
+    evpn_mac_binding_sync_cleanup(data);
+}
+
+static enum engine_input_handler_result
+evpn_mac_binding_sync_sb_ro_handler(struct engine_node *node OVS_UNUSED,
+                                    void *data_)
+{
+    struct ed_type_evpn_mac_binding_sync *data = data_;
+    if (data->sb_changes_pending) {
+        return EN_UNHANDLED;
+    }
+
+    return EN_HANDLED_UNCHANGED;
+}
+
 /* Define engine node functions for nodes that represent SB tables.
  *
  * en_sb_<TABLE_NAME>_run()
@@ -7314,6 +7420,8 @@ static ENGINE_NODE(nexthop_exchange);
 static ENGINE_NODE(evpn_vtep_binding, CLEAR_TRACKED_DATA);
 static ENGINE_NODE(evpn_fdb, CLEAR_TRACKED_DATA);
 static ENGINE_NODE(evpn_arp, CLEAR_TRACKED_DATA);
+static ENGINE_NODE(evpn_mac_binding_sync_waker);
+static ENGINE_NODE(evpn_mac_binding_sync, SB_WRITE);
 static ENGINE_NODE(datapaths_updated);
 static ENGINE_NODE(sb_cond_seqno);
 
@@ -7603,6 +7711,21 @@ inc_proc_ovn_controller_init(
     engine_add_input(&en_evpn_arp, &en_evpn_vtep_binding,
                      evpn_arp_vtep_binding_handler);
 
+    engine_add_input(&en_evpn_mac_binding_sync,
+                     &en_evpn_mac_binding_sync_waker, NULL);
+    engine_add_input(&en_evpn_mac_binding_sync, &en_evpn_arp, NULL);
+    /* MAC_Binding data is only used via an index for lookups. */
+    engine_add_input(&en_evpn_mac_binding_sync, &en_sb_mac_binding,
+                     engine_noop_handler);
+    /* Runtime data is only used for local_datapaths access. */
+    engine_add_input(&en_evpn_mac_binding_sync, &en_runtime_data,
+                     engine_noop_handler);
+    /* MAC cache data is only used for aging threshold lookup. */
+    engine_add_input(&en_evpn_mac_binding_sync, &en_mac_cache,
+                     engine_noop_handler);
+    engine_add_input(&en_evpn_mac_binding_sync, &en_sb_ro,
+                     evpn_mac_binding_sync_sb_ro_handler);
+
     engine_add_input(&en_pflow_output, &en_evpn_vtep_binding,
                      pflow_output_evpn_binding_handler);
     engine_add_input(&en_pflow_output, &en_evpn_fdb,
@@ -7624,6 +7747,8 @@ inc_proc_ovn_controller_init(
                      controller_output_route_exchange_handler);
     engine_add_input(&en_controller_output, &en_garp_rarp,
                      controller_output_garp_rarp_handler);
+    engine_add_input(&en_controller_output, &en_evpn_mac_binding_sync,
+                     controller_output_evpn_mac_binding_sync_handler);
 
     engine_add_input(&en_acl_id, &en_sb_acl_id, NULL);
     engine_add_input(&en_controller_output, &en_acl_id,
diff --git a/controller/physical.c b/controller/physical.c
index 452256e7a..8a70f913c 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -58,7 +58,6 @@
 #include "vec.h"
 #include "vswitch-idl.h"
 #include "hmapx.h"
-#include "neighbor-of.h"
 
 VLOG_DEFINE_THIS_MODULE(physical);
 
@@ -3706,28 +3705,11 @@ physical_consider_evpn_fdb(const struct evpn_fdb *fdb,
 }
 
 static void
-physical_consider_evpn_arp(const struct hmap *local_datapaths,
-                           const struct evpn_arp *arp,
+physical_consider_evpn_arp(const struct evpn_arp *arp,
                            struct ofpbuf *ofpacts,
                            struct match *match,
                            struct ovn_desired_flow_table *flow_table)
 {
-    /* Walk connected OVN routers and install neighbor flows for the ARPs
-     * learned on EVPN datapaths.*/
-    const struct peer_ports *peers;
-    VECTOR_FOR_EACH_PTR (&arp->ldp->peer_ports, peers) {
-        const struct sbrec_port_binding *remote_pb = peers->remote;
-        struct local_datapath *peer_ld =
-            get_local_datapath(local_datapaths,
-                               remote_pb->datapath->tunnel_key);
-        if (!peer_ld || peer_ld->is_switch) {
-            continue;
-        }
-
-        consider_neighbor_flow(remote_pb, &arp->flow_uuid, &arp->ip, arp->mac,
-                               flow_table, arp->priority, false);
-    }
-
     /* Install EVPN ARP lookup flows in the dedicated side table for the
      * switch datapath.  These flows are matched by the chk_evpn_arp()
      * action.  On a hit they load the resolved MAC into eth.dst
@@ -3806,8 +3788,7 @@ physical_eval_evpn_flows(const struct physical_ctx *ctx,
 
     const struct evpn_arp *arp;
     HMAP_FOR_EACH (arp, hmap_node, ctx->evpn_arps) {
-        physical_consider_evpn_arp(ctx->local_datapaths, arp, ofpacts,
-                                   &match, flow_table);
+        physical_consider_evpn_arp(arp, ofpacts, &match, flow_table);
     }
 }
 
@@ -4016,8 +3997,7 @@ physical_handle_evpn_fdb_changes(struct 
ovn_desired_flow_table *flow_table,
 }
 
 void
-physical_handle_evpn_arp_changes(const struct hmap *local_datapaths,
-                                 struct ovn_desired_flow_table *flow_table,
+physical_handle_evpn_arp_changes(struct ovn_desired_flow_table *flow_table,
                                  const struct hmapx *updated_arps,
                                  const struct uuidset *removed_arps)
 {
@@ -4030,8 +4010,7 @@ physical_handle_evpn_arp_changes(const struct hmap 
*local_datapaths,
         const struct evpn_arp *arp = node->data;
 
         ofctrl_remove_flows(flow_table, &arp->flow_uuid);
-        physical_consider_evpn_arp(local_datapaths, arp, &ofpacts,
-                                   &match, flow_table);
+        physical_consider_evpn_arp(arp, &ofpacts, &match, flow_table);
     }
     ofpbuf_uninit(&ofpacts);
 
diff --git a/controller/physical.h b/controller/physical.h
index b02caea88..8218096d5 100644
--- a/controller/physical.h
+++ b/controller/physical.h
@@ -106,8 +106,7 @@ void physical_handle_evpn_fdb_changes(struct 
ovn_desired_flow_table *,
                                       struct ovn_extend_table *group_table,
                                       const struct hmapx *updated_fdbs,
                                       const struct uuidset *removed_fdbs);
-void physical_handle_evpn_arp_changes(const struct hmap *local_datapaths,
-                                      struct ovn_desired_flow_table *,
+void physical_handle_evpn_arp_changes(struct ovn_desired_flow_table *,
                                       const struct hmapx *updated_arps,
                                       const struct uuidset *removed_arps);
 #endif /* controller/physical.h */
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index 216831e6e..333dcedb6 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -4918,7 +4918,7 @@ run_put_mac_binding(struct ovsdb_idl_txn *ovnsb_idl_txn,
     ipv6_format_mapped(&mb->data.ip, &ip_s);
     mac_binding_add_to_sb(ovnsb_idl_txn, sbrec_mac_binding_by_lport_ip,
                           pb->logical_port, pb->datapath, mb->data.mac,
-                          ds_cstr(&ip_s), false);
+                          ds_cstr(&ip_s), false, NULL);
     ds_destroy(&ip_s);
 }
 
diff --git a/lib/mac-binding-index.c b/lib/mac-binding-index.c
index ad6be0a4e..3e49b07f3 100644
--- a/lib/mac-binding-index.c
+++ b/lib/mac-binding-index.c
@@ -52,27 +52,34 @@ mac_binding_lookup(struct ovsdb_idl_index 
*sbrec_mac_binding_by_lport_ip,
 }
 
 /* Update or add an IP-MAC binding for 'logical_port'.
- * Caller should make sure that 'ovnsb_idl_txn' is valid. */
-void
+ * Caller should make sure that 'ovnsb_idl_txn' is valid.
+ * Returns the SB row that was inserted or updated, or NULL
+ * if 'update_only' is true and no existing row was found. */
+const struct sbrec_mac_binding *
 mac_binding_add_to_sb(struct ovsdb_idl_txn *ovnsb_idl_txn,
                       struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
                       const char *logical_port,
                       const struct sbrec_datapath_binding *dp,
                       struct eth_addr ea, const char *ip,
-                      bool update_only)
+                      bool update_only,
+                      const struct sbrec_mac_binding *sb_mb)
 {
     /* Convert ethernet argument to string form for database. */
     char mac_string[ETH_ADDR_STRLEN + 1];
     snprintf(mac_string, sizeof mac_string, ETH_ADDR_FMT, ETH_ADDR_ARGS(ea));
 
-    const struct sbrec_mac_binding *b =
-            mac_binding_lookup(sbrec_mac_binding_by_lport_ip,
-                               logical_port, ip);
+    const struct sbrec_mac_binding *b = sb_mb
+            ? sb_mb
+            : mac_binding_lookup(sbrec_mac_binding_by_lport_ip,
+                                 logical_port, ip);
     if (!b) {
         if (update_only) {
-            return;
+            return NULL;
         }
-        b = sbrec_mac_binding_insert(ovnsb_idl_txn);
+
+        /* Make sure the uuid persists between txn inserts. */
+        struct uuid uuid = uuid_random();
+        b = sbrec_mac_binding_insert_persist_uuid(ovnsb_idl_txn, &uuid);
         sbrec_mac_binding_set_logical_port(b, logical_port);
         sbrec_mac_binding_set_ip(b, ip);
         sbrec_mac_binding_set_datapath(b, dp);
@@ -91,4 +98,6 @@ mac_binding_add_to_sb(struct ovsdb_idl_txn *ovnsb_idl_txn,
             sbrec_mac_binding_set_timestamp(b, time_wall_msec());
         }
     }
+
+    return b;
 }
diff --git a/lib/mac-binding-index.h b/lib/mac-binding-index.h
index 3bcb29359..8832eda16 100644
--- a/lib/mac-binding-index.h
+++ b/lib/mac-binding-index.h
@@ -27,10 +27,11 @@ const struct sbrec_mac_binding *
 mac_binding_lookup(struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
                    const char *logical_port, const char *ip);
 
-void mac_binding_add_to_sb(
+const struct sbrec_mac_binding *mac_binding_add_to_sb(
     struct ovsdb_idl_txn *,
     struct ovsdb_idl_index *sbrec_mac_binding_by_lport_ip,
     const char *logical_port, const struct sbrec_datapath_binding *,
-    struct eth_addr, const char *ip, bool update_only);
+    struct eth_addr, const char *ip, bool update_only,
+    const struct sbrec_mac_binding *sb_mb);
 
 #endif /* lib/mac-binding-index.h */
diff --git a/ovn-sb.xml b/ovn-sb.xml
index d5c5210dc..a147f2675 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -4185,6 +4185,14 @@ tcp.flags = RST;
       </li>
     </ol>
 
+    <p>
+      In EVPN deployments, <code>ovn-controller</code> also writes rows to
+      this table for MAC bindings learned through EVPN Type-2 routes (via
+      FRR and the kernel neighbor table).  These entries are keyed by the
+      router port connected to the EVPN logical switch and behave identically
+      to ARP/ND-learned bindings for consumption and aging purposes.
+    </p>
+
     <column name="logical_port">
       The logical port on which the binding was discovered.
     </column>
diff --git a/tests/ovn-inc-proc-graph-dump.at b/tests/ovn-inc-proc-graph-dump.at
index ea70293ce..a56fa8bd8 100644
--- a/tests/ovn-inc-proc-graph-dump.at
+++ b/tests/ovn-inc-proc-graph-dump.at
@@ -483,6 +483,14 @@ digraph "Incremental-Processing-Engine" {
        SB_datapath_binding -> garp_rarp 
[[label="garp_rarp_sb_datapath_binding_handler"]];
        SB_mac_binding -> garp_rarp [[label="engine_noop_handler"]];
        runtime_data -> garp_rarp [[label="garp_rarp_runtime_data_handler"]];
+       evpn_mac_binding_sync_waker [[style=filled, shape=box, fillcolor=white, 
label="evpn_mac_binding_sync_waker"]];
+       evpn_mac_binding_sync [[style=filled, shape=box, fillcolor=white, 
label="evpn_mac_binding_sync"]];
+       evpn_mac_binding_sync_waker -> evpn_mac_binding_sync [[label=""]];
+       evpn_arp -> evpn_mac_binding_sync [[label=""]];
+       SB_mac_binding -> evpn_mac_binding_sync [[label="engine_noop_handler"]];
+       runtime_data -> evpn_mac_binding_sync [[label="engine_noop_handler"]];
+       mac_cache -> evpn_mac_binding_sync [[label="engine_noop_handler"]];
+       sb_ro -> evpn_mac_binding_sync 
[[label="evpn_mac_binding_sync_sb_ro_handler"]];
        SB_acl_id [[style=filled, shape=box, fillcolor=white, 
label="SB_acl_id"]];
        acl_id [[style=filled, shape=box, fillcolor=white, label="acl_id"]];
        SB_acl_id -> acl_id [[label=""]];
@@ -498,6 +506,7 @@ digraph "Incremental-Processing-Engine" {
        bfd_chassis -> controller_output 
[[label="controller_output_bfd_chassis_handler"]];
        route_exchange -> controller_output 
[[label="controller_output_route_exchange_handler"]];
        garp_rarp -> controller_output 
[[label="controller_output_garp_rarp_handler"]];
+       evpn_mac_binding_sync -> controller_output 
[[label="controller_output_evpn_mac_binding_sync_handler"]];
        acl_id -> controller_output 
[[label="controller_output_acl_id_handler"]];
        datapaths_updated -> controller_output 
[[label="controller_output_datapaths_updated_handler"]];
 }
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index d4f2ce69e..9fc27f976 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -18505,9 +18505,9 @@ rtr_dp_key=$(fetch_column Datapath tunnel_key 
external_ids:name=lr)
 rtr_port_key=$(fetch_column Port_Binding tunnel_key logical_port=lr-ls-evpn)
 
 # Simulate remote workload ARPs (type-2 MAC+IP EVPN route).
-# ovn-controller needs to add OF rules for ARP lookup but no rules for
-# MAC_CACHE use.  These entries do not age out automatically, their lifetime
-# is controlled by the BGP-EVPN control plane.
+# EVPN-learned MAC bindings are written to the SB MAC_Binding table and
+# distributed to all chassis.  These entries do not age out automatically,
+# their lifetime is controlled by the BGP-EVPN control plane.
 check ip neigh add dev $BR_NAME 172.16.1.50 lladdr f0:00:0f:16:10:50 nud noarp 
extern_learn
 check ip neigh add dev $BR_NAME 172.16.1.60 lladdr f0:00:0f:16:10:60 nud noarp 
extern_learn
 check ip neigh add dev $BR_NAME 172.16.1.70 lladdr f0:00:0f:16:10:70 nud noarp 
extern_learn
@@ -18525,35 +18525,52 @@ OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl 
evpn/vtep-arp-list | cut -d',' -f2- | s
  VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
 ])
 
+dnl Verify EVPN-learned MAC bindings appear in the SB MAC_Binding table.
+wait_row_count MAC_Binding 1 ip=172.16.1.50
+wait_row_count MAC_Binding 1 ip=172.16.1.60
+wait_row_count MAC_Binding 1 ip=172.16.1.70
+wait_row_count MAC_Binding 1 ip="172\:16\:\:50"
+wait_row_count MAC_Binding 1 ip="172\:16\:\:60"
+wait_row_count MAC_Binding 1 ip="172\:16\:\:70"
+
 AS_BOX([Check dynamic-routing-arp-prefer-local=true])
 check ovn-nbctl --wait=hv set Logical_Switch ls-evpn 
other_config:dynamic-routing-arp-prefer-local=true
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,arp_spa=172.16.1.50,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,arp_spa=172.16.1.60,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,arp_spa=172.16.1.70,arp_op=2
 actions=drop
 
priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,nw_src=172.16.1.50
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,nw_src=172.16.1.60
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,nw_src=172.16.1.70
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,ipv6_src=172:16::50
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,ipv6_src=172:16::60
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,ipv6_src=172:16::70
 actions=drop
 ])
 
 AS_BOX([Check dynamic-routing-arp-prefer-local=false])
@@ -18562,29 +18579,38 @@ check ovn-nbctl --wait=hv set Logical_Switch ls-evpn 
other_config:dynamic-routin
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,arp_spa=172.16.1.50,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,arp_spa=172.16.1.60,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,arp_spa=172.16.1.70,arp_op=2
 actions=drop
 
priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,nw_src=172.16.1.50
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,nw_src=172.16.1.60
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,nw_src=172.16.1.70
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,ipv6_src=172:16::50
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,ipv6_src=172:16::60
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,ipv6_src=172:16::70
 actions=drop
 ])
 
 # Check that the recompute won't change the UUIDs and flows.
@@ -18651,6 +18677,14 @@ check ip -6 neigh del dev $BR_NAME 172:16::70
 OVS_WAIT_UNTIL([test "$(ovs-ofctl dump-flows br-int 
table=OFTABLE_EVPN_ARP_LOOKUP | \
                          grep -c priority)" = "0"])
 
+dnl Verify EVPN MAC_Binding rows are deleted from SB.
+wait_row_count MAC_Binding 0 ip=172.16.1.50
+wait_row_count MAC_Binding 0 ip=172.16.1.60
+wait_row_count MAC_Binding 0 ip=172.16.1.70
+wait_row_count MAC_Binding 0 ip="172\:16\:\:50"
+wait_row_count MAC_Binding 0 ip="172\:16\:\:60"
+wait_row_count MAC_Binding 0 ip="172\:16\:\:70"
+
 dnl Re-add the EVPN entries for subsequent tests.
 check ip neigh add dev $BR_NAME 172.16.1.50 lladdr f0:00:0f:16:10:50 nud noarp 
extern_learn
 check ip neigh add dev $BR_NAME 172.16.1.60 lladdr f0:00:0f:16:10:60 nud noarp 
extern_learn
@@ -18790,23 +18824,23 @@ OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl 
evpn/vtep-arp-list | cut -d',' -f2- | s
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 check ovn-nbctl --wait=hv lr-del lr
@@ -19191,9 +19225,9 @@ rtr_dp_key=$(fetch_column Datapath tunnel_key 
external_ids:name=lr)
 rtr_port_key=$(fetch_column Port_Binding tunnel_key logical_port=lr-ls-evpn)
 
 # Simulate remote workload ARPs (type-2 MAC+IP EVPN route).
-# ovn-controller needs to add OF rules for ARP lookup but no rules for
-# MAC_CACHE use.  These entries do not age out automatically, their lifetime
-# is controlled by the BGP-EVPN control plane.
+# EVPN-learned MAC bindings are written to the SB MAC_Binding table and
+# distributed to all chassis.  These entries do not age out automatically,
+# their lifetime is controlled by the BGP-EVPN control plane.
 check ip neigh add dev $BR_NAME 172.16.1.50 lladdr f0:00:0f:16:10:50 nud noarp 
extern_learn
 check ip neigh add dev $BR_NAME 172.16.1.60 lladdr f0:00:0f:16:10:60 nud noarp 
extern_learn
 check ip neigh add dev $BR_NAME 172.16.1.70 lladdr f0:00:0f:16:10:70 nud noarp 
extern_learn
@@ -19211,35 +19245,52 @@ OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl 
evpn/vtep-arp-list | cut -d',' -f2- | s
  VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
 ])
 
+dnl Verify EVPN-learned MAC bindings appear in the SB MAC_Binding table.
+wait_row_count MAC_Binding 1 ip=172.16.1.50
+wait_row_count MAC_Binding 1 ip=172.16.1.60
+wait_row_count MAC_Binding 1 ip=172.16.1.70
+wait_row_count MAC_Binding 1 ip="172\:16\:\:50"
+wait_row_count MAC_Binding 1 ip="172\:16\:\:60"
+wait_row_count MAC_Binding 1 ip="172\:16\:\:70"
+
 AS_BOX([Check dynamic-routing-arp-prefer-local=true])
 check ovn-nbctl --wait=hv set Logical_Switch ls-evpn 
other_config:dynamic-routing-arp-prefer-local=true
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,arp_spa=172.16.1.50,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,arp_spa=172.16.1.60,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,arp_spa=172.16.1.70,arp_op=2
 actions=drop
 
priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,nw_src=172.16.1.50
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,nw_src=172.16.1.60
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,nw_src=172.16.1.70
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,ipv6_src=172:16::50
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,ipv6_src=172:16::60
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,ipv6_src=172:16::70
 actions=drop
 ])
 
 AS_BOX([Check dynamic-routing-arp-prefer-local=false])
@@ -19248,29 +19299,38 @@ check ovn-nbctl --wait=hv set Logical_Switch ls-evpn 
other_config:dynamic-routin
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,arp_spa=172.16.1.50,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,arp_spa=172.16.1.60,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,arp_spa=172.16.1.70,arp_op=2
 actions=drop
 
priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,nw_src=172.16.1.50
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,nw_src=172.16.1.60
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,nw_src=172.16.1.70
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,ipv6_src=172:16::50
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,ipv6_src=172:16::60
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,ipv6_src=172:16::70
 actions=drop
 ])
 
 # Check that the recompute won't change the UUIDs and flows.
@@ -19295,6 +19355,14 @@ check ip -6 neigh del dev $BR_NAME 172:16::70
 OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2- | 
sort], [0], [dnl
 ])
 
+dnl Verify EVPN MAC_Binding rows are deleted from SB.
+wait_row_count MAC_Binding 0 ip=172.16.1.50
+wait_row_count MAC_Binding 0 ip=172.16.1.60
+wait_row_count MAC_Binding 0 ip=172.16.1.70
+wait_row_count MAC_Binding 0 ip="172\:16\:\:50"
+wait_row_count MAC_Binding 0 ip="172\:16\:\:60"
+wait_row_count MAC_Binding 0 ip="172\:16\:\:70"
+
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
@@ -19334,23 +19402,23 @@ OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl 
evpn/vtep-arp-list | cut -d',' -f2- | s
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 check ovn-nbctl --wait=hv lr-del lr
@@ -19774,9 +19842,9 @@ rtr_dp_key=$(fetch_column Datapath tunnel_key 
external_ids:name=lr)
 rtr_port_key=$(fetch_column Port_Binding tunnel_key logical_port=lr-ls-evpn)
 
 # Simulate remote workload ARPs (type-2 MAC+IP EVPN route).
-# ovn-controller needs to add OF rules for ARP lookup but no rules for
-# MAC_CACHE use.  These entries do not age out automatically, their lifetime
-# is controlled by the BGP-EVPN control plane.
+# EVPN-learned MAC bindings are written to the SB MAC_Binding table and
+# distributed to all chassis.  These entries do not age out automatically,
+# their lifetime is controlled by the BGP-EVPN control plane.
 check ip neigh add dev $BR_NAME 172.16.1.50 lladdr f0:00:0f:16:10:50 nud noarp 
extern_learn
 check ip neigh add dev $BR_NAME 172.16.1.60 lladdr f0:00:0f:16:10:60 nud noarp 
extern_learn
 check ip neigh add dev $BR_NAME 172.16.1.70 lladdr f0:00:0f:16:10:70 nud noarp 
extern_learn
@@ -19794,35 +19862,52 @@ OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl 
evpn/vtep-arp-list | cut -d',' -f2- | s
  VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
 ])
 
+dnl Verify EVPN-learned MAC bindings appear in the SB MAC_Binding table.
+wait_row_count MAC_Binding 1 ip=172.16.1.50
+wait_row_count MAC_Binding 1 ip=172.16.1.60
+wait_row_count MAC_Binding 1 ip=172.16.1.70
+wait_row_count MAC_Binding 1 ip="172\:16\:\:50"
+wait_row_count MAC_Binding 1 ip="172\:16\:\:60"
+wait_row_count MAC_Binding 1 ip="172\:16\:\:70"
+
 AS_BOX([Check dynamic-routing-arp-prefer-local=true])
 check ovn-nbctl --wait=hv set Logical_Switch ls-evpn 
other_config:dynamic-routing-arp-prefer-local=true
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,arp_spa=172.16.1.50,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,arp_spa=172.16.1.60,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,arp_spa=172.16.1.70,arp_op=2
 actions=drop
 
priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,nw_src=172.16.1.50
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,nw_src=172.16.1.60
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,nw_src=172.16.1.70
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,ipv6_src=172:16::50
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,ipv6_src=172:16::60
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,ipv6_src=172:16::70
 actions=drop
 ])
 
 AS_BOX([Check dynamic-routing-arp-prefer-local=false])
@@ -19831,29 +19916,38 @@ check ovn-nbctl --wait=hv set Logical_Switch ls-evpn 
other_config:dynamic-routin
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,arp_spa=172.16.1.50,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,arp_spa=172.16.1.60,arp_op=2
 actions=drop
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,arp_spa=172.16.1.70,arp_op=2
 actions=drop
 
priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,nw_src=172.16.1.50
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,nw_src=172.16.1.60
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,nw_src=172.16.1.70
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,ipv6_src=172:16::50
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,ipv6_src=172:16::60
 actions=drop
+priority=100,ipv6,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,ipv6_src=172:16::70
 actions=drop
 ])
 
 # Check that the recompute won't change the UUIDs and flows.
@@ -19878,6 +19972,14 @@ check ip -6 neigh del dev $BR_NAME 172:16::70
 OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2- | 
sort], [0], [dnl
 ])
 
+dnl Verify EVPN MAC_Binding rows are deleted from SB.
+wait_row_count MAC_Binding 0 ip=172.16.1.50
+wait_row_count MAC_Binding 0 ip=172.16.1.60
+wait_row_count MAC_Binding 0 ip=172.16.1.70
+wait_row_count MAC_Binding 0 ip="172\:16\:\:50"
+wait_row_count MAC_Binding 0 ip="172\:16\:\:60"
+wait_row_count MAC_Binding 0 ip="172\:16\:\:70"
+
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
@@ -19917,23 +20019,23 @@ OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl 
evpn/vtep-arp-list | cut -d',' -f2- | s
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
-priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=100,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
                    awk '{print $[7], $[8]}' | sort], [0], [dnl
 
priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
-priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=100,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
 ])
 
 check ovn-nbctl --wait=hv lr-del lr
-- 
2.55.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to