Commit 63757225 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge tag 'mlx5-updates-2022-07-28' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2022-07-28

Misc updates to mlx5 driver:

1) Gal corrects to use skb_tcp_all_headers on encapsulated skbs.

2) Roi Adds the support for offloading standalone police actions.

3) lama, did some refactoring to minimize code coupling with
mlx5e_priv "god object" in some of the follows, and converts some of the
objects to pointers to preserve on memory when these objects aren't needed.
This is part one of two parts series.

* tag 'mlx5-updates-2022-07-28' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux:
  net/mlx5e: Move mlx5e_init_l2_addr to en_main
  net/mlx5e: Split en_fs ndo's and move to en_main
  net/mlx5e: Separate mlx5e_set_rx_mode_work and move caller to en_main
  net/mlx5e: Add mdev to flow_steering struct
  net/mlx5e: Report flow steering errors with mdev err report API
  net/mlx5e: Convert mlx5e_flow_steering member of mlx5e_priv to pointer
  net/mlx5e: Allocate VLAN and TC for featured profiles only
  net/mlx5e: Make mlx5e_tc_table private
  net/mlx5e: Convert mlx5e_tc_table member of mlx5e_flow_steering to pointer
  net/mlx5e: TC, Support tc action api for police
  net/mlx5e: TC, Separate get/update/replace meter functions
  net/mlx5e: Add red and green counters for metering
  net/mlx5e: TC, Allocate post meter ft per rule
  net/mlx5: DR, Add support for flow metering ASO
  net/mlx5e: Fix wrong use of skb_tcp_all_headers() with encapsulation
====================

Link: https://lore.kernel.org/r/20220728205728.143074-1-saeed@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 84a8d931 069448b2
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -921,7 +921,7 @@ struct mlx5e_priv {
	struct mlx5e_rx_res       *rx_res;
	u32                       *tx_rates;

	struct mlx5e_flow_steering fs;
	struct mlx5e_flow_steering *fs;

	struct workqueue_struct    *wq;
	struct work_struct         update_carrier_work;
@@ -987,6 +987,8 @@ enum mlx5e_profile_feature {
	MLX5E_PROFILE_FEATURE_PTP_RX,
	MLX5E_PROFILE_FEATURE_PTP_TX,
	MLX5E_PROFILE_FEATURE_QOS_HTB,
	MLX5E_PROFILE_FEATURE_FS_VLAN,
	MLX5E_PROFILE_FEATURE_FS_TC,
};

struct mlx5e_profile {
@@ -1022,7 +1024,6 @@ void mlx5e_shampo_dealloc_hd(struct mlx5e_rq *rq, u16 len, u16 start, bool close
void mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats);
void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s);

void mlx5e_init_l2_addr(struct mlx5e_priv *priv);
int mlx5e_self_test_num(struct mlx5e_priv *priv);
int mlx5e_self_test_fill_strings(struct mlx5e_priv *priv, u8 *data);
void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
+17 −27
Original line number Diff line number Diff line
@@ -15,29 +15,6 @@ enum {
	MLX5E_TC_MISS_LEVEL,
};

struct mlx5e_tc_table {
	/* Protects the dynamic assignment of the t parameter
	 * which is the nic tc root table.
	 */
	struct mutex			t_lock;
	struct mlx5_flow_table		*t;
	struct mlx5_flow_table		*miss_t;
	struct mlx5_fs_chains           *chains;
	struct mlx5e_post_act		*post_act;

	struct rhashtable               ht;

	struct mod_hdr_tbl mod_hdr;
	struct mutex hairpin_tbl_lock; /* protects hairpin_tbl */
	DECLARE_HASHTABLE(hairpin_tbl, 8);

	struct notifier_block     netdevice_nb;
	struct netdev_net_notifier	netdevice_nn;

	struct mlx5_tc_ct_priv         *ct;
	struct mapping_ctx             *mapping;
};

struct mlx5e_flow_table {
	int num_groups;
	struct mlx5_flow_table *t;
@@ -160,16 +137,20 @@ static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv) { return -EOPNOTSU
struct mlx5e_accel_fs_tcp;
#endif

struct mlx5e_profile;
struct mlx5e_fs_udp;
struct mlx5e_fs_any;
struct mlx5e_ptp_fs;

struct mlx5e_flow_steering {
	bool				state_destroy;
	bool				vlan_strip_disable;
	struct mlx5_core_dev		*mdev;
	struct mlx5_flow_namespace      *ns;
#ifdef CONFIG_MLX5_EN_RXNFC
	struct mlx5e_ethtool_steering   ethtool;
#endif
	struct mlx5e_tc_table           tc;
	struct mlx5e_tc_table           *tc;
	struct mlx5e_promisc_table      promisc;
	struct mlx5e_vlan_table         *vlan;
	struct mlx5e_l2_table           l2;
@@ -200,13 +181,22 @@ void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv);
int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);

int mlx5e_fs_init(struct mlx5e_priv *priv);
void mlx5e_fs_cleanup(struct mlx5e_priv *priv);
struct mlx5e_flow_steering *mlx5e_fs_init(const struct mlx5e_profile *profile,
					  struct mlx5_core_dev *mdev,
					  bool state_destroy);
void mlx5e_fs_cleanup(struct mlx5e_flow_steering *fs);

int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int  trap_id, int tir_num);
void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv);
int mlx5e_add_mac_trap(struct mlx5e_priv *priv, int  trap_id, int tir_num);
void mlx5e_remove_mac_trap(struct mlx5e_priv *priv);

void mlx5e_fs_set_rx_mode_work(struct mlx5e_flow_steering *fs, struct net_device *netdev);
int mlx5e_fs_vlan_rx_add_vid(struct mlx5e_flow_steering *fs,
			     struct net_device *netdev,
			     __be16 proto, u16 vid);
int mlx5e_fs_vlan_rx_kill_vid(struct mlx5e_flow_steering *fs,
			      struct net_device *netdev,
			      __be16 proto, u16 vid);
void mlx5e_fs_init_l2_addr(struct mlx5e_flow_steering *fs, struct net_device *netdev);
#endif /* __MLX5E_FLOW_STEER_H__ */
+36 −36
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,
	if (!spec)
		return ERR_PTR(-ENOMEM);

	fs_udp = priv->fs.udp;
	fs_udp = priv->fs->udp;
	ft = fs_udp->tables[type].t;

	fs_udp_set_dport_flow(spec, type, d_port);
@@ -121,10 +121,10 @@ static int fs_udp_add_default_rule(struct mlx5e_priv *priv, enum fs_udp_type typ
	struct mlx5e_fs_udp *fs_udp;
	int err;

	fs_udp = priv->fs.udp;
	fs_udp = priv->fs->udp;
	fs_udp_t = &fs_udp->tables[type];

	dest = mlx5_ttc_get_default_dest(priv->fs.ttc, fs_udp2tt(type));
	dest = mlx5_ttc_get_default_dest(priv->fs->ttc, fs_udp2tt(type));
	rule = mlx5_add_flow_rules(fs_udp_t->t, NULL, &flow_act, &dest, 1);
	if (IS_ERR(rule)) {
		err = PTR_ERR(rule);
@@ -208,7 +208,7 @@ static int fs_udp_create_groups(struct mlx5e_flow_table *ft, enum fs_udp_type ty

static int fs_udp_create_table(struct mlx5e_priv *priv, enum fs_udp_type type)
{
	struct mlx5e_flow_table *ft = &priv->fs.udp->tables[type];
	struct mlx5e_flow_table *ft = &priv->fs->udp->tables[type];
	struct mlx5_flow_table_attr ft_attr = {};
	int err;

@@ -218,7 +218,7 @@ static int fs_udp_create_table(struct mlx5e_priv *priv, enum fs_udp_type type)
	ft_attr.level = MLX5E_FS_TT_UDP_FT_LEVEL;
	ft_attr.prio = MLX5E_NIC_PRIO;

	ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);
	ft->t = mlx5_create_flow_table(priv->fs->ns, &ft_attr);
	if (IS_ERR(ft->t)) {
		err = PTR_ERR(ft->t);
		ft->t = NULL;
@@ -259,7 +259,7 @@ static int fs_udp_disable(struct mlx5e_priv *priv)

	for (i = 0; i < FS_UDP_NUM_TYPES; i++) {
		/* Modify ttc rules destination to point back to the indir TIRs */
		err = mlx5_ttc_fwd_default_dest(priv->fs.ttc, fs_udp2tt(i));
		err = mlx5_ttc_fwd_default_dest(priv->fs->ttc, fs_udp2tt(i));
		if (err) {
			netdev_err(priv->netdev,
				   "%s: modify ttc[%d] default destination failed, err(%d)\n",
@@ -278,10 +278,10 @@ static int fs_udp_enable(struct mlx5e_priv *priv)

	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
	for (i = 0; i < FS_UDP_NUM_TYPES; i++) {
		dest.ft = priv->fs.udp->tables[i].t;
		dest.ft = priv->fs->udp->tables[i].t;

		/* Modify ttc rules destination to point on the accel_fs FTs */
		err = mlx5_ttc_fwd_dest(priv->fs.ttc, fs_udp2tt(i), &dest);
		err = mlx5_ttc_fwd_dest(priv->fs->ttc, fs_udp2tt(i), &dest);
		if (err) {
			netdev_err(priv->netdev,
				   "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
@@ -294,7 +294,7 @@ static int fs_udp_enable(struct mlx5e_priv *priv)

void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_priv *priv)
{
	struct mlx5e_fs_udp *fs_udp = priv->fs.udp;
	struct mlx5e_fs_udp *fs_udp = priv->fs->udp;
	int i;

	if (!fs_udp)
@@ -309,20 +309,20 @@ void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_priv *priv)
		fs_udp_destroy_table(fs_udp, i);

	kfree(fs_udp);
	priv->fs.udp = NULL;
	priv->fs->udp = NULL;
}

int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_priv *priv)
{
	int i, err;

	if (priv->fs.udp) {
		priv->fs.udp->ref_cnt++;
	if (priv->fs->udp) {
		priv->fs->udp->ref_cnt++;
		return 0;
	}

	priv->fs.udp = kzalloc(sizeof(*priv->fs.udp), GFP_KERNEL);
	if (!priv->fs.udp)
	priv->fs->udp = kzalloc(sizeof(*priv->fs->udp), GFP_KERNEL);
	if (!priv->fs->udp)
		return -ENOMEM;

	for (i = 0; i < FS_UDP_NUM_TYPES; i++) {
@@ -335,16 +335,16 @@ int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_priv *priv)
	if (err)
		goto err_destroy_tables;

	priv->fs.udp->ref_cnt = 1;
	priv->fs->udp->ref_cnt = 1;

	return 0;

err_destroy_tables:
	while (--i >= 0)
		fs_udp_destroy_table(priv->fs.udp, i);
		fs_udp_destroy_table(priv->fs->udp, i);

	kfree(priv->fs.udp);
	priv->fs.udp = NULL;
	kfree(priv->fs->udp);
	priv->fs->udp = NULL;
	return err;
}

@@ -371,7 +371,7 @@ mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_priv *priv,
	if (!spec)
		return ERR_PTR(-ENOMEM);

	fs_any = priv->fs.any;
	fs_any = priv->fs->any;
	ft = fs_any->table.t;

	fs_any_set_ethertype_flow(spec, ether_type);
@@ -398,10 +398,10 @@ static int fs_any_add_default_rule(struct mlx5e_priv *priv)
	struct mlx5e_fs_any *fs_any;
	int err;

	fs_any = priv->fs.any;
	fs_any = priv->fs->any;
	fs_any_t = &fs_any->table;

	dest = mlx5_ttc_get_default_dest(priv->fs.ttc, MLX5_TT_ANY);
	dest = mlx5_ttc_get_default_dest(priv->fs->ttc, MLX5_TT_ANY);
	rule = mlx5_add_flow_rules(fs_any_t->t, NULL, &flow_act, &dest, 1);
	if (IS_ERR(rule)) {
		err = PTR_ERR(rule);
@@ -474,7 +474,7 @@ static int fs_any_create_groups(struct mlx5e_flow_table *ft)

static int fs_any_create_table(struct mlx5e_priv *priv)
{
	struct mlx5e_flow_table *ft = &priv->fs.any->table;
	struct mlx5e_flow_table *ft = &priv->fs->any->table;
	struct mlx5_flow_table_attr ft_attr = {};
	int err;

@@ -484,7 +484,7 @@ static int fs_any_create_table(struct mlx5e_priv *priv)
	ft_attr.level = MLX5E_FS_TT_ANY_FT_LEVEL;
	ft_attr.prio = MLX5E_NIC_PRIO;

	ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);
	ft->t = mlx5_create_flow_table(priv->fs->ns, &ft_attr);
	if (IS_ERR(ft->t)) {
		err = PTR_ERR(ft->t);
		ft->t = NULL;
@@ -514,7 +514,7 @@ static int fs_any_disable(struct mlx5e_priv *priv)
	int err;

	/* Modify ttc rules destination to point back to the indir TIRs */
	err = mlx5_ttc_fwd_default_dest(priv->fs.ttc, MLX5_TT_ANY);
	err = mlx5_ttc_fwd_default_dest(priv->fs->ttc, MLX5_TT_ANY);
	if (err) {
		netdev_err(priv->netdev,
			   "%s: modify ttc[%d] default destination failed, err(%d)\n",
@@ -530,10 +530,10 @@ static int fs_any_enable(struct mlx5e_priv *priv)
	int err;

	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
	dest.ft = priv->fs.any->table.t;
	dest.ft = priv->fs->any->table.t;

	/* Modify ttc rules destination to point on the accel_fs FTs */
	err = mlx5_ttc_fwd_dest(priv->fs.ttc, MLX5_TT_ANY, &dest);
	err = mlx5_ttc_fwd_dest(priv->fs->ttc, MLX5_TT_ANY, &dest);
	if (err) {
		netdev_err(priv->netdev,
			   "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
@@ -555,7 +555,7 @@ static void fs_any_destroy_table(struct mlx5e_fs_any *fs_any)

void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_priv *priv)
{
	struct mlx5e_fs_any *fs_any = priv->fs.any;
	struct mlx5e_fs_any *fs_any = priv->fs->any;

	if (!fs_any)
		return;
@@ -568,20 +568,20 @@ void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_priv *priv)
	fs_any_destroy_table(fs_any);

	kfree(fs_any);
	priv->fs.any = NULL;
	priv->fs->any = NULL;
}

int mlx5e_fs_tt_redirect_any_create(struct mlx5e_priv *priv)
{
	int err;

	if (priv->fs.any) {
		priv->fs.any->ref_cnt++;
	if (priv->fs->any) {
		priv->fs->any->ref_cnt++;
		return 0;
	}

	priv->fs.any = kzalloc(sizeof(*priv->fs.any), GFP_KERNEL);
	if (!priv->fs.any)
	priv->fs->any = kzalloc(sizeof(*priv->fs->any), GFP_KERNEL);
	if (!priv->fs->any)
		return -ENOMEM;

	err = fs_any_create_table(priv);
@@ -592,14 +592,14 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_priv *priv)
	if (err)
		goto err_destroy_table;

	priv->fs.any->ref_cnt = 1;
	priv->fs->any->ref_cnt = 1;

	return 0;

err_destroy_table:
	fs_any_destroy_table(priv->fs.any);
	fs_any_destroy_table(priv->fs->any);

	kfree(priv->fs.any);
	priv->fs.any = NULL;
	kfree(priv->fs->any);
	priv->fs->any = NULL;
	return err;
}
+4 −4
Original line number Diff line number Diff line
@@ -624,7 +624,7 @@ static int mlx5e_ptp_set_state(struct mlx5e_ptp *c, struct mlx5e_params *params)

static void mlx5e_ptp_rx_unset_fs(struct mlx5e_priv *priv)
{
	struct mlx5e_ptp_fs *ptp_fs = priv->fs.ptp_fs;
	struct mlx5e_ptp_fs *ptp_fs = priv->fs->ptp_fs;

	if (!ptp_fs->valid)
		return;
@@ -641,7 +641,7 @@ static void mlx5e_ptp_rx_unset_fs(struct mlx5e_priv *priv)
static int mlx5e_ptp_rx_set_fs(struct mlx5e_priv *priv)
{
	u32 tirn = mlx5e_rx_res_get_tirn_ptp(priv->rx_res);
	struct mlx5e_ptp_fs *ptp_fs = priv->fs.ptp_fs;
	struct mlx5e_ptp_fs *ptp_fs = priv->fs->ptp_fs;
	struct mlx5_flow_handle *rule;
	int err;

@@ -808,13 +808,13 @@ int mlx5e_ptp_alloc_rx_fs(struct mlx5e_priv *priv)
	if (!ptp_fs)
		return -ENOMEM;

	priv->fs.ptp_fs = ptp_fs;
	priv->fs->ptp_fs = ptp_fs;
	return 0;
}

void mlx5e_ptp_free_rx_fs(struct mlx5e_priv *priv)
{
	struct mlx5e_ptp_fs *ptp_fs = priv->fs.ptp_fs;
	struct mlx5e_ptp_fs *ptp_fs = priv->fs->ptp_fs;

	if (!mlx5e_profile_feature_cap(priv->profile, PTP_RX))
		return;
+116 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "en/tc/sample.h"
#include "en_accel/ipsec_rxtx.h"
#include "en/tc/int_port.h"
#include "en/tc/act/act.h"

struct mlx5e_rep_indr_block_priv {
	struct net_device *netdev;
@@ -511,6 +512,120 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev, struct Qdisc *sch,
	return 0;
}

static int
mlx5e_rep_indr_replace_act(struct mlx5e_rep_priv *rpriv,
			   struct flow_offload_action *fl_act)

{
	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
	enum mlx5_flow_namespace_type ns_type;
	struct flow_action_entry *action;
	struct mlx5e_tc_act *act;
	bool add = false;
	int i;

	/* There is no use case currently for more than one action (e.g. pedit).
	 * when there will be, need to handle cleaning multiple actions on err.
	 */
	if (!flow_offload_has_one_action(&fl_act->action))
		return -EOPNOTSUPP;

	if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS)
		ns_type = MLX5_FLOW_NAMESPACE_FDB;
	else
		ns_type = MLX5_FLOW_NAMESPACE_KERNEL;

	flow_action_for_each(i, action, &fl_act->action) {
		act = mlx5e_tc_act_get(action->id, ns_type);
		if (!act)
			continue;

		if (!act->offload_action)
			continue;

		if (!act->offload_action(priv, fl_act, action))
			add = true;
	}

	return add ? 0 : -EOPNOTSUPP;
}

static int
mlx5e_rep_indr_destroy_act(struct mlx5e_rep_priv *rpriv,
			   struct flow_offload_action *fl_act)
{
	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
	enum mlx5_flow_namespace_type ns_type;
	struct mlx5e_tc_act *act;

	if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS)
		ns_type = MLX5_FLOW_NAMESPACE_FDB;
	else
		ns_type = MLX5_FLOW_NAMESPACE_KERNEL;

	act = mlx5e_tc_act_get(fl_act->id, ns_type);
	if (!act || !act->destroy_action)
		return -EOPNOTSUPP;

	return act->destroy_action(priv, fl_act);
}

static int
mlx5e_rep_indr_stats_act(struct mlx5e_rep_priv *rpriv,
			 struct flow_offload_action *fl_act)

{
	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
	enum mlx5_flow_namespace_type ns_type;
	struct mlx5e_tc_act *act;

	if (esw && esw->mode == MLX5_ESWITCH_OFFLOADS)
		ns_type = MLX5_FLOW_NAMESPACE_FDB;
	else
		ns_type = MLX5_FLOW_NAMESPACE_KERNEL;

	act = mlx5e_tc_act_get(fl_act->id, ns_type);
	if (!act || !act->stats_action)
		return -EOPNOTSUPP;

	return act->stats_action(priv, fl_act);
}

static int
mlx5e_rep_indr_setup_act(struct mlx5e_rep_priv *rpriv,
			 struct flow_offload_action *fl_act)
{
	switch (fl_act->command) {
	case FLOW_ACT_REPLACE:
		return mlx5e_rep_indr_replace_act(rpriv, fl_act);
	case FLOW_ACT_DESTROY:
		return mlx5e_rep_indr_destroy_act(rpriv, fl_act);
	case FLOW_ACT_STATS:
		return mlx5e_rep_indr_stats_act(rpriv, fl_act);
	default:
		return -EOPNOTSUPP;
	}
}

static int
mlx5e_rep_indr_no_dev_setup(struct mlx5e_rep_priv *rpriv,
			    enum tc_setup_type type,
			    void *data)
{
	if (!data)
		return -EOPNOTSUPP;

	switch (type) {
	case TC_SETUP_ACT:
		return mlx5e_rep_indr_setup_act(rpriv, data);
	default:
		return -EOPNOTSUPP;
	}
}

static
int mlx5e_rep_indr_setup_cb(struct net_device *netdev, struct Qdisc *sch, void *cb_priv,
			    enum tc_setup_type type, void *type_data,
@@ -518,7 +633,7 @@ int mlx5e_rep_indr_setup_cb(struct net_device *netdev, struct Qdisc *sch, void *
			    void (*cleanup)(struct flow_block_cb *block_cb))
{
	if (!netdev)
		return -EOPNOTSUPP;
		return mlx5e_rep_indr_no_dev_setup(cb_priv, type, data);

	switch (type) {
	case TC_SETUP_BLOCK:
Loading