aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2022-02-01 15:20:13 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2022-02-01 15:21:16 +0000
commit2c0ade806aa7b450dc4f4c53b5345050eb6dcb4b (patch)
treefbcc7b765cc185af8e41ba76407061d75b09b6d9
parent0ee1b09eaa99ed96885fd024a32baf182411a35a (diff)
-rw-r--r--sys/conf/files2
-rw-r--r--sys/dev/mlx5/device.h6
-rw-r--r--sys/dev/mlx5/mlx5_core/fs_tcp.h41
-rw-r--r--sys/dev/mlx5/mlx5_core/mlx5_fs_tcp.c404
-rw-r--r--sys/dev/mlx5/mlx5_en/en.h15
-rw-r--r--sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c57
-rw-r--r--sys/dev/mlx5/mlx5_ifc.h6
-rw-r--r--sys/modules/mlx5/Makefile1
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 \