mlx5-updates-2021-04-13
mlx5 core and netdev driver updates 1) E-Switch updates from Parav, 1.1) Devlink parameter to control mlx5 metadata enablement for E-Switch 1.2) Trivial cleanups for E-Switch code 1.3) Dynamically allocate vport steering namespaces only when required 2) From Jianbo, Use variably sized data structures for Software steering 3) Several minor cleanups -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEGhZs6bAKwk/OTgTpSD+KveBX+j4FAmB3LmAACgkQSD+KveBX +j6pfAf+MX75+oMpkrSdyLu6ZXIlc4aFWzJmbzngZud+Du1OrUZY3GSwT65Lq6rV ZJ7YAuqwbRB3JzxcWO4u+yEhLoWaY/G/Hyns6OKvIeXZzKhBAQTLU5GrYppVkS9f 1xTpbDbaOlQ0qi63NfQgTEK+XKzP8EFwt53UXZsSmq7tTzZJ85bLRRdGU5HeYBgD SS6q+7jdZZ8PCClpfK8qZ7L6JlEXPG91HKpRMWGz2FHZhN7tFRk5PGDiF3hOpXOn 0fPlg4dQ6u0/fFwOoSkUoSpzR5tSm1mjByTT0MYo/sQx+lQsFAJfXkDiHNdjKBHF 3wLpMzOkhay1iJvYYeK887Kts14LsQ== =sgu9 -----END PGP SIGNATURE----- Merge tag 'mlx5-updates-2021-04-13' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux Saeed Mahameed says: ==================== mlx5-updates-2021-04-13 mlx5 core and netdev driver updates 1) E-Switch updates from Parav, 1.1) Devlink parameter to control mlx5 metadata enablement for E-Switch 1.2) Trivial cleanups for E-Switch code 1.3) Dynamically allocate vport steering namespaces only when required 2) From Jianbo, Use variably sized data structures for Software steering 3) Several minor cleanups ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4a65912fde
|
@ -183,6 +183,40 @@ User command examples:
|
|||
values:
|
||||
cmode driverinit value true
|
||||
|
||||
esw_port_metadata: Eswitch port metadata state
|
||||
----------------------------------------------
|
||||
When applicable, disabling Eswitch metadata can increase packet rate
|
||||
up to 20% depending on the use case and packet sizes.
|
||||
|
||||
Eswitch port metadata state controls whether to internally tag packets with
|
||||
metadata. Metadata tagging must be enabled for multi-port RoCE, failover
|
||||
between representors and stacked devices.
|
||||
By default metadata is enabled on the supported devices in E-switch.
|
||||
Metadata is applicable only for E-switch in switchdev mode and
|
||||
users may disable it when NONE of the below use cases will be in use:
|
||||
1. HCA is in Dual/multi-port RoCE mode.
|
||||
2. VF/SF representor bonding (Usually used for Live migration)
|
||||
3. Stacked devices
|
||||
|
||||
When metadata is disabled, the above use cases will fail to initialize if
|
||||
users try to enable them.
|
||||
|
||||
- Show eswitch port metadata::
|
||||
|
||||
$ devlink dev param show pci/0000:06:00.0 name esw_port_metadata
|
||||
pci/0000:06:00.0:
|
||||
name esw_port_metadata type driver-specific
|
||||
values:
|
||||
cmode runtime value true
|
||||
|
||||
- Disable eswitch port metadata::
|
||||
|
||||
$ devlink dev param set pci/0000:06:00.0 name esw_port_metadata value false cmode runtime
|
||||
|
||||
- Change eswitch mode to switchdev mode where after choosing the metadata value::
|
||||
|
||||
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
|
||||
|
||||
mlx5 subfunction
|
||||
================
|
||||
mlx5 supports subfunction management using devlink port (see :ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>`) interface.
|
||||
|
|
|
@ -50,7 +50,7 @@ mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o
|
|||
# Core extra
|
||||
#
|
||||
mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offloads_termtbl.o \
|
||||
ecpf.o rdma.o
|
||||
ecpf.o rdma.o esw/legacy.o
|
||||
mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \
|
||||
esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \
|
||||
esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o \
|
||||
|
|
|
@ -456,6 +456,50 @@ static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_devlink_esw_port_metadata_set(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
if (!MLX5_ESWITCH_MANAGER(dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return mlx5_esw_offloads_vport_metadata_set(dev->priv.eswitch, ctx->val.vbool);
|
||||
}
|
||||
|
||||
static int mlx5_devlink_esw_port_metadata_get(struct devlink *devlink, u32 id,
|
||||
struct devlink_param_gset_ctx *ctx)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
|
||||
if (!MLX5_ESWITCH_MANAGER(dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ctx->val.vbool = mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_devlink_esw_port_metadata_validate(struct devlink *devlink, u32 id,
|
||||
union devlink_param_value val,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
u8 esw_mode;
|
||||
|
||||
if (!MLX5_ESWITCH_MANAGER(dev)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "E-Switch is unsupported");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
esw_mode = mlx5_eswitch_mode(dev);
|
||||
if (esw_mode == MLX5_ESWITCH_OFFLOADS) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"E-Switch must either disabled or non switchdev mode");
|
||||
return -EBUSY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int mlx5_devlink_enable_remote_dev_reset_set(struct devlink *devlink, u32 id,
|
||||
|
@ -490,6 +534,12 @@ static const struct devlink_param mlx5_devlink_params[] = {
|
|||
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
|
||||
NULL, NULL,
|
||||
mlx5_devlink_large_group_num_validate),
|
||||
DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_PORT_METADATA,
|
||||
"esw_port_metadata", DEVLINK_PARAM_TYPE_BOOL,
|
||||
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
||||
mlx5_devlink_esw_port_metadata_get,
|
||||
mlx5_devlink_esw_port_metadata_set,
|
||||
mlx5_devlink_esw_port_metadata_validate),
|
||||
#endif
|
||||
DEVLINK_PARAM_GENERIC(ENABLE_REMOTE_DEV_RESET, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
||||
mlx5_devlink_enable_remote_dev_reset_get,
|
||||
|
@ -519,6 +569,18 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
|
|||
devlink_param_driverinit_value_set(devlink,
|
||||
MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
|
||||
value);
|
||||
|
||||
if (MLX5_ESWITCH_MANAGER(dev)) {
|
||||
if (mlx5_esw_vport_match_metadata_supported(dev->priv.eswitch)) {
|
||||
dev->priv.eswitch->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
|
||||
value.vbool = true;
|
||||
} else {
|
||||
value.vbool = false;
|
||||
}
|
||||
devlink_param_driverinit_value_set(devlink,
|
||||
MLX5_DEVLINK_PARAM_ID_ESW_PORT_METADATA,
|
||||
value);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ enum mlx5_devlink_param_id {
|
|||
MLX5_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
|
||||
MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE,
|
||||
MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
|
||||
MLX5_DEVLINK_PARAM_ID_ESW_PORT_METADATA,
|
||||
};
|
||||
|
||||
struct mlx5_trap_ctx {
|
||||
|
|
|
@ -392,11 +392,11 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv)
|
|||
{
|
||||
struct arfs_rule *arfs_rule;
|
||||
struct hlist_node *htmp;
|
||||
HLIST_HEAD(del_list);
|
||||
int quota = 0;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
HLIST_HEAD(del_list);
|
||||
spin_lock_bh(&priv->fs.arfs->arfs_lock);
|
||||
mlx5e_for_each_arfs_rule(arfs_rule, htmp, priv->fs.arfs->arfs_tables, i, j) {
|
||||
if (!work_pending(&arfs_rule->arfs_work) &&
|
||||
|
@ -422,10 +422,10 @@ static void arfs_del_rules(struct mlx5e_priv *priv)
|
|||
{
|
||||
struct hlist_node *htmp;
|
||||
struct arfs_rule *rule;
|
||||
HLIST_HEAD(del_list);
|
||||
int i;
|
||||
int j;
|
||||
|
||||
HLIST_HEAD(del_list);
|
||||
spin_lock_bh(&priv->fs.arfs->arfs_lock);
|
||||
mlx5e_for_each_arfs_rule(rule, htmp, priv->fs.arfs->arfs_tables, i, j) {
|
||||
hlist_del_init(&rule->hlist);
|
||||
|
|
|
@ -510,6 +510,7 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params,
|
|||
rq->page_pool = NULL;
|
||||
goto err_free_by_rq_type;
|
||||
}
|
||||
if (xdp_rxq_info_is_reg(&rq->xdp_rxq))
|
||||
err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq,
|
||||
MEM_TYPE_PAGE_POOL, rq->page_pool);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,509 @@
|
|||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
|
||||
/* Copyright (c) 2021 Mellanox Technologies Ltd */
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/mlx5/driver.h>
|
||||
#include <linux/mlx5/mlx5_ifc.h>
|
||||
#include <linux/mlx5/vport.h>
|
||||
#include <linux/mlx5/fs.h>
|
||||
#include "esw/acl/lgcy.h"
|
||||
#include "esw/legacy.h"
|
||||
#include "mlx5_core.h"
|
||||
#include "eswitch.h"
|
||||
#include "fs_core.h"
|
||||
|
||||
enum {
|
||||
LEGACY_VEPA_PRIO = 0,
|
||||
LEGACY_FDB_PRIO,
|
||||
};
|
||||
|
||||
static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
struct mlx5_flow_table_attr ft_attr = {};
|
||||
struct mlx5_core_dev *dev = esw->dev;
|
||||
struct mlx5_flow_namespace *root_ns;
|
||||
struct mlx5_flow_table *fdb;
|
||||
int err;
|
||||
|
||||
root_ns = mlx5_get_fdb_sub_ns(dev, 0);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get FDB flow namespace\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* num FTE 2, num FG 2 */
|
||||
ft_attr.prio = LEGACY_VEPA_PRIO;
|
||||
ft_attr.max_fte = 2;
|
||||
ft_attr.autogroup.max_num_groups = 2;
|
||||
fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
|
||||
if (IS_ERR(fdb)) {
|
||||
err = PTR_ERR(fdb);
|
||||
esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
esw->fdb_table.legacy.vepa_fdb = fdb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
esw_debug(esw->dev, "Destroy FDB Table\n");
|
||||
if (!esw->fdb_table.legacy.fdb)
|
||||
return;
|
||||
|
||||
if (esw->fdb_table.legacy.promisc_grp)
|
||||
mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
|
||||
if (esw->fdb_table.legacy.allmulti_grp)
|
||||
mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
|
||||
if (esw->fdb_table.legacy.addr_grp)
|
||||
mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
|
||||
mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
|
||||
|
||||
esw->fdb_table.legacy.fdb = NULL;
|
||||
esw->fdb_table.legacy.addr_grp = NULL;
|
||||
esw->fdb_table.legacy.allmulti_grp = NULL;
|
||||
esw->fdb_table.legacy.promisc_grp = NULL;
|
||||
atomic64_set(&esw->user_count, 0);
|
||||
}
|
||||
|
||||
static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
|
||||
struct mlx5_flow_table_attr ft_attr = {};
|
||||
struct mlx5_core_dev *dev = esw->dev;
|
||||
struct mlx5_flow_namespace *root_ns;
|
||||
struct mlx5_flow_table *fdb;
|
||||
struct mlx5_flow_group *g;
|
||||
void *match_criteria;
|
||||
int table_size;
|
||||
u32 *flow_group_in;
|
||||
u8 *dmac;
|
||||
int err = 0;
|
||||
|
||||
esw_debug(dev, "Create FDB log_max_size(%d)\n",
|
||||
MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
|
||||
|
||||
root_ns = mlx5_get_fdb_sub_ns(dev, 0);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get FDB flow namespace\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_group_in = kvzalloc(inlen, GFP_KERNEL);
|
||||
if (!flow_group_in)
|
||||
return -ENOMEM;
|
||||
|
||||
table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
|
||||
ft_attr.max_fte = table_size;
|
||||
ft_attr.prio = LEGACY_FDB_PRIO;
|
||||
fdb = mlx5_create_flow_table(root_ns, &ft_attr);
|
||||
if (IS_ERR(fdb)) {
|
||||
err = PTR_ERR(fdb);
|
||||
esw_warn(dev, "Failed to create FDB Table err %d\n", err);
|
||||
goto out;
|
||||
}
|
||||
esw->fdb_table.legacy.fdb = fdb;
|
||||
|
||||
/* Addresses group : Full match unicast/multicast addresses */
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
|
||||
MLX5_MATCH_OUTER_HEADERS);
|
||||
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
|
||||
dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
|
||||
/* Preserve 2 entries for allmulti and promisc rules*/
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
|
||||
eth_broadcast_addr(dmac);
|
||||
g = mlx5_create_flow_group(fdb, flow_group_in);
|
||||
if (IS_ERR(g)) {
|
||||
err = PTR_ERR(g);
|
||||
esw_warn(dev, "Failed to create flow group err(%d)\n", err);
|
||||
goto out;
|
||||
}
|
||||
esw->fdb_table.legacy.addr_grp = g;
|
||||
|
||||
/* Allmulti group : One rule that forwards any mcast traffic */
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
|
||||
MLX5_MATCH_OUTER_HEADERS);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
|
||||
eth_zero_addr(dmac);
|
||||
dmac[0] = 0x01;
|
||||
g = mlx5_create_flow_group(fdb, flow_group_in);
|
||||
if (IS_ERR(g)) {
|
||||
err = PTR_ERR(g);
|
||||
esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
|
||||
goto out;
|
||||
}
|
||||
esw->fdb_table.legacy.allmulti_grp = g;
|
||||
|
||||
/* Promiscuous group :
|
||||
* One rule that forward all unmatched traffic from previous groups
|
||||
*/
|
||||
eth_zero_addr(dmac);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
|
||||
MLX5_MATCH_MISC_PARAMETERS);
|
||||
MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
|
||||
g = mlx5_create_flow_group(fdb, flow_group_in);
|
||||
if (IS_ERR(g)) {
|
||||
err = PTR_ERR(g);
|
||||
esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
|
||||
goto out;
|
||||
}
|
||||
esw->fdb_table.legacy.promisc_grp = g;
|
||||
|
||||
out:
|
||||
if (err)
|
||||
esw_destroy_legacy_fdb_table(esw);
|
||||
|
||||
kvfree(flow_group_in);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
esw_debug(esw->dev, "Destroy VEPA Table\n");
|
||||
if (!esw->fdb_table.legacy.vepa_fdb)
|
||||
return;
|
||||
|
||||
mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
|
||||
esw->fdb_table.legacy.vepa_fdb = NULL;
|
||||
}
|
||||
|
||||
static int esw_create_legacy_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
int err;
|
||||
|
||||
memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
|
||||
atomic64_set(&esw->user_count, 0);
|
||||
|
||||
err = esw_create_legacy_vepa_table(esw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = esw_create_legacy_fdb_table(esw);
|
||||
if (err)
|
||||
esw_destroy_legacy_vepa_table(esw);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
|
||||
{
|
||||
if (esw->fdb_table.legacy.vepa_uplink_rule)
|
||||
mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
|
||||
|
||||
if (esw->fdb_table.legacy.vepa_star_rule)
|
||||
mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
|
||||
|
||||
esw->fdb_table.legacy.vepa_uplink_rule = NULL;
|
||||
esw->fdb_table.legacy.vepa_star_rule = NULL;
|
||||
}
|
||||
|
||||
static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
esw_cleanup_vepa_rules(esw);
|
||||
esw_destroy_legacy_fdb_table(esw);
|
||||
esw_destroy_legacy_vepa_table(esw);
|
||||
}
|
||||
|
||||
#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
|
||||
MLX5_VPORT_MC_ADDR_CHANGE | \
|
||||
MLX5_VPORT_PROMISC_CHANGE)
|
||||
|
||||
int esw_legacy_enable(struct mlx5_eswitch *esw)
|
||||
{
|
||||
struct mlx5_vport *vport;
|
||||
int ret, i;
|
||||
|
||||
ret = esw_create_legacy_table(esw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
|
||||
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
|
||||
|
||||
ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
|
||||
if (ret)
|
||||
esw_destroy_legacy_table(esw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void esw_legacy_disable(struct mlx5_eswitch *esw)
|
||||
{
|
||||
struct esw_mc_addr *mc_promisc;
|
||||
|
||||
mlx5_eswitch_disable_pf_vf_vports(esw);
|
||||
|
||||
mc_promisc = &esw->mc_promisc;
|
||||
if (mc_promisc->uplink_rule)
|
||||
mlx5_del_flow_rules(mc_promisc->uplink_rule);
|
||||
|
||||
esw_destroy_legacy_table(esw);
|
||||
}
|
||||
|
||||
static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
|
||||
u8 setting)
|
||||
{
|
||||
struct mlx5_flow_destination dest = {};
|
||||
struct mlx5_flow_act flow_act = {};
|
||||
struct mlx5_flow_handle *flow_rule;
|
||||
struct mlx5_flow_spec *spec;
|
||||
int err = 0;
|
||||
void *misc;
|
||||
|
||||
if (!setting) {
|
||||
esw_cleanup_vepa_rules(esw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (esw->fdb_table.legacy.vepa_uplink_rule)
|
||||
return 0;
|
||||
|
||||
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Uplink rule forward uplink traffic to FDB */
|
||||
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
|
||||
MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
|
||||
|
||||
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
|
||||
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
|
||||
|
||||
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||
dest.ft = esw->fdb_table.legacy.fdb;
|
||||
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
|
||||
&flow_act, &dest, 1);
|
||||
if (IS_ERR(flow_rule)) {
|
||||
err = PTR_ERR(flow_rule);
|
||||
goto out;
|
||||
} else {
|
||||
esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
|
||||
}
|
||||
|
||||
/* Star rule to forward all traffic to uplink vport */
|
||||
memset(&dest, 0, sizeof(dest));
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
|
||||
dest.vport.num = MLX5_VPORT_UPLINK;
|
||||
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
|
||||
&flow_act, &dest, 1);
|
||||
if (IS_ERR(flow_rule)) {
|
||||
err = PTR_ERR(flow_rule);
|
||||
goto out;
|
||||
} else {
|
||||
esw->fdb_table.legacy.vepa_star_rule = flow_rule;
|
||||
}
|
||||
|
||||
out:
|
||||
kvfree(spec);
|
||||
if (err)
|
||||
esw_cleanup_vepa_rules(esw);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!esw)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = _mlx5_eswitch_set_vepa_locked(esw, setting);
|
||||
|
||||
out:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
|
||||
{
|
||||
if (!esw)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return -EPERM;
|
||||
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int esw_legacy_vport_acl_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Only non manager vports need ACL in legacy mode */
|
||||
if (mlx5_esw_is_manager_vport(esw, vport->vport))
|
||||
return 0;
|
||||
|
||||
ret = esw_acl_ingress_lgcy_setup(esw, vport);
|
||||
if (ret)
|
||||
goto ingress_err;
|
||||
|
||||
ret = esw_acl_egress_lgcy_setup(esw, vport);
|
||||
if (ret)
|
||||
goto egress_err;
|
||||
|
||||
return 0;
|
||||
|
||||
egress_err:
|
||||
esw_acl_ingress_lgcy_cleanup(esw, vport);
|
||||
ingress_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void esw_legacy_vport_acl_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
|
||||
{
|
||||
if (mlx5_esw_is_manager_vport(esw, vport->vport))
|
||||
return;
|
||||
|
||||
esw_acl_egress_lgcy_cleanup(esw, vport);
|
||||
esw_acl_ingress_lgcy_cleanup(esw, vport);
|
||||
}
|
||||
|
||||
int mlx5_esw_query_vport_drop_stats(struct mlx5_core_dev *dev,
|
||||
struct mlx5_vport *vport,
|
||||
struct mlx5_vport_drop_stats *stats)
|
||||
{
|
||||
u64 rx_discard_vport_down, tx_discard_vport_down;
|
||||
struct mlx5_eswitch *esw = dev->priv.eswitch;
|
||||
u64 bytes = 0;
|
||||
int err = 0;
|
||||
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (!vport->enabled)
|
||||
goto unlock;
|
||||
|
||||
if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter))
|
||||
mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
|
||||
&stats->rx_dropped, &bytes);
|
||||
|
||||
if (vport->ingress.legacy.drop_counter)
|
||||
mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
|
||||
&stats->tx_dropped, &bytes);
|
||||
|
||||
if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
|
||||
!MLX5_CAP_GEN(dev, transmit_discard_vport_down))
|
||||
goto unlock;
|
||||
|
||||
err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
|
||||
&rx_discard_vport_down,
|
||||
&tx_discard_vport_down);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
|
||||
stats->rx_dropped += rx_discard_vport_down;
|
||||
if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
|
||||
stats->tx_dropped += tx_discard_vport_down;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
|
||||
u16 vport, u16 vlan, u8 qos)
|
||||
{
|
||||
u8 set_flags = 0;
|
||||
int err = 0;
|
||||
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return -EPERM;
|
||||
|
||||
if (vlan || qos)
|
||||
set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY) {
|
||||
if (!vlan)
|
||||
goto unlock; /* compatibility with libvirt */
|
||||
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
|
||||
u16 vport, bool spoofchk)
|
||||
{
|
||||
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
|
||||
bool pschk;
|
||||
int err = 0;
|
||||
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return -EPERM;
|
||||
if (IS_ERR(evport))
|
||||
return PTR_ERR(evport);
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
pschk = evport->info.spoofchk;
|
||||
evport->info.spoofchk = spoofchk;
|
||||
if (pschk && !is_valid_ether_addr(evport->info.mac))
|
||||
mlx5_core_warn(esw->dev,
|
||||
"Spoofchk in set while MAC is invalid, vport(%d)\n",
|
||||
evport->vport);
|
||||
if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
|
||||
err = esw_acl_ingress_lgcy_setup(esw, evport);
|
||||
if (err)
|
||||
evport->info.spoofchk = pschk;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
|
||||
u16 vport, bool setting)
|
||||
{
|
||||
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
|
||||
int err = 0;
|
||||
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return -EPERM;
|
||||
if (IS_ERR(evport))
|
||||
return PTR_ERR(evport);
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
evport->info.trusted = setting;
|
||||
if (evport->enabled)
|
||||
esw_vport_change_handle_locked(evport);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
|
||||
/* Copyright (c) 2021 Mellanox Technologies Ltd */
|
||||
|
||||
#ifndef __MLX5_ESW_LEGACY_H__
|
||||
#define __MLX5_ESW_LEGACY_H__
|
||||
|
||||
#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
|
||||
MLX5_VPORT_MC_ADDR_CHANGE | \
|
||||
MLX5_VPORT_PROMISC_CHANGE)
|
||||
|
||||
struct mlx5_eswitch;
|
||||
|
||||
int esw_legacy_enable(struct mlx5_eswitch *esw);
|
||||
void esw_legacy_disable(struct mlx5_eswitch *esw);
|
||||
|
||||
int esw_legacy_vport_acl_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
|
||||
void esw_legacy_vport_acl_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
|
||||
|
||||
int mlx5_esw_query_vport_drop_stats(struct mlx5_core_dev *dev,
|
||||
struct mlx5_vport *vport,
|
||||
struct mlx5_vport_drop_stats *stats);
|
||||
#endif
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/mlx5/vport.h>
|
||||
#include <linux/mlx5/fs.h>
|
||||
#include "esw/acl/lgcy.h"
|
||||
#include "esw/legacy.h"
|
||||
#include "mlx5_core.h"
|
||||
#include "lib/eq.h"
|
||||
#include "eswitch.h"
|
||||
|
@ -61,9 +62,6 @@ struct vport_addr {
|
|||
bool mc_promisc;
|
||||
};
|
||||
|
||||
static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw);
|
||||
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw);
|
||||
|
||||
static int mlx5_eswitch_check(const struct mlx5_core_dev *dev)
|
||||
{
|
||||
if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
|
||||
|
@ -278,226 +276,6 @@ esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport)
|
|||
return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
|
||||
}
|
||||
|
||||
enum {
|
||||
LEGACY_VEPA_PRIO = 0,
|
||||
LEGACY_FDB_PRIO,
|
||||
};
|
||||
|
||||
static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
struct mlx5_flow_table_attr ft_attr = {};
|
||||
struct mlx5_core_dev *dev = esw->dev;
|
||||
struct mlx5_flow_namespace *root_ns;
|
||||
struct mlx5_flow_table *fdb;
|
||||
int err;
|
||||
|
||||
root_ns = mlx5_get_fdb_sub_ns(dev, 0);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get FDB flow namespace\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* num FTE 2, num FG 2 */
|
||||
ft_attr.prio = LEGACY_VEPA_PRIO;
|
||||
ft_attr.max_fte = 2;
|
||||
ft_attr.autogroup.max_num_groups = 2;
|
||||
fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
|
||||
if (IS_ERR(fdb)) {
|
||||
err = PTR_ERR(fdb);
|
||||
esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
|
||||
return err;
|
||||
}
|
||||
esw->fdb_table.legacy.vepa_fdb = fdb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
|
||||
struct mlx5_flow_table_attr ft_attr = {};
|
||||
struct mlx5_core_dev *dev = esw->dev;
|
||||
struct mlx5_flow_namespace *root_ns;
|
||||
struct mlx5_flow_table *fdb;
|
||||
struct mlx5_flow_group *g;
|
||||
void *match_criteria;
|
||||
int table_size;
|
||||
u32 *flow_group_in;
|
||||
u8 *dmac;
|
||||
int err = 0;
|
||||
|
||||
esw_debug(dev, "Create FDB log_max_size(%d)\n",
|
||||
MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
|
||||
|
||||
root_ns = mlx5_get_fdb_sub_ns(dev, 0);
|
||||
if (!root_ns) {
|
||||
esw_warn(dev, "Failed to get FDB flow namespace\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
flow_group_in = kvzalloc(inlen, GFP_KERNEL);
|
||||
if (!flow_group_in)
|
||||
return -ENOMEM;
|
||||
|
||||
table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
|
||||
ft_attr.max_fte = table_size;
|
||||
ft_attr.prio = LEGACY_FDB_PRIO;
|
||||
fdb = mlx5_create_flow_table(root_ns, &ft_attr);
|
||||
if (IS_ERR(fdb)) {
|
||||
err = PTR_ERR(fdb);
|
||||
esw_warn(dev, "Failed to create FDB Table err %d\n", err);
|
||||
goto out;
|
||||
}
|
||||
esw->fdb_table.legacy.fdb = fdb;
|
||||
|
||||
/* Addresses group : Full match unicast/multicast addresses */
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
|
||||
MLX5_MATCH_OUTER_HEADERS);
|
||||
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
|
||||
dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
|
||||
/* Preserve 2 entries for allmulti and promisc rules*/
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
|
||||
eth_broadcast_addr(dmac);
|
||||
g = mlx5_create_flow_group(fdb, flow_group_in);
|
||||
if (IS_ERR(g)) {
|
||||
err = PTR_ERR(g);
|
||||
esw_warn(dev, "Failed to create flow group err(%d)\n", err);
|
||||
goto out;
|
||||
}
|
||||
esw->fdb_table.legacy.addr_grp = g;
|
||||
|
||||
/* Allmulti group : One rule that forwards any mcast traffic */
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
|
||||
MLX5_MATCH_OUTER_HEADERS);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
|
||||
eth_zero_addr(dmac);
|
||||
dmac[0] = 0x01;
|
||||
g = mlx5_create_flow_group(fdb, flow_group_in);
|
||||
if (IS_ERR(g)) {
|
||||
err = PTR_ERR(g);
|
||||
esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
|
||||
goto out;
|
||||
}
|
||||
esw->fdb_table.legacy.allmulti_grp = g;
|
||||
|
||||
/* Promiscuous group :
|
||||
* One rule that forward all unmatched traffic from previous groups
|
||||
*/
|
||||
eth_zero_addr(dmac);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
|
||||
MLX5_MATCH_MISC_PARAMETERS);
|
||||
MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
|
||||
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
|
||||
g = mlx5_create_flow_group(fdb, flow_group_in);
|
||||
if (IS_ERR(g)) {
|
||||
err = PTR_ERR(g);
|
||||
esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
|
||||
goto out;
|
||||
}
|
||||
esw->fdb_table.legacy.promisc_grp = g;
|
||||
|
||||
out:
|
||||
if (err)
|
||||
esw_destroy_legacy_fdb_table(esw);
|
||||
|
||||
kvfree(flow_group_in);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
esw_debug(esw->dev, "Destroy VEPA Table\n");
|
||||
if (!esw->fdb_table.legacy.vepa_fdb)
|
||||
return;
|
||||
|
||||
mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
|
||||
esw->fdb_table.legacy.vepa_fdb = NULL;
|
||||
}
|
||||
|
||||
static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
esw_debug(esw->dev, "Destroy FDB Table\n");
|
||||
if (!esw->fdb_table.legacy.fdb)
|
||||
return;
|
||||
|
||||
if (esw->fdb_table.legacy.promisc_grp)
|
||||
mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
|
||||
if (esw->fdb_table.legacy.allmulti_grp)
|
||||
mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
|
||||
if (esw->fdb_table.legacy.addr_grp)
|
||||
mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
|
||||
mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
|
||||
|
||||
esw->fdb_table.legacy.fdb = NULL;
|
||||
esw->fdb_table.legacy.addr_grp = NULL;
|
||||
esw->fdb_table.legacy.allmulti_grp = NULL;
|
||||
esw->fdb_table.legacy.promisc_grp = NULL;
|
||||
atomic64_set(&esw->user_count, 0);
|
||||
}
|
||||
|
||||
static int esw_create_legacy_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
int err;
|
||||
|
||||
memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
|
||||
atomic64_set(&esw->user_count, 0);
|
||||
|
||||
err = esw_create_legacy_vepa_table(esw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = esw_create_legacy_fdb_table(esw);
|
||||
if (err)
|
||||
esw_destroy_legacy_vepa_table(esw);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
|
||||
{
|
||||
esw_cleanup_vepa_rules(esw);
|
||||
esw_destroy_legacy_fdb_table(esw);
|
||||
esw_destroy_legacy_vepa_table(esw);
|
||||
}
|
||||
|
||||
#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
|
||||
MLX5_VPORT_MC_ADDR_CHANGE | \
|
||||
MLX5_VPORT_PROMISC_CHANGE)
|
||||
|
||||
static int esw_legacy_enable(struct mlx5_eswitch *esw)
|
||||
{
|
||||
struct mlx5_vport *vport;
|
||||
int ret, i;
|
||||
|
||||
ret = esw_create_legacy_table(esw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
|
||||
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
|
||||
|
||||
ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
|
||||
if (ret)
|
||||
esw_destroy_legacy_table(esw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void esw_legacy_disable(struct mlx5_eswitch *esw)
|
||||
{
|
||||
struct esw_mc_addr *mc_promisc;
|
||||
|
||||
mlx5_eswitch_disable_pf_vf_vports(esw);
|
||||
|
||||
mc_promisc = &esw->mc_promisc;
|
||||
if (mc_promisc->uplink_rule)
|
||||
mlx5_del_flow_rules(mc_promisc->uplink_rule);
|
||||
|
||||
esw_destroy_legacy_table(esw);
|
||||
}
|
||||
|
||||
/* E-Switch vport UC/MC lists management */
|
||||
typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
|
||||
struct vport_addr *vaddr);
|
||||
|
@ -919,7 +697,7 @@ static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw,
|
|||
(promisc_all || promisc_mc));
|
||||
}
|
||||
|
||||
static void esw_vport_change_handle_locked(struct mlx5_vport *vport)
|
||||
void esw_vport_change_handle_locked(struct mlx5_vport *vport)
|
||||
{
|
||||
struct mlx5_core_dev *dev = vport->dev;
|
||||
struct mlx5_eswitch *esw = dev->priv.eswitch;
|
||||
|
@ -1170,56 +948,20 @@ static void node_guid_gen_from_mac(u64 *node_guid, const u8 *mac)
|
|||
((u8 *)node_guid)[0] = mac[5];
|
||||
}
|
||||
|
||||
static int esw_vport_create_legacy_acl_tables(struct mlx5_eswitch *esw,
|
||||
struct mlx5_vport *vport)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Only non manager vports need ACL in legacy mode */
|
||||
if (mlx5_esw_is_manager_vport(esw, vport->vport))
|
||||
return 0;
|
||||
|
||||
ret = esw_acl_ingress_lgcy_setup(esw, vport);
|
||||
if (ret)
|
||||
goto ingress_err;
|
||||
|
||||
ret = esw_acl_egress_lgcy_setup(esw, vport);
|
||||
if (ret)
|
||||
goto egress_err;
|
||||
|
||||
return 0;
|
||||
|
||||
egress_err:
|
||||
esw_acl_ingress_lgcy_cleanup(esw, vport);
|
||||
ingress_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int esw_vport_setup_acl(struct mlx5_eswitch *esw,
|
||||
struct mlx5_vport *vport)
|
||||
{
|
||||
if (esw->mode == MLX5_ESWITCH_LEGACY)
|
||||
return esw_vport_create_legacy_acl_tables(esw, vport);
|
||||
return esw_legacy_vport_acl_setup(esw, vport);
|
||||
else
|
||||
return esw_vport_create_offloads_acl_tables(esw, vport);
|
||||
}
|
||||
|
||||
static void esw_vport_destroy_legacy_acl_tables(struct mlx5_eswitch *esw,
|
||||
struct mlx5_vport *vport)
|
||||
|
||||
{
|
||||
if (mlx5_esw_is_manager_vport(esw, vport->vport))
|
||||
return;
|
||||
|
||||
esw_acl_egress_lgcy_cleanup(esw, vport);
|
||||
esw_acl_ingress_lgcy_cleanup(esw, vport);
|
||||
}
|
||||
|
||||
static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw,
|
||||
struct mlx5_vport *vport)
|
||||
{
|
||||
if (esw->mode == MLX5_ESWITCH_LEGACY)
|
||||
esw_vport_destroy_legacy_acl_tables(esw, vport);
|
||||
esw_legacy_vport_acl_cleanup(esw, vport);
|
||||
else
|
||||
esw_vport_destroy_offloads_acl_tables(esw, vport);
|
||||
}
|
||||
|
@ -1390,15 +1132,9 @@ const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
|
|||
{
|
||||
int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out);
|
||||
u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
|
||||
u16 max_sf_vports;
|
||||
u32 *out;
|
||||
int err;
|
||||
|
||||
max_sf_vports = mlx5_sf_max_functions(dev);
|
||||
/* Device interface is array of 64-bits */
|
||||
if (max_sf_vports)
|
||||
outlen += DIV_ROUND_UP(max_sf_vports, BITS_PER_TYPE(__be64)) * sizeof(__be64);
|
||||
|
||||
out = kvzalloc(outlen, GFP_KERNEL);
|
||||
if (!out)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@ -1449,8 +1185,6 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
|
|||
}
|
||||
|
||||
/* Public E-Switch API */
|
||||
#define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))
|
||||
|
||||
int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
|
||||
enum mlx5_eswitch_vport_event enabled_events)
|
||||
{
|
||||
|
@ -1633,6 +1367,47 @@ static void mlx5_esw_mode_change_notify(struct mlx5_eswitch *esw, u16 mode)
|
|||
blocking_notifier_call_chain(&esw->n_head, 0, &info);
|
||||
}
|
||||
|
||||
static int mlx5_esw_acls_ns_init(struct mlx5_eswitch *esw)
|
||||
{
|
||||
struct mlx5_core_dev *dev = esw->dev;
|
||||
int total_vports;
|
||||
int err;
|
||||
|
||||
total_vports = mlx5_eswitch_get_total_vports(dev);
|
||||
|
||||
if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
|
||||
err = mlx5_fs_egress_acls_init(dev, total_vports);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
esw_warn(dev, "engress ACL is not supported by FW\n");
|
||||
}
|
||||
|
||||
if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
|
||||
err = mlx5_fs_ingress_acls_init(dev, total_vports);
|
||||
if (err)
|
||||
goto err;
|
||||
} else {
|
||||
esw_warn(dev, "ingress ACL is not supported by FW\n");
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
|
||||
mlx5_fs_egress_acls_cleanup(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch *esw)
|
||||
{
|
||||
struct mlx5_core_dev *dev = esw->dev;
|
||||
|
||||
if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
|
||||
mlx5_fs_ingress_acls_cleanup(dev);
|
||||
if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
|
||||
mlx5_fs_egress_acls_cleanup(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* mlx5_eswitch_enable_locked - Enable eswitch
|
||||
* @esw: Pointer to eswitch
|
||||
|
@ -1661,14 +1436,12 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs)
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
|
||||
esw_warn(esw->dev, "ingress ACL is not supported by FW\n");
|
||||
|
||||
if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support))
|
||||
esw_warn(esw->dev, "engress ACL is not supported by FW\n");
|
||||
|
||||
mlx5_eswitch_get_devlink_param(esw);
|
||||
|
||||
err = mlx5_esw_acls_ns_init(esw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mlx5_eswitch_update_num_of_vfs(esw, num_vfs);
|
||||
|
||||
esw_create_tsar(esw);
|
||||
|
@ -1704,6 +1477,7 @@ abort:
|
|||
mlx5_rescan_drivers(esw->dev);
|
||||
|
||||
esw_destroy_tsar(esw);
|
||||
mlx5_esw_acls_ns_cleanup(esw);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1719,7 +1493,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (!ESW_ALLOWED(esw))
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return 0;
|
||||
|
||||
down_write(&esw->mode_lock);
|
||||
|
@ -1772,6 +1546,7 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)
|
|||
mlx5_rescan_drivers(esw->dev);
|
||||
|
||||
esw_destroy_tsar(esw);
|
||||
mlx5_esw_acls_ns_cleanup(esw);
|
||||
|
||||
if (clear_vf)
|
||||
mlx5_eswitch_clear_vf_vports_info(esw);
|
||||
|
@ -1779,7 +1554,7 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)
|
|||
|
||||
void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf)
|
||||
{
|
||||
if (!ESW_ALLOWED(esw))
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return;
|
||||
|
||||
down_write(&esw->mode_lock);
|
||||
|
@ -1862,7 +1637,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
|
|||
abort:
|
||||
if (esw->work_queue)
|
||||
destroy_workqueue(esw->work_queue);
|
||||
esw_offloads_cleanup_reps(esw);
|
||||
kfree(esw->vports);
|
||||
kfree(esw);
|
||||
return err;
|
||||
|
@ -1877,7 +1651,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
|
|||
|
||||
esw->dev->priv.eswitch = NULL;
|
||||
destroy_workqueue(esw->work_queue);
|
||||
esw_offloads_cleanup_reps(esw);
|
||||
mutex_destroy(&esw->state_lock);
|
||||
WARN_ON(!xa_empty(&esw->offloads.vhca_map));
|
||||
xa_destroy(&esw->offloads.vhca_map);
|
||||
|
@ -1885,6 +1658,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
|
|||
mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr);
|
||||
mutex_destroy(&esw->offloads.encap_tbl_lock);
|
||||
mutex_destroy(&esw->offloads.decap_tbl_lock);
|
||||
esw_offloads_cleanup_reps(esw);
|
||||
kfree(esw->vports);
|
||||
kfree(esw);
|
||||
}
|
||||
|
@ -2030,7 +1804,7 @@ int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
|
|||
int other_vport = 1;
|
||||
int err = 0;
|
||||
|
||||
if (!ESW_ALLOWED(esw))
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return -EPERM;
|
||||
if (IS_ERR(evport))
|
||||
return PTR_ERR(evport);
|
||||
|
@ -2112,205 +1886,6 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
|
|||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
|
||||
u16 vport, u16 vlan, u8 qos)
|
||||
{
|
||||
u8 set_flags = 0;
|
||||
int err = 0;
|
||||
|
||||
if (!ESW_ALLOWED(esw))
|
||||
return -EPERM;
|
||||
|
||||
if (vlan || qos)
|
||||
set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY) {
|
||||
if (!vlan)
|
||||
goto unlock; /* compatibility with libvirt */
|
||||
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
|
||||
u16 vport, bool spoofchk)
|
||||
{
|
||||
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
|
||||
bool pschk;
|
||||
int err = 0;
|
||||
|
||||
if (!ESW_ALLOWED(esw))
|
||||
return -EPERM;
|
||||
if (IS_ERR(evport))
|
||||
return PTR_ERR(evport);
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
pschk = evport->info.spoofchk;
|
||||
evport->info.spoofchk = spoofchk;
|
||||
if (pschk && !is_valid_ether_addr(evport->info.mac))
|
||||
mlx5_core_warn(esw->dev,
|
||||
"Spoofchk in set while MAC is invalid, vport(%d)\n",
|
||||
evport->vport);
|
||||
if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
|
||||
err = esw_acl_ingress_lgcy_setup(esw, evport);
|
||||
if (err)
|
||||
evport->info.spoofchk = pschk;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
|
||||
{
|
||||
if (esw->fdb_table.legacy.vepa_uplink_rule)
|
||||
mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
|
||||
|
||||
if (esw->fdb_table.legacy.vepa_star_rule)
|
||||
mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
|
||||
|
||||
esw->fdb_table.legacy.vepa_uplink_rule = NULL;
|
||||
esw->fdb_table.legacy.vepa_star_rule = NULL;
|
||||
}
|
||||
|
||||
static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
|
||||
u8 setting)
|
||||
{
|
||||
struct mlx5_flow_destination dest = {};
|
||||
struct mlx5_flow_act flow_act = {};
|
||||
struct mlx5_flow_handle *flow_rule;
|
||||
struct mlx5_flow_spec *spec;
|
||||
int err = 0;
|
||||
void *misc;
|
||||
|
||||
if (!setting) {
|
||||
esw_cleanup_vepa_rules(esw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (esw->fdb_table.legacy.vepa_uplink_rule)
|
||||
return 0;
|
||||
|
||||
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Uplink rule forward uplink traffic to FDB */
|
||||
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
|
||||
MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
|
||||
|
||||
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
|
||||
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
|
||||
|
||||
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||
dest.ft = esw->fdb_table.legacy.fdb;
|
||||
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
|
||||
&flow_act, &dest, 1);
|
||||
if (IS_ERR(flow_rule)) {
|
||||
err = PTR_ERR(flow_rule);
|
||||
goto out;
|
||||
} else {
|
||||
esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
|
||||
}
|
||||
|
||||
/* Star rule to forward all traffic to uplink vport */
|
||||
memset(&dest, 0, sizeof(dest));
|
||||
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
|
||||
dest.vport.num = MLX5_VPORT_UPLINK;
|
||||
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
|
||||
&flow_act, &dest, 1);
|
||||
if (IS_ERR(flow_rule)) {
|
||||
err = PTR_ERR(flow_rule);
|
||||
goto out;
|
||||
} else {
|
||||
esw->fdb_table.legacy.vepa_star_rule = flow_rule;
|
||||
}
|
||||
|
||||
out:
|
||||
kvfree(spec);
|
||||
if (err)
|
||||
esw_cleanup_vepa_rules(esw);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!esw)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!ESW_ALLOWED(esw))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = _mlx5_eswitch_set_vepa_locked(esw, setting);
|
||||
|
||||
out:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
|
||||
{
|
||||
if (!esw)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!ESW_ALLOWED(esw))
|
||||
return -EPERM;
|
||||
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
|
||||
u16 vport, bool setting)
|
||||
{
|
||||
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
|
||||
int err = 0;
|
||||
|
||||
if (!ESW_ALLOWED(esw))
|
||||
return -EPERM;
|
||||
if (IS_ERR(evport))
|
||||
return PTR_ERR(evport);
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto unlock;
|
||||
}
|
||||
evport->info.trusted = setting;
|
||||
if (evport->enabled)
|
||||
esw_vport_change_handle_locked(evport);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
|
||||
{
|
||||
u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
|
||||
|
@ -2376,7 +1951,7 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
|
|||
bool max_rate_supported;
|
||||
int err = 0;
|
||||
|
||||
if (!ESW_ALLOWED(esw))
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return -EPERM;
|
||||
if (IS_ERR(evport))
|
||||
return PTR_ERR(evport);
|
||||
|
@ -2415,50 +1990,6 @@ unlock:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
|
||||
struct mlx5_vport *vport,
|
||||
struct mlx5_vport_drop_stats *stats)
|
||||
{
|
||||
struct mlx5_eswitch *esw = dev->priv.eswitch;
|
||||
u64 rx_discard_vport_down, tx_discard_vport_down;
|
||||
u64 bytes = 0;
|
||||
int err = 0;
|
||||
|
||||
if (esw->mode != MLX5_ESWITCH_LEGACY)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&esw->state_lock);
|
||||
if (!vport->enabled)
|
||||
goto unlock;
|
||||
|
||||
if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter))
|
||||
mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
|
||||
&stats->rx_dropped, &bytes);
|
||||
|
||||
if (vport->ingress.legacy.drop_counter)
|
||||
mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
|
||||
&stats->tx_dropped, &bytes);
|
||||
|
||||
if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
|
||||
!MLX5_CAP_GEN(dev, transmit_discard_vport_down))
|
||||
goto unlock;
|
||||
|
||||
err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
|
||||
&rx_discard_vport_down,
|
||||
&tx_discard_vport_down);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
|
||||
stats->rx_dropped += rx_discard_vport_down;
|
||||
if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
|
||||
stats->tx_dropped += tx_discard_vport_down;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&esw->state_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
|
||||
u16 vport_num,
|
||||
struct ifla_vf_stats *vf_stats)
|
||||
|
@ -2526,7 +2057,7 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
|
|||
vf_stats->broadcast =
|
||||
MLX5_GET_CTR(out, received_eth_broadcast.packets);
|
||||
|
||||
err = mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats);
|
||||
err = mlx5_esw_query_vport_drop_stats(esw->dev, vport, &stats);
|
||||
if (err)
|
||||
goto free_out;
|
||||
vf_stats->rx_dropped = stats.rx_dropped;
|
||||
|
@ -2541,7 +2072,7 @@ u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev)
|
|||
{
|
||||
struct mlx5_eswitch *esw = dev->priv.eswitch;
|
||||
|
||||
return ESW_ALLOWED(esw) ? esw->mode : MLX5_ESWITCH_NONE;
|
||||
return mlx5_esw_allowed(esw) ? esw->mode : MLX5_ESWITCH_NONE;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
|
||||
|
||||
|
@ -2551,7 +2082,7 @@ mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
|
|||
struct mlx5_eswitch *esw;
|
||||
|
||||
esw = dev->priv.eswitch;
|
||||
return ESW_ALLOWED(esw) ? esw->offloads.encap :
|
||||
return mlx5_esw_allowed(esw) ? esw->offloads.encap :
|
||||
DEVLINK_ESWITCH_ENCAP_MODE_NONE;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
|
||||
|
@ -2597,7 +2128,7 @@ bool mlx5_esw_hold(struct mlx5_core_dev *mdev)
|
|||
struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
||||
|
||||
/* e.g. VF doesn't have eswitch so nothing to do */
|
||||
if (!ESW_ALLOWED(esw))
|
||||
if (!mlx5_esw_allowed(esw))
|
||||
return true;
|
||||
|
||||
if (down_read_trylock(&esw->mode_lock) != 0)
|
||||
|
@ -2614,7 +2145,7 @@ void mlx5_esw_release(struct mlx5_core_dev *mdev)
|
|||
{
|
||||
struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
||||
|
||||
if (ESW_ALLOWED(esw))
|
||||
if (mlx5_esw_allowed(esw))
|
||||
up_read(&esw->mode_lock);
|
||||
}
|
||||
|
||||
|
@ -2626,7 +2157,7 @@ void mlx5_esw_get(struct mlx5_core_dev *mdev)
|
|||
{
|
||||
struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
||||
|
||||
if (ESW_ALLOWED(esw))
|
||||
if (mlx5_esw_allowed(esw))
|
||||
atomic64_inc(&esw->user_count);
|
||||
}
|
||||
|
||||
|
@ -2638,7 +2169,7 @@ void mlx5_esw_put(struct mlx5_core_dev *mdev)
|
|||
{
|
||||
struct mlx5_eswitch *esw = mdev->priv.eswitch;
|
||||
|
||||
if (ESW_ALLOWED(esw))
|
||||
if (mlx5_esw_allowed(esw))
|
||||
atomic64_dec_if_positive(&esw->user_count);
|
||||
}
|
||||
|
||||
|
|
|
@ -152,7 +152,6 @@ enum mlx5_eswitch_vport_event {
|
|||
|
||||
struct mlx5_vport {
|
||||
struct mlx5_core_dev *dev;
|
||||
int vport;
|
||||
struct hlist_head uc_list[MLX5_L2_ADDR_HASH_SIZE];
|
||||
struct hlist_head mc_list[MLX5_L2_ADDR_HASH_SIZE];
|
||||
struct mlx5_flow_handle *promisc_rule;
|
||||
|
@ -174,6 +173,7 @@ struct mlx5_vport {
|
|||
u32 max_rate;
|
||||
} qos;
|
||||
|
||||
u16 vport;
|
||||
bool enabled;
|
||||
enum mlx5_eswitch_vport_event enabled_events;
|
||||
struct devlink_port *dl_port;
|
||||
|
@ -314,6 +314,8 @@ int esw_offloads_enable(struct mlx5_eswitch *esw);
|
|||
void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw);
|
||||
int esw_offloads_init_reps(struct mlx5_eswitch *esw);
|
||||
|
||||
bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw);
|
||||
int mlx5_esw_offloads_vport_metadata_set(struct mlx5_eswitch *esw, bool enable);
|
||||
u32 mlx5_esw_match_metadata_alloc(struct mlx5_eswitch *esw);
|
||||
void mlx5_esw_match_metadata_free(struct mlx5_eswitch *esw, u32 metadata);
|
||||
|
||||
|
@ -519,6 +521,11 @@ const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev);
|
|||
#define esw_debug(dev, format, ...) \
|
||||
mlx5_core_dbg_mask(dev, MLX5_DEBUG_ESWITCH_MASK, format, ##__VA_ARGS__)
|
||||
|
||||
static inline bool mlx5_esw_allowed(const struct mlx5_eswitch *esw)
|
||||
{
|
||||
return esw && MLX5_ESWITCH_MANAGER(esw->dev);
|
||||
}
|
||||
|
||||
/* The returned number is valid only when the dev is eswitch manager. */
|
||||
static inline u16 mlx5_eswitch_manager_vport(struct mlx5_core_dev *dev)
|
||||
{
|
||||
|
@ -807,6 +814,8 @@ void mlx5_esw_put(struct mlx5_core_dev *dev);
|
|||
int mlx5_esw_try_lock(struct mlx5_eswitch *esw);
|
||||
void mlx5_esw_unlock(struct mlx5_eswitch *esw);
|
||||
|
||||
void esw_vport_change_handle_locked(struct mlx5_vport *vport);
|
||||
|
||||
#else /* CONFIG_MLX5_ESWITCH */
|
||||
/* eswitch API stubs */
|
||||
static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }
|
||||
|
|
|
@ -986,12 +986,13 @@ static void mlx5_eswitch_del_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
|
|||
static int
|
||||
mlx5_eswitch_add_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
|
||||
{
|
||||
int num_vfs, vport_num, rule_idx = 0, err = 0;
|
||||
struct mlx5_flow_destination dest = {};
|
||||
struct mlx5_flow_act flow_act = {0};
|
||||
int num_vfs, rule_idx = 0, err = 0;
|
||||
struct mlx5_flow_handle *flow_rule;
|
||||
struct mlx5_flow_handle **flows;
|
||||
struct mlx5_flow_spec *spec;
|
||||
u16 vport_num;
|
||||
|
||||
num_vfs = esw->esw_funcs.num_vfs;
|
||||
flows = kvzalloc(num_vfs * sizeof(*flows), GFP_KERNEL);
|
||||
|
@ -2351,8 +2352,7 @@ static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
|
|||
mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
|
||||
}
|
||||
|
||||
static bool
|
||||
esw_check_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
|
||||
bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
|
||||
{
|
||||
if (!MLX5_CAP_ESW(esw->dev, esw_uplink_ingress_acl))
|
||||
return false;
|
||||
|
@ -2452,6 +2452,28 @@ metadata_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
int mlx5_esw_offloads_vport_metadata_set(struct mlx5_eswitch *esw, bool enable)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
down_write(&esw->mode_lock);
|
||||
if (esw->mode != MLX5_ESWITCH_NONE) {
|
||||
err = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
if (!mlx5_esw_vport_match_metadata_supported(esw)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto done;
|
||||
}
|
||||
if (enable)
|
||||
esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
|
||||
else
|
||||
esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
|
||||
done:
|
||||
up_write(&esw->mode_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
esw_vport_create_offloads_acl_tables(struct mlx5_eswitch *esw,
|
||||
struct mlx5_vport *vport)
|
||||
|
@ -2673,9 +2695,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
|
|||
if (err)
|
||||
goto err_metadata;
|
||||
|
||||
if (esw_check_vport_match_metadata_supported(esw))
|
||||
esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
|
||||
|
||||
err = esw_offloads_metadata_init(esw);
|
||||
if (err)
|
||||
goto err_metadata;
|
||||
|
@ -2725,7 +2744,6 @@ err_pool:
|
|||
err_vport_metadata:
|
||||
esw_offloads_metadata_uninit(esw);
|
||||
err_metadata:
|
||||
esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
|
||||
mlx5_rdma_disable_roce(esw->dev);
|
||||
mutex_destroy(&esw->offloads.termtbl_mutex);
|
||||
return err;
|
||||
|
@ -2761,7 +2779,6 @@ void esw_offloads_disable(struct mlx5_eswitch *esw)
|
|||
esw_offloads_steering_cleanup(esw);
|
||||
mapping_destroy(esw->offloads.reg_c0_obj_pool);
|
||||
esw_offloads_metadata_uninit(esw);
|
||||
esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
|
||||
mlx5_rdma_disable_roce(esw->dev);
|
||||
mutex_destroy(&esw->offloads.termtbl_mutex);
|
||||
esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
|
||||
|
|
|
@ -850,7 +850,7 @@ mlx5_fpga_ipsec_release_sa_ctx(struct mlx5_fpga_ipsec_sa_ctx *sa_ctx)
|
|||
return;
|
||||
}
|
||||
|
||||
if (sa_ctx->fpga_xfrm->accel_xfrm.attrs.action &
|
||||
if (sa_ctx->fpga_xfrm->accel_xfrm.attrs.action ==
|
||||
MLX5_ACCEL_ESP_ACTION_DECRYPT)
|
||||
ida_free(&fipsec->halloc, sa_ctx->sa_handle);
|
||||
|
||||
|
@ -1085,6 +1085,7 @@ static int fpga_ipsec_fs_create_fte(struct mlx5_flow_root_namespace *ns,
|
|||
rule->ctx = mlx5_fpga_ipsec_fs_create_sa_ctx(dev, fte, is_egress);
|
||||
if (IS_ERR(rule->ctx)) {
|
||||
int err = PTR_ERR(rule->ctx);
|
||||
|
||||
kfree(rule);
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -2229,17 +2229,21 @@ struct mlx5_flow_namespace *mlx5_get_flow_vport_acl_namespace(struct mlx5_core_d
|
|||
{
|
||||
struct mlx5_flow_steering *steering = dev->priv.steering;
|
||||
|
||||
if (!steering || vport >= mlx5_eswitch_get_total_vports(dev))
|
||||
if (!steering)
|
||||
return NULL;
|
||||
|
||||
switch (type) {
|
||||
case MLX5_FLOW_NAMESPACE_ESW_EGRESS:
|
||||
if (vport >= steering->esw_egress_acl_vports)
|
||||
return NULL;
|
||||
if (steering->esw_egress_root_ns &&
|
||||
steering->esw_egress_root_ns[vport])
|
||||
return &steering->esw_egress_root_ns[vport]->ns;
|
||||
else
|
||||
return NULL;
|
||||
case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
|
||||
if (vport >= steering->esw_ingress_acl_vports)
|
||||
return NULL;
|
||||
if (steering->esw_ingress_root_ns &&
|
||||
steering->esw_ingress_root_ns[vport])
|
||||
return &steering->esw_ingress_root_ns[vport]->ns;
|
||||
|
@ -2571,43 +2575,11 @@ static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns)
|
|||
clean_tree(&root_ns->ns.node);
|
||||
}
|
||||
|
||||
static void cleanup_egress_acls_root_ns(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_flow_steering *steering = dev->priv.steering;
|
||||
int i;
|
||||
|
||||
if (!steering->esw_egress_root_ns)
|
||||
return;
|
||||
|
||||
for (i = 0; i < mlx5_eswitch_get_total_vports(dev); i++)
|
||||
cleanup_root_ns(steering->esw_egress_root_ns[i]);
|
||||
|
||||
kfree(steering->esw_egress_root_ns);
|
||||
steering->esw_egress_root_ns = NULL;
|
||||
}
|
||||
|
||||
static void cleanup_ingress_acls_root_ns(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_flow_steering *steering = dev->priv.steering;
|
||||
int i;
|
||||
|
||||
if (!steering->esw_ingress_root_ns)
|
||||
return;
|
||||
|
||||
for (i = 0; i < mlx5_eswitch_get_total_vports(dev); i++)
|
||||
cleanup_root_ns(steering->esw_ingress_root_ns[i]);
|
||||
|
||||
kfree(steering->esw_ingress_root_ns);
|
||||
steering->esw_ingress_root_ns = NULL;
|
||||
}
|
||||
|
||||
void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_flow_steering *steering = dev->priv.steering;
|
||||
|
||||
cleanup_root_ns(steering->root_ns);
|
||||
cleanup_egress_acls_root_ns(dev);
|
||||
cleanup_ingress_acls_root_ns(dev);
|
||||
cleanup_root_ns(steering->fdb_root_ns);
|
||||
steering->fdb_root_ns = NULL;
|
||||
kfree(steering->fdb_sub_ns);
|
||||
|
@ -2852,10 +2824,9 @@ static int init_ingress_acl_root_ns(struct mlx5_flow_steering *steering, int vpo
|
|||
return PTR_ERR_OR_ZERO(prio);
|
||||
}
|
||||
|
||||
static int init_egress_acls_root_ns(struct mlx5_core_dev *dev)
|
||||
int mlx5_fs_egress_acls_init(struct mlx5_core_dev *dev, int total_vports)
|
||||
{
|
||||
struct mlx5_flow_steering *steering = dev->priv.steering;
|
||||
int total_vports = mlx5_eswitch_get_total_vports(dev);
|
||||
int err;
|
||||
int i;
|
||||
|
||||
|
@ -2871,7 +2842,7 @@ static int init_egress_acls_root_ns(struct mlx5_core_dev *dev)
|
|||
if (err)
|
||||
goto cleanup_root_ns;
|
||||
}
|
||||
|
||||
steering->esw_egress_acl_vports = total_vports;
|
||||
return 0;
|
||||
|
||||
cleanup_root_ns:
|
||||
|
@ -2882,10 +2853,24 @@ cleanup_root_ns:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int init_ingress_acls_root_ns(struct mlx5_core_dev *dev)
|
||||
void mlx5_fs_egress_acls_cleanup(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_flow_steering *steering = dev->priv.steering;
|
||||
int i;
|
||||
|
||||
if (!steering->esw_egress_root_ns)
|
||||
return;
|
||||
|
||||
for (i = 0; i < steering->esw_egress_acl_vports; i++)
|
||||
cleanup_root_ns(steering->esw_egress_root_ns[i]);
|
||||
|
||||
kfree(steering->esw_egress_root_ns);
|
||||
steering->esw_egress_root_ns = NULL;
|
||||
}
|
||||
|
||||
int mlx5_fs_ingress_acls_init(struct mlx5_core_dev *dev, int total_vports)
|
||||
{
|
||||
struct mlx5_flow_steering *steering = dev->priv.steering;
|
||||
int total_vports = mlx5_eswitch_get_total_vports(dev);
|
||||
int err;
|
||||
int i;
|
||||
|
||||
|
@ -2901,7 +2886,7 @@ static int init_ingress_acls_root_ns(struct mlx5_core_dev *dev)
|
|||
if (err)
|
||||
goto cleanup_root_ns;
|
||||
}
|
||||
|
||||
steering->esw_ingress_acl_vports = total_vports;
|
||||
return 0;
|
||||
|
||||
cleanup_root_ns:
|
||||
|
@ -2912,6 +2897,21 @@ cleanup_root_ns:
|
|||
return err;
|
||||
}
|
||||
|
||||
void mlx5_fs_ingress_acls_cleanup(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_flow_steering *steering = dev->priv.steering;
|
||||
int i;
|
||||
|
||||
if (!steering->esw_ingress_root_ns)
|
||||
return;
|
||||
|
||||
for (i = 0; i < steering->esw_ingress_acl_vports; i++)
|
||||
cleanup_root_ns(steering->esw_ingress_root_ns[i]);
|
||||
|
||||
kfree(steering->esw_ingress_root_ns);
|
||||
steering->esw_ingress_root_ns = NULL;
|
||||
}
|
||||
|
||||
static int init_egress_root_ns(struct mlx5_flow_steering *steering)
|
||||
{
|
||||
int err;
|
||||
|
@ -2974,16 +2974,6 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
|
|||
if (err)
|
||||
goto err;
|
||||
}
|
||||
if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
|
||||
err = init_egress_acls_root_ns(dev);
|
||||
if (err)
|
||||
goto err;
|
||||
}
|
||||
if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
|
||||
err = init_ingress_acls_root_ns(dev);
|
||||
if (err)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (MLX5_CAP_FLOWTABLE_SNIFFER_RX(dev, ft_support)) {
|
||||
|
|
|
@ -129,6 +129,8 @@ struct mlx5_flow_steering {
|
|||
struct mlx5_flow_root_namespace *rdma_rx_root_ns;
|
||||
struct mlx5_flow_root_namespace *rdma_tx_root_ns;
|
||||
struct mlx5_flow_root_namespace *egress_root_ns;
|
||||
int esw_egress_acl_vports;
|
||||
int esw_ingress_acl_vports;
|
||||
};
|
||||
|
||||
struct fs_node {
|
||||
|
@ -287,6 +289,11 @@ int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,
|
|||
int mlx5_init_fs(struct mlx5_core_dev *dev);
|
||||
void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
|
||||
|
||||
int mlx5_fs_egress_acls_init(struct mlx5_core_dev *dev, int total_vports);
|
||||
void mlx5_fs_egress_acls_cleanup(struct mlx5_core_dev *dev);
|
||||
int mlx5_fs_ingress_acls_init(struct mlx5_core_dev *dev, int total_vports);
|
||||
void mlx5_fs_ingress_acls_cleanup(struct mlx5_core_dev *dev);
|
||||
|
||||
#define fs_get_obj(v, _node) {v = container_of((_node), typeof(*v), node); }
|
||||
|
||||
#define fs_list_for_each_entry(pos, root) \
|
||||
|
|
|
@ -603,8 +603,6 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
|
|||
if (err)
|
||||
mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
|
||||
err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Must be called with intf_mutex held */
|
||||
|
|
|
@ -167,7 +167,6 @@ static void irq_set_name(char *name, int vecidx)
|
|||
|
||||
snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d",
|
||||
vecidx - MLX5_IRQ_VEC_COMP_BASE);
|
||||
return;
|
||||
}
|
||||
|
||||
static int request_irqs(struct mlx5_core_dev *dev, int nvec)
|
||||
|
|
|
@ -180,5 +180,4 @@ del_roce_addr:
|
|||
mlx5_rdma_del_roce_addr(dev);
|
||||
disable_roce:
|
||||
mlx5_nic_vport_disable_roce(dev);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -270,15 +270,14 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
|
|||
{
|
||||
struct mlx5_eswitch *esw = dev->priv.eswitch;
|
||||
struct mlx5_sf *sf;
|
||||
u16 hw_fn_id;
|
||||
int err;
|
||||
|
||||
sf = mlx5_sf_alloc(table, new_attr->sfnum, extack);
|
||||
if (IS_ERR(sf))
|
||||
return PTR_ERR(sf);
|
||||
|
||||
hw_fn_id = mlx5_sf_sw_to_hw_id(dev, sf->id);
|
||||
err = mlx5_esw_offloads_sf_vport_enable(esw, &sf->dl_port, hw_fn_id, new_attr->sfnum);
|
||||
err = mlx5_esw_offloads_sf_vport_enable(esw, &sf->dl_port, sf->hw_fn_id,
|
||||
new_attr->sfnum);
|
||||
if (err)
|
||||
goto esw_err;
|
||||
*new_port_index = sf->port_index;
|
||||
|
|
|
@ -67,8 +67,8 @@ int mlx5_sf_hw_table_sf_alloc(struct mlx5_core_dev *dev, u32 usr_sfnum)
|
|||
goto exist_err;
|
||||
}
|
||||
|
||||
hw_fn_id = mlx5_sf_sw_to_hw_id(table->dev, sw_id);
|
||||
err = mlx5_cmd_alloc_sf(table->dev, hw_fn_id);
|
||||
hw_fn_id = mlx5_sf_sw_to_hw_id(dev, sw_id);
|
||||
err = mlx5_cmd_alloc_sf(dev, hw_fn_id);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
|
@ -80,7 +80,7 @@ int mlx5_sf_hw_table_sf_alloc(struct mlx5_core_dev *dev, u32 usr_sfnum)
|
|||
return sw_id;
|
||||
|
||||
vhca_err:
|
||||
mlx5_cmd_dealloc_sf(table->dev, hw_fn_id);
|
||||
mlx5_cmd_dealloc_sf(dev, hw_fn_id);
|
||||
err:
|
||||
table->sfs[i].allocated = false;
|
||||
exist_err:
|
||||
|
@ -93,8 +93,8 @@ static void _mlx5_sf_hw_id_free(struct mlx5_core_dev *dev, u16 id)
|
|||
struct mlx5_sf_hw_table *table = dev->priv.sf_hw_table;
|
||||
u16 hw_fn_id;
|
||||
|
||||
hw_fn_id = mlx5_sf_sw_to_hw_id(table->dev, id);
|
||||
mlx5_cmd_dealloc_sf(table->dev, hw_fn_id);
|
||||
hw_fn_id = mlx5_sf_sw_to_hw_id(dev, id);
|
||||
mlx5_cmd_dealloc_sf(dev, hw_fn_id);
|
||||
table->sfs[id].allocated = false;
|
||||
table->sfs[id].pending_delete = false;
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ void mlx5_sf_hw_table_sf_deferred_free(struct mlx5_core_dev *dev, u16 id)
|
|||
goto err;
|
||||
state = MLX5_GET(query_vhca_state_out, out, vhca_state_context.vhca_state);
|
||||
if (state == MLX5_VHCA_STATE_ALLOCATED) {
|
||||
mlx5_cmd_dealloc_sf(table->dev, hw_fn_id);
|
||||
mlx5_cmd_dealloc_sf(dev, hw_fn_id);
|
||||
table->sfs[id].allocated = false;
|
||||
} else {
|
||||
table->sfs[id].pending_delete = true;
|
||||
|
@ -216,7 +216,7 @@ int mlx5_sf_hw_table_create(struct mlx5_core_dev *dev)
|
|||
return 0;
|
||||
|
||||
table->vhca_nb.notifier_call = mlx5_sf_hw_vhca_event;
|
||||
return mlx5_vhca_event_notifier_register(table->dev, &table->vhca_nb);
|
||||
return mlx5_vhca_event_notifier_register(dev, &table->vhca_nb);
|
||||
}
|
||||
|
||||
void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev)
|
||||
|
@ -226,7 +226,7 @@ void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev)
|
|||
if (!table)
|
||||
return;
|
||||
|
||||
mlx5_vhca_event_notifier_unregister(table->dev, &table->vhca_nb);
|
||||
mlx5_vhca_event_notifier_unregister(dev, &table->vhca_nb);
|
||||
/* Dealloc SFs whose firmware event has been missed. */
|
||||
mlx5_sf_hw_dealloc_all(table);
|
||||
}
|
||||
|
|
|
@ -313,8 +313,8 @@ static int dr_action_handle_cs_recalc(struct mlx5dr_domain *dmn,
|
|||
* table, since there is an *assumption* that in such case FW
|
||||
* will recalculate the CS.
|
||||
*/
|
||||
if (dest_action->dest_tbl.is_fw_tbl) {
|
||||
*final_icm_addr = dest_action->dest_tbl.fw_tbl.rx_icm_addr;
|
||||
if (dest_action->dest_tbl->is_fw_tbl) {
|
||||
*final_icm_addr = dest_action->dest_tbl->fw_tbl.rx_icm_addr;
|
||||
} else {
|
||||
mlx5dr_dbg(dmn,
|
||||
"Destination FT should be terminating when modify TTL is used\n");
|
||||
|
@ -326,8 +326,8 @@ static int dr_action_handle_cs_recalc(struct mlx5dr_domain *dmn,
|
|||
/* If destination is vport we will get the FW flow table
|
||||
* that recalculates the CS and forwards to the vport.
|
||||
*/
|
||||
ret = mlx5dr_domain_cache_get_recalc_cs_ft_addr(dest_action->vport.dmn,
|
||||
dest_action->vport.caps->num,
|
||||
ret = mlx5dr_domain_cache_get_recalc_cs_ft_addr(dest_action->vport->dmn,
|
||||
dest_action->vport->caps->num,
|
||||
final_icm_addr);
|
||||
if (ret) {
|
||||
mlx5dr_err(dmn, "Failed to get FW cs recalc flow table\n");
|
||||
|
@ -369,6 +369,7 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
|
|||
action_domain = dr_action_get_action_domain(dmn->type, nic_dmn->ste_type);
|
||||
|
||||
for (i = 0; i < num_actions; i++) {
|
||||
struct mlx5dr_action_dest_tbl *dest_tbl;
|
||||
struct mlx5dr_action *action;
|
||||
int max_actions_type = 1;
|
||||
u32 action_type;
|
||||
|
@ -382,37 +383,38 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
|
|||
break;
|
||||
case DR_ACTION_TYP_FT:
|
||||
dest_action = action;
|
||||
if (!action->dest_tbl.is_fw_tbl) {
|
||||
if (action->dest_tbl.tbl->dmn != dmn) {
|
||||
dest_tbl = action->dest_tbl;
|
||||
if (!dest_tbl->is_fw_tbl) {
|
||||
if (dest_tbl->tbl->dmn != dmn) {
|
||||
mlx5dr_err(dmn,
|
||||
"Destination table belongs to a different domain\n");
|
||||
goto out_invalid_arg;
|
||||
}
|
||||
if (action->dest_tbl.tbl->level <= matcher->tbl->level) {
|
||||
if (dest_tbl->tbl->level <= matcher->tbl->level) {
|
||||
mlx5_core_warn_once(dmn->mdev,
|
||||
"Connecting table to a lower/same level destination table\n");
|
||||
mlx5dr_dbg(dmn,
|
||||
"Connecting table at level %d to a destination table at level %d\n",
|
||||
matcher->tbl->level,
|
||||
action->dest_tbl.tbl->level);
|
||||
dest_tbl->tbl->level);
|
||||
}
|
||||
attr.final_icm_addr = rx_rule ?
|
||||
action->dest_tbl.tbl->rx.s_anchor->chunk->icm_addr :
|
||||
action->dest_tbl.tbl->tx.s_anchor->chunk->icm_addr;
|
||||
dest_tbl->tbl->rx.s_anchor->chunk->icm_addr :
|
||||
dest_tbl->tbl->tx.s_anchor->chunk->icm_addr;
|
||||
} else {
|
||||
struct mlx5dr_cmd_query_flow_table_details output;
|
||||
int ret;
|
||||
|
||||
/* get the relevant addresses */
|
||||
if (!action->dest_tbl.fw_tbl.rx_icm_addr) {
|
||||
if (!action->dest_tbl->fw_tbl.rx_icm_addr) {
|
||||
ret = mlx5dr_cmd_query_flow_table(dmn->mdev,
|
||||
action->dest_tbl.fw_tbl.type,
|
||||
action->dest_tbl.fw_tbl.id,
|
||||
dest_tbl->fw_tbl.type,
|
||||
dest_tbl->fw_tbl.id,
|
||||
&output);
|
||||
if (!ret) {
|
||||
action->dest_tbl.fw_tbl.tx_icm_addr =
|
||||
dest_tbl->fw_tbl.tx_icm_addr =
|
||||
output.sw_owner_icm_root_1;
|
||||
action->dest_tbl.fw_tbl.rx_icm_addr =
|
||||
dest_tbl->fw_tbl.rx_icm_addr =
|
||||
output.sw_owner_icm_root_0;
|
||||
} else {
|
||||
mlx5dr_err(dmn,
|
||||
|
@ -422,50 +424,50 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
|
|||
}
|
||||
}
|
||||
attr.final_icm_addr = rx_rule ?
|
||||
action->dest_tbl.fw_tbl.rx_icm_addr :
|
||||
action->dest_tbl.fw_tbl.tx_icm_addr;
|
||||
dest_tbl->fw_tbl.rx_icm_addr :
|
||||
dest_tbl->fw_tbl.tx_icm_addr;
|
||||
}
|
||||
break;
|
||||
case DR_ACTION_TYP_QP:
|
||||
mlx5dr_info(dmn, "Domain doesn't support QP\n");
|
||||
goto out_invalid_arg;
|
||||
case DR_ACTION_TYP_CTR:
|
||||
attr.ctr_id = action->ctr.ctr_id +
|
||||
action->ctr.offeset;
|
||||
attr.ctr_id = action->ctr->ctr_id +
|
||||
action->ctr->offeset;
|
||||
break;
|
||||
case DR_ACTION_TYP_TAG:
|
||||
attr.flow_tag = action->flow_tag;
|
||||
attr.flow_tag = action->flow_tag->flow_tag;
|
||||
break;
|
||||
case DR_ACTION_TYP_TNL_L2_TO_L2:
|
||||
break;
|
||||
case DR_ACTION_TYP_TNL_L3_TO_L2:
|
||||
attr.decap_index = action->rewrite.index;
|
||||
attr.decap_actions = action->rewrite.num_of_actions;
|
||||
attr.decap_index = action->rewrite->index;
|
||||
attr.decap_actions = action->rewrite->num_of_actions;
|
||||
attr.decap_with_vlan =
|
||||
attr.decap_actions == WITH_VLAN_NUM_HW_ACTIONS;
|
||||
break;
|
||||
case DR_ACTION_TYP_MODIFY_HDR:
|
||||
attr.modify_index = action->rewrite.index;
|
||||
attr.modify_actions = action->rewrite.num_of_actions;
|
||||
recalc_cs_required = action->rewrite.modify_ttl &&
|
||||
attr.modify_index = action->rewrite->index;
|
||||
attr.modify_actions = action->rewrite->num_of_actions;
|
||||
recalc_cs_required = action->rewrite->modify_ttl &&
|
||||
!mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps);
|
||||
break;
|
||||
case DR_ACTION_TYP_L2_TO_TNL_L2:
|
||||
case DR_ACTION_TYP_L2_TO_TNL_L3:
|
||||
attr.reformat_size = action->reformat.reformat_size;
|
||||
attr.reformat_id = action->reformat.reformat_id;
|
||||
attr.reformat_size = action->reformat->reformat_size;
|
||||
attr.reformat_id = action->reformat->reformat_id;
|
||||
break;
|
||||
case DR_ACTION_TYP_VPORT:
|
||||
attr.hit_gvmi = action->vport.caps->vhca_gvmi;
|
||||
attr.hit_gvmi = action->vport->caps->vhca_gvmi;
|
||||
dest_action = action;
|
||||
if (rx_rule) {
|
||||
/* Loopback on WIRE vport is not supported */
|
||||
if (action->vport.caps->num == WIRE_PORT)
|
||||
if (action->vport->caps->num == WIRE_PORT)
|
||||
goto out_invalid_arg;
|
||||
|
||||
attr.final_icm_addr = action->vport.caps->icm_address_rx;
|
||||
attr.final_icm_addr = action->vport->caps->icm_address_rx;
|
||||
} else {
|
||||
attr.final_icm_addr = action->vport.caps->icm_address_tx;
|
||||
attr.final_icm_addr = action->vport->caps->icm_address_tx;
|
||||
}
|
||||
break;
|
||||
case DR_ACTION_TYP_POP_VLAN:
|
||||
|
@ -477,7 +479,7 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
|
|||
if (attr.vlans.count == MLX5DR_MAX_VLANS)
|
||||
return -EINVAL;
|
||||
|
||||
attr.vlans.headers[attr.vlans.count++] = action->push_vlan.vlan_hdr;
|
||||
attr.vlans.headers[attr.vlans.count++] = action->push_vlan->vlan_hdr;
|
||||
break;
|
||||
default:
|
||||
goto out_invalid_arg;
|
||||
|
@ -530,17 +532,37 @@ out_invalid_arg:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static unsigned int action_size[DR_ACTION_TYP_MAX] = {
|
||||
[DR_ACTION_TYP_TNL_L2_TO_L2] = sizeof(struct mlx5dr_action_reformat),
|
||||
[DR_ACTION_TYP_L2_TO_TNL_L2] = sizeof(struct mlx5dr_action_reformat),
|
||||
[DR_ACTION_TYP_TNL_L3_TO_L2] = sizeof(struct mlx5dr_action_rewrite),
|
||||
[DR_ACTION_TYP_L2_TO_TNL_L3] = sizeof(struct mlx5dr_action_reformat),
|
||||
[DR_ACTION_TYP_FT] = sizeof(struct mlx5dr_action_dest_tbl),
|
||||
[DR_ACTION_TYP_CTR] = sizeof(struct mlx5dr_action_ctr),
|
||||
[DR_ACTION_TYP_TAG] = sizeof(struct mlx5dr_action_flow_tag),
|
||||
[DR_ACTION_TYP_MODIFY_HDR] = sizeof(struct mlx5dr_action_rewrite),
|
||||
[DR_ACTION_TYP_VPORT] = sizeof(struct mlx5dr_action_vport),
|
||||
[DR_ACTION_TYP_PUSH_VLAN] = sizeof(struct mlx5dr_action_push_vlan),
|
||||
};
|
||||
|
||||
static struct mlx5dr_action *
|
||||
dr_action_create_generic(enum mlx5dr_action_type action_type)
|
||||
{
|
||||
struct mlx5dr_action *action;
|
||||
int extra_size;
|
||||
|
||||
action = kzalloc(sizeof(*action), GFP_KERNEL);
|
||||
if (action_type < DR_ACTION_TYP_MAX)
|
||||
extra_size = action_size[action_type];
|
||||
else
|
||||
return NULL;
|
||||
|
||||
action = kzalloc(sizeof(*action) + extra_size, GFP_KERNEL);
|
||||
if (!action)
|
||||
return NULL;
|
||||
|
||||
action->action_type = action_type;
|
||||
refcount_set(&action->refcount, 1);
|
||||
action->data = action + 1;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
@ -559,10 +581,10 @@ mlx5dr_action_create_dest_table_num(struct mlx5dr_domain *dmn, u32 table_num)
|
|||
if (!action)
|
||||
return NULL;
|
||||
|
||||
action->dest_tbl.is_fw_tbl = true;
|
||||
action->dest_tbl.fw_tbl.dmn = dmn;
|
||||
action->dest_tbl.fw_tbl.id = table_num;
|
||||
action->dest_tbl.fw_tbl.type = FS_FT_FDB;
|
||||
action->dest_tbl->is_fw_tbl = true;
|
||||
action->dest_tbl->fw_tbl.dmn = dmn;
|
||||
action->dest_tbl->fw_tbl.id = table_num;
|
||||
action->dest_tbl->fw_tbl.type = FS_FT_FDB;
|
||||
refcount_inc(&dmn->refcount);
|
||||
|
||||
return action;
|
||||
|
@ -579,7 +601,7 @@ mlx5dr_action_create_dest_table(struct mlx5dr_table *tbl)
|
|||
if (!action)
|
||||
goto dec_ref;
|
||||
|
||||
action->dest_tbl.tbl = tbl;
|
||||
action->dest_tbl->tbl = tbl;
|
||||
|
||||
return action;
|
||||
|
||||
|
@ -624,12 +646,12 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
|
|||
case DR_ACTION_TYP_VPORT:
|
||||
hw_dests[i].vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID;
|
||||
hw_dests[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
|
||||
hw_dests[i].vport.num = dest_action->vport.caps->num;
|
||||
hw_dests[i].vport.vhca_id = dest_action->vport.caps->vhca_gvmi;
|
||||
hw_dests[i].vport.num = dest_action->vport->caps->num;
|
||||
hw_dests[i].vport.vhca_id = dest_action->vport->caps->vhca_gvmi;
|
||||
if (reformat_action) {
|
||||
reformat_req = true;
|
||||
hw_dests[i].vport.reformat_id =
|
||||
reformat_action->reformat.reformat_id;
|
||||
reformat_action->reformat->reformat_id;
|
||||
ref_actions[num_of_ref++] = reformat_action;
|
||||
hw_dests[i].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID;
|
||||
}
|
||||
|
@ -637,10 +659,10 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
|
|||
|
||||
case DR_ACTION_TYP_FT:
|
||||
hw_dests[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
|
||||
if (dest_action->dest_tbl.is_fw_tbl)
|
||||
hw_dests[i].ft_id = dest_action->dest_tbl.fw_tbl.id;
|
||||
if (dest_action->dest_tbl->is_fw_tbl)
|
||||
hw_dests[i].ft_id = dest_action->dest_tbl->fw_tbl.id;
|
||||
else
|
||||
hw_dests[i].ft_id = dest_action->dest_tbl.tbl->table_id;
|
||||
hw_dests[i].ft_id = dest_action->dest_tbl->tbl->table_id;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -657,8 +679,8 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
|
|||
hw_dests,
|
||||
num_of_dests,
|
||||
reformat_req,
|
||||
&action->dest_tbl.fw_tbl.id,
|
||||
&action->dest_tbl.fw_tbl.group_id);
|
||||
&action->dest_tbl->fw_tbl.id,
|
||||
&action->dest_tbl->fw_tbl.group_id);
|
||||
if (ret)
|
||||
goto free_action;
|
||||
|
||||
|
@ -667,11 +689,11 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
|
|||
for (i = 0; i < num_of_ref; i++)
|
||||
refcount_inc(&ref_actions[i]->refcount);
|
||||
|
||||
action->dest_tbl.is_fw_tbl = true;
|
||||
action->dest_tbl.fw_tbl.dmn = dmn;
|
||||
action->dest_tbl.fw_tbl.type = FS_FT_FDB;
|
||||
action->dest_tbl.fw_tbl.ref_actions = ref_actions;
|
||||
action->dest_tbl.fw_tbl.num_of_ref_actions = num_of_ref;
|
||||
action->dest_tbl->is_fw_tbl = true;
|
||||
action->dest_tbl->fw_tbl.dmn = dmn;
|
||||
action->dest_tbl->fw_tbl.type = FS_FT_FDB;
|
||||
action->dest_tbl->fw_tbl.ref_actions = ref_actions;
|
||||
action->dest_tbl->fw_tbl.num_of_ref_actions = num_of_ref;
|
||||
|
||||
kfree(hw_dests);
|
||||
|
||||
|
@ -696,10 +718,10 @@ mlx5dr_action_create_dest_flow_fw_table(struct mlx5dr_domain *dmn,
|
|||
if (!action)
|
||||
return NULL;
|
||||
|
||||
action->dest_tbl.is_fw_tbl = 1;
|
||||
action->dest_tbl.fw_tbl.type = ft->type;
|
||||
action->dest_tbl.fw_tbl.id = ft->id;
|
||||
action->dest_tbl.fw_tbl.dmn = dmn;
|
||||
action->dest_tbl->is_fw_tbl = 1;
|
||||
action->dest_tbl->fw_tbl.type = ft->type;
|
||||
action->dest_tbl->fw_tbl.id = ft->id;
|
||||
action->dest_tbl->fw_tbl.dmn = dmn;
|
||||
|
||||
refcount_inc(&dmn->refcount);
|
||||
|
||||
|
@ -715,7 +737,7 @@ mlx5dr_action_create_flow_counter(u32 counter_id)
|
|||
if (!action)
|
||||
return NULL;
|
||||
|
||||
action->ctr.ctr_id = counter_id;
|
||||
action->ctr->ctr_id = counter_id;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
@ -728,7 +750,7 @@ struct mlx5dr_action *mlx5dr_action_create_tag(u32 tag_value)
|
|||
if (!action)
|
||||
return NULL;
|
||||
|
||||
action->flow_tag = tag_value & 0xffffff;
|
||||
action->flow_tag->flow_tag = tag_value & 0xffffff;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
@ -794,8 +816,8 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
action->reformat.reformat_id = reformat_id;
|
||||
action->reformat.reformat_size = data_sz;
|
||||
action->reformat->reformat_id = reformat_id;
|
||||
action->reformat->reformat_size = data_sz;
|
||||
return 0;
|
||||
}
|
||||
case DR_ACTION_TYP_TNL_L2_TO_L2:
|
||||
|
@ -811,28 +833,28 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
|
|||
data, data_sz,
|
||||
hw_actions,
|
||||
ACTION_CACHE_LINE_SIZE,
|
||||
&action->rewrite.num_of_actions);
|
||||
&action->rewrite->num_of_actions);
|
||||
if (ret) {
|
||||
mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
action->rewrite.chunk = mlx5dr_icm_alloc_chunk(dmn->action_icm_pool,
|
||||
action->rewrite->chunk = mlx5dr_icm_alloc_chunk(dmn->action_icm_pool,
|
||||
DR_CHUNK_SIZE_8);
|
||||
if (!action->rewrite.chunk) {
|
||||
if (!action->rewrite->chunk) {
|
||||
mlx5dr_dbg(dmn, "Failed allocating modify header chunk\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
action->rewrite.data = (void *)hw_actions;
|
||||
action->rewrite.index = (action->rewrite.chunk->icm_addr -
|
||||
action->rewrite->data = (void *)hw_actions;
|
||||
action->rewrite->index = (action->rewrite->chunk->icm_addr -
|
||||
dmn->info.caps.hdr_modify_icm_addr) /
|
||||
ACTION_CACHE_LINE_SIZE;
|
||||
|
||||
ret = mlx5dr_send_postsend_action(dmn, action);
|
||||
if (ret) {
|
||||
mlx5dr_dbg(dmn, "Writing decap l3 actions to ICM failed\n");
|
||||
mlx5dr_icm_free_chunk(action->rewrite.chunk);
|
||||
mlx5dr_icm_free_chunk(action->rewrite->chunk);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
|
@ -867,7 +889,7 @@ struct mlx5dr_action *mlx5dr_action_create_push_vlan(struct mlx5dr_domain *dmn,
|
|||
if (!action)
|
||||
return NULL;
|
||||
|
||||
action->push_vlan.vlan_hdr = vlan_hdr_h;
|
||||
action->push_vlan->vlan_hdr = vlan_hdr_h;
|
||||
return action;
|
||||
}
|
||||
|
||||
|
@ -898,7 +920,7 @@ mlx5dr_action_create_packet_reformat(struct mlx5dr_domain *dmn,
|
|||
if (!action)
|
||||
goto dec_ref;
|
||||
|
||||
action->reformat.dmn = dmn;
|
||||
action->reformat->dmn = dmn;
|
||||
|
||||
ret = dr_action_create_reformat_action(dmn,
|
||||
data_sz,
|
||||
|
@ -1104,17 +1126,17 @@ dr_action_modify_check_set_field_limitation(struct mlx5dr_action *action,
|
|||
const __be64 *sw_action)
|
||||
{
|
||||
u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
|
||||
struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||||
struct mlx5dr_domain *dmn = action->rewrite->dmn;
|
||||
|
||||
if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_A) {
|
||||
action->rewrite.allow_rx = 0;
|
||||
action->rewrite->allow_rx = 0;
|
||||
if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) {
|
||||
mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n",
|
||||
sw_field);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_B) {
|
||||
action->rewrite.allow_tx = 0;
|
||||
action->rewrite->allow_tx = 0;
|
||||
if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) {
|
||||
mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n",
|
||||
sw_field);
|
||||
|
@ -1122,7 +1144,7 @@ dr_action_modify_check_set_field_limitation(struct mlx5dr_action *action,
|
|||
}
|
||||
}
|
||||
|
||||
if (!action->rewrite.allow_rx && !action->rewrite.allow_tx) {
|
||||
if (!action->rewrite->allow_rx && !action->rewrite->allow_tx) {
|
||||
mlx5dr_dbg(dmn, "Modify SET actions not supported on both RX and TX\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1135,7 +1157,7 @@ dr_action_modify_check_add_field_limitation(struct mlx5dr_action *action,
|
|||
const __be64 *sw_action)
|
||||
{
|
||||
u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
|
||||
struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||||
struct mlx5dr_domain *dmn = action->rewrite->dmn;
|
||||
|
||||
if (sw_field != MLX5_ACTION_IN_FIELD_OUT_IP_TTL &&
|
||||
sw_field != MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT &&
|
||||
|
@ -1153,7 +1175,7 @@ static int
|
|||
dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action,
|
||||
const __be64 *sw_action)
|
||||
{
|
||||
struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||||
struct mlx5dr_domain *dmn = action->rewrite->dmn;
|
||||
u16 sw_fields[2];
|
||||
int i;
|
||||
|
||||
|
@ -1162,14 +1184,14 @@ dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action,
|
|||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_A) {
|
||||
action->rewrite.allow_rx = 0;
|
||||
action->rewrite->allow_rx = 0;
|
||||
if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) {
|
||||
mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n",
|
||||
sw_fields[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_B) {
|
||||
action->rewrite.allow_tx = 0;
|
||||
action->rewrite->allow_tx = 0;
|
||||
if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) {
|
||||
mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n",
|
||||
sw_fields[i]);
|
||||
|
@ -1178,7 +1200,7 @@ dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action,
|
|||
}
|
||||
}
|
||||
|
||||
if (!action->rewrite.allow_rx && !action->rewrite.allow_tx) {
|
||||
if (!action->rewrite->allow_rx && !action->rewrite->allow_tx) {
|
||||
mlx5dr_dbg(dmn, "Modify copy actions not supported on both RX and TX\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1190,7 +1212,7 @@ static int
|
|||
dr_action_modify_check_field_limitation(struct mlx5dr_action *action,
|
||||
const __be64 *sw_action)
|
||||
{
|
||||
struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||||
struct mlx5dr_domain *dmn = action->rewrite->dmn;
|
||||
u8 action_type;
|
||||
int ret;
|
||||
|
||||
|
@ -1239,7 +1261,7 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
|
|||
{
|
||||
const struct mlx5dr_ste_action_modify_field *hw_dst_action_info;
|
||||
const struct mlx5dr_ste_action_modify_field *hw_src_action_info;
|
||||
struct mlx5dr_domain *dmn = action->rewrite.dmn;
|
||||
struct mlx5dr_domain *dmn = action->rewrite->dmn;
|
||||
int ret, i, hw_idx = 0;
|
||||
__be64 *sw_action;
|
||||
__be64 hw_action;
|
||||
|
@ -1249,8 +1271,8 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
|
|||
|
||||
*modify_ttl = false;
|
||||
|
||||
action->rewrite.allow_rx = 1;
|
||||
action->rewrite.allow_tx = 1;
|
||||
action->rewrite->allow_rx = 1;
|
||||
action->rewrite->allow_tx = 1;
|
||||
|
||||
for (i = 0; i < num_sw_actions; i++) {
|
||||
sw_action = &sw_actions[i];
|
||||
|
@ -1358,11 +1380,11 @@ static int dr_action_create_modify_action(struct mlx5dr_domain *dmn,
|
|||
if (ret)
|
||||
goto free_hw_actions;
|
||||
|
||||
action->rewrite.chunk = chunk;
|
||||
action->rewrite.modify_ttl = modify_ttl;
|
||||
action->rewrite.data = (u8 *)hw_actions;
|
||||
action->rewrite.num_of_actions = num_hw_actions;
|
||||
action->rewrite.index = (chunk->icm_addr -
|
||||
action->rewrite->chunk = chunk;
|
||||
action->rewrite->modify_ttl = modify_ttl;
|
||||
action->rewrite->data = (u8 *)hw_actions;
|
||||
action->rewrite->num_of_actions = num_hw_actions;
|
||||
action->rewrite->index = (chunk->icm_addr -
|
||||
dmn->info.caps.hdr_modify_icm_addr) /
|
||||
ACTION_CACHE_LINE_SIZE;
|
||||
|
||||
|
@ -1399,7 +1421,7 @@ mlx5dr_action_create_modify_header(struct mlx5dr_domain *dmn,
|
|||
if (!action)
|
||||
goto dec_ref;
|
||||
|
||||
action->rewrite.dmn = dmn;
|
||||
action->rewrite->dmn = dmn;
|
||||
|
||||
ret = dr_action_create_modify_action(dmn,
|
||||
actions_sz,
|
||||
|
@ -1451,8 +1473,8 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn,
|
|||
if (!action)
|
||||
return NULL;
|
||||
|
||||
action->vport.dmn = vport_dmn;
|
||||
action->vport.caps = vport_cap;
|
||||
action->vport->dmn = vport_dmn;
|
||||
action->vport->caps = vport_cap;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
@ -1464,44 +1486,44 @@ int mlx5dr_action_destroy(struct mlx5dr_action *action)
|
|||
|
||||
switch (action->action_type) {
|
||||
case DR_ACTION_TYP_FT:
|
||||
if (action->dest_tbl.is_fw_tbl)
|
||||
refcount_dec(&action->dest_tbl.fw_tbl.dmn->refcount);
|
||||
if (action->dest_tbl->is_fw_tbl)
|
||||
refcount_dec(&action->dest_tbl->fw_tbl.dmn->refcount);
|
||||
else
|
||||
refcount_dec(&action->dest_tbl.tbl->refcount);
|
||||
refcount_dec(&action->dest_tbl->tbl->refcount);
|
||||
|
||||
if (action->dest_tbl.is_fw_tbl &&
|
||||
action->dest_tbl.fw_tbl.num_of_ref_actions) {
|
||||
if (action->dest_tbl->is_fw_tbl &&
|
||||
action->dest_tbl->fw_tbl.num_of_ref_actions) {
|
||||
struct mlx5dr_action **ref_actions;
|
||||
int i;
|
||||
|
||||
ref_actions = action->dest_tbl.fw_tbl.ref_actions;
|
||||
for (i = 0; i < action->dest_tbl.fw_tbl.num_of_ref_actions; i++)
|
||||
ref_actions = action->dest_tbl->fw_tbl.ref_actions;
|
||||
for (i = 0; i < action->dest_tbl->fw_tbl.num_of_ref_actions; i++)
|
||||
refcount_dec(&ref_actions[i]->refcount);
|
||||
|
||||
kfree(ref_actions);
|
||||
|
||||
mlx5dr_fw_destroy_md_tbl(action->dest_tbl.fw_tbl.dmn,
|
||||
action->dest_tbl.fw_tbl.id,
|
||||
action->dest_tbl.fw_tbl.group_id);
|
||||
mlx5dr_fw_destroy_md_tbl(action->dest_tbl->fw_tbl.dmn,
|
||||
action->dest_tbl->fw_tbl.id,
|
||||
action->dest_tbl->fw_tbl.group_id);
|
||||
}
|
||||
break;
|
||||
case DR_ACTION_TYP_TNL_L2_TO_L2:
|
||||
refcount_dec(&action->reformat.dmn->refcount);
|
||||
refcount_dec(&action->reformat->dmn->refcount);
|
||||
break;
|
||||
case DR_ACTION_TYP_TNL_L3_TO_L2:
|
||||
mlx5dr_icm_free_chunk(action->rewrite.chunk);
|
||||
refcount_dec(&action->reformat.dmn->refcount);
|
||||
mlx5dr_icm_free_chunk(action->rewrite->chunk);
|
||||
refcount_dec(&action->rewrite->dmn->refcount);
|
||||
break;
|
||||
case DR_ACTION_TYP_L2_TO_TNL_L2:
|
||||
case DR_ACTION_TYP_L2_TO_TNL_L3:
|
||||
mlx5dr_cmd_destroy_reformat_ctx((action->reformat.dmn)->mdev,
|
||||
action->reformat.reformat_id);
|
||||
refcount_dec(&action->reformat.dmn->refcount);
|
||||
mlx5dr_cmd_destroy_reformat_ctx((action->reformat->dmn)->mdev,
|
||||
action->reformat->reformat_id);
|
||||
refcount_dec(&action->reformat->dmn->refcount);
|
||||
break;
|
||||
case DR_ACTION_TYP_MODIFY_HDR:
|
||||
mlx5dr_icm_free_chunk(action->rewrite.chunk);
|
||||
kfree(action->rewrite.data);
|
||||
refcount_dec(&action->rewrite.dmn->refcount);
|
||||
mlx5dr_icm_free_chunk(action->rewrite->chunk);
|
||||
kfree(action->rewrite->data);
|
||||
refcount_dec(&action->rewrite->dmn->refcount);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -287,7 +287,7 @@ int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
|
|||
u32 *in;
|
||||
int err;
|
||||
|
||||
in = kzalloc(inlen, GFP_KERNEL);
|
||||
in = kvzalloc(inlen, GFP_KERNEL);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -302,7 +302,7 @@ int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
|
|||
*group_id = MLX5_GET(create_flow_group_out, out, group_id);
|
||||
|
||||
out:
|
||||
kfree(in);
|
||||
kvfree(in);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -406,7 +406,7 @@ static int dr_get_tbl_copy_details(struct mlx5dr_domain *dmn,
|
|||
alloc_size = *num_stes * DR_STE_SIZE;
|
||||
}
|
||||
|
||||
*data = kzalloc(alloc_size, GFP_KERNEL);
|
||||
*data = kvzalloc(alloc_size, GFP_KERNEL);
|
||||
if (!*data)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -505,7 +505,7 @@ int mlx5dr_send_postsend_htbl(struct mlx5dr_domain *dmn,
|
|||
}
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
kvfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -562,7 +562,7 @@ int mlx5dr_send_postsend_formatted_htbl(struct mlx5dr_domain *dmn,
|
|||
}
|
||||
|
||||
out_free:
|
||||
kfree(data);
|
||||
kvfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -572,12 +572,12 @@ int mlx5dr_send_postsend_action(struct mlx5dr_domain *dmn,
|
|||
struct postsend_info send_info = {};
|
||||
int ret;
|
||||
|
||||
send_info.write.addr = (uintptr_t)action->rewrite.data;
|
||||
send_info.write.length = action->rewrite.num_of_actions *
|
||||
send_info.write.addr = (uintptr_t)action->rewrite->data;
|
||||
send_info.write.length = action->rewrite->num_of_actions *
|
||||
DR_MODIFY_ACTION_SIZE;
|
||||
send_info.write.lkey = 0;
|
||||
send_info.remote_addr = action->rewrite.chunk->mr_addr;
|
||||
send_info.rkey = action->rewrite.chunk->rkey;
|
||||
send_info.remote_addr = action->rewrite->chunk->mr_addr;
|
||||
send_info.rkey = action->rewrite->chunk->rkey;
|
||||
|
||||
ret = dr_postsend_icm_data(dmn, &send_info);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
|
|||
last_htbl = tbl->rx.s_anchor;
|
||||
|
||||
tbl->rx.default_icm_addr = action ?
|
||||
action->dest_tbl.tbl->rx.s_anchor->chunk->icm_addr :
|
||||
action->dest_tbl->tbl->rx.s_anchor->chunk->icm_addr :
|
||||
tbl->rx.nic_dmn->default_icm_addr;
|
||||
|
||||
info.type = CONNECT_MISS;
|
||||
|
@ -53,7 +53,7 @@ int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
|
|||
last_htbl = tbl->tx.s_anchor;
|
||||
|
||||
tbl->tx.default_icm_addr = action ?
|
||||
action->dest_tbl.tbl->tx.s_anchor->chunk->icm_addr :
|
||||
action->dest_tbl->tbl->tx.s_anchor->chunk->icm_addr :
|
||||
tbl->tx.nic_dmn->default_icm_addr;
|
||||
|
||||
info.type = CONNECT_MISS;
|
||||
|
|
|
@ -806,11 +806,7 @@ struct mlx5dr_ste_action_modify_field {
|
|||
u8 l4_type;
|
||||
};
|
||||
|
||||
struct mlx5dr_action {
|
||||
enum mlx5dr_action_type action_type;
|
||||
refcount_t refcount;
|
||||
union {
|
||||
struct {
|
||||
struct mlx5dr_action_rewrite {
|
||||
struct mlx5dr_domain *dmn;
|
||||
struct mlx5dr_icm_chunk *chunk;
|
||||
u8 *data;
|
||||
|
@ -819,13 +815,15 @@ struct mlx5dr_action {
|
|||
u8 allow_rx:1;
|
||||
u8 allow_tx:1;
|
||||
u8 modify_ttl:1;
|
||||
} rewrite;
|
||||
struct {
|
||||
};
|
||||
|
||||
struct mlx5dr_action_reformat {
|
||||
struct mlx5dr_domain *dmn;
|
||||
u32 reformat_id;
|
||||
u32 reformat_size;
|
||||
} reformat;
|
||||
struct {
|
||||
};
|
||||
|
||||
struct mlx5dr_action_dest_tbl {
|
||||
u8 is_fw_tbl:1;
|
||||
union {
|
||||
struct mlx5dr_table *tbl;
|
||||
|
@ -840,19 +838,39 @@ struct mlx5dr_action {
|
|||
u32 num_of_ref_actions;
|
||||
} fw_tbl;
|
||||
};
|
||||
} dest_tbl;
|
||||
struct {
|
||||
};
|
||||
|
||||
struct mlx5dr_action_ctr {
|
||||
u32 ctr_id;
|
||||
u32 offeset;
|
||||
} ctr;
|
||||
struct {
|
||||
};
|
||||
|
||||
struct mlx5dr_action_vport {
|
||||
struct mlx5dr_domain *dmn;
|
||||
struct mlx5dr_cmd_vport_cap *caps;
|
||||
} vport;
|
||||
struct {
|
||||
};
|
||||
|
||||
struct mlx5dr_action_push_vlan {
|
||||
u32 vlan_hdr; /* tpid_pcp_dei_vid */
|
||||
} push_vlan;
|
||||
};
|
||||
|
||||
struct mlx5dr_action_flow_tag {
|
||||
u32 flow_tag;
|
||||
};
|
||||
|
||||
struct mlx5dr_action {
|
||||
enum mlx5dr_action_type action_type;
|
||||
refcount_t refcount;
|
||||
|
||||
union {
|
||||
void *data;
|
||||
struct mlx5dr_action_rewrite *rewrite;
|
||||
struct mlx5dr_action_reformat *reformat;
|
||||
struct mlx5dr_action_dest_tbl *dest_tbl;
|
||||
struct mlx5dr_action_ctr *ctr;
|
||||
struct mlx5dr_action_vport *vport;
|
||||
struct mlx5dr_action_push_vlan *push_vlan;
|
||||
struct mlx5dr_action_flow_tag *flow_tag;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -152,8 +152,7 @@ mlx5_eswitch_vport_match_metadata_enabled(const struct mlx5_eswitch *esw)
|
|||
};
|
||||
|
||||
static inline u32
|
||||
mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw,
|
||||
int vport_num)
|
||||
mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw, u16 vport_num)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue