Skip to content

Commit

Permalink
Merge branch 'mlx5-updates-2021-01-26'
Browse files Browse the repository at this point in the history
Saeed Mahameed says:

====================
mlx5 devlink traps support

Add support for devlink traps [1] reporting in mlx5,
mlx5 will also report/trap packets filtered due to dest mac steering miss

The first patch in the series defines the new DMAC trap type in devlink
for this purpose.

Other patches in the series are mlx5 only and they gradually traps support.
Supported traps:

DMAC: Drops due to destination MAC not configured in the MAC table
VLAN: Drops due to vlan not configured in the vlan table

Design note:
devlink instance is managed by the low level mlx5 core layer, mlx5 core will
serve as an abstraction layer for trap reporting, since we might have multiple
mlx5 interfaces who might want to report traps on the same device.
====================

Link: https://lore.kernel.org/r/20210126232419.175836-1-saeedm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Jan 28, 2021
2 parents 63368a7 + eb3862a commit 5cc921a
Show file tree
Hide file tree
Showing 18 changed files with 1,076 additions and 49 deletions.
5 changes: 5 additions & 0 deletions Documentation/networking/devlink/devlink-trap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,11 @@ be added to the following table:
- ``drop``
- Traps packets that the device decided to drop in case they hit a
blackhole nexthop
* - ``dmac_filter``
- ``drop``
- Traps incoming packets that the device decided to drop because
the destination MAC is not configured in the MAC table and
the interface is not in promiscuous mode

Driver-specific Packet Traps
============================
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 @@ -27,7 +27,7 @@ mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
en_selftest.o en/port.o en/monitor_stats.o en/health.o \
en/reporter_tx.o en/reporter_rx.o en/params.o en/xsk/pool.o \
en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o en/ptp.o \
en/qos.o
en/qos.o en/trap.o

#
# Netdev extra
Expand Down
188 changes: 188 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,91 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a
return 0;
}

static struct mlx5_devlink_trap *mlx5_find_trap_by_id(struct mlx5_core_dev *dev, int trap_id)
{
struct mlx5_devlink_trap *dl_trap;

list_for_each_entry(dl_trap, &dev->priv.traps, list)
if (dl_trap->trap.id == trap_id)
return dl_trap;

return NULL;
}

static int mlx5_devlink_trap_init(struct devlink *devlink, const struct devlink_trap *trap,
void *trap_ctx)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_devlink_trap *dl_trap;

dl_trap = kzalloc(sizeof(*dl_trap), GFP_KERNEL);
if (!dl_trap)
return -ENOMEM;

dl_trap->trap.id = trap->id;
dl_trap->trap.action = DEVLINK_TRAP_ACTION_DROP;
dl_trap->item = trap_ctx;

if (mlx5_find_trap_by_id(dev, trap->id)) {
kfree(dl_trap);
mlx5_core_err(dev, "Devlink trap: Trap 0x%x already found", trap->id);
return -EEXIST;
}

list_add_tail(&dl_trap->list, &dev->priv.traps);
return 0;
}

static void mlx5_devlink_trap_fini(struct devlink *devlink, const struct devlink_trap *trap,
void *trap_ctx)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_devlink_trap *dl_trap;

dl_trap = mlx5_find_trap_by_id(dev, trap->id);
if (!dl_trap) {
mlx5_core_err(dev, "Devlink trap: Missing trap id 0x%x", trap->id);
return;
}
list_del(&dl_trap->list);
kfree(dl_trap);
}

static int mlx5_devlink_trap_action_set(struct devlink *devlink,
const struct devlink_trap *trap,
enum devlink_trap_action action,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
enum devlink_trap_action action_orig;
struct mlx5_devlink_trap *dl_trap;
int err = 0;

dl_trap = mlx5_find_trap_by_id(dev, trap->id);
if (!dl_trap) {
mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id);
err = -EINVAL;
goto out;
}

if (action != DEVLINK_TRAP_ACTION_DROP && action != DEVLINK_TRAP_ACTION_TRAP) {
err = -EOPNOTSUPP;
goto out;
}

if (action == dl_trap->trap.action)
goto out;

action_orig = dl_trap->trap.action;
dl_trap->trap.action = action;
err = mlx5_blocking_notifier_call_chain(dev, MLX5_DRIVER_EVENT_TYPE_TRAP,
&dl_trap->trap);
if (err)
dl_trap->trap.action = action_orig;
out:
return err;
}

static const struct devlink_ops mlx5_devlink_ops = {
#ifdef CONFIG_MLX5_ESWITCH
.eswitch_mode_set = mlx5_devlink_eswitch_mode_set,
Expand All @@ -186,8 +271,59 @@ static const struct devlink_ops mlx5_devlink_ops = {
.reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET),
.reload_down = mlx5_devlink_reload_down,
.reload_up = mlx5_devlink_reload_up,
.trap_init = mlx5_devlink_trap_init,
.trap_fini = mlx5_devlink_trap_fini,
.trap_action_set = mlx5_devlink_trap_action_set,
};

void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb,
struct devlink_port *dl_port)
{
struct devlink *devlink = priv_to_devlink(dev);
struct mlx5_devlink_trap *dl_trap;

dl_trap = mlx5_find_trap_by_id(dev, trap_id);
if (!dl_trap) {
mlx5_core_err(dev, "Devlink trap: Report on invalid trap id 0x%x", trap_id);
return;
}

if (dl_trap->trap.action != DEVLINK_TRAP_ACTION_TRAP) {
mlx5_core_dbg(dev, "Devlink trap: Trap id %d has action %d", trap_id,
dl_trap->trap.action);
return;
}
devlink_trap_report(devlink, skb, dl_trap->item, dl_port, NULL);
}

int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev)
{
struct mlx5_devlink_trap *dl_trap;
int count = 0;

list_for_each_entry(dl_trap, &dev->priv.traps, list)
if (dl_trap->trap.action == DEVLINK_TRAP_ACTION_TRAP)
count++;

return count;
}

int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id,
enum devlink_trap_action *action)
{
struct mlx5_devlink_trap *dl_trap;

dl_trap = mlx5_find_trap_by_id(dev, trap_id);
if (!dl_trap) {
mlx5_core_err(dev, "Devlink trap: Get action on invalid trap id 0x%x",
trap_id);
return -EINVAL;
}

*action = dl_trap->trap.action;
return 0;
}

struct devlink *mlx5_devlink_alloc(void)
{
return devlink_alloc(&mlx5_devlink_ops, sizeof(struct mlx5_core_dev));
Expand Down Expand Up @@ -358,6 +494,49 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
#endif
}

#define MLX5_TRAP_DROP(_id, _group_id) \
DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \
DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT)

static const struct devlink_trap mlx5_traps_arr[] = {
MLX5_TRAP_DROP(INGRESS_VLAN_FILTER, L2_DROPS),
MLX5_TRAP_DROP(DMAC_FILTER, L2_DROPS),
};

static const struct devlink_trap_group mlx5_trap_groups_arr[] = {
DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0),
};

static int mlx5_devlink_traps_register(struct devlink *devlink)
{
struct mlx5_core_dev *core_dev = devlink_priv(devlink);
int err;

err = devlink_trap_groups_register(devlink, mlx5_trap_groups_arr,
ARRAY_SIZE(mlx5_trap_groups_arr));
if (err)
return err;

err = devlink_traps_register(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr),
&core_dev->priv);
if (err)
goto err_trap_group;
return 0;

err_trap_group:
devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
ARRAY_SIZE(mlx5_trap_groups_arr));
return err;
}

static void mlx5_devlink_traps_unregister(struct devlink *devlink)
{
devlink_traps_unregister(devlink, mlx5_traps_arr, ARRAY_SIZE(mlx5_traps_arr));
devlink_trap_groups_unregister(devlink, mlx5_trap_groups_arr,
ARRAY_SIZE(mlx5_trap_groups_arr));
}

int mlx5_devlink_register(struct devlink *devlink, struct device *dev)
{
int err;
Expand All @@ -372,15 +551,24 @@ int mlx5_devlink_register(struct devlink *devlink, struct device *dev)
goto params_reg_err;
mlx5_devlink_set_params_init_values(devlink);
devlink_params_publish(devlink);

err = mlx5_devlink_traps_register(devlink);
if (err)
goto traps_reg_err;

return 0;

traps_reg_err:
devlink_params_unregister(devlink, mlx5_devlink_params,
ARRAY_SIZE(mlx5_devlink_params));
params_reg_err:
devlink_unregister(devlink);
return err;
}

void mlx5_devlink_unregister(struct devlink *devlink)
{
mlx5_devlink_traps_unregister(devlink);
devlink_params_unregister(devlink, mlx5_devlink_params,
ARRAY_SIZE(mlx5_devlink_params));
devlink_unregister(devlink);
Expand Down
18 changes: 18 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/devlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@ enum mlx5_devlink_param_id {
MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
};

struct mlx5_trap_ctx {
int id;
int action;
};

struct mlx5_devlink_trap {
struct mlx5_trap_ctx trap;
void *item;
struct list_head list;
};

struct mlx5_core_dev;
void mlx5_devlink_trap_report(struct mlx5_core_dev *dev, int trap_id, struct sk_buff *skb,
struct devlink_port *dl_port);
int mlx5_devlink_trap_get_num_active(struct mlx5_core_dev *dev);
int mlx5_devlink_traps_get_action(struct mlx5_core_dev *dev, int trap_id,
enum devlink_trap_action *action);

struct devlink *mlx5_devlink_alloc(void);
void mlx5_devlink_free(struct devlink *devlink);
int mlx5_devlink_register(struct devlink *devlink, struct device *dev);
Expand Down
10 changes: 10 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ typedef bool (*mlx5e_fp_post_rx_wqes)(struct mlx5e_rq *rq);
typedef void (*mlx5e_fp_dealloc_wqe)(struct mlx5e_rq*, u16);

int mlx5e_rq_set_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params, bool xsk);
void mlx5e_rq_set_trap_handlers(struct mlx5e_rq *rq, struct mlx5e_params *params);

enum mlx5e_rq_flag {
MLX5E_RQ_FLAG_XDP_XMIT,
Expand Down Expand Up @@ -805,6 +806,8 @@ struct mlx5e_htb {
u16 defcls;
};

struct mlx5e_trap;

struct mlx5e_priv {
/* priv data path fields - start */
/* +1 for port ptp ts */
Expand Down Expand Up @@ -844,8 +847,10 @@ struct mlx5e_priv {

struct mlx5_core_dev *mdev;
struct net_device *netdev;
struct mlx5e_trap *en_trap;
struct mlx5e_stats stats;
struct mlx5e_channel_stats channel_stats[MLX5E_MAX_NUM_CHANNELS];
struct mlx5e_channel_stats trap_stats;
struct mlx5e_port_ptp_stats port_ptp_stats;
u16 max_nch;
u8 max_opened_tc;
Expand All @@ -854,6 +859,7 @@ struct mlx5e_priv {
u16 q_counter;
u16 drop_rq_q_counter;
struct notifier_block events_nb;
struct notifier_block blocking_events_nb;
int num_tc_x_num_ch;

struct udp_tunnel_nic_info nic_info;
Expand Down Expand Up @@ -961,6 +967,8 @@ int mlx5e_open_rq(struct mlx5e_channel *c, struct mlx5e_params *params,
int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq, int wait_time);
void mlx5e_deactivate_rq(struct mlx5e_rq *rq);
void mlx5e_close_rq(struct mlx5e_rq *rq);
int mlx5e_create_rq(struct mlx5e_rq *rq, struct mlx5e_rq_param *param);
void mlx5e_destroy_rq(struct mlx5e_rq *rq);

struct mlx5e_sq_param;
int mlx5e_open_icosq(struct mlx5e_channel *c, struct mlx5e_params *params,
Expand Down Expand Up @@ -1072,6 +1080,8 @@ void mlx5e_destroy_q_counters(struct mlx5e_priv *priv);
int mlx5e_open_drop_rq(struct mlx5e_priv *priv,
struct mlx5e_rq *drop_rq);
void mlx5e_close_drop_rq(struct mlx5e_rq *drop_rq);
int mlx5e_init_di_list(struct mlx5e_rq *rq, int wq_sz, int node);
void mlx5e_free_di_list(struct mlx5e_rq *rq);

int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv);

Expand Down
16 changes: 14 additions & 2 deletions drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ struct mlx5e_l2_rule {

#define MLX5E_L2_ADDR_HASH_SIZE BIT(BITS_PER_BYTE)

struct mlx5e_promisc_table {
struct mlx5e_flow_table ft;
struct mlx5_flow_handle *rule;
};

struct mlx5e_vlan_table {
struct mlx5e_flow_table ft;
DECLARE_BITMAP(active_cvlans, VLAN_N_VID);
Expand All @@ -53,6 +58,7 @@ struct mlx5e_vlan_table {
struct mlx5_flow_handle *untagged_rule;
struct mlx5_flow_handle *any_cvlan_rule;
struct mlx5_flow_handle *any_svlan_rule;
struct mlx5_flow_handle *trap_rule;
bool cvlan_filter_disabled;
};

Expand All @@ -62,7 +68,7 @@ struct mlx5e_l2_table {
struct hlist_head netdev_mc[MLX5E_L2_ADDR_HASH_SIZE];
struct mlx5e_l2_rule broadcast;
struct mlx5e_l2_rule allmulti;
struct mlx5e_l2_rule promisc;
struct mlx5_flow_handle *trap_rule;
bool broadcast_enabled;
bool allmulti_enabled;
bool promisc_enabled;
Expand Down Expand Up @@ -126,7 +132,8 @@ struct mlx5e_ttc_table {

/* NIC prio FTS */
enum {
MLX5E_VLAN_FT_LEVEL = 0,
MLX5E_PROMISC_FT_LEVEL,
MLX5E_VLAN_FT_LEVEL,
MLX5E_L2_FT_LEVEL,
MLX5E_TTC_FT_LEVEL,
MLX5E_INNER_TTC_FT_LEVEL,
Expand Down Expand Up @@ -241,6 +248,7 @@ struct mlx5e_flow_steering {
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 mlx5e_ttc_table ttc;
Expand Down Expand Up @@ -288,6 +296,10 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);

u8 mlx5e_get_proto_by_tunnel_type(enum mlx5e_tunnel_types tt);
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);

#endif /* __MLX5E_FLOW_STEER_H__ */

Loading

0 comments on commit 5cc921a

Please sign in to comment.