Populate and use the MAC cache table. The MAC cache has
the following entries:
ip,reg14=<MB_Port>,metadata=<MB_Datapath>,dl_src=<MB_MAC>,nw_src=<MB_IP> 
actions=drop
ipv6,reg14=<MB_Port>,metadata=<MB_Datapath>,dl_src=<MB_MAC>,ipv6_src=<MB_IP> 
actions=drop

The "mac_cache_use" action will resubmit packets from
"lr_in_learn_neighbor" table for MAC bindings that we already
know.

This is a preparation for the MAC binding refresh mechanism.

Signed-off-by: Ales Musil <[email protected]>
---
v2: Rebase on top of current main.
    Address comments from Mark:
    - Update test to ensure that the flows are installed.
---
 controller/lflow.c  | 21 +++++++++++++++++++++
 northd/northd.c     |  2 +-
 tests/ovn-northd.at |  2 +-
 tests/ovn.at        | 37 ++++++++++++++++++++++++++++++++-----
 4 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/controller/lflow.c b/controller/lflow.c
index 2b0058223..bc5f73279 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -1338,6 +1338,7 @@ consider_neighbor_flow(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
 
     struct match get_arp_match = MATCH_CATCHALL_INITIALIZER;
     struct match lookup_arp_match = MATCH_CATCHALL_INITIALIZER;
+    struct match mb_cache_use_match = MATCH_CATCHALL_INITIALIZER;
 
     if (strchr(ip, '.')) {
         ovs_be32 ip_addr;
@@ -1346,9 +1347,14 @@ consider_neighbor_flow(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
             VLOG_WARN_RL(&rl, "bad 'ip' %s", ip);
             return;
         }
+
         match_set_reg(&get_arp_match, 0, ntohl(ip_addr));
+
         match_set_reg(&lookup_arp_match, 0, ntohl(ip_addr));
         match_set_dl_type(&lookup_arp_match, htons(ETH_TYPE_ARP));
+
+        match_set_dl_type(&mb_cache_use_match, htons(ETH_TYPE_IP));
+        match_set_nw_src(&mb_cache_use_match, ip_addr);
     } else {
         struct in6_addr ip6;
         if (!ipv6_parse(ip, &ip6)) {
@@ -1364,6 +1370,9 @@ consider_neighbor_flow(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
         match_set_dl_type(&lookup_arp_match, htons(ETH_TYPE_IPV6));
         match_set_nw_proto(&lookup_arp_match, 58);
         match_set_icmp_code(&lookup_arp_match, 0);
+
+        match_set_dl_type(&mb_cache_use_match, htons(ETH_TYPE_IPV6));
+        match_set_ipv6_src(&mb_cache_use_match, &ip6);
     }
 
     match_set_metadata(&get_arp_match, htonll(pb->datapath->tunnel_key));
@@ -1373,6 +1382,11 @@ consider_neighbor_flow(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
     match_set_reg(&lookup_arp_match, MFF_LOG_INPORT - MFF_REG0,
                   pb->tunnel_key);
 
+    match_set_dl_src(&mb_cache_use_match, mac_addr);
+    match_set_reg(&mb_cache_use_match, MFF_LOG_INPORT - MFF_REG0,
+                  pb->tunnel_key);
+    match_set_metadata(&mb_cache_use_match, htonll(pb->datapath->tunnel_key));
+
     uint64_t stub[1024 / 8];
     struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub);
     uint8_t value = 1;
@@ -1393,6 +1407,13 @@ consider_neighbor_flow(struct ovsdb_idl_index 
*sbrec_port_binding_by_name,
                     &lookup_arp_match, &ofpacts,
                     b ? &b->header_.uuid : &smb->header_.uuid);
 
+    if (b) {
+        ofpbuf_clear(&ofpacts);
+        ofctrl_add_flow(flow_table, OFTABLE_MAC_CACHE_USE, priority,
+                        b->header_.uuid.parts[0], &mb_cache_use_match,
+                        &ofpacts, &b->header_.uuid);
+    }
+
     ofpbuf_uninit(&ofpacts);
 }
 
diff --git a/northd/northd.c b/northd/northd.c
index b9605862e..4e3c5d02a 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -12615,7 +12615,7 @@ build_neigh_learning_flows_for_lrouter(
                   learn_from_arp_request ? "" :
                   " || "REGBIT_LOOKUP_NEIGHBOR_IP_RESULT" == 0");
     ovn_lflow_add(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 100,
-                  ds_cstr(match), "next;");
+                  ds_cstr(match), "mac_cache_use; next;");
 
     ovn_lflow_metered(lflows, od, S_ROUTER_IN_LEARN_NEIGHBOR, 90,
                       "arp", "put_arp(inport, arp.spa, arp.sha); next;",
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 3e06f14c9..6298d4cec 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -7432,7 +7432,7 @@ AT_CHECK([cat lrflows | grep -e lr_in_lookup_neighbor -e 
lr_in_learn_neighbor |
   table=1 (lr_in_lookup_neighbor), priority=100  , match=(nd_na), 
action=(reg9[[2]] = lookup_nd(inport, nd.target, nd.tll); next;)
   table=1 (lr_in_lookup_neighbor), priority=100  , match=(nd_ns), 
action=(reg9[[2]] = lookup_nd(inport, ip6.src, nd.sll); next;)
   table=2 (lr_in_learn_neighbor), priority=0    , match=(1), action=(drop;)
-  table=2 (lr_in_learn_neighbor), priority=100  , match=(reg9[[2]] == 1), 
action=(next;)
+  table=2 (lr_in_learn_neighbor), priority=100  , match=(reg9[[2]] == 1), 
action=(mac_cache_use; next;)
   table=2 (lr_in_learn_neighbor), priority=90   , match=(arp), 
action=(put_arp(inport, arp.spa, arp.sha); next;)
   table=2 (lr_in_learn_neighbor), priority=90   , match=(nd_na), 
action=(put_nd(inport, nd.target, nd.tll); next;)
   table=2 (lr_in_learn_neighbor), priority=90   , match=(nd_ns), 
action=(put_nd(inport, ip6.src, nd.sll); next;)
diff --git a/tests/ovn.at b/tests/ovn.at
index 9e5a28017..f73c31974 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -34579,12 +34579,23 @@ send_garp() {
     mac_byte=$3
     ip_byte=${4-$3}
 
-    mac="0000000010$mac_byte"
-    ip=`ip_to_hex 192 168 10 $ip_byte`
-    packet=ffffffffffff${mac}08060001080006040002${mac}${ip}${mac}${ip}
+    mac="00:00:00:00:10:${mac_byte}"
+    ip="192.168.10.${ip_byte}"
+    packet=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='${mac}')/ \
+                      ARP(op=2, hwsrc='${mac}', hwdst='${mac}', \
+                      psrc='${ip}', pdst='${ip}')")
     as $hv ovs-appctl netdev-dummy/receive $dev $packet
 }
 
+send_udp() {
+    hv=$1
+    dev=$2
+    byte=$3
+
+    packet=$(fmt_pkt "Ether(dst='00:00:00:00:10:00', 
src='00:00:00:00:10:${byte}')/ \
+                      IP(dst='192.168.20.${byte}', 
src='192.168.10.${byte}')/UDP()")
+    as $hv ovs-appctl netdev-dummy/receive $dev $packet
+}
 # Check if the option is not present by default
 AT_CHECK([fetch_column nb:logical_router options name="gw" | grep -q 
mac_binding_age_threshold], [1])
 
@@ -34592,8 +34603,22 @@ AT_CHECK([fetch_column nb:logical_router options 
name="gw" | grep -q mac_binding
 send_garp hv1 ext1 10
 send_garp hv2 ext2 20
 
-OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.10"])
-OVS_WAIT_UNTIL([ovn-sbctl list mac_binding | grep -q "192.168.10.20"])
+wait_row_count mac_binding 1 ip="192.168.10.10"
+wait_row_count mac_binding 1 ip="192.168.10.20"
+
+dp_key=$(printf "0x%x" $(as hv1 fetch_column datapath tunnel_key 
external_ids:name=gw))
+port_key=$(printf "0x%x" $(as hv1 fetch_column port_binding tunnel_key 
logical_port=gw-public))
+
+AT_CHECK_UNQUOTED([as hv1 ovs-ofctl dump-flows br-int table=79 --no-stats | 
strip_cookie | sort], [0], [dnl
+ table=79, 
priority=100,ip,reg14=${port_key},metadata=${dp_key},dl_src=00:00:00:00:10:10,nw_src=192.168.10.10
 actions=drop
+ table=79, 
priority=100,ip,reg14=${port_key},metadata=${dp_key},dl_src=00:00:00:00:10:20,nw_src=192.168.10.20
 actions=drop
+])
+
+send_udp hv1 ext1 10
+send_udp hv2 ext2 20
+
+OVS_WAIT_UNTIL([as hv1 ovs-ofctl dump-flows br-int table=79 | grep 
"192.168.10.10" | grep -q "n_packets=1"])
+OVS_WAIT_UNTIL([as hv2 ovs-ofctl dump-flows br-int table=79 | grep 
"192.168.10.20" | grep -q "n_packets=1"])
 
 # Set the MAC binding aging threshold
 AT_CHECK([ovn-nbctl set logical_router gw options:mac_binding_age_threshold=1])
@@ -34610,6 +34635,8 @@ OVS_WAIT_UNTIL([
     test "0" = "$(ovn-sbctl list mac_binding | grep -c '192.168.10.20')"
 ])
 
+AT_CHECK([as hv1 ovs-ofctl dump-flows br-int table=79 --no-stats | 
strip_cookie], [0], [])
+
 OVN_CLEANUP([hv1], [hv2])
 AT_CLEANUP
 ])
-- 
2.41.0

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

Reply via email to