Blame view
net/8021q/vlan.c
15.8 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 |
/* * INET 802.1Q VLAN * Ethernet-type device handling. * * Authors: Ben Greear <greearb@candelatech.com> |
ad712087f [VLAN]: Update li... |
6 |
* Please send support related email to: netdev@vger.kernel.org |
1da177e4c Linux-2.6.12-rc2 |
7 |
* VLAN Home Page: http://www.candelatech.com/~greear/vlan.html |
122952fc2 [NET] 8021Q: Fix ... |
8 |
* |
1da177e4c Linux-2.6.12-rc2 |
9 10 11 12 13 14 15 16 17 18 19 |
* Fixes: * Fix for packet capture - Nick Eggleston <nick@dccinc.com>; * Add HW acceleration hooks - David S. Miller <davem@redhat.com>; * Correct all the locking - David S. Miller <davem@redhat.com>; * Use hash table for VLAN groups - David S. Miller <davem@redhat.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ |
afab2d299 net: 8021q: Add p... |
20 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
4fc268d24 [PATCH] capable/c... |
21 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 |
#include <linux/module.h> #include <linux/netdevice.h> #include <linux/skbuff.h> |
5a0e3ad6a include cleanup: ... |
25 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
26 |
#include <linux/init.h> |
82524746c rcu: split list.h... |
27 |
#include <linux/rculist.h> |
1da177e4c Linux-2.6.12-rc2 |
28 29 30 31 |
#include <net/p8022.h> #include <net/arp.h> #include <linux/rtnetlink.h> #include <linux/notifier.h> |
61362766d vlan: remove unne... |
32 |
#include <net/rtnetlink.h> |
e9dc86534 [NET]: Make devic... |
33 |
#include <net/net_namespace.h> |
d9ed0f0e2 [VLAN]: Introduce... |
34 |
#include <net/netns/generic.h> |
61362766d vlan: remove unne... |
35 |
#include <asm/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
36 37 38 39 40 41 42 43 |
#include <linux/if_vlan.h> #include "vlan.h" #include "vlanproc.h" #define DRV_VERSION "1.8" /* Global VLAN variables */ |
f99189b18 netns: net_identi... |
44 |
int vlan_net_id __read_mostly; |
d9ed0f0e2 [VLAN]: Introduce... |
45 |
|
b30200616 vlan: propogate e... |
46 47 |
const char vlan_fullname[] = "802.1Q VLAN Support"; const char vlan_version[] = DRV_VERSION; |
1da177e4c Linux-2.6.12-rc2 |
48 |
|
1da177e4c Linux-2.6.12-rc2 |
49 |
/* End of global variables definitions. */ |
9bb8582ef vlan: TCI related... |
50 |
static int vlan_group_prealloc_vid(struct vlan_group *vg, u16 vlan_id) |
67727184f [VLAN]: Reduce me... |
51 52 53 54 55 |
{ struct net_device **array; unsigned int size; ASSERT_RTNL(); |
9bb8582ef vlan: TCI related... |
56 |
array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; |
67727184f [VLAN]: Reduce me... |
57 58 59 60 61 62 63 |
if (array != NULL) return 0; size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN; array = kzalloc(size, GFP_KERNEL); if (array == NULL) return -ENOBUFS; |
9bb8582ef vlan: TCI related... |
64 |
vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN] = array; |
67727184f [VLAN]: Reduce me... |
65 |
return 0; |
42429aaee [VLAN]: Move vlan... |
66 |
} |
23289a37e net: add a list_h... |
67 |
void unregister_vlan_dev(struct net_device *dev, struct list_head *head) |
1da177e4c Linux-2.6.12-rc2 |
68 |
{ |
7da82c06d vlan: rename vlan... |
69 |
struct vlan_dev_priv *vlan = vlan_dev_priv(dev); |
af3015170 [VLAN]: Simplify ... |
70 |
struct net_device *real_dev = vlan->real_dev; |
5b9ea6e02 vlan: introduce v... |
71 |
struct vlan_info *vlan_info; |
1da177e4c Linux-2.6.12-rc2 |
72 |
struct vlan_group *grp; |
9bb8582ef vlan: TCI related... |
73 |
u16 vlan_id = vlan->vlan_id; |
1da177e4c Linux-2.6.12-rc2 |
74 75 |
ASSERT_RTNL(); |
acc5efbcd [VLAN]: Clean up ... |
76 |
|
5b9ea6e02 vlan: introduce v... |
77 78 79 80 |
vlan_info = rtnl_dereference(real_dev->vlan_info); BUG_ON(!vlan_info); grp = &vlan_info->grp; |
acc5efbcd [VLAN]: Clean up ... |
81 |
|
acc5efbcd [VLAN]: Clean up ... |
82 |
/* Take it out of our own structures, but be sure to interlock with |
ad1afb003 vlan_dev: VLAN 0 ... |
83 84 |
* HW accelerating devices or SW vlan input packet processing if * VLAN is not 0 (leave it there for 802.1p). |
acc5efbcd [VLAN]: Clean up ... |
85 |
*/ |
87002b03b net: introduce vl... |
86 87 |
if (vlan_id) vlan_vid_del(real_dev, vlan_id); |
1da177e4c Linux-2.6.12-rc2 |
88 |
|
5b9ea6e02 vlan: introduce v... |
89 |
grp->nr_vlan_devs--; |
acc5efbcd [VLAN]: Clean up ... |
90 |
|
55aee10de vlan: fix GVRP at... |
91 92 |
if (vlan->flags & VLAN_FLAG_GVRP) vlan_gvrp_request_leave(dev); |
29906f6a4 vlan: cleanup mul... |
93 |
vlan_group_set_device(grp, vlan_id, NULL); |
48752e1b1 vlan: remove one ... |
94 95 96 97 |
/* Because unregister_netdevice_queue() makes sure at least one rcu * grace period is respected before device freeing, * we dont need to call synchronize_net() here. */ |
23289a37e net: add a list_h... |
98 |
unregister_netdevice_queue(dev, head); |
ce305002e vlan: Move device... |
99 |
|
5b9ea6e02 vlan: introduce v... |
100 |
if (grp->nr_vlan_devs == 0) |
70c03b49b vlan: Add GVRP su... |
101 |
vlan_gvrp_uninit_applicant(real_dev); |
af3015170 [VLAN]: Simplify ... |
102 103 |
/* Get rid of the vlan's reference to real_dev */ dev_put(real_dev); |
1da177e4c Linux-2.6.12-rc2 |
104 |
} |
9bb8582ef vlan: TCI related... |
105 |
int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id) |
1da177e4c Linux-2.6.12-rc2 |
106 |
{ |
656299f70 vlan: convert to ... |
107 108 |
const char *name = real_dev->name; const struct net_device_ops *ops = real_dev->netdev_ops; |
40f98e1af [VLAN]: Clean up ... |
109 |
|
1da177e4c Linux-2.6.12-rc2 |
110 |
if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { |
afab2d299 net: 8021q: Add p... |
111 112 |
pr_info("VLANs not supported on %s ", name); |
c1d3ee992 [VLAN]: Split up ... |
113 |
return -EOPNOTSUPP; |
1da177e4c Linux-2.6.12-rc2 |
114 |
} |
1da177e4c Linux-2.6.12-rc2 |
115 |
if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && |
656299f70 vlan: convert to ... |
116 |
(!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) { |
afab2d299 net: 8021q: Add p... |
117 118 |
pr_info("Device %s has buggy VLAN hw accel ", name); |
c1d3ee992 [VLAN]: Split up ... |
119 |
return -EOPNOTSUPP; |
1da177e4c Linux-2.6.12-rc2 |
120 |
} |
65ac6a5fa vlan: Avoid hash ... |
121 |
if (vlan_find_dev(real_dev, vlan_id) != NULL) |
c1d3ee992 [VLAN]: Split up ... |
122 |
return -EEXIST; |
1da177e4c Linux-2.6.12-rc2 |
123 |
|
c1d3ee992 [VLAN]: Split up ... |
124 125 |
return 0; } |
07b5b17e1 [VLAN]: Use rtnl_... |
126 |
int register_vlan_dev(struct net_device *dev) |
e89fe42cd [VLAN]: Move devi... |
127 |
{ |
7da82c06d vlan: rename vlan... |
128 |
struct vlan_dev_priv *vlan = vlan_dev_priv(dev); |
e89fe42cd [VLAN]: Move devi... |
129 |
struct net_device *real_dev = vlan->real_dev; |
9bb8582ef vlan: TCI related... |
130 |
u16 vlan_id = vlan->vlan_id; |
5b9ea6e02 vlan: introduce v... |
131 132 |
struct vlan_info *vlan_info; struct vlan_group *grp; |
e89fe42cd [VLAN]: Move devi... |
133 |
int err; |
5b9ea6e02 vlan: introduce v... |
134 135 136 137 138 139 140 141 142 143 |
err = vlan_vid_add(real_dev, vlan_id); if (err) return err; vlan_info = rtnl_dereference(real_dev->vlan_info); /* vlan_info should be there now. vlan_vid_add took care of it */ BUG_ON(!vlan_info); grp = &vlan_info->grp; if (grp->nr_vlan_devs == 0) { |
70c03b49b vlan: Add GVRP su... |
144 145 |
err = vlan_gvrp_init_applicant(real_dev); if (err < 0) |
5b9ea6e02 vlan: introduce v... |
146 |
goto out_vid_del; |
e89fe42cd [VLAN]: Move devi... |
147 |
} |
67727184f [VLAN]: Reduce me... |
148 149 |
err = vlan_group_prealloc_vid(grp, vlan_id); if (err < 0) |
70c03b49b vlan: Add GVRP su... |
150 |
goto out_uninit_applicant; |
67727184f [VLAN]: Reduce me... |
151 |
|
e89fe42cd [VLAN]: Move devi... |
152 153 |
err = register_netdevice(dev); if (err < 0) |
70c03b49b vlan: Add GVRP su... |
154 |
goto out_uninit_applicant; |
e89fe42cd [VLAN]: Move devi... |
155 |
|
7da82c06d vlan: rename vlan... |
156 |
/* Account for reference in struct vlan_dev_priv */ |
e89fe42cd [VLAN]: Move devi... |
157 |
dev_hold(real_dev); |
fc4a74896 netdevice: provid... |
158 |
netif_stacked_transfer_operstate(real_dev, dev); |
e89fe42cd [VLAN]: Move devi... |
159 160 161 162 163 164 |
linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ /* So, got the sucker initialized, now lets place * it into our local structure. */ vlan_group_set_device(grp, vlan_id, dev); |
5b9ea6e02 vlan: introduce v... |
165 |
grp->nr_vlan_devs++; |
e89fe42cd [VLAN]: Move devi... |
166 |
|
e89fe42cd [VLAN]: Move devi... |
167 |
return 0; |
70c03b49b vlan: Add GVRP su... |
168 |
out_uninit_applicant: |
5b9ea6e02 vlan: introduce v... |
169 |
if (grp->nr_vlan_devs == 0) |
70c03b49b vlan: Add GVRP su... |
170 |
vlan_gvrp_uninit_applicant(real_dev); |
5b9ea6e02 vlan: introduce v... |
171 172 |
out_vid_del: vlan_vid_del(real_dev, vlan_id); |
e89fe42cd [VLAN]: Move devi... |
173 174 |
return err; } |
c1d3ee992 [VLAN]: Split up ... |
175 |
/* Attach a VLAN device to a mac address (ie Ethernet Card). |
2ae0bf69b [VLAN]: Return pr... |
176 |
* Returns 0 if the device was created or a negative error code otherwise. |
c1d3ee992 [VLAN]: Split up ... |
177 |
*/ |
9bb8582ef vlan: TCI related... |
178 |
static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) |
c1d3ee992 [VLAN]: Split up ... |
179 |
{ |
c1d3ee992 [VLAN]: Split up ... |
180 |
struct net_device *new_dev; |
7a17a2f79 [VLAN]: Make the ... |
181 182 |
struct net *net = dev_net(real_dev); struct vlan_net *vn = net_generic(net, vlan_net_id); |
c1d3ee992 [VLAN]: Split up ... |
183 |
char name[IFNAMSIZ]; |
2ae0bf69b [VLAN]: Return pr... |
184 |
int err; |
c1d3ee992 [VLAN]: Split up ... |
185 |
|
9bb8582ef vlan: TCI related... |
186 |
if (vlan_id >= VLAN_VID_MASK) |
2ae0bf69b [VLAN]: Return pr... |
187 |
return -ERANGE; |
c1d3ee992 [VLAN]: Split up ... |
188 |
|
9bb8582ef vlan: TCI related... |
189 |
err = vlan_check_real_dev(real_dev, vlan_id); |
2ae0bf69b [VLAN]: Return pr... |
190 191 |
if (err < 0) return err; |
c1d3ee992 [VLAN]: Split up ... |
192 |
|
1da177e4c Linux-2.6.12-rc2 |
193 |
/* Gotta set up the fields for the device. */ |
7a17a2f79 [VLAN]: Make the ... |
194 |
switch (vn->name_type) { |
1da177e4c Linux-2.6.12-rc2 |
195 196 |
case VLAN_NAME_TYPE_RAW_PLUS_VID: /* name will look like: eth1.0005 */ |
9bb8582ef vlan: TCI related... |
197 |
snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id); |
1da177e4c Linux-2.6.12-rc2 |
198 199 200 201 202 |
break; case VLAN_NAME_TYPE_PLUS_VID_NO_PAD: /* Put our vlan.VID in the name. * Name will look like: vlan5 */ |
9bb8582ef vlan: TCI related... |
203 |
snprintf(name, IFNAMSIZ, "vlan%i", vlan_id); |
1da177e4c Linux-2.6.12-rc2 |
204 205 206 207 208 |
break; case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD: /* Put our vlan.VID in the name. * Name will look like: eth0.5 */ |
9bb8582ef vlan: TCI related... |
209 |
snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id); |
1da177e4c Linux-2.6.12-rc2 |
210 211 212 213 214 215 |
break; case VLAN_NAME_TYPE_PLUS_VID: /* Put our vlan.VID in the name. * Name will look like: vlan0005 */ default: |
9bb8582ef vlan: TCI related... |
216 |
snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id); |
3ff50b799 [NET]: cleanup ex... |
217 |
} |
122952fc2 [NET] 8021Q: Fix ... |
218 |
|
7da82c06d vlan: rename vlan... |
219 |
new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name, vlan_setup); |
5dd8d1e9e [PATCH] lockdep: ... |
220 |
|
1da177e4c Linux-2.6.12-rc2 |
221 |
if (new_dev == NULL) |
2ae0bf69b [VLAN]: Return pr... |
222 |
return -ENOBUFS; |
1da177e4c Linux-2.6.12-rc2 |
223 |
|
65d292a2e [VLAN]: Allow vla... |
224 |
dev_net_set(new_dev, net); |
1da177e4c Linux-2.6.12-rc2 |
225 226 227 228 |
/* need 4 bytes for extra VLAN header info, * hope the underlying device can handle it. */ new_dev->mtu = real_dev->mtu; |
7da82c06d vlan: rename vlan... |
229 230 231 232 |
vlan_dev_priv(new_dev)->vlan_id = vlan_id; vlan_dev_priv(new_dev)->real_dev = real_dev; vlan_dev_priv(new_dev)->dent = NULL; vlan_dev_priv(new_dev)->flags = VLAN_FLAG_REORDER_HDR; |
1da177e4c Linux-2.6.12-rc2 |
233 |
|
07b5b17e1 [VLAN]: Use rtnl_... |
234 |
new_dev->rtnl_link_ops = &vlan_link_ops; |
2ae0bf69b [VLAN]: Return pr... |
235 236 |
err = register_vlan_dev(new_dev); if (err < 0) |
e89fe42cd [VLAN]: Move devi... |
237 |
goto out_free_newdev; |
1da177e4c Linux-2.6.12-rc2 |
238 |
|
2ae0bf69b [VLAN]: Return pr... |
239 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
240 |
|
1da177e4c Linux-2.6.12-rc2 |
241 242 |
out_free_newdev: free_netdev(new_dev); |
2ae0bf69b [VLAN]: Return pr... |
243 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
244 |
} |
8c979c26a [VLAN]: Fix MAC a... |
245 246 247 |
static void vlan_sync_address(struct net_device *dev, struct net_device *vlandev) { |
7da82c06d vlan: rename vlan... |
248 |
struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); |
8c979c26a [VLAN]: Fix MAC a... |
249 250 251 252 253 254 255 256 257 |
/* May be called without an actual change */ if (!compare_ether_addr(vlan->real_dev_addr, dev->dev_addr)) return; /* vlan address was different from the old address and is equal to * the new address */ if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && !compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) |
a748ee242 net: move address... |
258 |
dev_uc_del(dev, vlandev->dev_addr); |
8c979c26a [VLAN]: Fix MAC a... |
259 260 261 262 263 |
/* vlan address was equal to the old address and is different from * the new address */ if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) && compare_ether_addr(vlandev->dev_addr, dev->dev_addr)) |
a748ee242 net: move address... |
264 |
dev_uc_add(dev, vlandev->dev_addr); |
8c979c26a [VLAN]: Fix MAC a... |
265 266 267 |
memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); } |
5fb135705 [VLAN]: Propagate... |
268 269 270 |
static void vlan_transfer_features(struct net_device *dev, struct net_device *vlandev) { |
1ae4be22f vlan: vlan device... |
271 |
vlandev->gso_max_size = dev->gso_max_size; |
029f5fc31 8021q: set hard_h... |
272 273 274 275 276 |
if (dev->features & NETIF_F_HW_VLAN_TX) vlandev->hard_header_len = dev->hard_header_len; else vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN; |
b85daa532 vlan: adds fcoe o... |
277 278 279 |
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid; #endif |
8a0427bb6 vlan: convert VLA... |
280 281 |
netdev_update_features(vlandev); |
5fb135705 [VLAN]: Propagate... |
282 |
} |
802fb176d [VLAN]: Proc entr... |
283 284 285 286 287 288 |
static void __vlan_device_event(struct net_device *dev, unsigned long event) { switch (event) { case NETDEV_CHANGENAME: vlan_proc_rem_dev(dev); if (vlan_proc_add_dev(dev) < 0) |
afab2d299 net: 8021q: Add p... |
289 290 291 |
pr_warn("failed to change proc name for %s ", dev->name); |
802fb176d [VLAN]: Proc entr... |
292 |
break; |
30688a9a3 [VLAN]: Handle vl... |
293 294 |
case NETDEV_REGISTER: if (vlan_proc_add_dev(dev) < 0) |
afab2d299 net: 8021q: Add p... |
295 296 |
pr_warn("failed to add proc entry for %s ", dev->name); |
30688a9a3 [VLAN]: Handle vl... |
297 298 299 300 |
break; case NETDEV_UNREGISTER: vlan_proc_rem_dev(dev); break; |
802fb176d [VLAN]: Proc entr... |
301 302 |
} } |
2029cc2c8 [VLAN]: checkpatc... |
303 304 |
static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) |
1da177e4c Linux-2.6.12-rc2 |
305 306 |
{ struct net_device *dev = ptr; |
802fb176d [VLAN]: Proc entr... |
307 |
struct vlan_group *grp; |
5b9ea6e02 vlan: introduce v... |
308 |
struct vlan_info *vlan_info; |
1da177e4c Linux-2.6.12-rc2 |
309 310 |
int i, flgs; struct net_device *vlandev; |
7da82c06d vlan: rename vlan... |
311 |
struct vlan_dev_priv *vlan; |
29906f6a4 vlan: cleanup mul... |
312 |
LIST_HEAD(list); |
1da177e4c Linux-2.6.12-rc2 |
313 |
|
81d85346b vlan: Correctly h... |
314 |
if (is_vlan_dev(dev)) |
802fb176d [VLAN]: Proc entr... |
315 |
__vlan_device_event(dev, event); |
802fb176d [VLAN]: Proc entr... |
316 |
|
ad1afb003 vlan_dev: VLAN 0 ... |
317 |
if ((event == NETDEV_UP) && |
87002b03b net: introduce vl... |
318 |
(dev->features & NETIF_F_HW_VLAN_FILTER)) { |
afab2d299 net: 8021q: Add p... |
319 320 |
pr_info("adding VLAN 0 to HW filter on device %s ", |
ad1afb003 vlan_dev: VLAN 0 ... |
321 |
dev->name); |
87002b03b net: introduce vl... |
322 |
vlan_vid_add(dev, 0); |
ad1afb003 vlan_dev: VLAN 0 ... |
323 |
} |
5b9ea6e02 vlan: introduce v... |
324 325 |
vlan_info = rtnl_dereference(dev->vlan_info); if (!vlan_info) |
1da177e4c Linux-2.6.12-rc2 |
326 |
goto out; |
5b9ea6e02 vlan: introduce v... |
327 |
grp = &vlan_info->grp; |
1da177e4c Linux-2.6.12-rc2 |
328 329 330 331 332 333 334 335 |
/* It is OK that we do not hold the group lock right now, * as we run under the RTNL lock. */ switch (event) { case NETDEV_CHANGE: /* Propagate real device state to vlan devices */ |
b738127df vlan: Rename VLAN... |
336 |
for (i = 0; i < VLAN_N_VID; i++) { |
5c15bdec5 [VLAN]: Avoid a 4... |
337 |
vlandev = vlan_group_get_device(grp, i); |
1da177e4c Linux-2.6.12-rc2 |
338 339 |
if (!vlandev) continue; |
fc4a74896 netdevice: provid... |
340 |
netif_stacked_transfer_operstate(dev, vlandev); |
1da177e4c Linux-2.6.12-rc2 |
341 342 |
} break; |
8c979c26a [VLAN]: Fix MAC a... |
343 344 |
case NETDEV_CHANGEADDR: /* Adjust unicast filters on underlying device */ |
b738127df vlan: Rename VLAN... |
345 |
for (i = 0; i < VLAN_N_VID; i++) { |
8c979c26a [VLAN]: Fix MAC a... |
346 347 348 |
vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; |
d932e04a5 [VLAN]: Don't syn... |
349 350 351 |
flgs = vlandev->flags; if (!(flgs & IFF_UP)) continue; |
8c979c26a [VLAN]: Fix MAC a... |
352 353 |
vlan_sync_address(dev, vlandev); } |
2e477c9bd vlan: Propagate p... |
354 355 356 |
break; case NETDEV_CHANGEMTU: |
b738127df vlan: Rename VLAN... |
357 |
for (i = 0; i < VLAN_N_VID; i++) { |
2e477c9bd vlan: Propagate p... |
358 359 360 361 362 363 364 365 366 |
vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; if (vlandev->mtu <= dev->mtu) continue; dev_set_mtu(vlandev, dev->mtu); } |
8c979c26a [VLAN]: Fix MAC a... |
367 |
break; |
5fb135705 [VLAN]: Propagate... |
368 369 |
case NETDEV_FEAT_CHANGE: /* Propagate device features to underlying device */ |
b738127df vlan: Rename VLAN... |
370 |
for (i = 0; i < VLAN_N_VID; i++) { |
5fb135705 [VLAN]: Propagate... |
371 372 373 374 375 376 377 378 |
vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; vlan_transfer_features(dev, vlandev); } break; |
1da177e4c Linux-2.6.12-rc2 |
379 380 |
case NETDEV_DOWN: /* Put all VLANs for this dev in the down state too. */ |
b738127df vlan: Rename VLAN... |
381 |
for (i = 0; i < VLAN_N_VID; i++) { |
5c15bdec5 [VLAN]: Avoid a 4... |
382 |
vlandev = vlan_group_get_device(grp, i); |
1da177e4c Linux-2.6.12-rc2 |
383 384 385 386 387 388 |
if (!vlandev) continue; flgs = vlandev->flags; if (!(flgs & IFF_UP)) continue; |
7da82c06d vlan: rename vlan... |
389 |
vlan = vlan_dev_priv(vlandev); |
5e7565930 vlan: support "lo... |
390 391 |
if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) dev_change_flags(vlandev, flgs & ~IFF_UP); |
fc4a74896 netdevice: provid... |
392 |
netif_stacked_transfer_operstate(dev, vlandev); |
1da177e4c Linux-2.6.12-rc2 |
393 394 395 396 397 |
} break; case NETDEV_UP: /* Put all VLANs for this dev in the up state too. */ |
b738127df vlan: Rename VLAN... |
398 |
for (i = 0; i < VLAN_N_VID; i++) { |
5c15bdec5 [VLAN]: Avoid a 4... |
399 |
vlandev = vlan_group_get_device(grp, i); |
1da177e4c Linux-2.6.12-rc2 |
400 401 |
if (!vlandev) continue; |
122952fc2 [NET] 8021Q: Fix ... |
402 |
|
1da177e4c Linux-2.6.12-rc2 |
403 404 405 |
flgs = vlandev->flags; if (flgs & IFF_UP) continue; |
7da82c06d vlan: rename vlan... |
406 |
vlan = vlan_dev_priv(vlandev); |
5e7565930 vlan: support "lo... |
407 408 |
if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) dev_change_flags(vlandev, flgs | IFF_UP); |
fc4a74896 netdevice: provid... |
409 |
netif_stacked_transfer_operstate(dev, vlandev); |
1da177e4c Linux-2.6.12-rc2 |
410 411 |
} break; |
122952fc2 [NET] 8021Q: Fix ... |
412 |
|
1da177e4c Linux-2.6.12-rc2 |
413 |
case NETDEV_UNREGISTER: |
3b27e1055 netns: keep vlan ... |
414 415 416 |
/* twiddle thumbs on netns device moves */ if (dev->reg_state != NETREG_UNREGISTERING) break; |
b738127df vlan: Rename VLAN... |
417 |
for (i = 0; i < VLAN_N_VID; i++) { |
29906f6a4 vlan: cleanup mul... |
418 419 420 |
vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; |
5b9ea6e02 vlan: introduce v... |
421 |
/* removal of last vid destroys vlan_info, abort |
29906f6a4 vlan: cleanup mul... |
422 |
* afterwards */ |
5b9ea6e02 vlan: introduce v... |
423 |
if (vlan_info->nr_vids == 1) |
b738127df vlan: Rename VLAN... |
424 |
i = VLAN_N_VID; |
29906f6a4 vlan: cleanup mul... |
425 426 427 428 |
unregister_vlan_dev(vlandev, &list); } unregister_netdevice_many(&list); |
1da177e4c Linux-2.6.12-rc2 |
429 |
break; |
1c01fe14a net: forbid under... |
430 431 432 433 |
case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ return NOTIFY_BAD; |
99606477a vlan: Propagate N... |
434 435 |
case NETDEV_NOTIFY_PEERS: |
7c8994323 bonding, ipv4, ip... |
436 |
case NETDEV_BONDING_FAILOVER: |
99606477a vlan: Propagate N... |
437 438 439 440 441 |
/* Propagate to vlan devices */ for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; |
7c8994323 bonding, ipv4, ip... |
442 |
call_netdevice_notifiers(event, vlandev); |
99606477a vlan: Propagate N... |
443 444 |
} break; |
3ff50b799 [NET]: cleanup ex... |
445 |
} |
1da177e4c Linux-2.6.12-rc2 |
446 447 448 449 |
out: return NOTIFY_DONE; } |
69ab4b7d6 [VLAN]: Clean up ... |
450 451 452 |
static struct notifier_block vlan_notifier_block __read_mostly = { .notifier_call = vlan_device_event, }; |
1da177e4c Linux-2.6.12-rc2 |
453 454 455 456 457 |
/* * VLAN IOCTL handler. * o execute requested action or pass command to the device driver * arg is really a struct vlan_ioctl_args __user *. */ |
881d966b4 [NET]: Make the d... |
458 |
static int vlan_ioctl_handler(struct net *net, void __user *arg) |
1da177e4c Linux-2.6.12-rc2 |
459 |
{ |
c17d8874f [VLAN]: Convert n... |
460 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
461 |
struct vlan_ioctl_args args; |
c17d8874f [VLAN]: Convert n... |
462 |
struct net_device *dev = NULL; |
1da177e4c Linux-2.6.12-rc2 |
463 464 465 466 467 468 469 |
if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args))) return -EFAULT; /* Null terminate this sucker, just in case. */ args.device1[23] = 0; args.u.device2[23] = 0; |
c17d8874f [VLAN]: Convert n... |
470 |
rtnl_lock(); |
1da177e4c Linux-2.6.12-rc2 |
471 472 |
switch (args.cmd) { case SET_VLAN_INGRESS_PRIORITY_CMD: |
c17d8874f [VLAN]: Convert n... |
473 474 475 476 477 478 479 |
case SET_VLAN_EGRESS_PRIORITY_CMD: case SET_VLAN_FLAG_CMD: case ADD_VLAN_CMD: case DEL_VLAN_CMD: case GET_VLAN_REALDEV_NAME_CMD: case GET_VLAN_VID_CMD: err = -ENODEV; |
65d292a2e [VLAN]: Allow vla... |
480 |
dev = __dev_get_by_name(net, args.device1); |
c17d8874f [VLAN]: Convert n... |
481 482 483 484 |
if (!dev) goto out; err = -EINVAL; |
26a25239d vlan: Use is_vlan... |
485 |
if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev)) |
c17d8874f [VLAN]: Convert n... |
486 487 488 489 490 491 |
goto out; } switch (args.cmd) { case SET_VLAN_INGRESS_PRIORITY_CMD: err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
492 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
493 494 495 496 |
break; vlan_dev_set_ingress_priority(dev, args.u.skb_priority, args.vlan_qos); |
fffe470a8 [VLAN]: Fix SET_V... |
497 |
err = 0; |
1da177e4c Linux-2.6.12-rc2 |
498 499 500 |
break; case SET_VLAN_EGRESS_PRIORITY_CMD: |
c17d8874f [VLAN]: Convert n... |
501 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
502 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
503 504 |
break; err = vlan_dev_set_egress_priority(dev, |
1da177e4c Linux-2.6.12-rc2 |
505 506 507 508 509 |
args.u.skb_priority, args.vlan_qos); break; case SET_VLAN_FLAG_CMD: |
c17d8874f [VLAN]: Convert n... |
510 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
511 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
512 |
break; |
b3ce0325f vlan: Change vlan... |
513 514 515 |
err = vlan_dev_change_flags(dev, args.vlan_qos ? args.u.flag : 0, args.u.flag); |
1da177e4c Linux-2.6.12-rc2 |
516 517 518 |
break; case SET_VLAN_NAME_TYPE_CMD: |
c17d8874f [VLAN]: Convert n... |
519 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
520 |
if (!capable(CAP_NET_ADMIN)) |
e35de0261 [VLAN]: Lost rtnl... |
521 |
break; |
c17d8874f [VLAN]: Convert n... |
522 523 |
if ((args.u.name_type >= 0) && (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { |
7a17a2f79 [VLAN]: Make the ... |
524 525 526 527 |
struct vlan_net *vn; vn = net_generic(net, vlan_net_id); vn->name_type = args.u.name_type; |
1da177e4c Linux-2.6.12-rc2 |
528 529 530 531 532 533 534 |
err = 0; } else { err = -EINVAL; } break; case ADD_VLAN_CMD: |
c17d8874f [VLAN]: Convert n... |
535 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
536 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
537 |
break; |
2ae0bf69b [VLAN]: Return pr... |
538 |
err = register_vlan_device(dev, args.u.VID); |
1da177e4c Linux-2.6.12-rc2 |
539 540 541 |
break; case DEL_VLAN_CMD: |
c17d8874f [VLAN]: Convert n... |
542 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
543 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
544 |
break; |
23289a37e net: add a list_h... |
545 |
unregister_vlan_dev(dev, NULL); |
af3015170 [VLAN]: Simplify ... |
546 |
err = 0; |
1da177e4c Linux-2.6.12-rc2 |
547 |
break; |
1da177e4c Linux-2.6.12-rc2 |
548 |
case GET_VLAN_REALDEV_NAME_CMD: |
3f5f4346b [8021Q]: vlan_ioc... |
549 |
err = 0; |
c17d8874f [VLAN]: Convert n... |
550 |
vlan_dev_get_realdev_name(dev, args.u.device2); |
1da177e4c Linux-2.6.12-rc2 |
551 |
if (copy_to_user(arg, &args, |
2029cc2c8 [VLAN]: checkpatc... |
552 |
sizeof(struct vlan_ioctl_args))) |
1da177e4c Linux-2.6.12-rc2 |
553 |
err = -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
554 555 556 |
break; case GET_VLAN_VID_CMD: |
3f5f4346b [8021Q]: vlan_ioc... |
557 |
err = 0; |
22d1ba74b vlan: move struct... |
558 |
args.u.VID = vlan_dev_vlan_id(dev); |
1da177e4c Linux-2.6.12-rc2 |
559 |
if (copy_to_user(arg, &args, |
2029cc2c8 [VLAN]: checkpatc... |
560 |
sizeof(struct vlan_ioctl_args))) |
122952fc2 [NET] 8021Q: Fix ... |
561 |
err = -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
562 563 564 |
break; default: |
198a291ce [VLAN]: Remove no... |
565 |
err = -EOPNOTSUPP; |
c17d8874f [VLAN]: Convert n... |
566 |
break; |
3ff50b799 [NET]: cleanup ex... |
567 |
} |
7eb1b3d37 [VLAN]: Add two m... |
568 |
out: |
c17d8874f [VLAN]: Convert n... |
569 |
rtnl_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
570 571 |
return err; } |
2c8c1e729 net: spread __net... |
572 |
static int __net_init vlan_init_net(struct net *net) |
d9ed0f0e2 [VLAN]: Introduce... |
573 |
{ |
946d1a929 net: Simplify vla... |
574 |
struct vlan_net *vn = net_generic(net, vlan_net_id); |
d9ed0f0e2 [VLAN]: Introduce... |
575 |
int err; |
d9ed0f0e2 [VLAN]: Introduce... |
576 |
|
7a17a2f79 [VLAN]: Make the ... |
577 |
vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; |
cd1c70143 [VLAN]: Add a net... |
578 |
err = vlan_proc_init(net); |
cd1c70143 [VLAN]: Add a net... |
579 |
|
d9ed0f0e2 [VLAN]: Introduce... |
580 581 |
return err; } |
2c8c1e729 net: spread __net... |
582 |
static void __net_exit vlan_exit_net(struct net *net) |
d9ed0f0e2 [VLAN]: Introduce... |
583 |
{ |
cd1c70143 [VLAN]: Add a net... |
584 |
vlan_proc_cleanup(net); |
d9ed0f0e2 [VLAN]: Introduce... |
585 586 587 588 589 |
} static struct pernet_operations vlan_net_ops = { .init = vlan_init_net, .exit = vlan_exit_net, |
946d1a929 net: Simplify vla... |
590 591 |
.id = &vlan_net_id, .size = sizeof(struct vlan_net), |
d9ed0f0e2 [VLAN]: Introduce... |
592 |
}; |
69ab4b7d6 [VLAN]: Clean up ... |
593 594 595 |
static int __init vlan_proto_init(void) { int err; |
da7c06c4a net:8021q:vlan.c ... |
596 597 |
pr_info("%s v%s ", vlan_fullname, vlan_version); |
69ab4b7d6 [VLAN]: Clean up ... |
598 |
|
91e2ff352 net: Teach vlans ... |
599 |
err = register_pernet_subsys(&vlan_net_ops); |
d9ed0f0e2 [VLAN]: Introduce... |
600 601 |
if (err < 0) goto err0; |
69ab4b7d6 [VLAN]: Clean up ... |
602 603 604 |
err = register_netdevice_notifier(&vlan_notifier_block); if (err < 0) goto err2; |
70c03b49b vlan: Add GVRP su... |
605 |
err = vlan_gvrp_init(); |
69ab4b7d6 [VLAN]: Clean up ... |
606 607 |
if (err < 0) goto err3; |
70c03b49b vlan: Add GVRP su... |
608 609 610 |
err = vlan_netlink_init(); if (err < 0) goto err4; |
69ab4b7d6 [VLAN]: Clean up ... |
611 612 |
vlan_ioctl_set(vlan_ioctl_handler); return 0; |
70c03b49b vlan: Add GVRP su... |
613 614 |
err4: vlan_gvrp_uninit(); |
69ab4b7d6 [VLAN]: Clean up ... |
615 616 617 |
err3: unregister_netdevice_notifier(&vlan_notifier_block); err2: |
91e2ff352 net: Teach vlans ... |
618 |
unregister_pernet_subsys(&vlan_net_ops); |
d9ed0f0e2 [VLAN]: Introduce... |
619 |
err0: |
69ab4b7d6 [VLAN]: Clean up ... |
620 621 622 623 624 |
return err; } static void __exit vlan_cleanup_module(void) { |
69ab4b7d6 [VLAN]: Clean up ... |
625 626 627 628 |
vlan_ioctl_set(NULL); vlan_netlink_fini(); unregister_netdevice_notifier(&vlan_notifier_block); |
91e2ff352 net: Teach vlans ... |
629 |
unregister_pernet_subsys(&vlan_net_ops); |
6e327c11a 8021q: Vlan drive... |
630 |
rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
70c03b49b vlan: Add GVRP su... |
631 632 |
vlan_gvrp_uninit(); |
69ab4b7d6 [VLAN]: Clean up ... |
633 634 635 636 |
} module_init(vlan_proto_init); module_exit(vlan_cleanup_module); |
1da177e4c Linux-2.6.12-rc2 |
637 638 |
MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); |