aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dummy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dummy.c')
-rw-r--r--drivers/net/dummy.c82
1 files changed, 43 insertions, 39 deletions
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 60673bc292c0..756a6bcb038d 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -34,11 +34,12 @@
34#include <linux/etherdevice.h> 34#include <linux/etherdevice.h>
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/moduleparam.h> 36#include <linux/moduleparam.h>
37#include <linux/rtnetlink.h>
38#include <net/rtnetlink.h>
37 39
38static int numdummies = 1; 40static int numdummies = 1;
39 41
40static int dummy_xmit(struct sk_buff *skb, struct net_device *dev); 42static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
41static struct net_device_stats *dummy_get_stats(struct net_device *dev);
42 43
43static int dummy_set_address(struct net_device *dev, void *p) 44static int dummy_set_address(struct net_device *dev, void *p)
44{ 45{
@@ -56,13 +57,13 @@ static void set_multicast_list(struct net_device *dev)
56{ 57{
57} 58}
58 59
59static void __init dummy_setup(struct net_device *dev) 60static void dummy_setup(struct net_device *dev)
60{ 61{
61 /* Initialize the device structure. */ 62 /* Initialize the device structure. */
62 dev->get_stats = dummy_get_stats;
63 dev->hard_start_xmit = dummy_xmit; 63 dev->hard_start_xmit = dummy_xmit;
64 dev->set_multicast_list = set_multicast_list; 64 dev->set_multicast_list = set_multicast_list;
65 dev->set_mac_address = dummy_set_address; 65 dev->set_mac_address = dummy_set_address;
66 dev->destructor = free_netdev;
66 67
67 /* Fill in device structure with ethernet-generic values. */ 68 /* Fill in device structure with ethernet-generic values. */
68 ether_setup(dev); 69 ether_setup(dev);
@@ -76,77 +77,80 @@ static void __init dummy_setup(struct net_device *dev)
76 77
77static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) 78static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
78{ 79{
79 struct net_device_stats *stats = netdev_priv(dev); 80 dev->stats.tx_packets++;
80 81 dev->stats.tx_bytes += skb->len;
81 stats->tx_packets++;
82 stats->tx_bytes+=skb->len;
83 82
84 dev_kfree_skb(skb); 83 dev_kfree_skb(skb);
85 return 0; 84 return 0;
86} 85}
87 86
88static struct net_device_stats *dummy_get_stats(struct net_device *dev) 87static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
89{ 88{
90 return netdev_priv(dev); 89 if (tb[IFLA_ADDRESS]) {
90 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
91 return -EINVAL;
92 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
93 return -EADDRNOTAVAIL;
94 }
95 return 0;
91} 96}
92 97
93static struct net_device **dummies; 98static struct rtnl_link_ops dummy_link_ops __read_mostly = {
99 .kind = "dummy",
100 .setup = dummy_setup,
101 .validate = dummy_validate,
102};
94 103
95/* Number of dummy devices to be set up by this module. */ 104/* Number of dummy devices to be set up by this module. */
96module_param(numdummies, int, 0); 105module_param(numdummies, int, 0);
97MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices"); 106MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
98 107
99static int __init dummy_init_one(int index) 108static int __init dummy_init_one(void)
100{ 109{
101 struct net_device *dev_dummy; 110 struct net_device *dev_dummy;
102 int err; 111 int err;
103 112
104 dev_dummy = alloc_netdev(sizeof(struct net_device_stats), 113 dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
105 "dummy%d", dummy_setup);
106
107 if (!dev_dummy) 114 if (!dev_dummy)
108 return -ENOMEM; 115 return -ENOMEM;
109 116
110 if ((err = register_netdev(dev_dummy))) { 117 err = dev_alloc_name(dev_dummy, dev_dummy->name);
111 free_netdev(dev_dummy); 118 if (err < 0)
112 dev_dummy = NULL; 119 goto err;
113 } else {
114 dummies[index] = dev_dummy;
115 }
116 120
117 return err; 121 dev_dummy->rtnl_link_ops = &dummy_link_ops;
118} 122 err = register_netdevice(dev_dummy);
123 if (err < 0)
124 goto err;
125 return 0;
119 126
120static void dummy_free_one(int index) 127err:
121{ 128 free_netdev(dev_dummy);
122 unregister_netdev(dummies[index]); 129 return err;
123 free_netdev(dummies[index]);
124} 130}
125 131
126static int __init dummy_init_module(void) 132static int __init dummy_init_module(void)
127{ 133{
128 int i, err = 0; 134 int i, err = 0;
129 dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL); 135
130 if (!dummies) 136 rtnl_lock();
131 return -ENOMEM; 137 err = __rtnl_link_register(&dummy_link_ops);
138
132 for (i = 0; i < numdummies && !err; i++) 139 for (i = 0; i < numdummies && !err; i++)
133 err = dummy_init_one(i); 140 err = dummy_init_one();
134 if (err) { 141 if (err < 0)
135 i--; 142 __rtnl_link_unregister(&dummy_link_ops);
136 while (--i >= 0) 143 rtnl_unlock();
137 dummy_free_one(i); 144
138 }
139 return err; 145 return err;
140} 146}
141 147
142static void __exit dummy_cleanup_module(void) 148static void __exit dummy_cleanup_module(void)
143{ 149{
144 int i; 150 rtnl_link_unregister(&dummy_link_ops);
145 for (i = 0; i < numdummies; i++)
146 dummy_free_one(i);
147 kfree(dummies);
148} 151}
149 152
150module_init(dummy_init_module); 153module_init(dummy_init_module);
151module_exit(dummy_cleanup_module); 154module_exit(dummy_cleanup_module);
152MODULE_LICENSE("GPL"); 155MODULE_LICENSE("GPL");
156MODULE_ALIAS_RTNL_LINK("dummy");