Commit 9724fd5d authored by Vlad Buslov's avatar Vlad Buslov Committed by Saeed Mahameed
Browse files

net/mlx5: Bridge, add tracepoints



Move private bridge structures to dedicated headers that is accessible to
bridge tracepoint header. Implemented following tracepoints:

- Initialize FDB entry.
- Refresh FDB entry.
- Cleanup FDB entry.
- Create VLAN.
- Cleanup VLAN.
- Attach port to bridge.
- Detach port from bridge.

Usage example:

># cd /sys/kernel/debug/tracing
># echo mlx5:mlx5_esw_bridge_fdb_entry_init >> set_event
># cat trace
...
   kworker/u20:1-96      [001] ....   231.892503: mlx5_esw_bridge_fdb_entry_init: net_device=enp8s0f0_0 addr=e4:fd:05:08:00:02 vid=3 flags=0 lastuse=4294895695

Signed-off-by: default avatarVlad Buslov <vladbu@nvidia.com>
Reviewed-by: default avatarJianbo Liu <jianbol@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent cc2987c4
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -600,3 +600,59 @@ tc and eswitch offloads tracepoints:
    $ cat /sys/kernel/debug/tracing/trace
    ...
    kworker/u48:7-2221  [009] ...1  1475.387435: mlx5e_rep_neigh_update: netdev: ens1f0 MAC: 24:8a:07:9a:17:9a IPv4: 1.1.1.10 IPv6: ::ffff:1.1.1.10 neigh_connected=1

Bridge offloads tracepoints:

- mlx5_esw_bridge_fdb_entry_init: trace bridge FDB entry offloaded to mlx5::

    $ echo mlx5:mlx5_esw_bridge_fdb_entry_init >> set_event
    $ cat /sys/kernel/debug/tracing/trace
    ...
    kworker/u20:9-2217    [003] ...1   318.582243: mlx5_esw_bridge_fdb_entry_init: net_device=enp8s0f0_0 addr=e4:fd:05:08:00:02 vid=0 flags=0 used=0

- mlx5_esw_bridge_fdb_entry_cleanup: trace bridge FDB entry deleted from mlx5::

    $ echo mlx5:mlx5_esw_bridge_fdb_entry_cleanup >> set_event
    $ cat /sys/kernel/debug/tracing/trace
    ...
    ip-2581    [005] ...1   318.629871: mlx5_esw_bridge_fdb_entry_cleanup: net_device=enp8s0f0_1 addr=e4:fd:05:08:00:03 vid=0 flags=0 used=16

- mlx5_esw_bridge_fdb_entry_refresh: trace bridge FDB entry offload refreshed in
  mlx5::

    $ echo mlx5:mlx5_esw_bridge_fdb_entry_refresh >> set_event
    $ cat /sys/kernel/debug/tracing/trace
    ...
    kworker/u20:8-3849    [003] ...1       466716: mlx5_esw_bridge_fdb_entry_refresh: net_device=enp8s0f0_0 addr=e4:fd:05:08:00:02 vid=3 flags=0 used=0

- mlx5_esw_bridge_vlan_create: trace bridge VLAN object add on mlx5
  representor::

    $ echo mlx5:mlx5_esw_bridge_vlan_create >> set_event
    $ cat /sys/kernel/debug/tracing/trace
    ...
    ip-2560    [007] ...1   318.460258: mlx5_esw_bridge_vlan_create: vid=1 flags=6

- mlx5_esw_bridge_vlan_cleanup: trace bridge VLAN object delete from mlx5
  representor::

    $ echo mlx5:mlx5_esw_bridge_vlan_cleanup >> set_event
    $ cat /sys/kernel/debug/tracing/trace
    ...
    bridge-2582    [007] ...1   318.653496: mlx5_esw_bridge_vlan_cleanup: vid=2 flags=8

- mlx5_esw_bridge_vport_init: trace mlx5 vport assigned with bridge upper
  device::

    $ echo mlx5:mlx5_esw_bridge_vport_init >> set_event
    $ cat /sys/kernel/debug/tracing/trace
    ...
    ip-2560    [007] ...1   318.458915: mlx5_esw_bridge_vport_init: vport_num=1

- mlx5_esw_bridge_vport_cleanup: trace mlx5 vport removed from bridge upper
  device::

    $ echo mlx5:mlx5_esw_bridge_vport_cleanup >> set_event
    $ cat /sys/kernel/debug/tracing/trace
    ...
    ip-5387    [000] ...1       573713: mlx5_esw_bridge_vport_cleanup: vport_num=1
+25 −50
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2021 Mellanox Technologies. */

#include <linux/netdevice.h>
#include <linux/list.h>
#include <linux/rhashtable.h>
#include <linux/xarray.h>
#include <linux/if_bridge.h>
#include <linux/if_vlan.h>
#include <linux/if_ether.h>
#include <linux/notifier.h>
#include <net/netevent.h>
#include <net/switchdev.h>
#include "bridge.h"
#include "eswitch.h"
#include "fs_core.h"
#include "bridge_priv.h"
#define CREATE_TRACE_POINTS
#include "diag/bridge_tracepoint.h"

#define MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE 64000
#define MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_FROM 0
@@ -39,31 +37,6 @@ enum {
	MLX5_ESW_BRIDGE_LEVEL_SKIP_TABLE,
};

struct mlx5_esw_bridge_fdb_key {
	unsigned char addr[ETH_ALEN];
	u16 vid;
};

enum {
	MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER = BIT(0),
};

struct mlx5_esw_bridge_fdb_entry {
	struct mlx5_esw_bridge_fdb_key key;
	struct rhash_head ht_node;
	struct net_device *dev;
	struct list_head list;
	struct list_head vlan_list;
	u16 vport_num;
	u16 flags;

	struct mlx5_flow_handle *ingress_handle;
	struct mlx5_fc *ingress_counter;
	unsigned long lastuse;
	struct mlx5_flow_handle *egress_handle;
	struct mlx5_flow_handle *filter_handle;
};

static const struct rhashtable_params fdb_ht_params = {
	.key_offset = offsetof(struct mlx5_esw_bridge_fdb_entry, key),
	.key_len = sizeof(struct mlx5_esw_bridge_fdb_key),
@@ -71,19 +44,6 @@ static const struct rhashtable_params fdb_ht_params = {
	.automatic_shrinking = true,
};

struct mlx5_esw_bridge_vlan {
	u16 vid;
	u16 flags;
	struct list_head fdb_list;
	struct mlx5_pkt_reformat *pkt_reformat_push;
	struct mlx5_pkt_reformat *pkt_reformat_pop;
};

struct mlx5_esw_bridge_port {
	u16 vport_num;
	struct xarray vlans;
};

enum {
	MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG = BIT(0),
};
@@ -697,10 +657,23 @@ static void mlx5_esw_bridge_port_erase(struct mlx5_esw_bridge_port *port,
	xa_erase(&bridge->vports, port->vport_num);
}

static void mlx5_esw_bridge_fdb_entry_refresh(unsigned long lastuse,
					      struct mlx5_esw_bridge_fdb_entry *entry)
{
	trace_mlx5_esw_bridge_fdb_entry_refresh(entry);

	entry->lastuse = lastuse;
	mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
					   entry->key.vid,
					   SWITCHDEV_FDB_ADD_TO_BRIDGE);
}

static void
mlx5_esw_bridge_fdb_entry_cleanup(struct mlx5_esw_bridge_fdb_entry *entry,
				  struct mlx5_esw_bridge *bridge)
{
	trace_mlx5_esw_bridge_fdb_entry_cleanup(entry);

	rhashtable_remove_fast(&bridge->fdb_ht, &entry->ht_node, fdb_ht_params);
	mlx5_del_flow_rules(entry->egress_handle);
	if (entry->filter_handle)
@@ -842,6 +815,7 @@ mlx5_esw_bridge_vlan_create(u16 vid, u16 flags, struct mlx5_esw_bridge_port *por
	if (err)
		goto err_xa_insert;

	trace_mlx5_esw_bridge_vlan_create(vlan);
	return vlan;

err_xa_insert:
@@ -884,6 +858,7 @@ static void mlx5_esw_bridge_vlan_cleanup(struct mlx5_esw_bridge_port *port,
					 struct mlx5_esw_bridge_vlan *vlan,
					 struct mlx5_esw_bridge *bridge)
{
	trace_mlx5_esw_bridge_vlan_cleanup(vlan);
	mlx5_esw_bridge_vlan_flush(vlan, bridge);
	mlx5_esw_bridge_vlan_erase(port, vlan);
	kvfree(vlan);
@@ -1007,6 +982,8 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, const unsi
	else
		INIT_LIST_HEAD(&entry->vlan_list);
	list_add(&entry->list, &bridge->fdb_list);

	trace_mlx5_esw_bridge_fdb_entry_init(entry);
	return entry;

err_ht_init:
@@ -1078,6 +1055,7 @@ static int mlx5_esw_bridge_vport_init(struct mlx5_esw_bridge_offloads *br_offloa
			 vport->vport, err);
		goto err_port_insert;
	}
	trace_mlx5_esw_bridge_vport_init(port);

	vport->bridge = bridge;
	return 0;
@@ -1106,6 +1084,7 @@ static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_off
		return -EINVAL;
	}

	trace_mlx5_esw_bridge_vport_cleanup(port);
	mlx5_esw_bridge_port_vlans_flush(port, bridge);
	mlx5_esw_bridge_port_erase(port, bridge);
	kvfree(port);
@@ -1266,11 +1245,7 @@ void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads)
				continue;

			if (time_after(lastuse, entry->lastuse)) {
				entry->lastuse = lastuse;
				/* refresh existing bridge entry */
				mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
								   entry->key.vid,
								   SWITCHDEV_FDB_ADD_TO_BRIDGE);
				mlx5_esw_bridge_fdb_entry_refresh(lastuse, entry);
			} else if (time_is_before_jiffies(entry->lastuse + bridge->ageing_time)) {
				mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
								   entry->key.vid,
+53 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2021 Mellanox Technologies. */

#ifndef _MLX5_ESW_BRIDGE_PRIVATE_
#define _MLX5_ESW_BRIDGE_PRIVATE_

#include <linux/netdevice.h>
#include <linux/if_bridge.h>
#include <linux/if_vlan.h>
#include <linux/if_ether.h>
#include <linux/rhashtable.h>
#include <linux/xarray.h>
#include "fs_core.h"

struct mlx5_esw_bridge_fdb_key {
	unsigned char addr[ETH_ALEN];
	u16 vid;
};

enum {
	MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER = BIT(0),
};

struct mlx5_esw_bridge_fdb_entry {
	struct mlx5_esw_bridge_fdb_key key;
	struct rhash_head ht_node;
	struct net_device *dev;
	struct list_head list;
	struct list_head vlan_list;
	u16 vport_num;
	u16 flags;

	struct mlx5_flow_handle *ingress_handle;
	struct mlx5_fc *ingress_counter;
	unsigned long lastuse;
	struct mlx5_flow_handle *egress_handle;
	struct mlx5_flow_handle *filter_handle;
};

struct mlx5_esw_bridge_vlan {
	u16 vid;
	u16 flags;
	struct list_head fdb_list;
	struct mlx5_pkt_reformat *pkt_reformat_push;
	struct mlx5_pkt_reformat *pkt_reformat_pop;
};

struct mlx5_esw_bridge_port {
	u16 vport_num;
	struct xarray vlans;
};

#endif /* _MLX5_ESW_BRIDGE_PRIVATE_ */
+113 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2021 Mellanox Technologies. */

#undef TRACE_SYSTEM
#define TRACE_SYSTEM mlx5

#if !defined(_MLX5_ESW_BRIDGE_TRACEPOINT_) || defined(TRACE_HEADER_MULTI_READ)
#define _MLX5_ESW_BRIDGE_TRACEPOINT_

#include <linux/tracepoint.h>
#include "../bridge_priv.h"

DECLARE_EVENT_CLASS(mlx5_esw_bridge_fdb_template,
		    TP_PROTO(const struct mlx5_esw_bridge_fdb_entry *fdb),
		    TP_ARGS(fdb),
		    TP_STRUCT__entry(
			    __array(char, dev_name, IFNAMSIZ)
			    __array(unsigned char, addr, ETH_ALEN)
			    __field(u16, vid)
			    __field(u16, flags)
			    __field(unsigned int, used)
			    ),
		    TP_fast_assign(
			    strncpy(__entry->dev_name,
				    netdev_name(fdb->dev),
				    IFNAMSIZ);
			    memcpy(__entry->addr, fdb->key.addr, ETH_ALEN);
			    __entry->vid = fdb->key.vid;
			    __entry->flags = fdb->flags;
			    __entry->used = jiffies_to_msecs(jiffies - fdb->lastuse)
			    ),
		    TP_printk("net_device=%s addr=%pM vid=%hu flags=%hx used=%u",
			      __entry->dev_name,
			      __entry->addr,
			      __entry->vid,
			      __entry->flags,
			      __entry->used / 1000)
	);

DEFINE_EVENT(mlx5_esw_bridge_fdb_template,
	     mlx5_esw_bridge_fdb_entry_init,
	     TP_PROTO(const struct mlx5_esw_bridge_fdb_entry *fdb),
	     TP_ARGS(fdb)
	);
DEFINE_EVENT(mlx5_esw_bridge_fdb_template,
	     mlx5_esw_bridge_fdb_entry_refresh,
	     TP_PROTO(const struct mlx5_esw_bridge_fdb_entry *fdb),
	     TP_ARGS(fdb)
	);
DEFINE_EVENT(mlx5_esw_bridge_fdb_template,
	     mlx5_esw_bridge_fdb_entry_cleanup,
	     TP_PROTO(const struct mlx5_esw_bridge_fdb_entry *fdb),
	     TP_ARGS(fdb)
	);

DECLARE_EVENT_CLASS(mlx5_esw_bridge_vlan_template,
		    TP_PROTO(const struct mlx5_esw_bridge_vlan *vlan),
		    TP_ARGS(vlan),
		    TP_STRUCT__entry(
			    __field(u16, vid)
			    __field(u16, flags)
			    ),
		    TP_fast_assign(
			    __entry->vid = vlan->vid;
			    __entry->flags = vlan->flags;
			    ),
		    TP_printk("vid=%hu flags=%hx",
			      __entry->vid,
			      __entry->flags)
	);

DEFINE_EVENT(mlx5_esw_bridge_vlan_template,
	     mlx5_esw_bridge_vlan_create,
	     TP_PROTO(const struct mlx5_esw_bridge_vlan *vlan),
	     TP_ARGS(vlan)
	);
DEFINE_EVENT(mlx5_esw_bridge_vlan_template,
	     mlx5_esw_bridge_vlan_cleanup,
	     TP_PROTO(const struct mlx5_esw_bridge_vlan *vlan),
	     TP_ARGS(vlan)
	);

DECLARE_EVENT_CLASS(mlx5_esw_bridge_port_template,
		    TP_PROTO(const struct mlx5_esw_bridge_port *port),
		    TP_ARGS(port),
		    TP_STRUCT__entry(
			    __field(u16, vport_num)
			    ),
		    TP_fast_assign(
			    __entry->vport_num = port->vport_num;
			    ),
		    TP_printk("vport_num=%hu", __entry->vport_num)
	);

DEFINE_EVENT(mlx5_esw_bridge_port_template,
	     mlx5_esw_bridge_vport_init,
	     TP_PROTO(const struct mlx5_esw_bridge_port *port),
	     TP_ARGS(port)
	);
DEFINE_EVENT(mlx5_esw_bridge_port_template,
	     mlx5_esw_bridge_vport_cleanup,
	     TP_PROTO(const struct mlx5_esw_bridge_port *port),
	     TP_ARGS(port)
	);

#endif

/* This part must be outside protection */
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH esw/diag
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE bridge_tracepoint
#include <trace/define_trace.h>