mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
net/mlx5e: Add ethtool flow steering support
Implement etrhtool set_rxnfc callback to support ethtool flow spec direct steering. This patch adds only the support of ether flow type spec. L3/L4 flow specs support will be added in downstream patches. Signed-off-by: Maor Gottlieb <maorg@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0da2d66666
commit
6dc6071cfc
7 changed files with 456 additions and 12 deletions
|
@ -8,6 +8,6 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
|
|||
mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \
|
||||
en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \
|
||||
en_rx.o en_rx_am.o en_txrx.o en_clock.o vxlan.o \
|
||||
en_tc.o en_arfs.o en_rep.o
|
||||
en_tc.o en_arfs.o en_rep.o en_fs_ethtool.o
|
||||
|
||||
mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o
|
||||
|
|
|
@ -544,8 +544,22 @@ enum {
|
|||
MLX5E_ARFS_FT_LEVEL
|
||||
};
|
||||
|
||||
struct mlx5e_ethtool_table {
|
||||
struct mlx5_flow_table *ft;
|
||||
int num_rules;
|
||||
};
|
||||
|
||||
#define ETHTOOL_NUM_L2_FTS 4
|
||||
|
||||
struct mlx5e_ethtool_steering {
|
||||
struct mlx5e_ethtool_table l2_ft[ETHTOOL_NUM_L2_FTS];
|
||||
struct list_head rules;
|
||||
int tot_num_rules;
|
||||
};
|
||||
|
||||
struct mlx5e_flow_steering {
|
||||
struct mlx5_flow_namespace *ns;
|
||||
struct mlx5e_ethtool_steering ethtool;
|
||||
struct mlx5e_tc_table tc;
|
||||
struct mlx5e_vlan_table vlan;
|
||||
struct mlx5e_l2_table l2;
|
||||
|
@ -701,6 +715,12 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
|
|||
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);
|
||||
void mlx5e_init_l2_addr(struct mlx5e_priv *priv);
|
||||
void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft);
|
||||
int mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,
|
||||
struct ethtool_rx_flow_spec *fs);
|
||||
int mlx5e_ethtool_flow_remove(struct mlx5e_priv *priv,
|
||||
int location);
|
||||
void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv);
|
||||
void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv);
|
||||
void mlx5e_set_rx_mode_work(struct work_struct *work);
|
||||
|
||||
void mlx5e_fill_hwstamp(struct mlx5e_tstamp *clock, u64 timestamp,
|
||||
|
|
|
@ -1368,6 +1368,26 @@ static u32 mlx5e_get_priv_flags(struct net_device *netdev)
|
|||
return priv->pflags;
|
||||
}
|
||||
|
||||
static int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
|
||||
{
|
||||
int err = 0;
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
|
||||
switch (cmd->cmd) {
|
||||
case ETHTOOL_SRXCLSRLINS:
|
||||
err = mlx5e_ethtool_flow_replace(priv, &cmd->fs);
|
||||
break;
|
||||
case ETHTOOL_SRXCLSRLDEL:
|
||||
err = mlx5e_ethtool_flow_remove(priv, cmd->fs.location);
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct ethtool_ops mlx5e_ethtool_ops = {
|
||||
.get_drvinfo = mlx5e_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
|
@ -1387,6 +1407,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
|
|||
.get_rxfh = mlx5e_get_rxfh,
|
||||
.set_rxfh = mlx5e_set_rxfh,
|
||||
.get_rxnfc = mlx5e_get_rxnfc,
|
||||
.set_rxnfc = mlx5e_set_rxnfc,
|
||||
.get_tunable = mlx5e_get_tunable,
|
||||
.set_tunable = mlx5e_set_tunable,
|
||||
.get_pauseparam = mlx5e_get_pauseparam,
|
||||
|
|
|
@ -1084,6 +1084,8 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
|
|||
goto err_destroy_l2_table;
|
||||
}
|
||||
|
||||
mlx5e_ethtool_init_steering(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_l2_table:
|
||||
|
@ -1103,4 +1105,5 @@ void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv)
|
|||
mlx5e_destroy_l2_table(priv);
|
||||
mlx5e_destroy_ttc_table(priv);
|
||||
mlx5e_arfs_destroy_tables(priv);
|
||||
mlx5e_ethtool_cleanup_steering(priv);
|
||||
}
|
||||
|
|
393
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
Normal file
393
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
Normal file
|
@ -0,0 +1,393 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Mellanox Technologies. All rights reserved.
|
||||
*
|
||||
* This software is available to you under a choice of one of two
|
||||
* licenses. You may choose to be licensed under the terms of the GNU
|
||||
* General Public License (GPL) Version 2, available from the file
|
||||
* COPYING in the main directory of this source tree, or the
|
||||
* OpenIB.org BSD license below:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/mlx5/fs.h>
|
||||
#include "en.h"
|
||||
|
||||
struct mlx5e_ethtool_rule {
|
||||
struct list_head list;
|
||||
struct ethtool_rx_flow_spec flow_spec;
|
||||
struct mlx5_flow_rule *rule;
|
||||
struct mlx5e_ethtool_table *eth_ft;
|
||||
};
|
||||
|
||||
static void put_flow_table(struct mlx5e_ethtool_table *eth_ft)
|
||||
{
|
||||
if (!--eth_ft->num_rules) {
|
||||
mlx5_destroy_flow_table(eth_ft->ft);
|
||||
eth_ft->ft = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define MLX5E_ETHTOOL_L2_PRIO 0
|
||||
#define MLX5E_ETHTOOL_NUM_ENTRIES 64000
|
||||
#define MLX5E_ETHTOOL_NUM_GROUPS 10
|
||||
static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv,
|
||||
struct ethtool_rx_flow_spec *fs,
|
||||
int num_tuples)
|
||||
{
|
||||
struct mlx5e_ethtool_table *eth_ft;
|
||||
struct mlx5_flow_namespace *ns;
|
||||
struct mlx5_flow_table *ft;
|
||||
int max_tuples;
|
||||
int table_size;
|
||||
int prio;
|
||||
|
||||
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
|
||||
case ETHER_FLOW:
|
||||
max_tuples = ETHTOOL_NUM_L2_FTS;
|
||||
prio = max_tuples - num_tuples;
|
||||
eth_ft = &priv->fs.ethtool.l2_ft[prio];
|
||||
prio += MLX5E_ETHTOOL_L2_PRIO;
|
||||
break;
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
eth_ft->num_rules++;
|
||||
if (eth_ft->ft)
|
||||
return eth_ft;
|
||||
|
||||
ns = mlx5_get_flow_namespace(priv->mdev,
|
||||
MLX5_FLOW_NAMESPACE_ETHTOOL);
|
||||
if (!ns)
|
||||
return ERR_PTR(-ENOTSUPP);
|
||||
|
||||
table_size = min_t(u32, BIT(MLX5_CAP_FLOWTABLE(priv->mdev,
|
||||
flow_table_properties_nic_receive.log_max_ft_size)),
|
||||
MLX5E_ETHTOOL_NUM_ENTRIES);
|
||||
ft = mlx5_create_auto_grouped_flow_table(ns, prio,
|
||||
table_size,
|
||||
MLX5E_ETHTOOL_NUM_GROUPS, 0);
|
||||
if (IS_ERR(ft))
|
||||
return (void *)ft;
|
||||
|
||||
eth_ft->ft = ft;
|
||||
return eth_ft;
|
||||
}
|
||||
|
||||
static void mask_spec(u8 *mask, u8 *val, size_t size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < size; i++, mask++, val++)
|
||||
*((u8 *)val) = *((u8 *)mask) & *((u8 *)val);
|
||||
}
|
||||
|
||||
static int set_flow_attrs(u32 *match_c, u32 *match_v,
|
||||
struct ethtool_rx_flow_spec *fs)
|
||||
{
|
||||
void *outer_headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
|
||||
outer_headers);
|
||||
void *outer_headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
|
||||
outer_headers);
|
||||
u32 flow_type = fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT);
|
||||
struct ethhdr *eth_val;
|
||||
struct ethhdr *eth_mask;
|
||||
|
||||
switch (flow_type) {
|
||||
case ETHER_FLOW:
|
||||
eth_mask = &fs->m_u.ether_spec;
|
||||
eth_val = &fs->h_u.ether_spec;
|
||||
|
||||
mask_spec((u8 *)eth_mask, (u8 *)eth_val, sizeof(*eth_mask));
|
||||
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4,
|
||||
outer_headers_c, smac_47_16),
|
||||
eth_mask->h_source);
|
||||
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4,
|
||||
outer_headers_v, smac_47_16),
|
||||
eth_val->h_source);
|
||||
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4,
|
||||
outer_headers_c, dmac_47_16),
|
||||
eth_mask->h_dest);
|
||||
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4,
|
||||
outer_headers_v, dmac_47_16),
|
||||
eth_val->h_dest);
|
||||
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, ethertype,
|
||||
ntohs(eth_mask->h_proto));
|
||||
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, ethertype,
|
||||
ntohs(eth_val->h_proto));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((fs->flow_type & FLOW_EXT) &&
|
||||
(fs->m_ext.vlan_tci & cpu_to_be16(VLAN_VID_MASK))) {
|
||||
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
|
||||
vlan_tag, 1);
|
||||
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
|
||||
vlan_tag, 1);
|
||||
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
|
||||
first_vid, 0xfff);
|
||||
MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
|
||||
first_vid, ntohs(fs->h_ext.vlan_tci));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void add_rule_to_list(struct mlx5e_priv *priv,
|
||||
struct mlx5e_ethtool_rule *rule)
|
||||
{
|
||||
struct mlx5e_ethtool_rule *iter;
|
||||
struct list_head *head = &priv->fs.ethtool.rules;
|
||||
|
||||
list_for_each_entry(iter, &priv->fs.ethtool.rules, list) {
|
||||
if (iter->flow_spec.location > rule->flow_spec.location)
|
||||
break;
|
||||
head = &iter->list;
|
||||
}
|
||||
priv->fs.ethtool.tot_num_rules++;
|
||||
list_add(&rule->list, head);
|
||||
}
|
||||
|
||||
static bool outer_header_zero(u32 *match_criteria)
|
||||
{
|
||||
int size = MLX5_ST_SZ_BYTES(fte_match_param);
|
||||
char *outer_headers_c = MLX5_ADDR_OF(fte_match_param, match_criteria,
|
||||
outer_headers);
|
||||
|
||||
return outer_headers_c[0] == 0 && !memcmp(outer_headers_c,
|
||||
outer_headers_c + 1,
|
||||
size - 1);
|
||||
}
|
||||
|
||||
static struct mlx5_flow_rule *add_ethtool_flow_rule(struct mlx5e_priv *priv,
|
||||
struct mlx5_flow_table *ft,
|
||||
struct ethtool_rx_flow_spec *fs)
|
||||
{
|
||||
struct mlx5_flow_destination *dst = NULL;
|
||||
struct mlx5_flow_spec *spec;
|
||||
struct mlx5_flow_rule *rule;
|
||||
int err = 0;
|
||||
u32 action;
|
||||
|
||||
spec = mlx5_vzalloc(sizeof(*spec));
|
||||
if (!spec)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
err = set_flow_attrs(spec->match_criteria, spec->match_value,
|
||||
fs);
|
||||
if (err)
|
||||
goto free;
|
||||
|
||||
if (fs->ring_cookie == RX_CLS_FLOW_DISC) {
|
||||
action = MLX5_FLOW_CONTEXT_ACTION_DROP;
|
||||
} else {
|
||||
dst = kzalloc(sizeof(*dst), GFP_KERNEL);
|
||||
if (!dst) {
|
||||
err = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
|
||||
dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
|
||||
dst->tir_num = priv->direct_tir[fs->ring_cookie].tirn;
|
||||
action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||
}
|
||||
|
||||
spec->match_criteria_enable = (!outer_header_zero(spec->match_criteria));
|
||||
rule = mlx5_add_flow_rule(ft, spec, action,
|
||||
MLX5_FS_DEFAULT_FLOW_TAG, dst);
|
||||
if (IS_ERR(rule)) {
|
||||
err = PTR_ERR(rule);
|
||||
netdev_err(priv->netdev, "%s: failed to add ethtool steering rule: %d\n",
|
||||
__func__, err);
|
||||
goto free;
|
||||
}
|
||||
free:
|
||||
kvfree(spec);
|
||||
kfree(dst);
|
||||
return err ? ERR_PTR(err) : rule;
|
||||
}
|
||||
|
||||
static void del_ethtool_rule(struct mlx5e_priv *priv,
|
||||
struct mlx5e_ethtool_rule *eth_rule)
|
||||
{
|
||||
if (eth_rule->rule)
|
||||
mlx5_del_flow_rule(eth_rule->rule);
|
||||
list_del(ð_rule->list);
|
||||
priv->fs.ethtool.tot_num_rules--;
|
||||
put_flow_table(eth_rule->eth_ft);
|
||||
kfree(eth_rule);
|
||||
}
|
||||
|
||||
static struct mlx5e_ethtool_rule *find_ethtool_rule(struct mlx5e_priv *priv,
|
||||
int location)
|
||||
{
|
||||
struct mlx5e_ethtool_rule *iter;
|
||||
|
||||
list_for_each_entry(iter, &priv->fs.ethtool.rules, list) {
|
||||
if (iter->flow_spec.location == location)
|
||||
return iter;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct mlx5e_ethtool_rule *get_ethtool_rule(struct mlx5e_priv *priv,
|
||||
int location)
|
||||
{
|
||||
struct mlx5e_ethtool_rule *eth_rule;
|
||||
|
||||
eth_rule = find_ethtool_rule(priv, location);
|
||||
if (eth_rule)
|
||||
del_ethtool_rule(priv, eth_rule);
|
||||
|
||||
eth_rule = kzalloc(sizeof(*eth_rule), GFP_KERNEL);
|
||||
if (!eth_rule)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
add_rule_to_list(priv, eth_rule);
|
||||
return eth_rule;
|
||||
}
|
||||
|
||||
#define MAX_NUM_OF_ETHTOOL_RULES BIT(10)
|
||||
static int validate_flow(struct mlx5e_priv *priv,
|
||||
struct ethtool_rx_flow_spec *fs)
|
||||
{
|
||||
struct ethhdr *eth_mask;
|
||||
int num_tuples = 0;
|
||||
|
||||
if (fs->location >= MAX_NUM_OF_ETHTOOL_RULES)
|
||||
return -EINVAL;
|
||||
|
||||
if (fs->ring_cookie >= priv->params.num_channels &&
|
||||
fs->ring_cookie != RX_CLS_FLOW_DISC)
|
||||
return -EINVAL;
|
||||
|
||||
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
|
||||
case ETHER_FLOW:
|
||||
eth_mask = &fs->m_u.ether_spec;
|
||||
if (!is_zero_ether_addr(eth_mask->h_dest))
|
||||
num_tuples++;
|
||||
if (!is_zero_ether_addr(eth_mask->h_source))
|
||||
num_tuples++;
|
||||
if (eth_mask->h_proto)
|
||||
num_tuples++;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if ((fs->flow_type & FLOW_EXT)) {
|
||||
if (fs->m_ext.vlan_etype ||
|
||||
(fs->m_ext.vlan_tci != cpu_to_be16(VLAN_VID_MASK)))
|
||||
return -EINVAL;
|
||||
|
||||
if (fs->m_ext.vlan_tci) {
|
||||
if (be16_to_cpu(fs->h_ext.vlan_tci) >= VLAN_N_VID)
|
||||
return -EINVAL;
|
||||
}
|
||||
num_tuples++;
|
||||
}
|
||||
|
||||
return num_tuples;
|
||||
}
|
||||
|
||||
int mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,
|
||||
struct ethtool_rx_flow_spec *fs)
|
||||
{
|
||||
struct mlx5e_ethtool_table *eth_ft;
|
||||
struct mlx5e_ethtool_rule *eth_rule;
|
||||
struct mlx5_flow_rule *rule;
|
||||
int num_tuples;
|
||||
int err;
|
||||
|
||||
num_tuples = validate_flow(priv, fs);
|
||||
if (num_tuples <= 0) {
|
||||
netdev_warn(priv->netdev, "%s: flow is not valid\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
eth_ft = get_flow_table(priv, fs, num_tuples);
|
||||
if (IS_ERR(eth_ft))
|
||||
return PTR_ERR(eth_ft);
|
||||
|
||||
eth_rule = get_ethtool_rule(priv, fs->location);
|
||||
if (IS_ERR(eth_rule)) {
|
||||
put_flow_table(eth_ft);
|
||||
return PTR_ERR(eth_rule);
|
||||
}
|
||||
|
||||
eth_rule->flow_spec = *fs;
|
||||
eth_rule->eth_ft = eth_ft;
|
||||
if (!eth_ft->ft) {
|
||||
err = -EINVAL;
|
||||
goto del_ethtool_rule;
|
||||
}
|
||||
rule = add_ethtool_flow_rule(priv, eth_ft->ft, fs);
|
||||
if (IS_ERR(rule)) {
|
||||
err = PTR_ERR(rule);
|
||||
goto del_ethtool_rule;
|
||||
}
|
||||
|
||||
eth_rule->rule = rule;
|
||||
|
||||
return 0;
|
||||
|
||||
del_ethtool_rule:
|
||||
del_ethtool_rule(priv, eth_rule);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlx5e_ethtool_flow_remove(struct mlx5e_priv *priv,
|
||||
int location)
|
||||
{
|
||||
struct mlx5e_ethtool_rule *eth_rule;
|
||||
int err = 0;
|
||||
|
||||
if (location >= MAX_NUM_OF_ETHTOOL_RULES)
|
||||
return -ENOSPC;
|
||||
|
||||
eth_rule = find_ethtool_rule(priv, location);
|
||||
if (!eth_rule) {
|
||||
err = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
del_ethtool_rule(priv, eth_rule);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_ethtool_rule *iter;
|
||||
struct mlx5e_ethtool_rule *temp;
|
||||
|
||||
list_for_each_entry_safe(iter, temp, &priv->fs.ethtool.rules, list)
|
||||
del_ethtool_rule(priv, iter);
|
||||
}
|
||||
|
||||
void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv)
|
||||
{
|
||||
INIT_LIST_HEAD(&priv->fs.ethtool.rules);
|
||||
}
|
|
@ -67,13 +67,21 @@
|
|||
#define FS_REQUIRED_CAPS(...) {.arr_sz = INIT_CAPS_ARRAY_SIZE(__VA_ARGS__), \
|
||||
.caps = (long[]) {__VA_ARGS__} }
|
||||
|
||||
#define FS_CHAINING_CAPS FS_REQUIRED_CAPS(FS_CAP(flow_table_properties_nic_receive.flow_modify_en), \
|
||||
FS_CAP(flow_table_properties_nic_receive.modify_root), \
|
||||
FS_CAP(flow_table_properties_nic_receive.identified_miss_table_mode), \
|
||||
FS_CAP(flow_table_properties_nic_receive.flow_table_modify))
|
||||
|
||||
#define LEFTOVERS_NUM_LEVELS 1
|
||||
#define LEFTOVERS_NUM_PRIOS 1
|
||||
|
||||
#define BY_PASS_PRIO_NUM_LEVELS 1
|
||||
#define BY_PASS_MIN_LEVEL (KERNEL_MIN_LEVEL + MLX5_BY_PASS_NUM_PRIOS +\
|
||||
#define BY_PASS_MIN_LEVEL (ETHTOOL_MIN_LEVEL + MLX5_BY_PASS_NUM_PRIOS +\
|
||||
LEFTOVERS_NUM_PRIOS)
|
||||
|
||||
#define ETHTOOL_PRIO_NUM_LEVELS 1
|
||||
#define ETHTOOL_NUM_PRIOS 4
|
||||
#define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS)
|
||||
/* Vlan, mac, ttc, aRFS */
|
||||
#define KERNEL_NIC_PRIO_NUM_LEVELS 4
|
||||
#define KERNEL_NIC_NUM_PRIOS 1
|
||||
|
@ -103,27 +111,24 @@ static struct init_tree_node {
|
|||
int num_levels;
|
||||
} root_fs = {
|
||||
.type = FS_TYPE_NAMESPACE,
|
||||
.ar_size = 5,
|
||||
.ar_size = 6,
|
||||
.children = (struct init_tree_node[]) {
|
||||
ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0,
|
||||
FS_REQUIRED_CAPS(FS_CAP(flow_table_properties_nic_receive.flow_modify_en),
|
||||
FS_CAP(flow_table_properties_nic_receive.modify_root),
|
||||
FS_CAP(flow_table_properties_nic_receive.identified_miss_table_mode),
|
||||
FS_CAP(flow_table_properties_nic_receive.flow_table_modify)),
|
||||
FS_CHAINING_CAPS,
|
||||
ADD_NS(ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS,
|
||||
BY_PASS_PRIO_NUM_LEVELS))),
|
||||
ADD_PRIO(0, OFFLOADS_MIN_LEVEL, 0, {},
|
||||
ADD_NS(ADD_MULTIPLE_PRIO(OFFLOADS_NUM_PRIOS, OFFLOADS_MAX_FT))),
|
||||
|
||||
ADD_PRIO(0, ETHTOOL_MIN_LEVEL, 0,
|
||||
FS_CHAINING_CAPS,
|
||||
ADD_NS(ADD_MULTIPLE_PRIO(ETHTOOL_NUM_PRIOS,
|
||||
ETHTOOL_PRIO_NUM_LEVELS))),
|
||||
ADD_PRIO(0, KERNEL_MIN_LEVEL, 0, {},
|
||||
ADD_NS(ADD_MULTIPLE_PRIO(1, 1),
|
||||
ADD_MULTIPLE_PRIO(KERNEL_NIC_NUM_PRIOS,
|
||||
KERNEL_NIC_PRIO_NUM_LEVELS))),
|
||||
ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0,
|
||||
FS_REQUIRED_CAPS(FS_CAP(flow_table_properties_nic_receive.flow_modify_en),
|
||||
FS_CAP(flow_table_properties_nic_receive.modify_root),
|
||||
FS_CAP(flow_table_properties_nic_receive.identified_miss_table_mode),
|
||||
FS_CAP(flow_table_properties_nic_receive.flow_table_modify)),
|
||||
FS_CHAINING_CAPS,
|
||||
ADD_NS(ADD_MULTIPLE_PRIO(LEFTOVERS_NUM_PRIOS, LEFTOVERS_NUM_LEVELS))),
|
||||
ADD_PRIO(0, ANCHOR_MIN_LEVEL, 0, {},
|
||||
ADD_NS(ADD_MULTIPLE_PRIO(ANCHOR_NUM_PRIOS, ANCHOR_NUM_LEVELS))),
|
||||
|
@ -1375,6 +1380,7 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
|
|||
switch (type) {
|
||||
case MLX5_FLOW_NAMESPACE_BYPASS:
|
||||
case MLX5_FLOW_NAMESPACE_OFFLOADS:
|
||||
case MLX5_FLOW_NAMESPACE_ETHTOOL:
|
||||
case MLX5_FLOW_NAMESPACE_KERNEL:
|
||||
case MLX5_FLOW_NAMESPACE_LEFTOVERS:
|
||||
case MLX5_FLOW_NAMESPACE_ANCHOR:
|
||||
|
|
|
@ -55,6 +55,7 @@ static inline void build_leftovers_ft_param(int *priority,
|
|||
enum mlx5_flow_namespace_type {
|
||||
MLX5_FLOW_NAMESPACE_BYPASS,
|
||||
MLX5_FLOW_NAMESPACE_OFFLOADS,
|
||||
MLX5_FLOW_NAMESPACE_ETHTOOL,
|
||||
MLX5_FLOW_NAMESPACE_KERNEL,
|
||||
MLX5_FLOW_NAMESPACE_LEFTOVERS,
|
||||
MLX5_FLOW_NAMESPACE_ANCHOR,
|
||||
|
|
Loading…
Reference in a new issue