*
* Version: @(#)loopback.c 1.0.4b 08/16/93
*
- * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
+ * Authors: Ross Biro
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@scyld.com>
*
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/ethtool.h>
#include <net/sock.h>
#include <net/checksum.h>
#include <linux/if_ether.h> /* For the statistics structure. */
#include <linux/if_arp.h> /* For ARPHRD_ETHER */
#include <linux/ip.h>
#include <linux/tcp.h>
+#include <linux/percpu.h>
+static DEFINE_PER_CPU(struct net_device_stats, loopback_stats);
#define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16)
*/
static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct net_device_stats *stats = dev->priv;
+ struct net_device_stats *lb_stats;
skb_orphan(skb);
}
dev->last_rx = jiffies;
- if (likely(stats)) {
- stats->rx_bytes+=skb->len;
- stats->tx_bytes+=skb->len;
- stats->rx_packets++;
- stats->tx_packets++;
- }
+
+ lb_stats = &per_cpu(loopback_stats, get_cpu());
+ lb_stats->rx_bytes += skb->len;
+ lb_stats->tx_bytes += skb->len;
+ lb_stats->rx_packets++;
+ lb_stats->tx_packets++;
+ put_cpu();
netif_rx(skb);
static struct net_device_stats *get_stats(struct net_device *dev)
{
- return (struct net_device_stats *)dev->priv;
+ struct net_device_stats *stats = dev->priv;
+ int i;
+
+ if (!stats) {
+ return NULL;
+ }
+
+ memset(stats, 0, sizeof(struct net_device_stats));
+
+ for (i=0; i < NR_CPUS; i++) {
+ struct net_device_stats *lb_stats;
+
+ if (!cpu_possible(i))
+ continue;
+ lb_stats = &per_cpu(loopback_stats, i);
+ stats->rx_bytes += lb_stats->rx_bytes;
+ stats->tx_bytes += lb_stats->tx_bytes;
+ stats->rx_packets += lb_stats->rx_packets;
+ stats->tx_packets += lb_stats->tx_packets;
+ }
+
+ return stats;
}
+static u32 loopback_get_link(struct net_device *dev)
+{
+ return 1;
+}
+
+static struct ethtool_ops loopback_ethtool_ops = {
+ .get_link = loopback_get_link,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
+};
+
struct net_device loopback_dev = {
.name = "lo",
.mtu = (16 * 1024) + 20 + 20 + 12,
.rebuild_header = eth_rebuild_header,
.flags = IFF_LOOPBACK,
.features = NETIF_F_SG|NETIF_F_FRAGLIST
- |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA,
+ |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA
+ |NETIF_F_LLTX,
+ .ethtool_ops = &loopback_ethtool_ops,
};
/* Setup and register the of the LOOPBACK device. */