This patch adds support for TC to match on tunnel flags,
if supported by the kernel. If the kernel does not support this,
it will fall back to the previous behavior, ignoring the DF and
CSUM flags.

Acked-by: Roi Dayan <[email protected]>
Signed-off-by: Eelco Chaudron <[email protected]>
---
 lib/netdev-offload-tc.c | 74 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 68 insertions(+), 6 deletions(-)

diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index a2aa4062a..c6aa51c68 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -737,6 +737,36 @@ flower_tun_opt_to_match(struct match *match, struct 
tc_flower *flower)
     }
 }
 
+static void
+flower_tun_enc_flags_to_match(struct match *match, struct tc_flower *flower)
+{
+    uint32_t tc_flags = flower->key.tunnel.tc_enc_flags;
+    uint32_t tc_mask = flower->mask.tunnel.tc_enc_flags;
+    uint16_t *m_flags = &match->flow.tunnel.flags;
+    uint16_t *m_mask = &match->wc.masks.tunnel.flags;
+
+    if (tc_mask & TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM) {
+        if (tc_flags & TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM) {
+            *m_flags |= FLOW_TNL_F_OAM;
+        }
+        *m_mask |= FLOW_TNL_F_OAM;
+    }
+
+    if (tc_mask & TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT) {
+        if (tc_flags & TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT) {
+            *m_flags |= FLOW_TNL_F_DONT_FRAGMENT;
+        }
+        *m_mask |= FLOW_TNL_F_DONT_FRAGMENT;
+    }
+
+    if (tc_mask & TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM) {
+        if (tc_flags & TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM) {
+            *m_flags |= FLOW_TNL_F_CSUM;
+        }
+        *m_mask |= FLOW_TNL_F_CSUM;
+    }
+}
+
 static void
 parse_tc_flower_to_stats(struct tc_flower *flower,
                          struct dpif_flow_stats *stats)
@@ -1272,6 +1302,9 @@ parse_tc_flower_to_match(const struct netdev *netdev,
                                            flower->key.tunnel.gbp.flags,
                                            flower->mask.tunnel.gbp.flags);
         }
+        if (flower->mask.tunnel.tc_enc_flags) {
+            flower_tun_enc_flags_to_match(match, flower);
+        }
 
         if (!strcmp(netdev_get_type(netdev), "geneve")) {
             flower_tun_opt_to_match(match, flower);
@@ -2293,12 +2326,41 @@ netdev_tc_flow_put(struct netdev *netdev, struct match 
*match,
         memset(&tnl_mask->gbp_flags, 0, sizeof tnl_mask->gbp_flags);
         tnl_mask->flags &= ~FLOW_TNL_F_KEY;
 
-        /* XXX: This is wrong!  We're ignoring DF and CSUM flags configuration
-         * requested by the user.  However, TC for now has no way to pass
-         * these flags in a flower key and their masks are set by default,
-         * meaning tunnel offloading will not work at all if not cleared.
-         * Keeping incorrect behavior for now. */
-        tnl_mask->flags &= ~(FLOW_TNL_F_DONT_FRAGMENT | FLOW_TNL_F_CSUM);
+        if (enc_flags_support) {
+            if (tnl_mask->flags & FLOW_TNL_F_OAM) {
+                if (tnl->flags & FLOW_TNL_F_OAM) {
+                    flower.key.tunnel.tc_enc_flags |=
+                        TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM;
+                }
+                flower.mask.tunnel.tc_enc_flags |=
+                    TCA_FLOWER_KEY_FLAGS_TUNNEL_OAM;
+                tnl_mask->flags &= ~FLOW_TNL_F_OAM;
+            }
+            if (tnl_mask->flags & FLOW_TNL_F_DONT_FRAGMENT) {
+                if (tnl->flags & FLOW_TNL_F_DONT_FRAGMENT) {
+                    flower.key.tunnel.tc_enc_flags |=
+                        TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT;
+                }
+                flower.mask.tunnel.tc_enc_flags |=
+                    TCA_FLOWER_KEY_FLAGS_TUNNEL_DONT_FRAGMENT;
+                tnl_mask->flags &= ~FLOW_TNL_F_DONT_FRAGMENT;
+            }
+            if (tnl_mask->flags & FLOW_TNL_F_CSUM) {
+                if (tnl->flags & FLOW_TNL_F_CSUM) {
+                    flower.key.tunnel.tc_enc_flags |=
+                        TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM;
+                }
+                flower.mask.tunnel.tc_enc_flags |=
+                    TCA_FLOWER_KEY_FLAGS_TUNNEL_CSUM;
+                tnl_mask->flags &= ~FLOW_TNL_F_CSUM;
+            }
+        } else {
+            /* For kernels not supporting the encapsulation flags we're
+             * ignoring DF and CSUM flags configuration requested by the user.
+             * This to keep the old, incorrect behaviour, and allow tunnels to
+             * be offloaded by TC with these kernels. */
+            tnl_mask->flags &= ~(FLOW_TNL_F_DONT_FRAGMENT | FLOW_TNL_F_CSUM);
+        }
 
         if (!strcmp(netdev_get_type(netdev), "geneve")) {
             err = flower_match_to_tun_opt(&flower, tnl, tnl_mask);
-- 
2.46.0

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

Reply via email to