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 <amu...@redhat.com>
---
controller/lflow.c | 22 ++++++++++++++++++++++
controller/lflow.h | 1 +
northd/northd.c | 2 +-
tests/ovn-northd.at | 2 +-
tests/ovn.at | 23 ++++++++++++++++++++---
5 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/controller/lflow.c b/controller/lflow.c
index 22faaf013..bc5f73279 100644
--- a/controller/lflow.c
+++ b/controller/lflow.c
@@ -887,6 +887,7 @@ add_matches_to_flow_table(const struct sbrec_logical_flow
*lflow,
.fdb_lookup_ptable = OFTABLE_LOOKUP_FDB,
.in_port_sec_ptable = OFTABLE_CHK_IN_PORT_SEC,
.out_port_sec_ptable = OFTABLE_CHK_OUT_PORT_SEC,
+ .mac_cache_use_table = OFTABLE_MAC_CACHE_USE,
.ctrl_meter_id = ctrl_meter_id,
.common_nat_ct_zone = get_common_nat_zone(ldp),
};
@@ -1337,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;
@@ -1345,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)) {
@@ -1363,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));
@@ -1372,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;
@@ -1392,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/controller/lflow.h b/controller/lflow.h
index 2472dec29..5da4385e4 100644
--- a/controller/lflow.h
+++ b/controller/lflow.h
@@ -93,6 +93,7 @@ struct uuid;
#define OFTABLE_ECMP_NH_MAC 76
#define OFTABLE_ECMP_NH 77
#define OFTABLE_CHK_LB_AFFINITY 78
+#define OFTABLE_MAC_CACHE_USE 79
struct lflow_ctx_in {
struct ovsdb_idl_index *sbrec_multicast_group_by_name_datapath;
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 7fee42acf..7cee8a175 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -34532,12 +34532,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])
@@ -34548,6 +34559,12 @@ 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"])
+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])
AT_CHECK([fetch_column nb:logical_router options | grep -q
mac_binding_age_threshold=1])