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
