On Tue, Aug 25, 2026 at 3:16 PM Dumitru Ceara <[email protected]> wrote:

> On 8/19/26 8:39 AM, Ales Musil via dev wrote:
> > 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]>
> > ---
>
> Hi Ales,
>
> Thanks for the fix!
>
> Overall this looks good to me, please see some minor items inline.
>

Hi Dumitru,

thank you for the review.


>
> >  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.
>
> Arguably we don't need this NEWS item.  It's a bit of an implementation
> detail, I don't think users care that much about it.  I'd remove it.
>

Ok I can remove it.


>
> >     - 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);
>
> Nit: designated initializers like we do in other cases?
>

You are right.


>
> > +    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(). */
>
> Nit: this comment is a bit of AI slop, I think.  I'd remove it, it's
> obvious what's going on below and we know that lookup by UUID is O(1)
> amortized.
>

Indded I will get rid of it.


>
> > +    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;
>
> Isn't this a bit too conservative?  We might not have any pending
> changes, right?  Should we delay setting data->sb_changes_pending until
> we actually need to update the SB somewhere later in this function?
>

So I had a design that actually deffered the sb_changed_pending
for later, but it turned out to be a mess. So I have decided to make
it easier. Let me know if I should invest time in trying to come up
with better solution.


>
> > +        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
>
> Regards,
> Dumitru
>
>
Regards,
Ales
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to