aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dummy.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-09-27 16:50:33 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-29 16:23:30 -0400
commit6d81f41c58c69ddde497e9e640ba5805aa26e78c (patch)
tree9e4cadd10af9f487fabb99a393f095d185160a13 /drivers/net/dummy.c
parent745e20f1b626b1be4b100af5d4bf7b3439392f8f (diff)
dummy: percpu stats and lockless xmit
Converts dummy network device driver to : - percpu stats - 64bit stats - lockless xmit (NETIF_F_LLTX) - performance features added (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA) Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dummy.c')
-rw-r--r--drivers/net/dummy.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 37dcfdc63456..ff2d29b17858 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -36,6 +36,7 @@
36#include <linux/moduleparam.h> 36#include <linux/moduleparam.h>
37#include <linux/rtnetlink.h> 37#include <linux/rtnetlink.h>
38#include <net/rtnetlink.h> 38#include <net/rtnetlink.h>
39#include <linux/u64_stats_sync.h>
39 40
40static int numdummies = 1; 41static int numdummies = 1;
41 42
@@ -55,21 +56,69 @@ static void set_multicast_list(struct net_device *dev)
55{ 56{
56} 57}
57 58
59struct pcpu_dstats {
60 u64 tx_packets;
61 u64 tx_bytes;
62 struct u64_stats_sync syncp;
63};
64
65static struct rtnl_link_stats64 *dummy_get_stats64(struct net_device *dev,
66 struct rtnl_link_stats64 *stats)
67{
68 int i;
69
70 for_each_possible_cpu(i) {
71 const struct pcpu_dstats *dstats;
72 u64 tbytes, tpackets;
73 unsigned int start;
74
75 dstats = per_cpu_ptr(dev->dstats, i);
76 do {
77 start = u64_stats_fetch_begin(&dstats->syncp);
78 tbytes = dstats->tx_bytes;
79 tpackets = dstats->tx_packets;
80 } while (u64_stats_fetch_retry(&dstats->syncp, start));
81 stats->tx_bytes += tbytes;
82 stats->tx_packets += tpackets;
83 }
84 return stats;
85}
58 86
59static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev) 87static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
60{ 88{
61 dev->stats.tx_packets++; 89 struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
62 dev->stats.tx_bytes += skb->len; 90
91 u64_stats_update_begin(&dstats->syncp);
92 dstats->tx_packets++;
93 dstats->tx_bytes += skb->len;
94 u64_stats_update_end(&dstats->syncp);
63 95
64 dev_kfree_skb(skb); 96 dev_kfree_skb(skb);
65 return NETDEV_TX_OK; 97 return NETDEV_TX_OK;
66} 98}
67 99
100static int dummy_dev_init(struct net_device *dev)
101{
102 dev->dstats = alloc_percpu(struct pcpu_dstats);
103 if (!dev->dstats)
104 return -ENOMEM;
105
106 return 0;
107}
108
109static void dummy_dev_free(struct net_device *dev)
110{
111 free_percpu(dev->dstats);
112 free_netdev(dev);
113}
114
68static const struct net_device_ops dummy_netdev_ops = { 115static const struct net_device_ops dummy_netdev_ops = {
116 .ndo_init = dummy_dev_init,
69 .ndo_start_xmit = dummy_xmit, 117 .ndo_start_xmit = dummy_xmit,
70 .ndo_validate_addr = eth_validate_addr, 118 .ndo_validate_addr = eth_validate_addr,
71 .ndo_set_multicast_list = set_multicast_list, 119 .ndo_set_multicast_list = set_multicast_list,
72 .ndo_set_mac_address = dummy_set_address, 120 .ndo_set_mac_address = dummy_set_address,
121 .ndo_get_stats64 = dummy_get_stats64,
73}; 122};
74 123
75static void dummy_setup(struct net_device *dev) 124static void dummy_setup(struct net_device *dev)
@@ -78,14 +127,17 @@ static void dummy_setup(struct net_device *dev)
78 127
79 /* Initialize the device structure. */ 128 /* Initialize the device structure. */
80 dev->netdev_ops = &dummy_netdev_ops; 129 dev->netdev_ops = &dummy_netdev_ops;
81 dev->destructor = free_netdev; 130 dev->destructor = dummy_dev_free;
82 131
83 /* Fill in device structure with ethernet-generic values. */ 132 /* Fill in device structure with ethernet-generic values. */
84 dev->tx_queue_len = 0; 133 dev->tx_queue_len = 0;
85 dev->flags |= IFF_NOARP; 134 dev->flags |= IFF_NOARP;
86 dev->flags &= ~IFF_MULTICAST; 135 dev->flags &= ~IFF_MULTICAST;
136 dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
137 dev->features |= NETIF_F_NO_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
87 random_ether_addr(dev->dev_addr); 138 random_ether_addr(dev->dev_addr);
88} 139}
140
89static int dummy_validate(struct nlattr *tb[], struct nlattr *data[]) 141static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
90{ 142{
91 if (tb[IFLA_ADDRESS]) { 143 if (tb[IFLA_ADDRESS]) {