1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include <linux/module.h>
32#include <linux/kernel.h>
33#include <linux/netdevice.h>
34#include <linux/etherdevice.h>
35#include <linux/init.h>
36#include <linux/moduleparam.h>
37#include <linux/rtnetlink.h>
38#include <net/rtnetlink.h>
39#include <linux/u64_stats_sync.h>
40
41static int numdummies = 1;
42
43
44static void set_multicast_list(struct net_device *dev)
45{
46}
47
48struct pcpu_dstats {
49 u64 tx_packets;
50 u64 tx_bytes;
51 struct u64_stats_sync syncp;
52};
53
54static struct rtnl_link_stats64 *dummy_get_stats64(struct net_device *dev,
55 struct rtnl_link_stats64 *stats)
56{
57 int i;
58
59 for_each_possible_cpu(i) {
60 const struct pcpu_dstats *dstats;
61 u64 tbytes, tpackets;
62 unsigned int start;
63
64 dstats = per_cpu_ptr(dev->dstats, i);
65 do {
66 start = u64_stats_fetch_begin_bh(&dstats->syncp);
67 tbytes = dstats->tx_bytes;
68 tpackets = dstats->tx_packets;
69 } while (u64_stats_fetch_retry_bh(&dstats->syncp, start));
70 stats->tx_bytes += tbytes;
71 stats->tx_packets += tpackets;
72 }
73 return stats;
74}
75
76static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
77{
78 struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
79
80 u64_stats_update_begin(&dstats->syncp);
81 dstats->tx_packets++;
82 dstats->tx_bytes += skb->len;
83 u64_stats_update_end(&dstats->syncp);
84
85 dev_kfree_skb(skb);
86 return NETDEV_TX_OK;
87}
88
89static int dummy_dev_init(struct net_device *dev)
90{
91 dev->dstats = alloc_percpu(struct pcpu_dstats);
92 if (!dev->dstats)
93 return -ENOMEM;
94
95 return 0;
96}
97
98static void dummy_dev_uninit(struct net_device *dev)
99{
100 free_percpu(dev->dstats);
101}
102
103static const struct net_device_ops dummy_netdev_ops = {
104 .ndo_init = dummy_dev_init,
105 .ndo_uninit = dummy_dev_uninit,
106 .ndo_start_xmit = dummy_xmit,
107 .ndo_validate_addr = eth_validate_addr,
108 .ndo_set_rx_mode = set_multicast_list,
109 .ndo_set_mac_address = eth_mac_addr,
110 .ndo_get_stats64 = dummy_get_stats64,
111};
112
113static void dummy_setup(struct net_device *dev)
114{
115 ether_setup(dev);
116
117
118 dev->netdev_ops = &dummy_netdev_ops;
119 dev->destructor = free_netdev;
120
121
122 dev->tx_queue_len = 0;
123 dev->flags |= IFF_NOARP;
124 dev->flags &= ~IFF_MULTICAST;
125 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
126 dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
127 dev->features |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
128 eth_hw_addr_random(dev);
129}
130
131static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
132{
133 if (tb[IFLA_ADDRESS]) {
134 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
135 return -EINVAL;
136 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
137 return -EADDRNOTAVAIL;
138 }
139 return 0;
140}
141
142static struct rtnl_link_ops dummy_link_ops __read_mostly = {
143 .kind = "dummy",
144 .setup = dummy_setup,
145 .validate = dummy_validate,
146};
147
148
149module_param(numdummies, int, 0);
150MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
151
152static int __init dummy_init_one(void)
153{
154 struct net_device *dev_dummy;
155 int err;
156
157 dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
158 if (!dev_dummy)
159 return -ENOMEM;
160
161 dev_dummy->rtnl_link_ops = &dummy_link_ops;
162 err = register_netdevice(dev_dummy);
163 if (err < 0)
164 goto err;
165 return 0;
166
167err:
168 free_netdev(dev_dummy);
169 return err;
170}
171
172static int __init dummy_init_module(void)
173{
174 int i, err = 0;
175
176 rtnl_lock();
177 err = __rtnl_link_register(&dummy_link_ops);
178
179 for (i = 0; i < numdummies && !err; i++) {
180 err = dummy_init_one();
181 cond_resched();
182 }
183 if (err < 0)
184 __rtnl_link_unregister(&dummy_link_ops);
185 rtnl_unlock();
186
187 return err;
188}
189
190static void __exit dummy_cleanup_module(void)
191{
192 rtnl_link_unregister(&dummy_link_ops);
193}
194
195module_init(dummy_init_module);
196module_exit(dummy_cleanup_module);
197MODULE_LICENSE("GPL");
198MODULE_ALIAS_RTNL_LINK("dummy");
199