diff options
Diffstat (limited to 'drivers/net/dummy.c')
-rw-r--r-- | drivers/net/dummy.c | 82 |
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 | ||
38 | static int numdummies = 1; | 40 | static int numdummies = 1; |
39 | 41 | ||
40 | static int dummy_xmit(struct sk_buff *skb, struct net_device *dev); | 42 | static int dummy_xmit(struct sk_buff *skb, struct net_device *dev); |
41 | static struct net_device_stats *dummy_get_stats(struct net_device *dev); | ||
42 | 43 | ||
43 | static int dummy_set_address(struct net_device *dev, void *p) | 44 | static 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 | ||
59 | static void __init dummy_setup(struct net_device *dev) | 60 | static 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 | ||
77 | static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) | 78 | static 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 | ||
88 | static struct net_device_stats *dummy_get_stats(struct net_device *dev) | 87 | static 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 | ||
93 | static struct net_device **dummies; | 98 | static 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. */ |
96 | module_param(numdummies, int, 0); | 105 | module_param(numdummies, int, 0); |
97 | MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices"); | 106 | MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices"); |
98 | 107 | ||
99 | static int __init dummy_init_one(int index) | 108 | static 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 | ||
120 | static void dummy_free_one(int index) | 127 | err: |
121 | { | 128 | free_netdev(dev_dummy); |
122 | unregister_netdev(dummies[index]); | 129 | return err; |
123 | free_netdev(dummies[index]); | ||
124 | } | 130 | } |
125 | 131 | ||
126 | static int __init dummy_init_module(void) | 132 | static 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 | ||
142 | static void __exit dummy_cleanup_module(void) | 148 | static 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 | ||
150 | module_init(dummy_init_module); | 153 | module_init(dummy_init_module); |
151 | module_exit(dummy_cleanup_module); | 154 | module_exit(dummy_cleanup_module); |
152 | MODULE_LICENSE("GPL"); | 155 | MODULE_LICENSE("GPL"); |
156 | MODULE_ALIAS_RTNL_LINK("dummy"); | ||