Commit 39ac237c authored by Paul Blakey's avatar Paul Blakey Committed by Saeed Mahameed

net/mlx5: E-Switch, Refactor chains and priorities

To support the entire chain and prio range (32bit + 16bit),
instead of a using a static array of chains/prios of limited size, create
them dynamically, and use a rhashtable to search for existing chains/prio
combinations.

This will be used in next patch to actually increase the number using
unamanged tables support and ignore flow level capability.
Signed-off-by: default avatarPaul Blakey <paulb@mellanox.com>
Reviewed-by: default avatarRoi Dayan <roid@mellanox.com>
Reviewed-by: default avatarOz Shlomo <ozsh@mellanox.com>
Reviewed-by: default avatarMark Bloch <markb@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 82270e12
...@@ -42,7 +42,7 @@ mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += en/hv_vhca_stats.o ...@@ -42,7 +42,7 @@ mlx5_core-$(CONFIG_PCI_HYPERV_INTERFACE) += en/hv_vhca_stats.o
# Core extra # Core extra
# #
mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offloads_termtbl.o \ mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offloads_termtbl.o \
ecpf.o rdma.o ecpf.o rdma.o eswitch_offloads_chains.o
mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o
mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o mlx5_core-$(CONFIG_PTP_1588_CLOCK) += lib/clock.o
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <net/ipv6_stubs.h> #include <net/ipv6_stubs.h>
#include "eswitch.h" #include "eswitch.h"
#include "eswitch_offloads_chains.h"
#include "en.h" #include "en.h"
#include "en_rep.h" #include "en_rep.h"
#include "en_tc.h" #include "en_tc.h"
...@@ -1262,25 +1263,25 @@ static int mlx5e_rep_setup_ft_cb(enum tc_setup_type type, void *type_data, ...@@ -1262,25 +1263,25 @@ static int mlx5e_rep_setup_ft_cb(enum tc_setup_type type, void *type_data,
case TC_SETUP_CLSFLOWER: case TC_SETUP_CLSFLOWER:
memcpy(&tmp, f, sizeof(*f)); memcpy(&tmp, f, sizeof(*f));
if (!mlx5_eswitch_prios_supported(esw) || if (!mlx5_esw_chains_prios_supported(esw) ||
tmp.common.chain_index) tmp.common.chain_index)
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Re-use tc offload path by moving the ft flow to the /* Re-use tc offload path by moving the ft flow to the
* reserved ft chain. * reserved ft chain.
* *
* FT offload can use prio range [0, INT_MAX], so we * FT offload can use prio range [0, INT_MAX], so we normalize
* normalize it to range [1, mlx5_eswitch_get_prio_range(esw)] * it to range [1, mlx5_esw_chains_get_prio_range(esw)]
* as with tc, where prio 0 isn't supported. * as with tc, where prio 0 isn't supported.
* *
* We only support chain 0 of FT offload. * We only support chain 0 of FT offload.
*/ */
if (tmp.common.prio >= mlx5_eswitch_get_prio_range(esw)) if (tmp.common.prio >= mlx5_esw_chains_get_prio_range(esw))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (tmp.common.chain_index != 0) if (tmp.common.chain_index != 0)
return -EOPNOTSUPP; return -EOPNOTSUPP;
tmp.common.chain_index = mlx5_eswitch_get_ft_chain(esw); tmp.common.chain_index = mlx5_esw_chains_get_ft_chain(esw);
tmp.common.prio++; tmp.common.prio++;
err = mlx5e_rep_setup_tc_cls_flower(priv, &tmp, flags); err = mlx5e_rep_setup_tc_cls_flower(priv, &tmp, flags);
memcpy(&f->stats, &tmp.stats, sizeof(f->stats)); memcpy(&f->stats, &tmp.stats, sizeof(f->stats));
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include "en_rep.h" #include "en_rep.h"
#include "en_tc.h" #include "en_tc.h"
#include "eswitch.h" #include "eswitch.h"
#include "eswitch_offloads_chains.h"
#include "fs_core.h" #include "fs_core.h"
#include "en/port.h" #include "en/port.h"
#include "en/tc_tun.h" #include "en/tc_tun.h"
...@@ -1083,7 +1084,7 @@ mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw, ...@@ -1083,7 +1084,7 @@ mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw,
memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr)); memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr));
slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
slow_attr->split_count = 0; slow_attr->split_count = 0;
slow_attr->dest_chain = FDB_TC_SLOW_PATH_CHAIN; slow_attr->flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH;
rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr); rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr);
if (!IS_ERR(rule)) if (!IS_ERR(rule))
...@@ -1100,7 +1101,7 @@ mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, ...@@ -1100,7 +1101,7 @@ mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw,
memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr)); memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr));
slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
slow_attr->split_count = 0; slow_attr->split_count = 0;
slow_attr->dest_chain = FDB_TC_SLOW_PATH_CHAIN; slow_attr->flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH;
mlx5e_tc_unoffload_fdb_rules(esw, flow, slow_attr); mlx5e_tc_unoffload_fdb_rules(esw, flow, slow_attr);
flow_flag_clear(flow, SLOW); flow_flag_clear(flow, SLOW);
} }
...@@ -1160,19 +1161,18 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, ...@@ -1160,19 +1161,18 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
u32 max_chain = mlx5_eswitch_get_chain_range(esw);
struct mlx5_esw_flow_attr *attr = flow->esw_attr; struct mlx5_esw_flow_attr *attr = flow->esw_attr;
struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr; struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
u16 max_prio = mlx5_eswitch_get_prio_range(esw);
struct net_device *out_dev, *encap_dev = NULL; struct net_device *out_dev, *encap_dev = NULL;
struct mlx5_fc *counter = NULL; struct mlx5_fc *counter = NULL;
struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_priv *rpriv;
struct mlx5e_priv *out_priv; struct mlx5e_priv *out_priv;
bool encap_valid = true; bool encap_valid = true;
u32 max_prio, max_chain;
int err = 0; int err = 0;
int out_index; int out_index;
if (!mlx5_eswitch_prios_supported(esw) && attr->prio != 1) { if (!mlx5_esw_chains_prios_supported(esw) && attr->prio != 1) {
NL_SET_ERR_MSG(extack, "E-switch priorities unsupported, upgrade FW"); NL_SET_ERR_MSG(extack, "E-switch priorities unsupported, upgrade FW");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -1182,11 +1182,13 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, ...@@ -1182,11 +1182,13 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
* FDB_FT_CHAIN which is outside tc range. * FDB_FT_CHAIN which is outside tc range.
* See mlx5e_rep_setup_ft_cb(). * See mlx5e_rep_setup_ft_cb().
*/ */
max_chain = mlx5_esw_chains_get_chain_range(esw);
if (!mlx5e_is_ft_flow(flow) && attr->chain > max_chain) { if (!mlx5e_is_ft_flow(flow) && attr->chain > max_chain) {
NL_SET_ERR_MSG(extack, "Requested chain is out of supported range"); NL_SET_ERR_MSG(extack, "Requested chain is out of supported range");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
max_prio = mlx5_esw_chains_get_prio_range(esw);
if (attr->prio > max_prio) { if (attr->prio > max_prio) {
NL_SET_ERR_MSG(extack, "Requested priority is out of supported range"); NL_SET_ERR_MSG(extack, "Requested priority is out of supported range");
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -3469,7 +3471,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, ...@@ -3469,7 +3471,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
break; break;
case FLOW_ACTION_GOTO: { case FLOW_ACTION_GOTO: {
u32 dest_chain = act->chain_index; u32 dest_chain = act->chain_index;
u32 max_chain = mlx5_eswitch_get_chain_range(esw); u32 max_chain = mlx5_esw_chains_get_chain_range(esw);
if (ft_flow) { if (ft_flow) {
NL_SET_ERR_MSG_MOD(extack, "Goto action is not supported"); NL_SET_ERR_MSG_MOD(extack, "Goto action is not supported");
......
...@@ -157,7 +157,7 @@ enum offloads_fdb_flags { ...@@ -157,7 +157,7 @@ enum offloads_fdb_flags {
ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED = BIT(0), ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED = BIT(0),
}; };
extern const unsigned int ESW_POOLS[4]; struct mlx5_esw_chains_priv;
struct mlx5_eswitch_fdb { struct mlx5_eswitch_fdb {
union { union {
...@@ -182,14 +182,7 @@ struct mlx5_eswitch_fdb { ...@@ -182,14 +182,7 @@ struct mlx5_eswitch_fdb {
struct mlx5_flow_handle *miss_rule_multi; struct mlx5_flow_handle *miss_rule_multi;
int vlan_push_pop_refcount; int vlan_push_pop_refcount;
struct { struct mlx5_esw_chains_priv *esw_chains_priv;
struct mlx5_flow_table *fdb;
u32 num_rules;
} fdb_prio[FDB_NUM_CHAINS][FDB_TC_MAX_PRIO + 1][FDB_TC_LEVELS_PER_PRIO];
/* Protects fdb_prio table */
struct mutex fdb_prio_lock;
int fdb_left[ARRAY_SIZE(ESW_POOLS)];
} offloads; } offloads;
}; };
u32 flags; u32 flags;
...@@ -355,18 +348,6 @@ mlx5_eswitch_del_fwd_rule(struct mlx5_eswitch *esw, ...@@ -355,18 +348,6 @@ mlx5_eswitch_del_fwd_rule(struct mlx5_eswitch *esw,
struct mlx5_flow_handle *rule, struct mlx5_flow_handle *rule,
struct mlx5_esw_flow_attr *attr); struct mlx5_esw_flow_attr *attr);
bool
mlx5_eswitch_prios_supported(struct mlx5_eswitch *esw);
u16
mlx5_eswitch_get_prio_range(struct mlx5_eswitch *esw);
u32
mlx5_eswitch_get_chain_range(struct mlx5_eswitch *esw);
unsigned int
mlx5_eswitch_get_ft_chain(struct mlx5_eswitch *esw);
struct mlx5_flow_handle * struct mlx5_flow_handle *
mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport, mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport,
struct mlx5_flow_destination *dest); struct mlx5_flow_destination *dest);
...@@ -391,6 +372,11 @@ enum { ...@@ -391,6 +372,11 @@ enum {
MLX5_ESW_DEST_ENCAP_VALID = BIT(1), MLX5_ESW_DEST_ENCAP_VALID = BIT(1),
}; };
enum {
MLX5_ESW_ATTR_FLAG_VLAN_HANDLED = BIT(0),
MLX5_ESW_ATTR_FLAG_SLOW_PATH = BIT(1),
};
struct mlx5_esw_flow_attr { struct mlx5_esw_flow_attr {
struct mlx5_eswitch_rep *in_rep; struct mlx5_eswitch_rep *in_rep;
struct mlx5_core_dev *in_mdev; struct mlx5_core_dev *in_mdev;
...@@ -404,7 +390,6 @@ struct mlx5_esw_flow_attr { ...@@ -404,7 +390,6 @@ struct mlx5_esw_flow_attr {
u16 vlan_vid[MLX5_FS_VLAN_DEPTH]; u16 vlan_vid[MLX5_FS_VLAN_DEPTH];
u8 vlan_prio[MLX5_FS_VLAN_DEPTH]; u8 vlan_prio[MLX5_FS_VLAN_DEPTH];
u8 total_vlan; u8 total_vlan;
bool vlan_handled;
struct { struct {
u32 flags; u32 flags;
struct mlx5_eswitch_rep *rep; struct mlx5_eswitch_rep *rep;
...@@ -419,6 +404,7 @@ struct mlx5_esw_flow_attr { ...@@ -419,6 +404,7 @@ struct mlx5_esw_flow_attr {
u32 chain; u32 chain;
u16 prio; u16 prio;
u32 dest_chain; u32 dest_chain;
u32 flags;
struct mlx5e_tc_flow_parse_attr *parse_attr; struct mlx5e_tc_flow_parse_attr *parse_attr;
}; };
......
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2020 Mellanox Technologies. */
#ifndef __ML5_ESW_CHAINS_H__
#define __ML5_ESW_CHAINS_H__
bool
mlx5_esw_chains_prios_supported(struct mlx5_eswitch *esw);
u32
mlx5_esw_chains_get_prio_range(struct mlx5_eswitch *esw);
u32
mlx5_esw_chains_get_chain_range(struct mlx5_eswitch *esw);
u32
mlx5_esw_chains_get_ft_chain(struct mlx5_eswitch *esw);
struct mlx5_flow_table *
mlx5_esw_chains_get_table(struct mlx5_eswitch *esw, u32 chain, u32 prio,
u32 level);
void
mlx5_esw_chains_put_table(struct mlx5_eswitch *esw, u32 chain, u32 prio,
u32 level);
int mlx5_esw_chains_create(struct mlx5_eswitch *esw);
void mlx5_esw_chains_destroy(struct mlx5_eswitch *esw);
#endif /* __ML5_ESW_CHAINS_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment