The branch main has been updated by hselasky:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2c0ade806aa7b450dc4f4c53b5345050eb6dcb4b

commit 2c0ade806aa7b450dc4f4c53b5345050eb6dcb4b
Author:     Hans Petter Selasky <hsela...@freebsd.org>
AuthorDate: 2022-02-01 15:20:13 +0000
Commit:     Hans Petter Selasky <hsela...@freebsd.org>
CommitDate: 2022-02-01 15:21:16 +0000

    mlx5: Implement flow steering helper functions for TCP sockets.
    
    This change adds convenience functions to setup a flow steering rule based 
on
    a TCP socket. The helper function gets all the address information from the
    socket and returns a steering rule, to be used with HW TLS RX offload.
    
    MFC after:      1 week
    Sponsored by:   NVIDIA Networking
---
 sys/conf/files                            |   2 +
 sys/dev/mlx5/device.h                     |   6 +
 sys/dev/mlx5/mlx5_core/fs_tcp.h           |  41 +++
 sys/dev/mlx5/mlx5_core/mlx5_fs_tcp.c      | 404 ++++++++++++++++++++++++++++++
 sys/dev/mlx5/mlx5_en/en.h                 |  15 ++
 sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c |  57 +++--
 sys/dev/mlx5/mlx5_ifc.h                   |   6 +-
 sys/modules/mlx5/Makefile                 |   1 +
 8 files changed, 512 insertions(+), 20 deletions(-)

diff --git a/sys/conf/files b/sys/conf/files
index 48ec9511b32f..5f452f851ea6 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -4870,6 +4870,8 @@ dev/mlx5/mlx5_core/mlx5_eswitch.c         optional mlx5 
pci       \
        compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_fs_cmd.c               optional mlx5 pci       \
        compile-with "${OFED_C}"
+dev/mlx5/mlx5_core/mlx5_fs_tcp.c               optional mlx5 pci       \
+       compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_fs_tree.c              optional mlx5 pci       \
        compile-with "${OFED_C}"
 dev/mlx5/mlx5_core/mlx5_fw.c                   optional mlx5 pci       \
diff --git a/sys/dev/mlx5/device.h b/sys/dev/mlx5/device.h
index bd52d04244af..f183ca74c2d7 100644
--- a/sys/dev/mlx5/device.h
+++ b/sys/dev/mlx5/device.h
@@ -1039,6 +1039,12 @@ enum mlx5_mcam_feature_groups {
 #define MLX5_CAP_FLOWTABLE_MAX(mdev, cap) \
        MLX5_GET(flow_table_nic_cap, mdev->hca_caps_max[MLX5_CAP_FLOW_TABLE], 
cap)
 
+#define MLX5_CAP_FLOWTABLE_NIC_RX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive.cap)
+
+#define MLX5_CAP_FLOWTABLE_NIC_RX_MAX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE_MAX(mdev, flow_table_properties_nic_receive.cap)
+
 #define MLX5_CAP_ESW_FLOWTABLE(mdev, cap) \
        MLX5_GET(flow_table_eswitch_cap, \
                 mdev->hca_caps_cur[MLX5_CAP_ESWITCH_FLOW_TABLE], cap)
diff --git a/sys/dev/mlx5/mlx5_core/fs_tcp.h b/sys/dev/mlx5/mlx5_core/fs_tcp.h
new file mode 100644
index 000000000000..fa11ad9c4cb5
--- /dev/null
+++ b/sys/dev/mlx5/mlx5_core/fs_tcp.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2020-2021, Mellanox Technologies, Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __MLX5E_ACCEL_FS_TCP_H__
+#define        __MLX5E_ACCEL_FS_TCP_H__
+
+struct inpcb;
+struct mlx5_flow_rule;
+struct mlx5e_priv;
+
+int    mlx5e_accel_fs_tcp_create(struct mlx5e_priv *);
+void   mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *);
+struct mlx5_flow_rule *
+mlx5e_accel_fs_add_inpcb(struct mlx5e_priv *,
+    struct inpcb *, uint32_t tirn, uint32_t flow_tag, uint16_t vlan_id);
+#define        MLX5E_ACCEL_FS_ADD_INPCB_NO_VLAN 0xFFFF
+void   mlx5e_accel_fs_del_inpcb(struct mlx5_flow_rule *);
+
+#endif                                 /* __MLX5E_ACCEL_FS_TCP_H__ */
diff --git a/sys/dev/mlx5/mlx5_core/mlx5_fs_tcp.c 
b/sys/dev/mlx5/mlx5_core/mlx5_fs_tcp.c
new file mode 100644
index 000000000000..543c7a4ef502
--- /dev/null
+++ b/sys/dev/mlx5/mlx5_core/mlx5_fs_tcp.c
@@ -0,0 +1,404 @@
+/*-
+ * Copyright (c) 2020-2021, Mellanox Technologies, Ltd.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <dev/mlx5/mlx5_en/en.h>
+
+#include <dev/mlx5/mlx5_core/fs_core.h>
+#include <dev/mlx5/mlx5_core/fs_tcp.h>
+#include <dev/mlx5/device.h>
+
+#include <sys/domain.h>
+
+#include <netinet/in_pcb.h>
+
+#if defined(INET) || defined(INET6)
+static void
+accel_fs_tcp_set_ipv4_flow(struct mlx5_flow_spec *spec, struct inpcb *inp)
+{
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 
outer_headers.ip_protocol);
+       MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, 
IPPROTO_TCP);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 
outer_headers.ip_version);
+       MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, 
4);
+       memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
+           outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4),
+           &inp->inp_faddr, 4);
+       memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
+           outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
+           &inp->inp_laddr, 4);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+           outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+           outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
+}
+#endif
+
+#ifdef INET6
+static void
+accel_fs_tcp_set_ipv6_flow(struct mlx5_flow_spec *spec, struct inpcb *inp)
+{
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 
outer_headers.ip_protocol);
+       MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, 
IPPROTO_TCP);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 
outer_headers.ip_version);
+       MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_version, 
6);
+       memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
+           outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6),
+           &inp->in6p_faddr, 16);
+       memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
+           outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
+           &inp->in6p_laddr, 16);
+       memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+           outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6),
+           0xff, 16);
+       memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+           outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
+           0xff, 16);
+}
+#endif
+
+void
+mlx5e_accel_fs_del_inpcb(struct mlx5_flow_rule *rule)
+{
+       mlx5_del_flow_rule(rule);
+}
+
+struct mlx5_flow_rule *
+mlx5e_accel_fs_add_inpcb(struct mlx5e_priv *priv,
+    struct inpcb *inp, uint32_t tirn, uint32_t flow_tag,
+    uint16_t vlan_id)
+{
+       struct mlx5_flow_destination dest = {};
+       struct mlx5e_flow_table *ft = NULL;
+       struct mlx5e_accel_fs_tcp *fs_tcp;
+       struct mlx5_flow_rule *flow;
+       struct mlx5_flow_spec *spec;
+
+       spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
+       if (!spec)
+               return (ERR_PTR(-ENOMEM));
+
+       fs_tcp = &priv->fts.accel_tcp;
+
+       spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
+
+       INP_RLOCK(inp);
+       /* Set VLAN ID to match, if any. */
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 
outer_headers.cvlan_tag);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 
outer_headers.first_vid);
+       if (vlan_id != MLX5E_ACCEL_FS_ADD_INPCB_NO_VLAN) {
+               MLX5_SET_TO_ONES(fte_match_param, spec->match_value, 
outer_headers.cvlan_tag);
+               MLX5_SET(fte_match_param, spec->match_value, 
outer_headers.first_vid, vlan_id);
+       }
+
+       /* Set TCP port numbers. */
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+           outer_headers.tcp_dport);
+       MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
+           outer_headers.tcp_sport);
+       MLX5_SET(fte_match_param, spec->match_value, outer_headers.tcp_dport,
+           ntohs(inp->inp_lport));
+       MLX5_SET(fte_match_param, spec->match_value, outer_headers.tcp_sport,
+           ntohs(inp->inp_fport));
+
+       /* Set IP addresses. */
+       switch (INP_SOCKAF(inp->inp_socket)) {
+#ifdef INET
+       case AF_INET:
+               accel_fs_tcp_set_ipv4_flow(spec, inp);
+               ft = &fs_tcp->tables[MLX5E_ACCEL_FS_IPV4_TCP];
+               break;
+#endif
+#ifdef INET6
+       case AF_INET6:
+               if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
+                   IN6_IS_ADDR_V4MAPPED(&inp->in6p_faddr)) {
+                       accel_fs_tcp_set_ipv4_flow(spec, inp);
+                       ft = &fs_tcp->tables[MLX5E_ACCEL_FS_IPV4_TCP];
+               } else {
+                       accel_fs_tcp_set_ipv6_flow(spec, inp);
+                       ft = &fs_tcp->tables[MLX5E_ACCEL_FS_IPV6_TCP];
+               }
+               break;
+#endif
+       default:
+               break;
+       }
+       INP_RUNLOCK(inp);
+
+       if (!ft) {
+               flow = ERR_PTR(-EINVAL);
+               goto out;
+       }
+
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
+       dest.tir_num = tirn;
+
+       flow = mlx5_add_flow_rule(ft->t, spec->match_criteria_enable,
+           spec->match_criteria,
+           spec->match_value,
+           MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+           flow_tag,
+           &dest);
+out:
+       kvfree(spec);
+       return (flow);
+}
+
+static int
+accel_fs_tcp_add_default_rule(struct mlx5e_priv *priv, int type)
+{
+       static u32 match_criteria[MLX5_ST_SZ_DW(fte_match_param)];
+       static u32 match_value[MLX5_ST_SZ_DW(fte_match_param)];
+       struct mlx5_flow_destination dest = {};
+       struct mlx5e_accel_fs_tcp *fs_tcp;
+       struct mlx5_flow_rule *rule;
+
+       fs_tcp = &priv->fts.accel_tcp;
+
+       dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+
+       /*
+        * Traffic not matched by flow table rules should be forwarded
+        * to the next flow table in order to not be dropped by the
+        * default action. Refer to the diagram in
+        * mlx5_en_flow_table.c for more information about the order
+        * of flow tables.
+        */
+       dest.ft = (type == MLX5E_ACCEL_FS_TCP_NUM_TYPES - 1) ?
+           priv->fts.vlan.t : fs_tcp->tables[type + 1].t;
+
+       rule = mlx5_add_flow_rule(fs_tcp->tables[type].t, 0, match_criteria, 
match_value,
+           MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, MLX5_FS_DEFAULT_FLOW_TAG, &dest);
+       if (IS_ERR(rule))
+               return (PTR_ERR(rule));
+
+       fs_tcp->default_rules[type] = rule;
+       return (0);
+}
+
+#define        MLX5E_ACCEL_FS_TCP_NUM_GROUPS   (2)
+#define        MLX5E_ACCEL_FS_TCP_GROUP1_SIZE  (BIT(16) - 1)
+#define        MLX5E_ACCEL_FS_TCP_GROUP2_SIZE  (BIT(0))
+#define        MLX5E_ACCEL_FS_TCP_TABLE_SIZE   (MLX5E_ACCEL_FS_TCP_GROUP1_SIZE 
+\
+                                        MLX5E_ACCEL_FS_TCP_GROUP2_SIZE)
+static int
+accel_fs_tcp_create_groups(struct mlx5e_flow_table *ft, int type)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       void *outer_headers_c;
+       int ix = 0;
+       u32 *in;
+       int err;
+       u8 *mc;
+
+       ft->g = kcalloc(MLX5E_ACCEL_FS_TCP_NUM_GROUPS, sizeof(*ft->g), 
GFP_KERNEL);
+       in = kvzalloc(inlen, GFP_KERNEL);
+       if (!in || !ft->g) {
+               kfree(ft->g);
+               kvfree(in);
+               return (-ENOMEM);
+       }
+
+       mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
+       outer_headers_c = MLX5_ADDR_OF(fte_match_param, mc, outer_headers);
+       MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol);
+       MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_version);
+       MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, cvlan_tag);
+       MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, first_vid);
+
+       switch (type) {
+       case MLX5E_ACCEL_FS_IPV4_TCP:
+       case MLX5E_ACCEL_FS_IPV6_TCP:
+               MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, 
tcp_dport);
+               MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, 
tcp_sport);
+               break;
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+
+       switch (type) {
+       case MLX5E_ACCEL_FS_IPV4_TCP:
+               MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c,
+                   src_ipv4_src_ipv6.ipv4_layout.ipv4);
+               MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c,
+                   dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
+               break;
+       case MLX5E_ACCEL_FS_IPV6_TCP:
+               memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+                   src_ipv4_src_ipv6.ipv6_layout.ipv6),
+                   0xff, 16);
+               memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+                   dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
+                   0xff, 16);
+               break;
+       default:
+               err = -EINVAL;
+               goto out;
+       }
+
+       MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
+       MLX5_SET_CFG(in, start_flow_index, ix);
+       ix += MLX5E_ACCEL_FS_TCP_GROUP1_SIZE;
+       MLX5_SET_CFG(in, end_flow_index, ix - 1);
+       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
+       if (IS_ERR(ft->g[ft->num_groups]))
+               goto err;
+       ft->num_groups++;
+
+       /* Default Flow Group */
+       memset(in, 0, inlen);
+       MLX5_SET_CFG(in, start_flow_index, ix);
+       ix += MLX5E_ACCEL_FS_TCP_GROUP2_SIZE;
+       MLX5_SET_CFG(in, end_flow_index, ix - 1);
+       ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
+       if (IS_ERR(ft->g[ft->num_groups]))
+               goto err;
+       ft->num_groups++;
+
+       kvfree(in);
+       return (0);
+
+err:
+       err = PTR_ERR(ft->g[ft->num_groups]);
+       ft->g[ft->num_groups] = NULL;
+out:
+       kvfree(in);
+
+       return (err);
+}
+
+static void
+accel_fs_tcp_destroy_groups(struct mlx5e_flow_table *ft)
+{
+        int i;
+
+        for (i = ft->num_groups - 1; i >= 0; i--) {
+                if (!IS_ERR_OR_NULL(ft->g[i]))
+                        mlx5_destroy_flow_group(ft->g[i]);
+                ft->g[i] = NULL;
+        }
+        ft->num_groups = 0;
+}
+
+static int
+accel_fs_tcp_create_table(struct mlx5e_priv *priv, int type)
+{
+       struct mlx5e_flow_table *ft = &priv->fts.accel_tcp.tables[type];
+       int err;
+
+       ft->num_groups = 0;
+       ft->t = mlx5_create_flow_table(priv->fts.accel_tcp.ns, 0, "tcp",
+           MLX5E_ACCEL_FS_TCP_TABLE_SIZE);
+       if (IS_ERR(ft->t)) {
+               err = PTR_ERR(ft->t);
+               ft->t = NULL;
+               return (err);
+       }
+
+       err = accel_fs_tcp_create_groups(ft, type);
+       if (err)
+               goto err_destroy_flow_table;
+
+       return (0);
+
+err_destroy_flow_table:
+       mlx5_destroy_flow_table(ft->t);
+       ft->t = NULL;
+       return (err);
+}
+
+static void
+accel_fs_tcp_destroy_table(struct mlx5e_priv *priv, int i)
+{
+       struct mlx5e_accel_fs_tcp *fs_tcp;
+       struct mlx5e_flow_table *ft;
+
+       fs_tcp = &priv->fts.accel_tcp;
+       ft = fs_tcp->tables + i;
+
+       mlx5_del_flow_rule(fs_tcp->default_rules[i]);
+
+       accel_fs_tcp_destroy_groups(ft);
+       kfree(ft->g);
+       ft->g = NULL;
+       mlx5_destroy_flow_table(ft->t);
+       ft->t = NULL;
+}
+
+void
+mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *priv)
+{
+       int i;
+
+       if (!MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, 
ft_field_support.outer_ip_version))
+               return;
+
+       for (i = 0; i < MLX5E_ACCEL_FS_TCP_NUM_TYPES; i++)
+               accel_fs_tcp_destroy_table(priv, i);
+}
+
+int
+mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv)
+{
+       int i, err;
+
+       if (!MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, 
ft_field_support.outer_ip_version))
+               return (0);
+
+       /* Setup namespace pointer. */
+       priv->fts.accel_tcp.ns = mlx5_get_flow_namespace(
+           priv->mdev, MLX5_FLOW_NAMESPACE_OFFLOADS);
+
+       /*
+        * Create flow tables first, because the priority level is
+        * assigned at allocation time.
+        */
+       for (i = 0; i != MLX5E_ACCEL_FS_TCP_NUM_TYPES; i++) {
+               err = accel_fs_tcp_create_table(priv, i);
+               if (err)
+                       goto err_destroy_tables;
+       }
+
+       /* Create default rules last. */
+       for (i = 0; i != MLX5E_ACCEL_FS_TCP_NUM_TYPES; i++) {
+               err = accel_fs_tcp_add_default_rule(priv, i);
+               if (err)
+                       goto err_destroy_rules;
+       }
+       return (0);
+
+err_destroy_rules:
+       while (i--)
+               mlx5_del_flow_rule(priv->fts.accel_tcp.default_rules[i]);
+       i = MLX5E_ACCEL_FS_TCP_NUM_TYPES;
+
+err_destroy_tables:
+       while (i--)
+               accel_fs_tcp_destroy_table(priv, i);
+       return (err);
+}
diff --git a/sys/dev/mlx5/mlx5_en/en.h b/sys/dev/mlx5/mlx5_en/en.h
index 29898a626b38..c7e15b8968ba 100644
--- a/sys/dev/mlx5/mlx5_en/en.h
+++ b/sys/dev/mlx5/mlx5_en/en.h
@@ -72,6 +72,8 @@
 #include <dev/mlx5/mlx5_core/transobj.h>
 #include <dev/mlx5/mlx5_core/mlx5_core.h>
 
+#define        MLX5_SET_CFG(p, f, v) MLX5_SET(create_flow_group_in, p, f, v)
+
 #define        MLX5E_MAX_PRIORITY 8
 
 #define        MLX5E_MAX_FEC_10X_25X 4
@@ -1015,6 +1017,18 @@ struct mlx5e_flow_table {
        struct mlx5_flow_group **g;
 };
 
+enum accel_fs_tcp_type {
+       MLX5E_ACCEL_FS_IPV4_TCP,
+       MLX5E_ACCEL_FS_IPV6_TCP,
+       MLX5E_ACCEL_FS_TCP_NUM_TYPES,
+};
+
+struct mlx5e_accel_fs_tcp {
+       struct mlx5_flow_namespace *ns;
+       struct mlx5e_flow_table tables[MLX5E_ACCEL_FS_TCP_NUM_TYPES];
+       struct mlx5_flow_rule *default_rules[MLX5E_ACCEL_FS_TCP_NUM_TYPES];
+};
+
 struct mlx5e_flow_tables {
        struct mlx5_flow_namespace *ns;
        struct mlx5e_flow_table vlan;
@@ -1024,6 +1038,7 @@ struct mlx5e_flow_tables {
        struct mlx5e_flow_table main_vxlan;
        struct mlx5_flow_rule *main_vxlan_rule[MLX5E_NUM_TT];
        struct mlx5e_flow_table inner_rss;
+       struct mlx5e_accel_fs_tcp accel_tcp;
 };
 
 struct mlx5e_xmit_args {
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c 
b/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
index 10ff5a3e7417..5d52415381aa 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
@@ -33,28 +33,44 @@
 #include <linux/list.h>
 #include <dev/mlx5/fs.h>
 #include <dev/mlx5/mpfs.h>
+#include <dev/mlx5/mlx5_core/fs_tcp.h>
 
 /*
  * The flow tables with rules define the packet processing on receive.
- * Currently, the following structure is set up to handle different offloads
- * like VLAN decapsulation, packet classification, RSS hashing, VxLAN checksum
- * offloading:
+ * Currently the following structure is set up to handle different
+ * offloads like TLS RX offload, VLAN decapsulation, packet
+ * classification, RSS hashing, VxLAN checksum offloading:
  *
- *
- *   +=========+       +=========+     +=================+
- *   |VLAN ft: |       |VxLAN   |      |VxLAN Main       |
+ *   +=========+       +=========+      +=================+
+ *   |TCP/IPv4 |       |TCP/IPv4 |      |TCP/IPv4 Match   |
+ *   |Flowtable|------>|         |----->|Outer Proto Match|=====> TLS TIR n
+ *   |         |       |Catch-all|\     |                 |
+ *   +=========+       +=========+|     +=================+
+ *                                |
+ *       +------------------------+
+ *       V
+ *   +=========+       +=========+      +=================+
+ *   |TCP/IPv6 |       |TCP/IPv6 |      |TCP/IPv6 Match   |
+ *   |Flowtable|------>|         |----->|Outer Proto Match|=====> TLS TIR n
+ *   |         |       |Catch-all|\     |                 |
+ *   +=========+       +=========+|     +=================+
+ *                                |
+ *       +------------------------+
+ *       V
+ *   +=========+       +=========+      +=================+
+ *   |VLAN ft: |       |VxLAN    |      |VxLAN Main       |
  *   |CTAG/STAG|------>|      VNI|----->|Inner Proto Match|=====> Inner TIR n
- *   |VID/noVID|/      |Catch-all|\    |                 |
- *   +=========+       +=========+|    +=================+
- *                                       |
- *                               |
- *                               |
- *                               v
- *                     +=================+
- *                     |Main             |
- *                     |Outer Proto Match|=====> TIR n
- *                     |                 |
- *                             +=================+
+ *   |VID/noVID|/      |Catch-all|\     |                 |
+ *   +=========+       +=========+|     +=================+
+ *                                |
+ *                                |
+ *                                |
+ *                                v
+ *                      +=================+
+ *                      |Main             |
+ *                      |Outer Proto Match|=====> TIR n
+ *                      |                 |
+ *                      +=================+
  *
  * The path through flow rules directs each packet into an appropriate TIR,
  * according to the:
@@ -2292,8 +2308,14 @@ mlx5e_open_flow_tables(struct mlx5e_priv *priv)
        if (err)
                goto err_destroy_inner_rss_flow_table;
 
+       err = mlx5e_accel_fs_tcp_create(priv);
+       if (err)
+               goto err_del_vxlan_catchall_rule;
+
        return (0);
 
+err_del_vxlan_catchall_rule:
+       mlx5e_del_vxlan_catchall_rule(priv);
 err_destroy_inner_rss_flow_table:
        mlx5e_destroy_inner_rss_flow_table(priv);
 err_destroy_main_vxlan_flow_table:
@@ -2311,6 +2333,7 @@ err_destroy_vlan_flow_table:
 void
 mlx5e_close_flow_tables(struct mlx5e_priv *priv)
 {
+       mlx5e_accel_fs_tcp_destroy(priv);
        mlx5e_del_vxlan_catchall_rule(priv);
        mlx5e_destroy_inner_rss_flow_table(priv);
        mlx5e_destroy_main_vxlan_flow_table(priv);
diff --git a/sys/dev/mlx5/mlx5_ifc.h b/sys/dev/mlx5/mlx5_ifc.h
index 04aea2d0be3f..d128c9cb45cd 100644
--- a/sys/dev/mlx5/mlx5_ifc.h
+++ b/sys/dev/mlx5/mlx5_ifc.h
@@ -339,7 +339,7 @@ struct mlx5_ifc_flow_table_fields_supported_bits {
        u8         outer_dmac[0x1];
        u8         outer_smac[0x1];
        u8         outer_ether_type[0x1];
-       u8         reserved_0[0x1];
+       u8         outer_ip_version[0x1];
        u8         outer_first_prio[0x1];
        u8         outer_first_cfi[0x1];
        u8         outer_first_vid[0x1];
@@ -372,7 +372,7 @@ struct mlx5_ifc_flow_table_fields_supported_bits {
        u8         inner_dmac[0x1];
        u8         inner_smac[0x1];
        u8         inner_ether_type[0x1];
-       u8         reserved_3[0x1];
+       u8         inner_ip_version[0x1];
        u8         inner_first_prio[0x1];
        u8         inner_first_cfi[0x1];
        u8         inner_first_vid[0x1];
@@ -562,7 +562,7 @@ struct mlx5_ifc_fte_match_set_lyr_2_4_bits {
        u8         cvlan_tag[0x1];
        u8         svlan_tag[0x1];
        u8         frag[0x1];
-       u8         reserved_1[0x4];
+       u8         ip_version[0x4];
        u8         tcp_flags[0x9];
 
        u8         tcp_sport[0x10];
diff --git a/sys/modules/mlx5/Makefile b/sys/modules/mlx5/Makefile
index c9eccde7d610..f9e282789d1c 100644
--- a/sys/modules/mlx5/Makefile
+++ b/sys/modules/mlx5/Makefile
@@ -12,6 +12,7 @@ mlx5_diagnostics.c \
 mlx5_eq.c \
 mlx5_eswitch.c \
 mlx5_fs_cmd.c \
+mlx5_fs_tcp.c \
 mlx5_fs_tree.c \
 mlx5_fw.c \
 mlx5_fwdump.c \

Reply via email to