Skip to content

Commit

Permalink
Merge branch 'bridge-igmp-stats'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 30, 2016
2 parents 545c321 + 1080ab9 commit 641f7e4
Show file tree
Hide file tree
Showing 12 changed files with 497 additions and 52 deletions.
5 changes: 3 additions & 2 deletions include/net/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
26 changes: 26 additions & 0 deletions include/uapi/linux/if_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 2 additions & 0 deletions include/uapi/linux/if_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -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,
};

Expand Down
10 changes: 9 additions & 1 deletion net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 12 additions & 1 deletion net/bridge/br_forward.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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));
Expand All @@ -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);
Expand Down
9 changes: 7 additions & 2 deletions net/bridge/br_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ static int find_portno(struct net_bridge *br)
static struct net_bridge_port *new_nbp(struct net_bridge *br,
struct net_device *dev)
{
int index;
struct net_bridge_port *p;
int index, err;

index = find_portno(br);
if (index < 0)
Expand All @@ -366,7 +366,12 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
br_init_port(p);
br_set_state(p, BR_STATE_DISABLED);
br_stp_port_timer_init(p);
br_multicast_add_port(p);
err = br_multicast_add_port(p);
if (err) {
dev_put(dev);
kfree(p);
p = ERR_PTR(err);
}

return p;
}
Expand Down
3 changes: 3 additions & 0 deletions net/bridge/br_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ static int br_pass_frame_up(struct sk_buff *skb)
skb = br_handle_vlan(br, vg, skb);
if (!skb)
return NET_RX_DROP;
/* update the multicast stats if the packet is IGMP/MLD */
br_multicast_count(br, NULL, skb->protocol, br_multicast_igmp_type(skb),
BR_MCAST_DIR_TX);

return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
dev_net(indev), NULL, skb, indev, NULL,
Expand Down
Loading

0 comments on commit 641f7e4

Please sign in to comment.