diff options
Diffstat (limited to 'drivers/net/veth.c')
| -rw-r--r-- | drivers/net/veth.c | 69 | 
1 files changed, 35 insertions, 34 deletions
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 8461576fa01..7f78db7bd68 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -12,6 +12,7 @@  #include <linux/slab.h>  #include <linux/ethtool.h>  #include <linux/etherdevice.h> +#include <linux/u64_stats_sync.h>  #include <net/dst.h>  #include <net/xfrm.h> @@ -24,12 +25,12 @@  #define MAX_MTU 65535		/* Max L3 MTU (arbitrary) */  struct veth_net_stats { -	unsigned long	rx_packets; -	unsigned long	tx_packets; -	unsigned long	rx_bytes; -	unsigned long	tx_bytes; -	unsigned long	tx_dropped; -	unsigned long	rx_dropped; +	u64			rx_packets; +	u64			tx_packets; +	u64			rx_bytes; +	u64			tx_bytes; +	u64			rx_dropped; +	struct u64_stats_sync	syncp;  };  struct veth_priv { @@ -124,9 +125,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)  	stats = this_cpu_ptr(priv->stats);  	rcv_stats = this_cpu_ptr(rcv_priv->stats); -	if (!(rcv->flags & IFF_UP)) -		goto tx_drop; -  	/* don't change ip_summed == CHECKSUM_PARTIAL, as that  	   will cause bad checksum on forwarded packets */  	if (skb->ip_summed == CHECKSUM_NONE && @@ -137,21 +135,22 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)  	if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)  		goto rx_drop; +	u64_stats_update_begin(&stats->syncp);  	stats->tx_bytes += length;  	stats->tx_packets++; +	u64_stats_update_end(&stats->syncp); +	u64_stats_update_begin(&rcv_stats->syncp);  	rcv_stats->rx_bytes += length;  	rcv_stats->rx_packets++; +	u64_stats_update_end(&rcv_stats->syncp);  	return NETDEV_TX_OK; -tx_drop: -	kfree_skb(skb); -	stats->tx_dropped++; -	return NETDEV_TX_OK; -  rx_drop: +	u64_stats_update_begin(&rcv_stats->syncp);  	rcv_stats->rx_dropped++; +	u64_stats_update_end(&rcv_stats->syncp);  	return NETDEV_TX_OK;  } @@ -159,32 +158,34 @@ rx_drop:   * general routines   */ -static struct net_device_stats *veth_get_stats(struct net_device *dev) +static struct rtnl_link_stats64 *veth_get_stats64(struct net_device *dev, +						  struct rtnl_link_stats64 *tot)  { -	struct veth_priv *priv; +	struct veth_priv *priv = netdev_priv(dev);  	int cpu; -	struct veth_net_stats *stats, total = {0}; - -	priv = netdev_priv(dev);  	for_each_possible_cpu(cpu) { -		stats = per_cpu_ptr(priv->stats, cpu); +		struct veth_net_stats *stats = per_cpu_ptr(priv->stats, cpu); +		u64 rx_packets, rx_bytes, rx_dropped; +		u64 tx_packets, tx_bytes; +		unsigned int start; -		total.rx_packets += stats->rx_packets; -		total.tx_packets += stats->tx_packets; -		total.rx_bytes   += stats->rx_bytes; -		total.tx_bytes   += stats->tx_bytes; -		total.tx_dropped += stats->tx_dropped; -		total.rx_dropped += stats->rx_dropped; +		do { +			start = u64_stats_fetch_begin_bh(&stats->syncp); +			rx_packets = stats->rx_packets; +			tx_packets = stats->tx_packets; +			rx_bytes = stats->rx_bytes; +			tx_bytes = stats->tx_bytes; +			rx_dropped = stats->rx_dropped; +		} while (u64_stats_fetch_retry_bh(&stats->syncp, start)); +		tot->rx_packets += rx_packets; +		tot->tx_packets += tx_packets; +		tot->rx_bytes   += rx_bytes; +		tot->tx_bytes   += tx_bytes; +		tot->rx_dropped += rx_dropped;  	} -	dev->stats.rx_packets = total.rx_packets; -	dev->stats.tx_packets = total.tx_packets; -	dev->stats.rx_bytes   = total.rx_bytes; -	dev->stats.tx_bytes   = total.tx_bytes; -	dev->stats.tx_dropped = total.tx_dropped; -	dev->stats.rx_dropped = total.rx_dropped; -	return &dev->stats; +	return tot;  }  static int veth_open(struct net_device *dev) @@ -254,7 +255,7 @@ static const struct net_device_ops veth_netdev_ops = {  	.ndo_stop            = veth_close,  	.ndo_start_xmit      = veth_xmit,  	.ndo_change_mtu      = veth_change_mtu, -	.ndo_get_stats       = veth_get_stats, +	.ndo_get_stats64     = veth_get_stats64,  	.ndo_set_mac_address = eth_mac_addr,  };  |