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

Commit 7eebb0b2 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

loopback: packet drops accounting



We can in some situations drop packets in netif_rx()

loopback driver does not report these (unlikely) drops to its stats,
and incorrectly change packets/bytes counts.

After this patch applied, "ifconfig lo" can reports these drops as in :

# ifconfig lo
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:692562900 errors:3228 dropped:3228 overruns:0 frame:0
          TX packets:692562900 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2865674174 (2.6 GiB)  TX bytes:2865674174 (2.6 GiB)

I initialy chose to reflect those errors only in tx_dropped/tx_errors, but David
convinced me that it was really RX errors, as loopback_xmit() really starts
a RX process. (calling eth_type_trans() for example, that itself pulls the ethernet header)

These errors are accounted in rx_dropped/rx_errors.

Signed-off-by: default avatarEric Dumazet <dada1@cosmosbay.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eb62efd2
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@
struct pcpu_lstats {
	unsigned long packets;
	unsigned long bytes;
	unsigned long drops;
};

/*
@@ -71,6 +72,7 @@ struct pcpu_lstats {
static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct pcpu_lstats *pcpu_lstats, *lb_stats;
	int len;

	skb_orphan(skb);

@@ -79,10 +81,13 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
	/* it's OK to use per_cpu_ptr() because BHs are off */
	pcpu_lstats = dev->ml_priv;
	lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());
	lb_stats->bytes += skb->len;
	lb_stats->packets++;

	netif_rx(skb);
	len = skb->len;
	if (likely(netif_rx(skb) == NET_RX_SUCCESS)) {
		lb_stats->bytes += len;
		lb_stats->packets++;
	} else
		lb_stats->drops++;

	return 0;
}
@@ -93,6 +98,7 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev)
	struct net_device_stats *stats = &dev->stats;
	unsigned long bytes = 0;
	unsigned long packets = 0;
	unsigned long drops = 0;
	int i;

	pcpu_lstats = dev->ml_priv;
@@ -102,9 +108,12 @@ static struct net_device_stats *loopback_get_stats(struct net_device *dev)
		lb_stats = per_cpu_ptr(pcpu_lstats, i);
		bytes   += lb_stats->bytes;
		packets += lb_stats->packets;
		drops   += lb_stats->drops;
	}
	stats->rx_packets = packets;
	stats->tx_packets = packets;
	stats->rx_dropped = drops;
	stats->rx_errors  = drops;
	stats->rx_bytes   = bytes;
	stats->tx_bytes   = bytes;
	return stats;