Commit 248d3b4c authored by Tariq Toukan's avatar Tariq Toukan Committed by Saeed Mahameed

net/mlx5e: Support flow classification into RSS contexts

Extend the existing flow classification support, to steer
flows not only directly to a receive ring, but also into
the new RSS contexts.

Create needed TIR objects on demand, and hold reference
on the RSS context.
Signed-off-by: default avatarTariq Toukan <tariqt@nvidia.com>
Reviewed-by: default avatarMaxim Mikityanskiy <maximmi@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent f01cc58c
...@@ -367,6 +367,30 @@ u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt, ...@@ -367,6 +367,30 @@ u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
return mlx5e_tir_get_tirn(tir); return mlx5e_tir_get_tirn(tir);
} }
/* Fill the "tirn" output parameter.
* Create the requested TIR if it's its first usage.
*/
int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss,
enum mlx5_traffic_types tt,
const struct mlx5e_lro_param *init_lro_param,
bool inner, u32 *tirn)
{
struct mlx5e_tir *tir;
tir = rss_get_tir(rss, tt, inner);
if (!tir) { /* TIR doesn't exist, create one */
int err;
err = mlx5e_rss_create_tir(rss, tt, init_lro_param, inner);
if (err)
return err;
tir = rss_get_tir(rss, tt, inner);
}
*tirn = mlx5e_tir_get_tirn(tir);
return 0;
}
static void mlx5e_rss_apply(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns) static void mlx5e_rss_apply(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns)
{ {
int err; int err;
......
...@@ -28,6 +28,11 @@ unsigned int mlx5e_rss_refcnt_read(struct mlx5e_rss *rss); ...@@ -28,6 +28,11 @@ unsigned int mlx5e_rss_refcnt_read(struct mlx5e_rss *rss);
u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt, u32 mlx5e_rss_get_tirn(struct mlx5e_rss *rss, enum mlx5_traffic_types tt,
bool inner); bool inner);
int mlx5e_rss_obtain_tirn(struct mlx5e_rss *rss,
enum mlx5_traffic_types tt,
const struct mlx5e_lro_param *init_lro_param,
bool inner, u32 *tirn);
void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns); void mlx5e_rss_enable(struct mlx5e_rss *rss, u32 *rqns, unsigned int num_rqns);
void mlx5e_rss_disable(struct mlx5e_rss *rss); void mlx5e_rss_disable(struct mlx5e_rss *rss);
......
...@@ -245,6 +245,28 @@ int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res) ...@@ -245,6 +245,28 @@ int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res)
return cnt; return cnt;
} }
int mlx5e_rx_res_rss_index(struct mlx5e_rx_res *res, struct mlx5e_rss *rss)
{
int i;
if (!rss)
return -EINVAL;
for (i = 0; i < MLX5E_MAX_NUM_RSS; i++)
if (rss == res->rss[i])
return i;
return -ENOENT;
}
struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx)
{
if (rss_idx >= MLX5E_MAX_NUM_RSS)
return NULL;
return res->rss[rss_idx];
}
/* End of API rx_res_rss_* */ /* End of API rx_res_rss_* */
struct mlx5e_rx_res *mlx5e_rx_res_alloc(void) struct mlx5e_rx_res *mlx5e_rx_res_alloc(void)
......
...@@ -62,6 +62,8 @@ int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param ...@@ -62,6 +62,8 @@ int mlx5e_rx_res_lro_set_param(struct mlx5e_rx_res *res, struct mlx5e_lro_param
int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch); int mlx5e_rx_res_rss_init(struct mlx5e_rx_res *res, u32 *rss_idx, unsigned int init_nch);
int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx); int mlx5e_rx_res_rss_destroy(struct mlx5e_rx_res *res, u32 rss_idx);
int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res); int mlx5e_rx_res_rss_cnt(struct mlx5e_rx_res *res);
int mlx5e_rx_res_rss_index(struct mlx5e_rx_res *res, struct mlx5e_rss *rss);
struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx);
/* Workaround for hairpin */ /* Workaround for hairpin */
struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res); struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res);
......
...@@ -35,11 +35,19 @@ ...@@ -35,11 +35,19 @@
#include "en/params.h" #include "en/params.h"
#include "en/xsk/pool.h" #include "en/xsk/pool.h"
static int flow_type_to_traffic_type(u32 flow_type);
static u32 flow_type_mask(u32 flow_type)
{
return flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
}
struct mlx5e_ethtool_rule { struct mlx5e_ethtool_rule {
struct list_head list; struct list_head list;
struct ethtool_rx_flow_spec flow_spec; struct ethtool_rx_flow_spec flow_spec;
struct mlx5_flow_handle *rule; struct mlx5_flow_handle *rule;
struct mlx5e_ethtool_table *eth_ft; struct mlx5e_ethtool_table *eth_ft;
struct mlx5e_rss *rss;
}; };
static void put_flow_table(struct mlx5e_ethtool_table *eth_ft) static void put_flow_table(struct mlx5e_ethtool_table *eth_ft)
...@@ -66,7 +74,7 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv, ...@@ -66,7 +74,7 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv,
int table_size; int table_size;
int prio; int prio;
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { switch (flow_type_mask(fs->flow_type)) {
case TCP_V4_FLOW: case TCP_V4_FLOW:
case UDP_V4_FLOW: case UDP_V4_FLOW:
case TCP_V6_FLOW: case TCP_V6_FLOW:
...@@ -329,7 +337,7 @@ static int set_flow_attrs(u32 *match_c, u32 *match_v, ...@@ -329,7 +337,7 @@ static int set_flow_attrs(u32 *match_c, u32 *match_v,
outer_headers); outer_headers);
void *outer_headers_v = MLX5_ADDR_OF(fte_match_param, match_v, void *outer_headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
outer_headers); outer_headers);
u32 flow_type = fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT); u32 flow_type = flow_type_mask(fs->flow_type);
switch (flow_type) { switch (flow_type) {
case TCP_V4_FLOW: case TCP_V4_FLOW:
...@@ -397,10 +405,53 @@ static bool outer_header_zero(u32 *match_criteria) ...@@ -397,10 +405,53 @@ static bool outer_header_zero(u32 *match_criteria)
size - 1); size - 1);
} }
static int flow_get_tirn(struct mlx5e_priv *priv,
struct mlx5e_ethtool_rule *eth_rule,
struct ethtool_rx_flow_spec *fs,
u32 rss_context, u32 *tirn)
{
if (fs->flow_type & FLOW_RSS) {
struct mlx5e_lro_param lro_param;
struct mlx5e_rss *rss;
u32 flow_type;
int err;
int tt;
rss = mlx5e_rx_res_rss_get(priv->rx_res, rss_context);
if (!rss)
return -ENOENT;
flow_type = flow_type_mask(fs->flow_type);
tt = flow_type_to_traffic_type(flow_type);
if (tt < 0)
return -EINVAL;
lro_param = mlx5e_get_lro_param(&priv->channels.params);
err = mlx5e_rss_obtain_tirn(rss, tt, &lro_param, false, tirn);
if (err)
return err;
eth_rule->rss = rss;
mlx5e_rss_refcnt_inc(eth_rule->rss);
} else {
struct mlx5e_params *params = &priv->channels.params;
enum mlx5e_rq_group group;
u16 ix;
mlx5e_qid_get_ch_and_group(params, fs->ring_cookie, &ix, &group);
*tirn = group == MLX5E_RQ_GROUP_XSK ?
mlx5e_rx_res_get_tirn_xsk(priv->rx_res, ix) :
mlx5e_rx_res_get_tirn_direct(priv->rx_res, ix);
}
return 0;
}
static struct mlx5_flow_handle * static struct mlx5_flow_handle *
add_ethtool_flow_rule(struct mlx5e_priv *priv, add_ethtool_flow_rule(struct mlx5e_priv *priv,
struct mlx5e_ethtool_rule *eth_rule,
struct mlx5_flow_table *ft, struct mlx5_flow_table *ft,
struct ethtool_rx_flow_spec *fs) struct ethtool_rx_flow_spec *fs, u32 rss_context)
{ {
struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND }; struct mlx5_flow_act flow_act = { .flags = FLOW_ACT_NO_APPEND };
struct mlx5_flow_destination *dst = NULL; struct mlx5_flow_destination *dst = NULL;
...@@ -419,23 +470,17 @@ add_ethtool_flow_rule(struct mlx5e_priv *priv, ...@@ -419,23 +470,17 @@ add_ethtool_flow_rule(struct mlx5e_priv *priv,
if (fs->ring_cookie == RX_CLS_FLOW_DISC) { if (fs->ring_cookie == RX_CLS_FLOW_DISC) {
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
} else { } else {
struct mlx5e_params *params = &priv->channels.params;
enum mlx5e_rq_group group;
u16 ix;
mlx5e_qid_get_ch_and_group(params, fs->ring_cookie, &ix, &group);
dst = kzalloc(sizeof(*dst), GFP_KERNEL); dst = kzalloc(sizeof(*dst), GFP_KERNEL);
if (!dst) { if (!dst) {
err = -ENOMEM; err = -ENOMEM;
goto free; goto free;
} }
err = flow_get_tirn(priv, eth_rule, fs, rss_context, &dst->tir_num);
if (err)
goto free;
dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR; dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
if (group == MLX5E_RQ_GROUP_XSK)
dst->tir_num = mlx5e_rx_res_get_tirn_xsk(priv->rx_res, ix);
else
dst->tir_num = mlx5e_rx_res_get_tirn_direct(priv->rx_res, ix);
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
} }
...@@ -459,6 +504,8 @@ static void del_ethtool_rule(struct mlx5e_priv *priv, ...@@ -459,6 +504,8 @@ static void del_ethtool_rule(struct mlx5e_priv *priv,
{ {
if (eth_rule->rule) if (eth_rule->rule)
mlx5_del_flow_rules(eth_rule->rule); mlx5_del_flow_rules(eth_rule->rule);
if (eth_rule->rss)
mlx5e_rss_refcnt_dec(eth_rule->rss);
list_del(&eth_rule->list); list_del(&eth_rule->list);
priv->fs.ethtool.tot_num_rules--; priv->fs.ethtool.tot_num_rules--;
put_flow_table(eth_rule->eth_ft); put_flow_table(eth_rule->eth_ft);
...@@ -619,7 +666,7 @@ static int validate_flow(struct mlx5e_priv *priv, ...@@ -619,7 +666,7 @@ static int validate_flow(struct mlx5e_priv *priv,
fs->ring_cookie)) fs->ring_cookie))
return -EINVAL; return -EINVAL;
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { switch (flow_type_mask(fs->flow_type)) {
case ETHER_FLOW: case ETHER_FLOW:
num_tuples += validate_ethter(fs); num_tuples += validate_ethter(fs);
break; break;
...@@ -668,7 +715,7 @@ static int validate_flow(struct mlx5e_priv *priv, ...@@ -668,7 +715,7 @@ static int validate_flow(struct mlx5e_priv *priv,
static int static int
mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv, mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,
struct ethtool_rx_flow_spec *fs) struct ethtool_rx_flow_spec *fs, u32 rss_context)
{ {
struct mlx5e_ethtool_table *eth_ft; struct mlx5e_ethtool_table *eth_ft;
struct mlx5e_ethtool_rule *eth_rule; struct mlx5e_ethtool_rule *eth_rule;
...@@ -699,7 +746,7 @@ mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv, ...@@ -699,7 +746,7 @@ mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,
err = -EINVAL; err = -EINVAL;
goto del_ethtool_rule; goto del_ethtool_rule;
} }
rule = add_ethtool_flow_rule(priv, eth_ft->ft, fs); rule = add_ethtool_flow_rule(priv, eth_rule, eth_ft->ft, fs, rss_context);
if (IS_ERR(rule)) { if (IS_ERR(rule)) {
err = PTR_ERR(rule); err = PTR_ERR(rule);
goto del_ethtool_rule; goto del_ethtool_rule;
...@@ -745,10 +792,20 @@ mlx5e_ethtool_get_flow(struct mlx5e_priv *priv, ...@@ -745,10 +792,20 @@ mlx5e_ethtool_get_flow(struct mlx5e_priv *priv,
return -EINVAL; return -EINVAL;
list_for_each_entry(eth_rule, &priv->fs.ethtool.rules, list) { list_for_each_entry(eth_rule, &priv->fs.ethtool.rules, list) {
if (eth_rule->flow_spec.location == location) { int index;
info->fs = eth_rule->flow_spec;
if (eth_rule->flow_spec.location != location)
continue;
if (!info)
return 0; return 0;
} info->fs = eth_rule->flow_spec;
if (!eth_rule->rss)
return 0;
index = mlx5e_rx_res_rss_index(priv->rx_res, eth_rule->rss);
if (index < 0)
return index;
info->rss_context = index;
return 0;
} }
return -ENOENT; return -ENOENT;
...@@ -764,7 +821,7 @@ mlx5e_ethtool_get_all_flows(struct mlx5e_priv *priv, ...@@ -764,7 +821,7 @@ mlx5e_ethtool_get_all_flows(struct mlx5e_priv *priv,
info->data = MAX_NUM_OF_ETHTOOL_RULES; info->data = MAX_NUM_OF_ETHTOOL_RULES;
while ((!err || err == -ENOENT) && idx < info->rule_cnt) { while ((!err || err == -ENOENT) && idx < info->rule_cnt) {
err = mlx5e_ethtool_get_flow(priv, info, location); err = mlx5e_ethtool_get_flow(priv, NULL, location);
if (!err) if (!err)
rule_locs[idx++] = location; rule_locs[idx++] = location;
location++; location++;
...@@ -887,7 +944,7 @@ int mlx5e_ethtool_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) ...@@ -887,7 +944,7 @@ int mlx5e_ethtool_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
switch (cmd->cmd) { switch (cmd->cmd) {
case ETHTOOL_SRXCLSRLINS: case ETHTOOL_SRXCLSRLINS:
err = mlx5e_ethtool_flow_replace(priv, &cmd->fs); err = mlx5e_ethtool_flow_replace(priv, &cmd->fs, cmd->rss_context);
break; break;
case ETHTOOL_SRXCLSRLDEL: case ETHTOOL_SRXCLSRLDEL:
err = mlx5e_ethtool_flow_remove(priv, cmd->fs.location); err = mlx5e_ethtool_flow_remove(priv, cmd->fs.location);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment