netdev_tc_flow_put() ignores the tunnel.tp_dst mask.  That results
in the exact match on the value.  TC supports the masked match on
this field and it does return the mask back during the flow dump
even if it wasn't provided initially.  OVS should correctly handle
that.  There is a problem though.  Some drivers (mlx5) doesn't
support offloading if the destination port is not an exact match [1].

Keeping the logic as-is for now, but making it explicit and somewhat
documented in the comment, so it is clear what is happening and we can
revisit this in the future.

[1] 
https://patchwork.ozlabs.org/project/openvswitch/patch/20220704224505.1117988-3-i.maxim...@ovn.org/#2927396

Signed-off-by: Ilya Maximets <i.maxim...@ovn.org>
---
 lib/netdev-offload-tc.c |  8 +++++++-
 lib/tc.c                | 13 ++++++++++---
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 750cc5682..336507d59 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -1115,7 +1115,8 @@ parse_tc_flower_to_match(struct tc_flower *flower,
                                      flower->mask.tunnel.ttl);
         }
         if (flower->key.tunnel.tp_dst) {
-            match_set_tun_tp_dst(match, flower->key.tunnel.tp_dst);
+            match_set_tun_tp_dst_masked(match, flower->key.tunnel.tp_dst,
+                                        flower->mask.tunnel.tp_dst);
         }
         if (flower->key.tunnel.metadata.present.len) {
             flower_tun_opt_to_match(match, flower);
@@ -1989,6 +1990,11 @@ netdev_tc_flow_put(struct netdev *netdev, struct match 
*match,
         flower.mask.tunnel.ipv6.ipv6_dst = tnl_mask->ipv6_dst;
         flower.mask.tunnel.tos = tnl_mask->ip_tos;
         flower.mask.tunnel.ttl = tnl_mask->ip_ttl;
+        /* XXX: We should be setting the mask from 'tnl_mask->tp_dst' here, but
+         * some hardware drivers (mlx5) doesn't support masked matches and will
+         * refuse to offload such flows keeping them in software path.
+         * Degrading the flow down to exact match for now as a workaround. */
+        flower.mask.tunnel.tp_dst = OVS_BE16_MAX;
         flower.mask.tunnel.id = (tnl->flags & FLOW_TNL_F_KEY) ? 
tnl_mask->tun_id : 0;
         flower_match_to_tun_opt(&flower, tnl, tnl_mask);
         flower.tunnel = true;
diff --git a/lib/tc.c b/lib/tc.c
index 0f3f27c11..7006e5e01 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -411,6 +411,8 @@ static const struct nl_policy tca_flower_policy[] = {
                                            .optional = true, },
     [TCA_FLOWER_KEY_ENC_UDP_DST_PORT] = { .type = NL_A_U16,
                                           .optional = true, },
+    [TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK] = { .type = NL_A_U16,
+                                               .optional = true, },
     [TCA_FLOWER_KEY_FLAGS] = { .type = NL_A_BE32, .optional = true, },
     [TCA_FLOWER_KEY_FLAGS_MASK] = { .type = NL_A_BE32, .optional = true, },
     [TCA_FLOWER_KEY_IP_TTL] = { .type = NL_A_U8,
@@ -781,7 +783,9 @@ nl_parse_flower_tunnel(struct nlattr **attrs, struct 
tc_flower *flower)
         flower->key.tunnel.ipv6.ipv6_dst =
             nl_attr_get_in6_addr(attrs[TCA_FLOWER_KEY_ENC_IPV6_DST]);
     }
-    if (attrs[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]) {
+    if (attrs[TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK]) {
+        flower->mask.tunnel.tp_dst =
+            nl_attr_get_be16(attrs[TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK]);
         flower->key.tunnel.tp_dst =
             nl_attr_get_be16(attrs[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
     }
@@ -3388,13 +3392,14 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request, struct 
tc_flower *flower)
     struct in6_addr *ipv6_dst_mask = &flower->mask.tunnel.ipv6.ipv6_dst;
     struct in6_addr *ipv6_src = &flower->key.tunnel.ipv6.ipv6_src;
     struct in6_addr *ipv6_dst = &flower->key.tunnel.ipv6.ipv6_dst;
-    ovs_be16 tp_dst = flower->key.tunnel.tp_dst;
     ovs_be32 id = be64_to_be32(flower->key.tunnel.id);
+    ovs_be16 tp_dst = flower->key.tunnel.tp_dst;
     uint8_t tos = flower->key.tunnel.tos;
     uint8_t ttl = flower->key.tunnel.ttl;
     uint8_t tos_mask = flower->mask.tunnel.tos;
     uint8_t ttl_mask = flower->mask.tunnel.ttl;
     ovs_be64 id_mask = flower->mask.tunnel.id;
+    ovs_be16 tp_dst_mask = flower->mask.tunnel.tp_dst;
 
     if (ipv4_dst_mask || ipv4_src_mask) {
         nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,
@@ -3420,8 +3425,10 @@ nl_msg_put_flower_tunnel(struct ofpbuf *request, struct 
tc_flower *flower)
         nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_IP_TTL, ttl);
         nl_msg_put_u8(request, TCA_FLOWER_KEY_ENC_IP_TTL_MASK, ttl_mask);
     }
-    if (tp_dst) {
+    if (tp_dst_mask) {
         nl_msg_put_be16(request, TCA_FLOWER_KEY_ENC_UDP_DST_PORT, tp_dst);
+        nl_msg_put_be16(request, TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,
+                        tp_dst_mask);
     }
     if (id_mask) {
         nl_msg_put_be32(request, TCA_FLOWER_KEY_ENC_KEY_ID, id);
-- 
2.34.3

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to