From 0ea53574aa9a2e6d9dd3c40b431459a6434bf019 Mon Sep 17 00:00:00 2001 From: Eelco Chaudron Date: Wed, 29 Jan 2025 11:00:26 +0100 Subject: [PATCH] netdev-offload-tc: Fix ignore of dl type mask when installing flows. When TC parses the flow to install, it assumes that the datalink type mask is set. However, this may not always be the case, for example, when multiple VLANs exist but only one is enabled (vlan-limit). This patch will only process the dl_type if the mask is set. It also includes a unit test to verify that the TC rules are offloaded in this case. Fixes: 1be33d52af77 ("netdev-tc-offloads: Don't offload header modification on ip fragments.") Reported-at: https://issues.redhat.com/browse/FDP-1114 Acked-by: Aaron Conole Acked-by: Ilya Maximets Signed-off-by: Eelco Chaudron --- lib/netdev-offload-tc.c | 11 +++++++---- tests/system-offloads-traffic.at | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index f9ae60e94b3..66f2558ddb7 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -2251,6 +2251,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, const struct flow_tnl *tnl = &match->flow.tunnel; struct flow_tnl *tnl_mask = &mask->tunnel; struct dpif_flow_stats adjust_stats; + bool exact_match_on_dl_type; bool recirc_act = false; uint32_t block_id = 0; struct tcf_id id; @@ -2268,6 +2269,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, memset(&flower, 0, sizeof flower); + exact_match_on_dl_type = mask->dl_type == htons(0xffff); chain = key->recirc_id; mask->recirc_id = 0; @@ -2432,7 +2434,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, mask->dl_type = 0; mask->in_port.odp_port = 0; - if (key->dl_type == htons(ETH_P_ARP)) { + if (exact_match_on_dl_type && key->dl_type == htons(ETH_P_ARP)) { flower.key.arp.spa = key->nw_src; flower.key.arp.tpa = key->nw_dst; flower.key.arp.sha = key->arp_sha; @@ -2451,7 +2453,8 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, memset(&mask->arp_tha, 0, sizeof mask->arp_tha); } - if (is_ip_any(key) && !is_ipv6_fragment_and_masked(key, mask)) { + if (exact_match_on_dl_type && is_ip_any(key) + && !is_ipv6_fragment_and_masked(key, mask)) { flower.key.ip_proto = key->nw_proto; flower.mask.ip_proto = mask->nw_proto; mask->nw_proto = 0; @@ -2481,9 +2484,9 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, } else { /* This scenario should not occur. Currently, all installed IP DP * flows perform a fully masked match on the fragmentation bits. - * However, since TC depends on this behavior, we return ENOTSUPP + * However, since TC depends on this behavior, we return EOPNOTSUPP * for now in case this behavior changes in the future. */ - return EOPNOTSUPP; + return EOPNOTSUPP; } if (key->nw_proto == IPPROTO_TCP) { diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at index d33c782cf4f..7648d559468 100644 --- a/tests/system-offloads-traffic.at +++ b/tests/system-offloads-traffic.at @@ -946,3 +946,33 @@ AT_CHECK([tc -d filter show dev ovs-p0 ingress | grep -q "csum (iph)"], [0]) OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([offloads - 802.1ad should be offloaded]) +OVS_TRAFFIC_VSWITCHD_START( + [], [], [-- set Open_vSwitch . other_config:hw-offload=true]) +OVS_CHECK_8021AD() + +ADD_NAMESPACES(at_ns0, at_ns1) + +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24") +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24") + +ADD_SVLAN(p0, at_ns0, 4094, "10.255.2.1/24") +ADD_SVLAN(p1, at_ns1, 4094, "10.255.2.2/24") + +ADD_CVLAN(p0.4094, at_ns0, 100, "10.2.2.1/24") +ADD_CVLAN(p1.4094, at_ns1, 100, "10.2.2.2/24") + +AT_CHECK([ovs-ofctl add-flow br0 "priority=1 action=normal"]) + +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.2.2.2]) + +AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "eth_type(0x0800)" | DUMP_CLEAN_SORTED], [0], [dnl +in_port(2),eth(macs),eth_type(0x88a8),vlan(vid=4094,pcp=0),encap(eth_type(0x0800)), packets:0, bytes:0, used:0.001s, actions:output +in_port(3),eth(macs),eth_type(0x88a8),vlan(vid=4094,pcp=0),encap(eth_type(0x0800)), packets:0, bytes:0, used:0.001s, actions:output +]) + +AT_CHECK([ovs-appctl dpctl/dump-flows type=ovs | grep "eth_type(0x0800)" | DUMP_CLEAN_SORTED], [0], []) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP