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
40static int numdummies = 1;
41
42static int dummy_set_address(struct net_device *dev, void *p)
43{
44 struct sockaddr *sa = p;
45
46 if (!is_valid_ether_addr(sa->sa_data))
47 return -EADDRNOTAVAIL;
48
49 memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
50 return 0;
51}
52
53
54static void set_multicast_list(struct net_device *dev)
55{
56}
57
58
59static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
60{
61 dev->stats.tx_packets++;
62 dev->stats.tx_bytes += skb->len;
63
64 dev_kfree_skb(skb);
65 return NETDEV_TX_OK;
66}
67
68static const struct net_device_ops dummy_netdev_ops = {
69 .ndo_start_xmit = dummy_xmit,
70 .ndo_validate_addr = eth_validate_addr,
71 .ndo_set_multicast_list = set_multicast_list,
72 .ndo_set_mac_address = dummy_set_address,
73};
74
75static void dummy_setup(struct net_device *dev)
76{
77 ether_setup(dev);
78
79
80 dev->netdev_ops = &dummy_netdev_ops;
81 dev->destructor = free_netdev;
82
83
84 dev->tx_queue_len = 0;
85 dev->flags |= IFF_NOARP;
86 dev->flags &= ~IFF_MULTICAST;
87 random_ether_addr(dev->dev_addr);
88}
89static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
90{
91 if (tb[IFLA_ADDRESS]) {
92 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
93 return -EINVAL;
94 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
95 return -EADDRNOTAVAIL;
96 }
97 return 0;
98}
99
100static struct rtnl_link_ops dummy_link_ops __read_mostly = {
101 .kind = "dummy",
102 .setup = dummy_setup,
103 .validate = dummy_validate,
104};
105
106
107module_param(numdummies, int, 0);
108MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
109
110static int __init dummy_init_one(void)
111{
112 struct net_device *dev_dummy;
113 int err;
114
115 dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
116 if (!dev_dummy)
117 return -ENOMEM;
118
119 err = dev_alloc_name(dev_dummy, dev_dummy->name);
120 if (err < 0)
121 goto err;
122
123 dev_dummy->rtnl_link_ops = &dummy_link_ops;
124 err = register_netdevice(dev_dummy);
125 if (err < 0)
126 goto err;
127 return 0;
128
129err:
130 free_netdev(dev_dummy);
131 return err;
132}
133
134static int __init dummy_init_module(void)
135{
136 int i, err = 0;
137
138 rtnl_lock();
139 err = __rtnl_link_register(&dummy_link_ops);
140
141 for (i = 0; i < numdummies && !err; i++)
142 err = dummy_init_one();
143 if (err < 0)
144 __rtnl_link_unregister(&dummy_link_ops);
145 rtnl_unlock();
146
147 return err;
148}
149
150static void __exit dummy_cleanup_module(void)
151{
152 rtnl_link_unregister(&dummy_link_ops);
153}
154
155module_init(dummy_init_module);
156module_exit(dummy_cleanup_module);
157MODULE_LICENSE("GPL");
158MODULE_ALIAS_RTNL_LINK("dummy");
159