Skip to content

Commit

Permalink
Merge branch 'mlx5-ntuple-steering'
Browse files Browse the repository at this point in the history
Saeed Mahameed says:

====================
Mellanox 100G mlx5 ethtool ntuple steering

This series adds Ethernet ethtool ntuple steering 'ethtool -N|U' and exposes two more
counter sets to Ethtool statistics, RDMA vport and global flow control statistics.

We start from three refactoring patches of the flow steering infrastructure
    - mlx5_add_flow_rule will now receive mlx5 flow spec to simplify and reduce
      number of parameters
    - All low level steering objects are now wrapped in mlx5_flow_steering structure
      for better encapsulation
    - Flow steering object will now be removed properly and generically rather than
      traversing on a well-known steering tree objects

Patch#4 adds the infrastructure and the data structures needed for the ethtool ntuple
steering, all implemented in a new file 'en_fs_ethtool.c'.  Add the support for set_rxnfc
ethtool callback to add/remove/replace a flow spec of ethter type L2.

Patch#5 adds the support for L3/L4 flow specs and a higher priority in favor for L3/L4
rules when interleaving with L2 rules.

Patch#6 adds the support for get_rxnfc ethtool callback.

Patch#7,8 adds RDMA vport and global flow control statistics.

Applied on top: 8186f6e ('net-next: mediatek: fix compile error inside mtk_poll_controller()')
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 5, 2016
2 parents 019d0c9 + e989d5a commit 487884e
Show file tree
Hide file tree
Showing 15 changed files with 972 additions and 405 deletions.
21 changes: 9 additions & 12 deletions drivers/infiniband/hw/mlx5/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1528,41 +1528,39 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
{
struct mlx5_flow_table *ft = ft_prio->flow_table;
struct mlx5_ib_flow_handler *handler;
struct mlx5_flow_spec *spec;
void *ib_flow = flow_attr + 1;
u8 match_criteria_enable = 0;
unsigned int spec_index;
u32 *match_c;
u32 *match_v;
u32 action;
int err = 0;

if (!is_valid_attr(flow_attr))
return ERR_PTR(-EINVAL);

match_c = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
match_v = kzalloc(MLX5_ST_SZ_BYTES(fte_match_param), GFP_KERNEL);
spec = mlx5_vzalloc(sizeof(*spec));
handler = kzalloc(sizeof(*handler), GFP_KERNEL);
if (!handler || !match_c || !match_v) {
if (!handler || !spec) {
err = -ENOMEM;
goto free;
}

INIT_LIST_HEAD(&handler->list);

for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
err = parse_flow_attr(match_c, match_v, ib_flow);
err = parse_flow_attr(spec->match_criteria,
spec->match_value, ib_flow);
if (err < 0)
goto free;

ib_flow += ((union ib_flow_spec *)ib_flow)->size;
}

/* Outer header support only */
match_criteria_enable = (!outer_header_zero(match_c)) << 0;
spec->match_criteria_enable = (!outer_header_zero(spec->match_criteria))
<< 0;
action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
handler->rule = mlx5_add_flow_rule(ft, match_criteria_enable,
match_c, match_v,
handler->rule = mlx5_add_flow_rule(ft, spec,
action,
MLX5_FS_DEFAULT_FLOW_TAG,
dst);
Expand All @@ -1578,8 +1576,7 @@ static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
free:
if (err)
kfree(handler);
kfree(match_c);
kfree(match_v);
kvfree(spec);
return err ? ERR_PTR(err) : handler;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
26 changes: 26 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,24 @@ enum {
MLX5E_ARFS_FT_LEVEL
};

struct mlx5e_ethtool_table {
struct mlx5_flow_table *ft;
int num_rules;
};

#define ETHTOOL_NUM_L3_L4_FTS 7
#define ETHTOOL_NUM_L2_FTS 4

struct mlx5e_ethtool_steering {
struct mlx5e_ethtool_table l3_l4_ft[ETHTOOL_NUM_L3_L4_FTS];
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;
Expand Down Expand Up @@ -701,6 +717,16 @@ 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_get_flow(struct mlx5e_priv *priv, struct ethtool_rxnfc *info,
int location);
int mlx5e_ethtool_get_all_flows(struct mlx5e_priv *priv,
struct ethtool_rxnfc *info, u32 *rule_locs);
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,
Expand Down
68 changes: 29 additions & 39 deletions drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,12 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
{
struct arfs_table *arfs_t = &priv->fs.arfs.arfs_tables[type];
struct mlx5_flow_destination dest;
u8 match_criteria_enable = 0;
struct mlx5e_tir *tir = priv->indir_tir;
u32 *match_criteria;
u32 *match_value;
struct mlx5_flow_spec *spec;
int err = 0;

match_value = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
match_criteria = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
if (!match_value || !match_criteria) {
spec = mlx5_vzalloc(sizeof(*spec));
if (!spec) {
netdev_err(priv->netdev, "%s: alloc failed\n", __func__);
err = -ENOMEM;
goto out;
Expand All @@ -208,8 +205,7 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
goto out;
}

arfs_t->default_rule = mlx5_add_flow_rule(arfs_t->ft.t, match_criteria_enable,
match_criteria, match_value,
arfs_t->default_rule = mlx5_add_flow_rule(arfs_t->ft.t, spec,
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
MLX5_FS_DEFAULT_FLOW_TAG,
&dest);
Expand All @@ -220,8 +216,7 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
__func__, type);
}
out:
kvfree(match_criteria);
kvfree(match_value);
kvfree(spec);
return err;
}

Expand Down Expand Up @@ -475,23 +470,20 @@ static struct mlx5_flow_rule *arfs_add_rule(struct mlx5e_priv *priv,
struct mlx5_flow_rule *rule = NULL;
struct mlx5_flow_destination dest;
struct arfs_table *arfs_table;
u8 match_criteria_enable = 0;
struct mlx5_flow_spec *spec;
struct mlx5_flow_table *ft;
u32 *match_criteria;
u32 *match_value;
int err = 0;

match_value = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
match_criteria = mlx5_vzalloc(MLX5_ST_SZ_BYTES(fte_match_param));
if (!match_value || !match_criteria) {
spec = mlx5_vzalloc(sizeof(*spec));
if (!spec) {
netdev_err(priv->netdev, "%s: alloc failed\n", __func__);
err = -ENOMEM;
goto out;
}
match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.ethertype);
MLX5_SET(fte_match_param, match_value, outer_headers.ethertype,
MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype,
ntohs(tuple->etype));
arfs_table = arfs_get_table(arfs, tuple->ip_proto, tuple->etype);
if (!arfs_table) {
Expand All @@ -501,59 +493,58 @@ static struct mlx5_flow_rule *arfs_add_rule(struct mlx5e_priv *priv,

ft = arfs_table->ft.t;
if (tuple->ip_proto == IPPROTO_TCP) {
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.tcp_dport);
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.tcp_sport);
MLX5_SET(fte_match_param, match_value, outer_headers.tcp_dport,
MLX5_SET(fte_match_param, spec->match_value, outer_headers.tcp_dport,
ntohs(tuple->dst_port));
MLX5_SET(fte_match_param, match_value, outer_headers.tcp_sport,
MLX5_SET(fte_match_param, spec->match_value, outer_headers.tcp_sport,
ntohs(tuple->src_port));
} else {
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.udp_dport);
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.udp_sport);
MLX5_SET(fte_match_param, match_value, outer_headers.udp_dport,
MLX5_SET(fte_match_param, spec->match_value, outer_headers.udp_dport,
ntohs(tuple->dst_port));
MLX5_SET(fte_match_param, match_value, outer_headers.udp_sport,
MLX5_SET(fte_match_param, spec->match_value, outer_headers.udp_sport,
ntohs(tuple->src_port));
}
if (tuple->etype == htons(ETH_P_IP)) {
memcpy(MLX5_ADDR_OF(fte_match_param, match_value,
memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4),
&tuple->src_ipv4,
4);
memcpy(MLX5_ADDR_OF(fte_match_param, match_value,
memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
&tuple->dst_ipv4,
4);
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.src_ipv4_src_ipv6.ipv4_layout.ipv4);
MLX5_SET_TO_ONES(fte_match_param, match_criteria,
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
} else {
memcpy(MLX5_ADDR_OF(fte_match_param, match_value,
memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6),
&tuple->src_ipv6,
16);
memcpy(MLX5_ADDR_OF(fte_match_param, match_value,
memcpy(MLX5_ADDR_OF(fte_match_param, spec->match_value,
outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
&tuple->dst_ipv6,
16);
memset(MLX5_ADDR_OF(fte_match_param, match_criteria,
memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
outer_headers.src_ipv4_src_ipv6.ipv6_layout.ipv6),
0xff,
16);
memset(MLX5_ADDR_OF(fte_match_param, match_criteria,
memset(MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
outer_headers.dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
0xff,
16);
}
dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
dest.tir_num = priv->direct_tir[arfs_rule->rxq].tirn;
rule = mlx5_add_flow_rule(ft, match_criteria_enable, match_criteria,
match_value, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
rule = mlx5_add_flow_rule(ft, spec, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
MLX5_FS_DEFAULT_FLOW_TAG,
&dest);
if (IS_ERR(rule)) {
Expand All @@ -563,8 +554,7 @@ static struct mlx5_flow_rule *arfs_add_rule(struct mlx5e_priv *priv,
}

out:
kvfree(match_criteria);
kvfree(match_value);
kvfree(spec);
return err ? ERR_PTR(err) : rule;
}

Expand Down
65 changes: 62 additions & 3 deletions drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ static unsigned long mlx5e_query_pfc_combined(struct mlx5e_priv *priv)
return err ? 0 : pfc_en_tx | pfc_en_rx;
}

static bool mlx5e_query_global_pause_combined(struct mlx5e_priv *priv)
{
struct mlx5_core_dev *mdev = priv->mdev;
u32 rx_pause;
u32 tx_pause;
int err;

err = mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);

return err ? false : rx_pause | tx_pause;
}

#define MLX5E_NUM_Q_CNTRS(priv) (NUM_Q_COUNTERS * (!!priv->q_counter))
#define MLX5E_NUM_RQ_STATS(priv) \
(NUM_RQ_STATS * priv->params.num_channels * \
Expand All @@ -147,8 +159,8 @@ static unsigned long mlx5e_query_pfc_combined(struct mlx5e_priv *priv)
(NUM_SQ_STATS * priv->params.num_channels * priv->params.num_tc * \
test_bit(MLX5E_STATE_OPENED, &priv->state))
#define MLX5E_NUM_PFC_COUNTERS(priv) \
(hweight8(mlx5e_query_pfc_combined(priv)) * \
NUM_PPORT_PER_PRIO_PFC_COUNTERS)
((mlx5e_query_global_pause_combined(priv) + hweight8(mlx5e_query_pfc_combined(priv))) * \
NUM_PPORT_PER_PRIO_PFC_COUNTERS)

static int mlx5e_get_sset_count(struct net_device *dev, int sset)
{
Expand Down Expand Up @@ -210,8 +222,18 @@ static void mlx5e_fill_stats_strings(struct mlx5e_priv *priv, uint8_t *data)
pfc_combined = mlx5e_query_pfc_combined(priv);
for_each_set_bit(prio, &pfc_combined, NUM_PPORT_PRIO) {
for (i = 0; i < NUM_PPORT_PER_PRIO_PFC_COUNTERS; i++) {
char pfc_string[ETH_GSTRING_LEN];

snprintf(pfc_string, sizeof(pfc_string), "prio%d", prio);
sprintf(data + (idx++) * ETH_GSTRING_LEN,
pport_per_prio_pfc_stats_desc[i].format, prio);
pport_per_prio_pfc_stats_desc[i].format, pfc_string);
}
}

if (mlx5e_query_global_pause_combined(priv)) {
for (i = 0; i < NUM_PPORT_PER_PRIO_PFC_COUNTERS; i++) {
sprintf(data + (idx++) * ETH_GSTRING_LEN,
pport_per_prio_pfc_stats_desc[i].format, "global");
}
}

Expand Down Expand Up @@ -306,6 +328,13 @@ static void mlx5e_get_ethtool_stats(struct net_device *dev,
}
}

if (mlx5e_query_global_pause_combined(priv)) {
for (i = 0; i < NUM_PPORT_PER_PRIO_PFC_COUNTERS; i++) {
data[idx++] = MLX5E_READ_CTR64_BE(&priv->stats.pport.per_prio_counters[0],
pport_per_prio_pfc_stats_desc, 0);
}
}

if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
return;

Expand Down Expand Up @@ -931,6 +960,15 @@ static int mlx5e_get_rxnfc(struct net_device *netdev,
case ETHTOOL_GRXRINGS:
info->data = priv->params.num_channels;
break;
case ETHTOOL_GRXCLSRLCNT:
info->rule_cnt = priv->fs.ethtool.tot_num_rules;
break;
case ETHTOOL_GRXCLSRULE:
err = mlx5e_ethtool_get_flow(priv, info, info->fs.location);
break;
case ETHTOOL_GRXCLSRLALL:
err = mlx5e_ethtool_get_all_flows(priv, info, rule_locs);
break;
default:
err = -EOPNOTSUPP;
break;
Expand Down Expand Up @@ -1368,6 +1406,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,
Expand All @@ -1387,6 +1445,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,
Expand Down
Loading

0 comments on commit 487884e

Please sign in to comment.