Commit 406818ff authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

bridge: 64bit rx/tx counters

Use u64_stats_sync infrastructure to provide 64bit rx/tx
counters even on 32bit hosts.

It is safe to use a single u64_stats_sync for rx and tx,
because BH is disabled on both, and we use per_cpu data.
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 16b8a476
...@@ -38,8 +38,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -38,8 +38,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
} }
#endif #endif
u64_stats_update_begin(&brstats->syncp);
brstats->tx_packets++; brstats->tx_packets++;
brstats->tx_bytes += skb->len; brstats->tx_bytes += skb->len;
u64_stats_update_end(&brstats->syncp);
BR_INPUT_SKB_CB(skb)->brdev = dev; BR_INPUT_SKB_CB(skb)->brdev = dev;
...@@ -96,21 +98,25 @@ static int br_dev_stop(struct net_device *dev) ...@@ -96,21 +98,25 @@ static int br_dev_stop(struct net_device *dev)
return 0; return 0;
} }
static struct net_device_stats *br_get_stats(struct net_device *dev) static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev)
{ {
struct net_bridge *br = netdev_priv(dev); struct net_bridge *br = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats; struct rtnl_link_stats64 *stats = &dev->stats64;
struct br_cpu_netstats sum = { 0 }; struct br_cpu_netstats tmp, sum = { 0 };
unsigned int cpu; unsigned int cpu;
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
unsigned int start;
const struct br_cpu_netstats *bstats const struct br_cpu_netstats *bstats
= per_cpu_ptr(br->stats, cpu); = per_cpu_ptr(br->stats, cpu);
do {
sum.tx_bytes += bstats->tx_bytes; start = u64_stats_fetch_begin(&bstats->syncp);
sum.tx_packets += bstats->tx_packets; memcpy(&tmp, bstats, sizeof(tmp));
sum.rx_bytes += bstats->rx_bytes; } while (u64_stats_fetch_retry(&bstats->syncp, start));
sum.rx_packets += bstats->rx_packets; sum.tx_bytes += tmp.tx_bytes;
sum.tx_packets += tmp.tx_packets;
sum.rx_bytes += tmp.rx_bytes;
sum.rx_packets += tmp.rx_packets;
} }
stats->tx_bytes = sum.tx_bytes; stats->tx_bytes = sum.tx_bytes;
...@@ -300,7 +306,7 @@ static const struct net_device_ops br_netdev_ops = { ...@@ -300,7 +306,7 @@ static const struct net_device_ops br_netdev_ops = {
.ndo_open = br_dev_open, .ndo_open = br_dev_open,
.ndo_stop = br_dev_stop, .ndo_stop = br_dev_stop,
.ndo_start_xmit = br_dev_xmit, .ndo_start_xmit = br_dev_xmit,
.ndo_get_stats = br_get_stats, .ndo_get_stats64 = br_get_stats64,
.ndo_set_mac_address = br_set_mac_address, .ndo_set_mac_address = br_set_mac_address,
.ndo_set_multicast_list = br_dev_set_multicast_list, .ndo_set_multicast_list = br_dev_set_multicast_list,
.ndo_change_mtu = br_change_mtu, .ndo_change_mtu = br_change_mtu,
......
...@@ -27,8 +27,10 @@ static int br_pass_frame_up(struct sk_buff *skb) ...@@ -27,8 +27,10 @@ static int br_pass_frame_up(struct sk_buff *skb)
struct net_bridge *br = netdev_priv(brdev); struct net_bridge *br = netdev_priv(brdev);
struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
u64_stats_update_begin(&brstats->syncp);
brstats->rx_packets++; brstats->rx_packets++;
brstats->rx_bytes += skb->len; brstats->rx_bytes += skb->len;
u64_stats_update_end(&brstats->syncp);
indev = skb->dev; indev = skb->dev;
skb->dev = brdev; skb->dev = brdev;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/netpoll.h> #include <linux/netpoll.h>
#include <linux/u64_stats_sync.h>
#include <net/route.h> #include <net/route.h>
#define BR_HASH_BITS 8 #define BR_HASH_BITS 8
...@@ -156,10 +157,11 @@ struct net_bridge_port ...@@ -156,10 +157,11 @@ struct net_bridge_port
#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT) #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
struct br_cpu_netstats { struct br_cpu_netstats {
unsigned long rx_packets; u64 rx_packets;
unsigned long rx_bytes; u64 rx_bytes;
unsigned long tx_packets; u64 tx_packets;
unsigned long tx_bytes; u64 tx_bytes;
struct u64_stats_sync syncp;
}; };
struct net_bridge struct net_bridge
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment