Add a learn flow per EVPN binding, this flow will create flows for
corresponding workloads that are ingressing from EVPN tunnel. This
allows us to avoid flooding of traffic towards unknown workloads.
The dynamic FDBs are learned only for things that are not advertised
by the EVPN itself, in other words it doesn't affect or overwrite the
static FDBs.

Reported-at: https://issues.redhat.com/browse/FDP-1673
Signed-off-by: Ales Musil <[email protected]>
---
 TODO.rst                  |  3 --
 controller/evpn-binding.c |  8 +++++
 controller/evpn-binding.h |  1 +
 controller/lflow.h        |  1 +
 controller/physical.c     | 71 +++++++++++++++++++++++++++++++++++++++
 tests/multinode.at        | 19 +++++++++++
 tests/ovn-macros.at       |  1 +
 tests/system-ovn.at       | 44 ++++++++++++++++++++++--
 8 files changed, 142 insertions(+), 6 deletions(-)

diff --git a/TODO.rst b/TODO.rst
index b992b8e5a..3a264e76b 100644
--- a/TODO.rst
+++ b/TODO.rst
@@ -158,9 +158,6 @@ OVN To-do List
     $VNI1:$LOCAL_IP1,$VNI2:$LOCAL_IP2 combinations which will be properly
     reflected in physical flows for given LS with VNI.
 
-  * Learn FDBs dynamically from the incoming traffic for EVPN. The same way
-    we do for other traffic passing through LS.
-
   * Add support for EVPN L3, that involves MAC Binding learning and
     advertisement.
 
diff --git a/controller/evpn-binding.c b/controller/evpn-binding.c
index 4170239e1..12c0da4de 100644
--- a/controller/evpn-binding.c
+++ b/controller/evpn-binding.c
@@ -121,6 +121,14 @@ evpn_binding_run(const struct evpn_binding_ctx_in 
*b_ctx_in,
             updated = true;
         }
 
+        uint16_t fdb_age_threshold =
+            MIN(smap_get_uint(&edp->ldp->datapath->external_ids,
+                              "fdb_age_threshold", 0), UINT16_MAX);
+        if (binding->fdb_age_threshold != fdb_age_threshold) {
+            binding->fdb_age_threshold = fdb_age_threshold;
+            updated = true;
+        }
+
         if (updated) {
             hmapx_add(b_ctx_out->updated_bindings, binding);
 
diff --git a/controller/evpn-binding.h b/controller/evpn-binding.h
index 38fbea0d2..29b85fc16 100644
--- a/controller/evpn-binding.h
+++ b/controller/evpn-binding.h
@@ -64,6 +64,7 @@ struct evpn_binding {
 
     ofp_port_t tunnel_ofport;
     uint32_t dp_key;
+    uint16_t fdb_age_threshold;
 };
 
 struct evpn_datapath {
diff --git a/controller/lflow.h b/controller/lflow.h
index c8a87c886..a97abd824 100644
--- a/controller/lflow.h
+++ b/controller/lflow.h
@@ -103,6 +103,7 @@ struct uuid;
 #define OFTABLE_CT_STATE_SAVE            85
 #define OFTABLE_CT_ORIG_PROTO_LOAD       86
 #define OFTABLE_GET_REMOTE_FDB           87
+#define OFTABLE_LEARN_REMOTE_FDB         88
 
 /* Common defines shared between some controller components. */
 #define CHASSIS_FLOOD_INDEX_START 0x8000
diff --git a/controller/physical.c b/controller/physical.c
index 23a579f85..48715dec5 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -2667,6 +2667,7 @@ physical_consider_evpn_binding(const struct evpn_binding 
*binding,
 
     put_load(binding->dp_key, MFF_LOG_DATAPATH, 0, 32, ofpacts);
     put_load(binding->binding_key, MFF_LOG_INPORT, 0, 32, ofpacts);
+    put_resubmit(OFTABLE_LEARN_REMOTE_FDB, ofpacts);
     put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts);
 
     ofctrl_add_flow(flow_table, OFTABLE_PHY_TO_LOG, 1050,
@@ -2713,6 +2714,63 @@ physical_consider_evpn_binding(const struct evpn_binding 
*binding,
     ofctrl_add_flow(flow_table, OFTABLE_REMOTE_VTEP_OUTPUT, 55,
                     binding->flow_uuid.parts[0],
                     match, ofpacts, &binding->flow_uuid);
+
+    /* Dynamic FDB learn flows. */
+
+
+    ofpbuf_clear(ofpacts);
+    match_init_catchall(match);
+
+    match_set_metadata(match, htonll(binding->dp_key));
+    match_set_reg(match, MFF_LOG_INPORT - MFF_REG0, binding->binding_key);
+
+    /* This has to match the flow format installed by
+     * physical_consider_evpn_fdb(). */
+    size_t ol_offset = ofpacts->size;
+    struct ofpact_learn_spec *ol_spec;
+    struct ofpact_learn *ol = ofpact_put_LEARN(ofpacts);
+    ol->cookie = htonll(binding->flow_uuid.parts[0]);
+    ol->flags = NX_LEARN_F_DELETE_LEARNED;
+    ol->priority = 150;
+    ol->table_id = OFTABLE_GET_REMOTE_FDB;
+    ol->idle_timeout = binding->fdb_age_threshold;
+
+    /* Match the learned flow on the same metadata. */
+    ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
+    ol_spec->dst.field = mf_from_id(MFF_METADATA);
+    ol_spec->dst.ofs = 0;
+    ol_spec->dst.n_bits = ol_spec->dst.field->n_bits;
+    ol_spec->n_bits = ol_spec->dst.n_bits;
+    ol_spec->dst_type = NX_LEARN_DST_MATCH;
+    ol_spec->src_type = NX_LEARN_SRC_FIELD;
+    ol_spec->src.field = mf_from_id(MFF_METADATA);
+
+    /* Match ETH_DST on ETH_SRC of the incoming packet. */
+    ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
+    ol_spec->dst.field = mf_from_id(MFF_ETH_DST);
+    ol_spec->dst.ofs = 0;
+    ol_spec->dst.n_bits = ol_spec->dst.field->n_bits;
+    ol_spec->n_bits = ol_spec->dst.n_bits;
+    ol_spec->dst_type = NX_LEARN_DST_MATCH;
+    ol_spec->src_type = NX_LEARN_SRC_FIELD;
+    ol_spec->src.field = mf_from_id(MFF_ETH_SRC);
+
+    /* Load the INPORT value into REMOTE_OUTPORT. */
+    ol_spec = ofpbuf_put_zeros(ofpacts, sizeof *ol_spec);
+    ol_spec->dst.field = mf_from_id(MFF_LOG_REMOTE_OUTPORT);
+    ol_spec->dst.ofs = 0;
+    ol_spec->dst.n_bits = ol_spec->dst.field->n_bits;
+    ol_spec->n_bits = ol_spec->dst.n_bits;
+    ol_spec->dst_type = NX_LEARN_DST_LOAD;
+    ol_spec->src_type = NX_LEARN_SRC_FIELD;
+    ol_spec->src.field = mf_from_id(MFF_LOG_INPORT);
+
+    ol = ofpbuf_at_assert(ofpacts, ol_offset, sizeof *ol);
+    ofpact_finish_LEARN(ofpacts, &ol);
+
+    ofctrl_add_flow(flow_table, OFTABLE_LEARN_REMOTE_FDB, 100,
+                    binding->flow_uuid.parts[0],
+                    match, ofpacts, &binding->flow_uuid);
 }
 
 static void
@@ -2768,6 +2826,7 @@ physical_consider_evpn_fdb(const struct evpn_fdb *fdb,
                            struct ofpbuf *ofpacts, struct match *match,
                            struct ovn_desired_flow_table *flow_table)
 {
+    /* Static FDB flow. */
     ofpbuf_clear(ofpacts);
     match_init_catchall(match);
 
@@ -2778,6 +2837,18 @@ physical_consider_evpn_fdb(const struct evpn_fdb *fdb,
     ofctrl_add_flow(flow_table, OFTABLE_GET_REMOTE_FDB, 150,
                     fdb->flow_uuid.parts[0],
                     match, ofpacts, &fdb->flow_uuid);
+
+    /* Prevent dynamic learning if it's already known via static FDB. */
+    ofpbuf_clear(ofpacts);
+    match_init_catchall(match);
+
+    match_set_metadata(match, htonll(fdb->dp_key));
+    match_set_reg(match, MFF_LOG_INPORT - MFF_REG0, fdb->binding_key);
+    match_set_dl_src(match, fdb->mac);
+
+    ofctrl_add_flow(flow_table, OFTABLE_LEARN_REMOTE_FDB, 150,
+                    fdb->flow_uuid.parts[0],
+                    match, ofpacts, &fdb->flow_uuid);
 }
 
 static void
diff --git a/tests/multinode.at b/tests/multinode.at
index af9494509..c6a414af3 100644
--- a/tests/multinode.at
+++ b/tests/multinode.at
@@ -3693,6 +3693,7 @@ check m_as ovn-gw-1 ip netns exec fabric_workload ip link 
set evpn_host addr 00:
 check m_as ovn-gw-1 ip netns exec fabric_workload ip addr add dev evpn_host 
10.0.0.41/24
 check m_as ovn-gw-1 ip netns exec fabric_workload ip link set evpn_host up
 check m_as ovn-gw-1 ip netns exec fabric_workload ip r a default via 10.0.0.1
+check m_as ovn-gw-1 ip netns exec frr-ns ip link set address 00:00:10:00:00:81 
dev br-10
 check m_as ovn-gw-1 ip netns exec frr-ns ip a a dev br-10 10.0.0.81/24
 
 check m_as ovn-gw-2 ip netns add fabric_workload
@@ -3707,6 +3708,7 @@ check m_as ovn-gw-2 ip netns exec fabric_workload ip link 
set evpn_host addr 00:
 check m_as ovn-gw-2 ip netns exec fabric_workload ip addr add dev evpn_host 
10.0.0.42/24
 check m_as ovn-gw-2 ip netns exec fabric_workload ip link set evpn_host up
 check m_as ovn-gw-2 ip netns exec fabric_workload ip r a default via 10.0.0.1
+check m_as ovn-gw-2 ip netns exec frr-ns ip link set address 00:00:10:00:00:82 
dev br-10
 check m_as ovn-gw-2 ip netns exec frr-ns ip a a dev br-10 10.0.0.82/24
 
 AS_BOX([Checking EVPN MACs on External BGP host])
@@ -3809,6 +3811,18 @@ AS_BOX([Check traffic to "fabric" hosts - ping from 
internal hosts])
 OVS_WAIT_UNTIL([m_as ovn-gw-1 ip netns exec w-int1 ping -W 1 -c 1 10.0.0.41])
 OVS_WAIT_UNTIL([m_as ovn-gw-2 ip netns exec w-int2 ping -W 1 -c 1 10.0.0.42])
 
+AS_BOX([Check traffic to "fabric" hosts - ping from VNI bridge])
+OVS_WAIT_UNTIL([m_as ovn-gw-1 ip netns exec frr-ns ip vrf exec vrf-10 ping -W 
1 -c 3 10.0.0.11])
+OVS_WAIT_UNTIL([m_as ovn-gw-2 ip netns exec frr-ns ip vrf exec vrf-10 ping -W 
1 -c 3 10.0.0.12])
+
+# Check if the dynamic FDB was created.
+OVS_WAIT_FOR_OUTPUT([m_as ovn-gw-1 ovs-ofctl dump-flows br-int 
table=OFTABLE_GET_REMOTE_FDB,dl_dst=00:00:10:00:00:81 | grep -c "cookie"], [0], 
[dnl
+1
+])
+OVS_WAIT_FOR_OUTPUT([m_as ovn-gw-2 ovs-ofctl dump-flows br-int 
table=OFTABLE_GET_REMOTE_FDB,dl_dst=00:00:10:00:00:82 | grep -c "cookie"], [0], 
[dnl
+1
+])
+
 # Remove "workloads" (VIF LSPs) on both chassis.
 check multinode_nbctl --wait=hv lsp-del w1 -- lsp-del w2
 
@@ -3831,6 +3845,11 @@ MAC               Type   Flags Intf/Remote ES/VTEP       
     VLAN  Seq #'s
 00:00:00:00:02:00 local        evpn_host_peer                       0/0
 ])
 
+# Check if the dynamic FDB was removed.
+check multinode_nbctl --wait=hv remove logical_switch ls other_config 
dynamic-routing-vni
+OVS_WAIT_FOR_OUTPUT([m_as ovn-gw-1 ovs-ofctl dump-flows br-int 
table=OFTABLE_GET_REMOTE_FDB,dl_dst=00:00:10:00:00:81 | grep -q "cookie"], [1])
+OVS_WAIT_FOR_OUTPUT([m_as ovn-gw-2 ovs-ofctl dump-flows br-int 
table=OFTABLE_GET_REMOTE_FDB,dl_dst=00:00:10:00:00:82 | grep -q "cookie"], [1])
+
 AT_CLEANUP
 
 AT_SETUP([redirect-bridged to non-gw destination switch port])
diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at
index 357465fa9..cc16fe029 100644
--- a/tests/ovn-macros.at
+++ b/tests/ovn-macros.at
@@ -1517,5 +1517,6 @@ m4_define([OFTABLE_FLOOD_REMOTE_CHASSIS], [84])
 m4_define([OFTABLE_CT_STATE_SAVE], [85])
 m4_define([OFTABLE_CT_ORIG_PROTO_LOAD], [86])
 m4_define([OFTABLE_GET_REMOTE_FDB], [87])
+m4_define([OFTABLE_LEARN_REMOTE_FDB], [88])
 
 m4_define([OFTABLE_SAVE_INPORT_HEX], [m4_eval(OFTABLE_SAVE_INPORT, 16)])
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 64ec460ba..fd07195e6 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -18495,7 +18495,7 @@ OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl 
evpn/vtep-multicast-group-list | cut -d
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG | grep 
priority=1050 | \
                    awk '{print $7, $8}' | sort], [0], [dnl
-priority=1050,tun_id=0xa,tun_src=169.0.0.10,tun_dst=169.0.0.1,in_port=$ofport 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000001->NXM_NX_REG14[[]],resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
+priority=1050,tun_id=0xa,tun_src=169.0.0.10,tun_dst=169.0.0.1,in_port=$ofport 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000001->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
 ])
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int 
table=OFTABLE_REMOTE_VTEP_OUTPUT | grep output | \
@@ -18507,6 +18507,11 @@ priority=50,reg15=0x8004,metadata=0x$dp_key 
actions=load:0xa9000001->NXM_NX_TUN_
 priority=55,reg10=0x1/0x1,reg15=0x80000001,metadata=0x$dp_key 
actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa900000a->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
 ])
 
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $7, $8}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+])
+
 # Simulate second remote VTEP.
 check bridge fdb append 00:00:00:00:00:00 dev vxlan-$vni dst 169.0.0.20 static 
permanent
 
@@ -18528,8 +18533,8 @@ AT_CHECK([ovn-appctl evpn/vtep-multicast-group-list | 
wc -l], [0], [1
 
 AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG | grep 
priority=1050 | \
                    awk '{print $7, $8}' | sort], [0], [dnl
-priority=1050,tun_id=0xa,tun_src=169.0.0.10,tun_dst=169.0.0.1,in_port=$ofport 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000001->NXM_NX_REG14[[]],resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
-priority=1050,tun_id=0xa,tun_src=169.0.0.20,tun_dst=169.0.0.1,in_port=$ofport 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000002->NXM_NX_REG14[[]],resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
+priority=1050,tun_id=0xa,tun_src=169.0.0.10,tun_dst=169.0.0.1,in_port=$ofport 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000001->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
+priority=1050,tun_id=0xa,tun_src=169.0.0.20,tun_dst=169.0.0.1,in_port=$ofport 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000002->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
 ])
 
 ovs-ofctl dump-flows br-int table=OFTABLE_REMOTE_VTEP_OUTPUT > 
oftable_remote_vtep_output
@@ -18541,6 +18546,12 @@ 
priority=55,reg10=0x1/0x1,reg15=0x80000001,metadata=0x$dp_key actions=load:0xa90
 priority=55,reg10=0x1/0x1,reg15=0x80000002,metadata=0x$dp_key 
actions=load:0xa9000001->NXM_NX_TUN_IPV4_SRC[[]],load:0xa9000014->NXM_NX_TUN_IPV4_DST[[]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
 ])
 
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $7, $8}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000002,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+])
+
 AT_CHECK([grep "resubmit" oftable_remote_vtep_output | grep -c 
"load:0xa900000a"], [0], [3
 ])
 AT_CHECK([grep "resubmit" oftable_remote_vtep_output | grep -c 
"load:0xa9000014"], [0], [3
@@ -18562,6 +18573,14 @@ 
priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:50 actions=load:0x80000001
 priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:60 
actions=load:0x80000002->NXM_NX_REG1[[]]
 ])
 
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $7, $8}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000002,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50 
actions=drop
+priority=150,reg14=0x80000002,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60 
actions=drop
+])
+
 # Check that the recompute won't change the UUIDs and tunnel keys.
 ovn-appctl evpn/vtep-binding-list > bindings_before
 ovn-appctl evpn/vtep-multicast-group-list > mc_groups_before
@@ -18598,6 +18617,25 @@ check ovn-nbctl --wait=hv remove logical_switch 
ls-evpn other_config dynamic-rou
 OVS_WAIT_FOR_OUTPUT([bridge fdb show | grep "lo-10" | grep "f0:00:0f:16:01" | 
sort], [0], [dnl
 ])
 
+check ovn-nbctl --wait=hv set logical_switch ls-evpn 
other_config:fdb_age_threshold=300
+ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $7, $8}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,idle_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000002,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,idle_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50 
actions=drop
+priority=150,reg14=0x80000002,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60 
actions=drop
+])
+
+check ovn-nbctl --wait=hv remove logical_switch ls-evpn other_config 
fdb_age_threshold
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $7, $8}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000002,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50 
actions=drop
+priority=150,reg14=0x80000002,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60 
actions=drop
+])
+
 AS_BOX([L2 EVPN ARP learning])
 # Add a router connected to the EVPN logical switch.
 check ovn-nbctl --wait=hv                                    \
-- 
2.51.0

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

Reply via email to