Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 641f7e40 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bridge-igmp-stats'



Nikolay Aleksandrov says:

====================
net: bridge: add support for IGMP/MLD stats

This patchset adds support for the new IFLA_STATS_LINK_XSTATS_SLAVE
attribute which can be used with RTM_GETSTATS in order to export per-slave
statistics. It works by passing the attribute to the linkxstats callback
and if the callback user supports it - it should dump that slave's stats.
This is much more scalable and permits us to request only a single port's
statistics instead of dumping everything every time.
The second patch adds support for per-port IGMP/MLD statistics and uses
the new API to export them for the bridge and its ports. The stats are
made in a very lightweight manner, the normal fast-path is not affected
at all and the flood paths (br_flood/br_multicast_flood) are only affected
if the packet is IGMP and the IGMP stats have been enabled using cache-hot
data for the check.

v2: Patch 01 is new, patch 02 has been reworked to use the new API, also
in addition counters for IGMP/MLD parse errors have been added and members
are added for per-port multicast traffic stats. The multicast counting has
been slightly optimized (moved the br_multicast_count inside the IPv4/6
IGMP functions after the checks for IGMP traffic) to avoid one conditional
that was on all of the multicast traffic path (both IGMP and other).
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 545c321b 1080ab95
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -98,10 +98,11 @@ struct rtnl_link_ops {
						   const struct net_device *dev,
						   const struct net_device *slave_dev);
	struct net		*(*get_link_net)(const struct net_device *dev);
	size_t			(*get_linkxstats_size)(const struct net_device *dev);
	size_t			(*get_linkxstats_size)(const struct net_device *dev,
						       int attr);
	int			(*fill_linkxstats)(struct sk_buff *skb,
						   const struct net_device *dev,
						   int *prividx);
						   int *prividx, int attr);
};

int __rtnl_link_register(struct rtnl_link_ops *ops);
+26 −0
Original line number Diff line number Diff line
@@ -247,8 +247,34 @@ enum {
enum {
	BRIDGE_XSTATS_UNSPEC,
	BRIDGE_XSTATS_VLAN,
	BRIDGE_XSTATS_MCAST,
	BRIDGE_XSTATS_PAD,
	__BRIDGE_XSTATS_MAX
};
#define BRIDGE_XSTATS_MAX (__BRIDGE_XSTATS_MAX - 1)

enum {
	BR_MCAST_DIR_RX,
	BR_MCAST_DIR_TX,
	BR_MCAST_DIR_SIZE
};

/* IGMP/MLD statistics */
struct br_mcast_stats {
	__u64 igmp_queries[BR_MCAST_DIR_SIZE];
	__u64 igmp_leaves[BR_MCAST_DIR_SIZE];
	__u64 igmp_v1reports[BR_MCAST_DIR_SIZE];
	__u64 igmp_v2reports[BR_MCAST_DIR_SIZE];
	__u64 igmp_v3reports[BR_MCAST_DIR_SIZE];
	__u64 igmp_parse_errors;

	__u64 mld_queries[BR_MCAST_DIR_SIZE];
	__u64 mld_leaves[BR_MCAST_DIR_SIZE];
	__u64 mld_v1reports[BR_MCAST_DIR_SIZE];
	__u64 mld_v2reports[BR_MCAST_DIR_SIZE];
	__u64 mld_parse_errors;

	__u64 mcast_bytes[BR_MCAST_DIR_SIZE];
	__u64 mcast_packets[BR_MCAST_DIR_SIZE];
};
#endif /* _UAPI_LINUX_IF_BRIDGE_H */
+2 −0
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ enum {
	IFLA_BR_VLAN_DEFAULT_PVID,
	IFLA_BR_PAD,
	IFLA_BR_VLAN_STATS_ENABLED,
	IFLA_BR_MCAST_STATS_ENABLED,
	__IFLA_BR_MAX,
};

@@ -822,6 +823,7 @@ enum {
	IFLA_STATS_UNSPEC, /* also used as 64bit pad attribute */
	IFLA_STATS_LINK_64,
	IFLA_STATS_LINK_XSTATS,
	IFLA_STATS_LINK_XSTATS_SLAVE,
	__IFLA_STATS_MAX,
};

+9 −1
Original line number Diff line number Diff line
@@ -104,8 +104,16 @@ static int br_dev_init(struct net_device *dev)
		return -ENOMEM;

	err = br_vlan_init(br);
	if (err)
	if (err) {
		free_percpu(br->stats);
		return err;
	}

	err = br_multicast_init_stats(br);
	if (err) {
		free_percpu(br->stats);
		br_vlan_flush(br);
	}
	br_set_lockdep_class(dev);

	return err;
+12 −1
Original line number Diff line number Diff line
@@ -198,8 +198,10 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb,
					   struct sk_buff *skb),
		     bool unicast)
{
	struct net_bridge_port *p;
	u8 igmp_type = br_multicast_igmp_type(skb);
	__be16 proto = skb->protocol;
	struct net_bridge_port *prev;
	struct net_bridge_port *p;

	prev = NULL;

@@ -218,6 +220,9 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb,
		prev = maybe_deliver(prev, p, skb, __packet_hook);
		if (IS_ERR(prev))
			goto out;
		if (prev == p)
			br_multicast_count(p->br, p, proto, igmp_type,
					   BR_MCAST_DIR_TX);
	}

	if (!prev)
@@ -257,9 +262,12 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
					struct sk_buff *skb))
{
	struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
	u8 igmp_type = br_multicast_igmp_type(skb);
	struct net_bridge *br = netdev_priv(dev);
	struct net_bridge_port *prev = NULL;
	struct net_bridge_port_group *p;
	__be16 proto = skb->protocol;

	struct hlist_node *rp;

	rp = rcu_dereference(hlist_first_rcu(&br->router_list));
@@ -277,6 +285,9 @@ static void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
		prev = maybe_deliver(prev, port, skb, __packet_hook);
		if (IS_ERR(prev))
			goto out;
		if (prev == port)
			br_multicast_count(port->br, port, proto, igmp_type,
					   BR_MCAST_DIR_TX);

		if ((unsigned long)lport >= (unsigned long)port)
			p = rcu_dereference(p->next);
Loading