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 void 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_irq(&dstats->syncp);
67 tbytes = dstats->tx_bytes;
68 tpackets = dstats->tx_packets;
69 } while (u64_stats_fetch_retry_irq(&dstats->syncp, start));
70 stats->tx_bytes += tbytes;
71 stats->tx_packets += tpackets;
72 }
73}
74
75static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
76{
77 struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
78
79 u64_stats_update_begin(&dstats->syncp);
80 dstats->tx_packets++;
81 dstats->tx_bytes += skb->len;
82 u64_stats_update_end(&dstats->syncp);
83
84 dev_kfree_skb(skb);
85 return NETDEV_TX_OK;
86}
87
88static int dummy_dev_init(struct net_device *dev)
89{
90 dev->dstats = alloc_percpu(struct pcpu_dstats);
91 if (!dev->dstats)
92 return -ENOMEM;
93
94 return 0;
95}
96
97static void dummy_dev_uninit(struct net_device *dev)
98{
99 free_percpu(dev->dstats);
100}
101
102static int dummy_change_carrier(struct net_device *dev, bool new_carrier)
103{
104 if (new_carrier)
105 netif_carrier_on(dev);
106 else
107 netif_carrier_off(dev);
108 return 0;
109}
110
111static const struct net_device_ops dummy_netdev_ops = {
112 .ndo_init = dummy_dev_init,
113 .ndo_uninit = dummy_dev_uninit,
114 .ndo_start_xmit = dummy_xmit,
115 .ndo_validate_addr = eth_validate_addr,
116 .ndo_set_rx_mode = set_multicast_list,
117 .ndo_set_mac_address = eth_mac_addr,
118 .ndo_get_stats64 = dummy_get_stats64,
119 .ndo_change_carrier = dummy_change_carrier,
120};
121
122static void dummy_setup(struct net_device *dev)
123{
124 ether_setup(dev);
125
126
127 dev->netdev_ops = &dummy_netdev_ops;
128 dev->extended->needs_free_netdev = true;
129
130
131 dev->flags |= IFF_NOARP;
132 dev->flags &= ~IFF_MULTICAST;
133 dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
134 dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO;
135 dev->features |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
136 eth_hw_addr_random(dev);
137
138 dev->extended->min_mtu = 0;
139 dev->extended->max_mtu = 0;
140}
141
142static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
143{
144 if (tb[IFLA_ADDRESS]) {
145 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
146 return -EINVAL;
147 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
148 return -EADDRNOTAVAIL;
149 }
150 return 0;
151}
152
153static struct rtnl_link_ops dummy_link_ops __read_mostly = {
154 .kind = "dummy",
155 .setup = dummy_setup,
156 .validate = dummy_validate,
157};
158
159
160module_param(numdummies, int, 0);
161MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
162
163static int __init dummy_init_one(void)
164{
165 struct net_device *dev_dummy;
166 int err;
167
168 dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
169 if (!dev_dummy)
170 return -ENOMEM;
171
172 dev_dummy->rtnl_link_ops = &dummy_link_ops;
173 err = register_netdevice(dev_dummy);
174 if (err < 0)
175 goto err;
176 return 0;
177
178err:
179 free_netdev(dev_dummy);
180 return err;
181}
182
183static int __init dummy_init_module(void)
184{
185 int i, err = 0;
186
187 rtnl_lock();
188 err = __rtnl_link_register(&dummy_link_ops);
189 if (err < 0)
190 goto out;
191
192 for (i = 0; i < numdummies && !err; i++) {
193 err = dummy_init_one();
194 cond_resched();
195 }
196 if (err < 0)
197 __rtnl_link_unregister(&dummy_link_ops);
198
199out:
200 rtnl_unlock();
201
202 return err;
203}
204
205static void __exit dummy_cleanup_module(void)
206{
207 rtnl_link_unregister(&dummy_link_ops);
208}
209
210module_init(dummy_init_module);
211module_exit(dummy_cleanup_module);
212MODULE_LICENSE("GPL");
213MODULE_ALIAS_RTNL_LINK("dummy");
214