Commit 1cd5ea44 authored by David S. Miller's avatar David S. Miller
Browse files

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

mlx5-updates-2022-08-22

Roi Dayan Says:
===============
Add support for SF tunnel offload

Mlx5 driver only supports VF tunnel offload.
To add support for SF tunnel offload the driver needs to:
1. Add send-to-vport metadata matching rules like done for VFs.
2. Set an indirect table for SF vport, same as VF vport.

info smaller sub functions for better maintainability.

rules from esw init phase to representor load phase.
SFs could be created after esw initialized and thus the send-to-vport
meta rules would not be created for those SFs.
By moving the creation of the rules to representor load phase
we ensure creating the rules also for SFs created later.

===============

Lama Kayal Says:
================
Make flow steering API loosely coupled from mlx5e_priv, in a manner to
introduce more readable and maintainable modules.

Make TC's private, let mlx5e_flow_steering struct be dynamically allocated,
and introduce its API to maintain the code via setters and getters
instead of publicly exposing it.

Introduce flow steering debug macros to provide an elegant finish to the
decoupled flow steering API, where errors related to flow steering shall
be reported via them.

All flow steering related files will drop any coupling to mlx5e_priv,
instead they will get the relevant members as input. Among these,
fs_tt_redirect, fs_tc, and arfs.
================
parents fef5de75 72e0bcd1
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -856,11 +856,6 @@ enum {
	MLX5E_STATE_XDP_ACTIVE,
};

enum {
	MLX5E_TC_PRIO = 0,
	MLX5E_NIC_PRIO
};

struct mlx5e_modify_sq_param {
	int curr_state;
	int next_state;
+80 −78
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include "lib/fs_ttc.h"

struct mlx5e_post_act;
struct mlx5e_tc_table;

enum {
	MLX5E_TC_FT_LEVEL = 0,
@@ -15,6 +16,11 @@ enum {
	MLX5E_TC_MISS_LEVEL,
};

enum {
	MLX5E_TC_PRIO = 0,
	MLX5E_NIC_PRIO
};

struct mlx5e_flow_table {
	int num_groups;
	struct mlx5_flow_table *t;
@@ -83,54 +89,28 @@ enum {
#endif
};

struct mlx5e_priv;

#ifdef CONFIG_MLX5_EN_RXNFC

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;
};

void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv);
void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv);
int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd);
int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
			    struct ethtool_rxnfc *info, u32 *rule_locs);
#else
static inline void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv)    { }
static inline void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv) { }
static inline int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd)
{ return -EOPNOTSUPP; }
static inline int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
					  struct ethtool_rxnfc *info, u32 *rule_locs)
{ return -EOPNOTSUPP; }
#endif /* CONFIG_MLX5_EN_RXNFC */
struct mlx5e_flow_steering;
struct mlx5e_rx_res;

#ifdef CONFIG_MLX5_EN_ARFS
struct mlx5e_arfs_tables;

int mlx5e_arfs_create_tables(struct mlx5e_priv *priv);
void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv);
int mlx5e_arfs_enable(struct mlx5e_priv *priv);
int mlx5e_arfs_disable(struct mlx5e_priv *priv);
int mlx5e_arfs_create_tables(struct mlx5e_flow_steering *fs,
			     struct mlx5e_rx_res *rx_res, bool ntuple);
void mlx5e_arfs_destroy_tables(struct mlx5e_flow_steering *fs, bool ntuple);
int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs);
int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs);
int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
			u16 rxq_index, u32 flow_id);
#else
static inline int mlx5e_arfs_create_tables(struct mlx5e_priv *priv) { return 0; }
static inline void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv) {}
static inline int mlx5e_arfs_enable(struct mlx5e_priv *priv) { return -EOPNOTSUPP; }
static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv) {	return -EOPNOTSUPP; }
static inline int mlx5e_arfs_create_tables(struct mlx5e_flow_steering *fs,
					   struct mlx5e_rx_res *rx_res, bool ntuple)
{ return 0; }
static inline void mlx5e_arfs_destroy_tables(struct mlx5e_flow_steering *fs, bool ntuple) {}
static inline int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs)
{ return -EOPNOTSUPP; }
static inline int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs)
{ return -EOPNOTSUPP; }
#endif

#ifdef CONFIG_MLX5_EN_TLS
@@ -142,54 +122,63 @@ 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_promisc_table      promisc;
	struct mlx5e_vlan_table         *vlan;
	struct mlx5e_l2_table           l2;
	struct mlx5_ttc_table           *ttc;
	struct mlx5_ttc_table           *inner_ttc;
#ifdef CONFIG_MLX5_EN_ARFS
	struct mlx5e_arfs_tables       *arfs;
#endif
#ifdef CONFIG_MLX5_EN_TLS
	struct mlx5e_accel_fs_tcp      *accel_tcp;
#endif
	struct mlx5e_fs_udp            *udp;
	struct mlx5e_fs_any            *any;
	struct mlx5e_ptp_fs            *ptp_fs;
};

void mlx5e_set_ttc_params(struct mlx5e_priv *priv,
void mlx5e_set_ttc_params(struct mlx5e_flow_steering *fs,
			  struct mlx5e_rx_res *rx_res,
			  struct ttc_params *ttc_params, bool tunnel);

void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv);
int mlx5e_create_ttc_table(struct mlx5e_priv *priv);
void mlx5e_destroy_ttc_table(struct mlx5e_flow_steering *fs);
int mlx5e_create_ttc_table(struct mlx5e_flow_steering  *fs,
			   struct mlx5e_rx_res *rx_res);

void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft);

void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv);
void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv);
void mlx5e_enable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc);
void mlx5e_disable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc);

int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);
int mlx5e_create_flow_steering(struct mlx5e_flow_steering *fs,
			       struct mlx5e_rx_res *rx_res,
			       const struct mlx5e_profile *profile,
			       struct net_device *netdev);
void mlx5e_destroy_flow_steering(struct mlx5e_flow_steering *fs, bool ntuple,
				 const struct mlx5e_profile *profile);

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);
struct mlx5e_vlan_table *mlx5e_fs_get_vlan(struct mlx5e_flow_steering *fs);
void mlx5e_fs_set_tc(struct mlx5e_flow_steering *fs, struct mlx5e_tc_table *tc);
struct mlx5e_tc_table *mlx5e_fs_get_tc(struct mlx5e_flow_steering *fs);
struct mlx5e_l2_table *mlx5e_fs_get_l2(struct mlx5e_flow_steering *fs);
struct mlx5_flow_namespace *mlx5e_fs_get_ns(struct mlx5e_flow_steering *fs, bool egress);
void mlx5e_fs_set_ns(struct mlx5e_flow_steering *fs, struct mlx5_flow_namespace *ns, bool egress);
#ifdef CONFIG_MLX5_EN_RXNFC
struct mlx5e_ethtool_steering *mlx5e_fs_get_ethtool(struct mlx5e_flow_steering *fs);
#endif
struct mlx5_ttc_table *mlx5e_fs_get_ttc(struct mlx5e_flow_steering *fs, bool inner);
void mlx5e_fs_set_ttc(struct mlx5e_flow_steering *fs, struct mlx5_ttc_table *ttc, bool inner);
#ifdef CONFIG_MLX5_EN_ARFS
struct mlx5e_arfs_tables *mlx5e_fs_get_arfs(struct mlx5e_flow_steering *fs);
void mlx5e_fs_set_arfs(struct mlx5e_flow_steering *fs, struct mlx5e_arfs_tables *arfs);
#endif
struct mlx5e_ptp_fs *mlx5e_fs_get_ptp(struct mlx5e_flow_steering *fs);
void mlx5e_fs_set_ptp(struct mlx5e_flow_steering *fs, struct mlx5e_ptp_fs *ptp_fs);
struct mlx5e_fs_any *mlx5e_fs_get_any(struct mlx5e_flow_steering *fs);
void mlx5e_fs_set_any(struct mlx5e_flow_steering *fs, struct mlx5e_fs_any *any);
struct mlx5e_fs_udp *mlx5e_fs_get_udp(struct mlx5e_flow_steering *fs);
void mlx5e_fs_set_udp(struct mlx5e_flow_steering *fs, struct mlx5e_fs_udp *udp);
#ifdef CONFIG_MLX5_EN_TLS
struct mlx5e_accel_fs_tcp *mlx5e_fs_get_accel_tcp(struct mlx5e_flow_steering *fs);
void mlx5e_fs_set_accel_tcp(struct mlx5e_flow_steering *fs, struct mlx5e_accel_fs_tcp *accel_tcp);
#endif
void mlx5e_fs_set_state_destroy(struct mlx5e_flow_steering *fs, bool state_destroy);
void mlx5e_fs_set_vlan_strip_disable(struct mlx5e_flow_steering *fs, bool vlan_strip_disable);

struct mlx5_core_dev *mlx5e_fs_get_mdev(struct mlx5e_flow_steering *fs);
int mlx5e_add_vlan_trap(struct mlx5e_flow_steering *fs, int  trap_id, int tir_num);
void mlx5e_remove_vlan_trap(struct mlx5e_flow_steering *fs);
int mlx5e_add_mac_trap(struct mlx5e_flow_steering *fs, int  trap_id, int tir_num);
void mlx5e_remove_mac_trap(struct mlx5e_flow_steering *fs);
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,
@@ -198,5 +187,18 @@ 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);

#define fs_err(fs, fmt, ...) \
	mlx5_core_err(mlx5e_fs_get_mdev(fs), fmt, ##__VA_ARGS__)

#define fs_dbg(fs, fmt, ...) \
	mlx5_core_dbg(mlx5e_fs_get_mdev(fs), fmt, ##__VA_ARGS__)

#define fs_warn(fs, fmt, ...) \
	mlx5_core_warn(mlx5e_fs_get_mdev(fs), fmt, ##__VA_ARGS__)

#define fs_warn_once(fs, fmt, ...) \
	mlx5_core_warn_once(mlx5e_fs_get_mdev(fs), fmt, ##__VA_ARGS__)

#endif /* __MLX5E_FLOW_STEER_H__ */
+29 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */

#ifndef __MLX5E_FS_ETHTOOL_H__
#define __MLX5E_FS_ETHTOOL_H__

struct mlx5e_priv;
struct mlx5e_ethtool_steering;
#ifdef CONFIG_MLX5_EN_RXNFC
int mlx5e_ethtool_alloc(struct mlx5e_ethtool_steering **ethtool);
void mlx5e_ethtool_free(struct mlx5e_ethtool_steering *ethtool);
void mlx5e_ethtool_init_steering(struct mlx5e_flow_steering *fs);
void mlx5e_ethtool_cleanup_steering(struct mlx5e_flow_steering *fs);
int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd);
int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
			    struct ethtool_rxnfc *info, u32 *rule_locs);
#else
static inline int mlx5e_ethtool_alloc(struct mlx5e_ethtool_steering **ethtool)
{ return 0; }
static inline void mlx5e_ethtool_free(struct mlx5e_ethtool_steering *ethtool) { }
static inline void mlx5e_ethtool_init_steering(struct mlx5e_flow_steering *fs) { }
static inline void mlx5e_ethtool_cleanup_steering(struct mlx5e_flow_steering *fs) { }
static inline int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd)
{ return -EOPNOTSUPP; }
static inline int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
					  struct ethtool_rxnfc *info, u32 *rule_locs)
{ return -EOPNOTSUPP; }
#endif
#endif
+98 −90
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */

#include <linux/netdevice.h>
#include "en/fs_tt_redirect.h"
#include "fs_core.h"
#include "mlx5_core.h"

enum fs_udp_type {
	FS_IPV4_UDP,
@@ -74,17 +74,17 @@ static void fs_udp_set_dport_flow(struct mlx5_flow_spec *spec, enum fs_udp_type
}

struct mlx5_flow_handle *
mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,
mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_flow_steering *fs,
				  enum mlx5_traffic_types ttc_type,
				  u32 tir_num, u16 d_port)
{
	struct mlx5e_fs_udp *fs_udp = mlx5e_fs_get_udp(fs);
	enum fs_udp_type type = tt2fs_udp(ttc_type);
	struct mlx5_flow_destination dest = {};
	struct mlx5_flow_table *ft = NULL;
	MLX5_DECLARE_FLOW_ACT(flow_act);
	struct mlx5_flow_handle *rule;
	struct mlx5_flow_spec *spec;
	struct mlx5e_fs_udp *fs_udp;
	int err;

	if (type == FS_UDP_NUM_TYPES)
@@ -94,7 +94,6 @@ mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,
	if (!spec)
		return ERR_PTR(-ENOMEM);

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

	fs_udp_set_dport_flow(spec, type, d_port);
@@ -106,30 +105,29 @@ mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,

	if (IS_ERR(rule)) {
		err = PTR_ERR(rule);
		netdev_err(priv->netdev, "%s: add %s rule failed, err %d\n",
		fs_err(fs, "%s: add %s rule failed, err %d\n",
		       __func__, fs_udp_type2str(type), err);
	}
	return rule;
}

static int fs_udp_add_default_rule(struct mlx5e_priv *priv, enum fs_udp_type type)
static int fs_udp_add_default_rule(struct mlx5e_flow_steering *fs, enum fs_udp_type type)
{
	struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
	struct mlx5e_fs_udp *fs_udp = mlx5e_fs_get_udp(fs);
	struct mlx5e_flow_table *fs_udp_t;
	struct mlx5_flow_destination dest;
	MLX5_DECLARE_FLOW_ACT(flow_act);
	struct mlx5_flow_handle *rule;
	struct mlx5e_fs_udp *fs_udp;
	int err;

	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(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);
		netdev_err(priv->netdev,
			   "%s: add default rule failed, fs type=%d, err %d\n",
		fs_err(fs, "%s: add default rule failed, fs type=%d, err %d\n",
		       __func__, type, err);
		return err;
	}
@@ -206,33 +204,36 @@ static int fs_udp_create_groups(struct mlx5e_flow_table *ft, enum fs_udp_type ty
	return err;
}

static int fs_udp_create_table(struct mlx5e_priv *priv, enum fs_udp_type type)
static int fs_udp_create_table(struct mlx5e_flow_steering *fs, enum fs_udp_type type)
{
	struct mlx5e_flow_table *ft = &priv->fs->udp->tables[type];
	struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(fs, false);
	struct mlx5e_fs_udp *fs_udp = mlx5e_fs_get_udp(fs);
	struct mlx5_flow_table_attr ft_attr = {};
	struct mlx5e_flow_table *ft;
	int err;

	ft = &fs_udp->tables[type];
	ft->num_groups = 0;

	ft_attr.max_fte = MLX5E_FS_UDP_TABLE_SIZE;
	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(ns, &ft_attr);
	if (IS_ERR(ft->t)) {
		err = PTR_ERR(ft->t);
		ft->t = NULL;
		return err;
	}

	netdev_dbg(priv->netdev, "Created fs %s table id %u level %u\n",
	mlx5_core_dbg(mlx5e_fs_get_mdev(fs), "Created fs %s table id %u level %u\n",
		      fs_udp_type2str(type), ft->t->id, ft->t->level);

	err = fs_udp_create_groups(ft, type);
	if (err)
		goto err;

	err = fs_udp_add_default_rule(priv, type);
	err = fs_udp_add_default_rule(fs, type);
	if (err)
		goto err;

@@ -253,16 +254,16 @@ static void fs_udp_destroy_table(struct mlx5e_fs_udp *fs_udp, int i)
	fs_udp->tables[i].t = NULL;
}

static int fs_udp_disable(struct mlx5e_priv *priv)
static int fs_udp_disable(struct mlx5e_flow_steering *fs)
{
	struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
	int err, i;

	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(ttc, fs_udp2tt(i));
		if (err) {
			netdev_err(priv->netdev,
				   "%s: modify ttc[%d] default destination failed, err(%d)\n",
			fs_err(fs, "%s: modify ttc[%d] default destination failed, err(%d)\n",
			       __func__, fs_udp2tt(i), err);
			return err;
		}
@@ -271,20 +272,21 @@ static int fs_udp_disable(struct mlx5e_priv *priv)
	return 0;
}

static int fs_udp_enable(struct mlx5e_priv *priv)
static int fs_udp_enable(struct mlx5e_flow_steering *fs)
{
	struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
	struct mlx5e_fs_udp *udp = mlx5e_fs_get_udp(fs);
	struct mlx5_flow_destination dest = {};
	int err, i;

	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 = 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(ttc, fs_udp2tt(i), &dest);
		if (err) {
			netdev_err(priv->netdev,
				   "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
			fs_err(fs, "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
			       __func__, fs_udp2tt(i), err);
			return err;
		}
@@ -292,9 +294,9 @@ static int fs_udp_enable(struct mlx5e_priv *priv)
	return 0;
}

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

	if (!fs_udp)
@@ -303,48 +305,50 @@ void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_priv *priv)
	if (--fs_udp->ref_cnt)
		return;

	fs_udp_disable(priv);
	fs_udp_disable(fs);

	for (i = 0; i < FS_UDP_NUM_TYPES; i++)
		fs_udp_destroy_table(fs_udp, i);

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

int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_priv *priv)
int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_flow_steering *fs)
{
	struct mlx5e_fs_udp *udp = mlx5e_fs_get_udp(fs);
	int i, err;

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

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

	for (i = 0; i < FS_UDP_NUM_TYPES; i++) {
		err = fs_udp_create_table(priv, i);
		err = fs_udp_create_table(fs, i);
		if (err)
			goto err_destroy_tables;
	}

	err = fs_udp_enable(priv);
	err = fs_udp_enable(fs);
	if (err)
		goto err_destroy_tables;

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

	return 0;

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

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

@@ -356,22 +360,21 @@ static void fs_any_set_ethertype_flow(struct mlx5_flow_spec *spec, u16 ether_typ
}

struct mlx5_flow_handle *
mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_priv *priv,
mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_flow_steering *fs,
				  u32 tir_num, u16 ether_type)
{
	struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
	struct mlx5_flow_destination dest = {};
	struct mlx5_flow_table *ft = NULL;
	MLX5_DECLARE_FLOW_ACT(flow_act);
	struct mlx5_flow_handle *rule;
	struct mlx5_flow_spec *spec;
	struct mlx5e_fs_any *fs_any;
	int err;

	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
	if (!spec)
		return ERR_PTR(-ENOMEM);

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

	fs_any_set_ethertype_flow(spec, ether_type);
@@ -383,30 +386,28 @@ mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_priv *priv,

	if (IS_ERR(rule)) {
		err = PTR_ERR(rule);
		netdev_err(priv->netdev, "%s: add ANY rule failed, err %d\n",
		fs_err(fs, "%s: add ANY rule failed, err %d\n",
		       __func__, err);
	}
	return rule;
}

static int fs_any_add_default_rule(struct mlx5e_priv *priv)
static int fs_any_add_default_rule(struct mlx5e_flow_steering *fs)
{
	struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
	struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
	struct mlx5e_flow_table *fs_any_t;
	struct mlx5_flow_destination dest;
	MLX5_DECLARE_FLOW_ACT(flow_act);
	struct mlx5_flow_handle *rule;
	struct mlx5e_fs_any *fs_any;
	int err;

	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(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);
		netdev_err(priv->netdev,
			   "%s: add default rule failed, fs type=ANY, err %d\n",
		fs_err(fs, "%s: add default rule failed, fs type=ANY, err %d\n",
		       __func__, err);
		return err;
	}
@@ -472,9 +473,11 @@ static int fs_any_create_groups(struct mlx5e_flow_table *ft)
	return err;
}

static int fs_any_create_table(struct mlx5e_priv *priv)
static int fs_any_create_table(struct mlx5e_flow_steering *fs)
{
	struct mlx5e_flow_table *ft = &priv->fs->any->table;
	struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(fs, false);
	struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
	struct mlx5e_flow_table *ft = &fs_any->table;
	struct mlx5_flow_table_attr ft_attr = {};
	int err;

@@ -484,21 +487,21 @@ 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(ns, &ft_attr);
	if (IS_ERR(ft->t)) {
		err = PTR_ERR(ft->t);
		ft->t = NULL;
		return err;
	}

	netdev_dbg(priv->netdev, "Created fs ANY table id %u level %u\n",
	mlx5_core_dbg(mlx5e_fs_get_mdev(fs), "Created fs ANY table id %u level %u\n",
		      ft->t->id, ft->t->level);

	err = fs_any_create_groups(ft);
	if (err)
		goto err;

	err = fs_any_add_default_rule(priv);
	err = fs_any_add_default_rule(fs);
	if (err)
		goto err;

@@ -509,14 +512,15 @@ static int fs_any_create_table(struct mlx5e_priv *priv)
	return err;
}

static int fs_any_disable(struct mlx5e_priv *priv)
static int fs_any_disable(struct mlx5e_flow_steering *fs)
{
	struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
	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(ttc, MLX5_TT_ANY);
	if (err) {
		netdev_err(priv->netdev,
		fs_err(fs,
		       "%s: modify ttc[%d] default destination failed, err(%d)\n",
		       __func__, MLX5_TT_ANY, err);
		return err;
@@ -524,18 +528,20 @@ static int fs_any_disable(struct mlx5e_priv *priv)
	return 0;
}

static int fs_any_enable(struct mlx5e_priv *priv)
static int fs_any_enable(struct mlx5e_flow_steering *fs)
{
	struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
	struct mlx5e_fs_any *any = mlx5e_fs_get_any(fs);
	struct mlx5_flow_destination dest = {};
	int err;

	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
	dest.ft = priv->fs->any->table.t;
	dest.ft = 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(ttc, MLX5_TT_ANY, &dest);
	if (err) {
		netdev_err(priv->netdev,
		fs_err(fs,
		       "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
		       __func__, MLX5_TT_ANY, err);
		return err;
@@ -553,9 +559,9 @@ static void fs_any_destroy_table(struct mlx5e_fs_any *fs_any)
	fs_any->table.t = NULL;
}

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

	if (!fs_any)
		return;
@@ -563,43 +569,45 @@ void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_priv *priv)
	if (--fs_any->ref_cnt)
		return;

	fs_any_disable(priv);
	fs_any_disable(fs);

	fs_any_destroy_table(fs_any);

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

int mlx5e_fs_tt_redirect_any_create(struct mlx5e_priv *priv)
int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs)
{
	struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
	int err;

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

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

	err = fs_any_create_table(priv);
	err = fs_any_create_table(fs);
	if (err)
		return err;

	err = fs_any_enable(priv);
	err = fs_any_enable(fs);
	if (err)
		goto err_destroy_table;

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

	return 0;

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

	kfree(priv->fs->any);
	priv->fs->any = NULL;
	kfree(fs_any);
	mlx5e_fs_set_any(fs, NULL);
	return err;
}
+6 −7
Original line number Diff line number Diff line
@@ -4,23 +4,22 @@
#ifndef __MLX5E_FS_TT_REDIRECT_H__
#define __MLX5E_FS_TT_REDIRECT_H__

#include "en.h"
#include "en/fs.h"

void mlx5e_fs_tt_redirect_del_rule(struct mlx5_flow_handle *rule);

/* UDP traffic type redirect */
struct mlx5_flow_handle *
mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,
mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_flow_steering *fs,
				  enum mlx5_traffic_types ttc_type,
				  u32 tir_num, u16 d_port);
void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_priv *priv);
int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_priv *priv);
void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_flow_steering *fs);
int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_flow_steering *fs);

/* ANY traffic type redirect*/
struct mlx5_flow_handle *
mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_priv *priv,
mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_flow_steering *fs,
				  u32 tir_num, u16 ether_type);
void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_priv *priv);
int mlx5e_fs_tt_redirect_any_create(struct mlx5e_priv *priv);
void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_flow_steering *fs);
int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs);
#endif
Loading