Blame view
net/8021q/vlan.c
16.7 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. */ |
5c15bdec5 [VLAN]: Avoid a 4... |
50 51 52 |
static void vlan_group_free(struct vlan_group *grp) { int i; |
2029cc2c8 [VLAN]: checkpatc... |
53 |
for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) |
5c15bdec5 [VLAN]: Avoid a 4... |
54 55 56 |
kfree(grp->vlan_devices_arrays[i]); kfree(grp); } |
a9fde2607 [VLAN]: Tag vlan_... |
57 |
static struct vlan_group *vlan_group_alloc(struct net_device *real_dev) |
42429aaee [VLAN]: Move vlan... |
58 59 |
{ struct vlan_group *grp; |
42429aaee [VLAN]: Move vlan... |
60 61 62 63 |
grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); if (!grp) return NULL; |
a9fde2607 [VLAN]: Tag vlan_... |
64 |
grp->real_dev = real_dev; |
42429aaee [VLAN]: Move vlan... |
65 |
return grp; |
67727184f [VLAN]: Reduce me... |
66 |
} |
42429aaee [VLAN]: Move vlan... |
67 |
|
9bb8582ef vlan: TCI related... |
68 |
static int vlan_group_prealloc_vid(struct vlan_group *vg, u16 vlan_id) |
67727184f [VLAN]: Reduce me... |
69 70 71 72 73 |
{ struct net_device **array; unsigned int size; ASSERT_RTNL(); |
9bb8582ef vlan: TCI related... |
74 |
array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; |
67727184f [VLAN]: Reduce me... |
75 76 77 78 79 80 81 |
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... |
82 |
vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN] = array; |
67727184f [VLAN]: Reduce me... |
83 |
return 0; |
42429aaee [VLAN]: Move vlan... |
84 |
} |
1da177e4c Linux-2.6.12-rc2 |
85 86 |
static void vlan_rcu_free(struct rcu_head *rcu) { |
5c15bdec5 [VLAN]: Avoid a 4... |
87 |
vlan_group_free(container_of(rcu, struct vlan_group, rcu)); |
1da177e4c Linux-2.6.12-rc2 |
88 |
} |
23289a37e net: add a list_h... |
89 |
void unregister_vlan_dev(struct net_device *dev, struct list_head *head) |
1da177e4c Linux-2.6.12-rc2 |
90 |
{ |
9dfebcc64 [VLAN]: Turn VLAN... |
91 |
struct vlan_dev_info *vlan = vlan_dev_info(dev); |
af3015170 [VLAN]: Simplify ... |
92 |
struct net_device *real_dev = vlan->real_dev; |
656299f70 vlan: convert to ... |
93 |
const struct net_device_ops *ops = real_dev->netdev_ops; |
1da177e4c Linux-2.6.12-rc2 |
94 |
struct vlan_group *grp; |
9bb8582ef vlan: TCI related... |
95 |
u16 vlan_id = vlan->vlan_id; |
1da177e4c Linux-2.6.12-rc2 |
96 97 |
ASSERT_RTNL(); |
acc5efbcd [VLAN]: Clean up ... |
98 |
|
b616b09af vlan: rcu annotat... |
99 |
grp = rtnl_dereference(real_dev->vlgrp); |
af3015170 [VLAN]: Simplify ... |
100 |
BUG_ON(!grp); |
acc5efbcd [VLAN]: Clean up ... |
101 |
|
acc5efbcd [VLAN]: Clean up ... |
102 |
/* Take it out of our own structures, but be sure to interlock with |
ad1afb003 vlan_dev: VLAN 0 ... |
103 104 |
* HW accelerating devices or SW vlan input packet processing if * VLAN is not 0 (leave it there for 802.1p). |
acc5efbcd [VLAN]: Clean up ... |
105 |
*/ |
ad1afb003 vlan_dev: VLAN 0 ... |
106 |
if (vlan_id && (real_dev->features & NETIF_F_HW_VLAN_FILTER)) |
656299f70 vlan: convert to ... |
107 |
ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id); |
1da177e4c Linux-2.6.12-rc2 |
108 |
|
af3015170 [VLAN]: Simplify ... |
109 |
grp->nr_vlans--; |
acc5efbcd [VLAN]: Clean up ... |
110 |
|
55aee10de vlan: fix GVRP at... |
111 112 |
if (vlan->flags & VLAN_FLAG_GVRP) vlan_gvrp_request_leave(dev); |
29906f6a4 vlan: cleanup mul... |
113 |
vlan_group_set_device(grp, vlan_id, NULL); |
48752e1b1 vlan: remove one ... |
114 115 116 117 |
/* 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... |
118 |
unregister_netdevice_queue(dev, head); |
ce305002e vlan: Move device... |
119 |
|
acc5efbcd [VLAN]: Clean up ... |
120 |
/* If the group is now empty, kill off the group. */ |
af3015170 [VLAN]: Simplify ... |
121 |
if (grp->nr_vlans == 0) { |
70c03b49b vlan: Add GVRP su... |
122 |
vlan_gvrp_uninit_applicant(real_dev); |
a9b3cd7f3 rcu: convert uses... |
123 |
RCU_INIT_POINTER(real_dev->vlgrp, NULL); |
acc5efbcd [VLAN]: Clean up ... |
124 |
|
acc5efbcd [VLAN]: Clean up ... |
125 126 |
/* Free the group, after all cpu's are done. */ call_rcu(&grp->rcu, vlan_rcu_free); |
1da177e4c Linux-2.6.12-rc2 |
127 |
} |
af3015170 [VLAN]: Simplify ... |
128 129 |
/* Get rid of the vlan's reference to real_dev */ dev_put(real_dev); |
1da177e4c Linux-2.6.12-rc2 |
130 |
} |
9bb8582ef vlan: TCI related... |
131 |
int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id) |
1da177e4c Linux-2.6.12-rc2 |
132 |
{ |
656299f70 vlan: convert to ... |
133 134 |
const char *name = real_dev->name; const struct net_device_ops *ops = real_dev->netdev_ops; |
40f98e1af [VLAN]: Clean up ... |
135 |
|
1da177e4c Linux-2.6.12-rc2 |
136 |
if (real_dev->features & NETIF_F_VLAN_CHALLENGED) { |
afab2d299 net: 8021q: Add p... |
137 138 |
pr_info("VLANs not supported on %s ", name); |
c1d3ee992 [VLAN]: Split up ... |
139 |
return -EOPNOTSUPP; |
1da177e4c Linux-2.6.12-rc2 |
140 |
} |
1da177e4c Linux-2.6.12-rc2 |
141 |
if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) && |
656299f70 vlan: convert to ... |
142 |
(!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) { |
afab2d299 net: 8021q: Add p... |
143 144 |
pr_info("Device %s has buggy VLAN hw accel ", name); |
c1d3ee992 [VLAN]: Split up ... |
145 |
return -EOPNOTSUPP; |
1da177e4c Linux-2.6.12-rc2 |
146 |
} |
65ac6a5fa vlan: Avoid hash ... |
147 |
if (vlan_find_dev(real_dev, vlan_id) != NULL) |
c1d3ee992 [VLAN]: Split up ... |
148 |
return -EEXIST; |
1da177e4c Linux-2.6.12-rc2 |
149 |
|
c1d3ee992 [VLAN]: Split up ... |
150 151 |
return 0; } |
07b5b17e1 [VLAN]: Use rtnl_... |
152 |
int register_vlan_dev(struct net_device *dev) |
e89fe42cd [VLAN]: Move devi... |
153 |
{ |
9dfebcc64 [VLAN]: Turn VLAN... |
154 |
struct vlan_dev_info *vlan = vlan_dev_info(dev); |
e89fe42cd [VLAN]: Move devi... |
155 |
struct net_device *real_dev = vlan->real_dev; |
656299f70 vlan: convert to ... |
156 |
const struct net_device_ops *ops = real_dev->netdev_ops; |
9bb8582ef vlan: TCI related... |
157 |
u16 vlan_id = vlan->vlan_id; |
e89fe42cd [VLAN]: Move devi... |
158 159 |
struct vlan_group *grp, *ngrp = NULL; int err; |
b616b09af vlan: rcu annotat... |
160 |
grp = rtnl_dereference(real_dev->vlgrp); |
e89fe42cd [VLAN]: Move devi... |
161 |
if (!grp) { |
a9fde2607 [VLAN]: Tag vlan_... |
162 |
ngrp = grp = vlan_group_alloc(real_dev); |
e89fe42cd [VLAN]: Move devi... |
163 164 |
if (!grp) return -ENOBUFS; |
70c03b49b vlan: Add GVRP su... |
165 166 167 |
err = vlan_gvrp_init_applicant(real_dev); if (err < 0) goto out_free_group; |
e89fe42cd [VLAN]: Move devi... |
168 |
} |
67727184f [VLAN]: Reduce me... |
169 170 |
err = vlan_group_prealloc_vid(grp, vlan_id); if (err < 0) |
70c03b49b vlan: Add GVRP su... |
171 |
goto out_uninit_applicant; |
67727184f [VLAN]: Reduce me... |
172 |
|
e89fe42cd [VLAN]: Move devi... |
173 174 |
err = register_netdevice(dev); if (err < 0) |
70c03b49b vlan: Add GVRP su... |
175 |
goto out_uninit_applicant; |
e89fe42cd [VLAN]: Move devi... |
176 177 178 |
/* Account for reference in struct vlan_dev_info */ dev_hold(real_dev); |
fc4a74896 netdevice: provid... |
179 |
netif_stacked_transfer_operstate(real_dev, dev); |
e89fe42cd [VLAN]: Move devi... |
180 181 182 183 184 185 |
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); |
af3015170 [VLAN]: Simplify ... |
186 |
grp->nr_vlans++; |
65ac6a5fa vlan: Avoid hash ... |
187 |
if (ngrp) { |
65ac6a5fa vlan: Avoid hash ... |
188 189 |
rcu_assign_pointer(real_dev->vlgrp, ngrp); } |
e89fe42cd [VLAN]: Move devi... |
190 |
if (real_dev->features & NETIF_F_HW_VLAN_FILTER) |
656299f70 vlan: convert to ... |
191 |
ops->ndo_vlan_rx_add_vid(real_dev, vlan_id); |
e89fe42cd [VLAN]: Move devi... |
192 |
|
e89fe42cd [VLAN]: Move devi... |
193 |
return 0; |
70c03b49b vlan: Add GVRP su... |
194 195 196 |
out_uninit_applicant: if (ngrp) vlan_gvrp_uninit_applicant(real_dev); |
e89fe42cd [VLAN]: Move devi... |
197 |
out_free_group: |
6b863d1d3 vlan: Fix registe... |
198 |
if (ngrp) { |
6b863d1d3 vlan: Fix registe... |
199 200 201 |
/* Free the group, after all cpu's are done. */ call_rcu(&ngrp->rcu, vlan_rcu_free); } |
e89fe42cd [VLAN]: Move devi... |
202 203 |
return err; } |
c1d3ee992 [VLAN]: Split up ... |
204 |
/* Attach a VLAN device to a mac address (ie Ethernet Card). |
2ae0bf69b [VLAN]: Return pr... |
205 |
* Returns 0 if the device was created or a negative error code otherwise. |
c1d3ee992 [VLAN]: Split up ... |
206 |
*/ |
9bb8582ef vlan: TCI related... |
207 |
static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) |
c1d3ee992 [VLAN]: Split up ... |
208 |
{ |
c1d3ee992 [VLAN]: Split up ... |
209 |
struct net_device *new_dev; |
7a17a2f79 [VLAN]: Make the ... |
210 211 |
struct net *net = dev_net(real_dev); struct vlan_net *vn = net_generic(net, vlan_net_id); |
c1d3ee992 [VLAN]: Split up ... |
212 |
char name[IFNAMSIZ]; |
2ae0bf69b [VLAN]: Return pr... |
213 |
int err; |
c1d3ee992 [VLAN]: Split up ... |
214 |
|
9bb8582ef vlan: TCI related... |
215 |
if (vlan_id >= VLAN_VID_MASK) |
2ae0bf69b [VLAN]: Return pr... |
216 |
return -ERANGE; |
c1d3ee992 [VLAN]: Split up ... |
217 |
|
9bb8582ef vlan: TCI related... |
218 |
err = vlan_check_real_dev(real_dev, vlan_id); |
2ae0bf69b [VLAN]: Return pr... |
219 220 |
if (err < 0) return err; |
c1d3ee992 [VLAN]: Split up ... |
221 |
|
1da177e4c Linux-2.6.12-rc2 |
222 |
/* Gotta set up the fields for the device. */ |
7a17a2f79 [VLAN]: Make the ... |
223 |
switch (vn->name_type) { |
1da177e4c Linux-2.6.12-rc2 |
224 225 |
case VLAN_NAME_TYPE_RAW_PLUS_VID: /* name will look like: eth1.0005 */ |
9bb8582ef vlan: TCI related... |
226 |
snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id); |
1da177e4c Linux-2.6.12-rc2 |
227 228 229 230 231 |
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... |
232 |
snprintf(name, IFNAMSIZ, "vlan%i", vlan_id); |
1da177e4c Linux-2.6.12-rc2 |
233 234 235 236 237 |
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... |
238 |
snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id); |
1da177e4c Linux-2.6.12-rc2 |
239 240 241 242 243 244 |
break; case VLAN_NAME_TYPE_PLUS_VID: /* Put our vlan.VID in the name. * Name will look like: vlan0005 */ default: |
9bb8582ef vlan: TCI related... |
245 |
snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id); |
3ff50b799 [NET]: cleanup ex... |
246 |
} |
122952fc2 [NET] 8021Q: Fix ... |
247 |
|
4af429d29 vlan: lockless tr... |
248 |
new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name, vlan_setup); |
5dd8d1e9e [PATCH] lockdep: ... |
249 |
|
1da177e4c Linux-2.6.12-rc2 |
250 |
if (new_dev == NULL) |
2ae0bf69b [VLAN]: Return pr... |
251 |
return -ENOBUFS; |
1da177e4c Linux-2.6.12-rc2 |
252 |
|
65d292a2e [VLAN]: Allow vla... |
253 |
dev_net_set(new_dev, net); |
1da177e4c Linux-2.6.12-rc2 |
254 255 256 257 |
/* need 4 bytes for extra VLAN header info, * hope the underlying device can handle it. */ new_dev->mtu = real_dev->mtu; |
9bb8582ef vlan: TCI related... |
258 |
vlan_dev_info(new_dev)->vlan_id = vlan_id; |
9dfebcc64 [VLAN]: Turn VLAN... |
259 260 261 |
vlan_dev_info(new_dev)->real_dev = real_dev; vlan_dev_info(new_dev)->dent = NULL; vlan_dev_info(new_dev)->flags = VLAN_FLAG_REORDER_HDR; |
1da177e4c Linux-2.6.12-rc2 |
262 |
|
07b5b17e1 [VLAN]: Use rtnl_... |
263 |
new_dev->rtnl_link_ops = &vlan_link_ops; |
2ae0bf69b [VLAN]: Return pr... |
264 265 |
err = register_vlan_dev(new_dev); if (err < 0) |
e89fe42cd [VLAN]: Move devi... |
266 |
goto out_free_newdev; |
1da177e4c Linux-2.6.12-rc2 |
267 |
|
2ae0bf69b [VLAN]: Return pr... |
268 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
269 |
|
1da177e4c Linux-2.6.12-rc2 |
270 271 |
out_free_newdev: free_netdev(new_dev); |
2ae0bf69b [VLAN]: Return pr... |
272 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
273 |
} |
8c979c26a [VLAN]: Fix MAC a... |
274 275 276 |
static void vlan_sync_address(struct net_device *dev, struct net_device *vlandev) { |
9dfebcc64 [VLAN]: Turn VLAN... |
277 |
struct vlan_dev_info *vlan = vlan_dev_info(vlandev); |
8c979c26a [VLAN]: Fix MAC a... |
278 279 280 281 282 283 284 285 286 |
/* 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... |
287 |
dev_uc_del(dev, vlandev->dev_addr); |
8c979c26a [VLAN]: Fix MAC a... |
288 289 290 291 292 |
/* 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... |
293 |
dev_uc_add(dev, vlandev->dev_addr); |
8c979c26a [VLAN]: Fix MAC a... |
294 295 296 |
memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); } |
5fb135705 [VLAN]: Propagate... |
297 298 299 |
static void vlan_transfer_features(struct net_device *dev, struct net_device *vlandev) { |
1ae4be22f vlan: vlan device... |
300 |
vlandev->gso_max_size = dev->gso_max_size; |
029f5fc31 8021q: set hard_h... |
301 302 303 304 305 |
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... |
306 307 308 |
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid; #endif |
8a0427bb6 vlan: convert VLA... |
309 310 |
netdev_update_features(vlandev); |
5fb135705 [VLAN]: Propagate... |
311 |
} |
802fb176d [VLAN]: Proc entr... |
312 313 314 315 316 317 |
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... |
318 319 320 |
pr_warn("failed to change proc name for %s ", dev->name); |
802fb176d [VLAN]: Proc entr... |
321 |
break; |
30688a9a3 [VLAN]: Handle vl... |
322 323 |
case NETDEV_REGISTER: if (vlan_proc_add_dev(dev) < 0) |
afab2d299 net: 8021q: Add p... |
324 325 |
pr_warn("failed to add proc entry for %s ", dev->name); |
30688a9a3 [VLAN]: Handle vl... |
326 327 328 329 |
break; case NETDEV_UNREGISTER: vlan_proc_rem_dev(dev); break; |
802fb176d [VLAN]: Proc entr... |
330 331 |
} } |
2029cc2c8 [VLAN]: checkpatc... |
332 333 |
static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr) |
1da177e4c Linux-2.6.12-rc2 |
334 335 |
{ struct net_device *dev = ptr; |
802fb176d [VLAN]: Proc entr... |
336 |
struct vlan_group *grp; |
1da177e4c Linux-2.6.12-rc2 |
337 338 |
int i, flgs; struct net_device *vlandev; |
5e7565930 vlan: support "lo... |
339 |
struct vlan_dev_info *vlan; |
29906f6a4 vlan: cleanup mul... |
340 |
LIST_HEAD(list); |
1da177e4c Linux-2.6.12-rc2 |
341 |
|
81d85346b vlan: Correctly h... |
342 |
if (is_vlan_dev(dev)) |
802fb176d [VLAN]: Proc entr... |
343 |
__vlan_device_event(dev, event); |
802fb176d [VLAN]: Proc entr... |
344 |
|
ad1afb003 vlan_dev: VLAN 0 ... |
345 346 347 |
if ((event == NETDEV_UP) && (dev->features & NETIF_F_HW_VLAN_FILTER) && dev->netdev_ops->ndo_vlan_rx_add_vid) { |
afab2d299 net: 8021q: Add p... |
348 349 |
pr_info("adding VLAN 0 to HW filter on device %s ", |
ad1afb003 vlan_dev: VLAN 0 ... |
350 351 352 |
dev->name); dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0); } |
b616b09af vlan: rcu annotat... |
353 |
grp = rtnl_dereference(dev->vlgrp); |
1da177e4c Linux-2.6.12-rc2 |
354 355 356 357 358 359 360 361 362 363 |
if (!grp) goto out; /* 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... |
364 |
for (i = 0; i < VLAN_N_VID; i++) { |
5c15bdec5 [VLAN]: Avoid a 4... |
365 |
vlandev = vlan_group_get_device(grp, i); |
1da177e4c Linux-2.6.12-rc2 |
366 367 |
if (!vlandev) continue; |
fc4a74896 netdevice: provid... |
368 |
netif_stacked_transfer_operstate(dev, vlandev); |
1da177e4c Linux-2.6.12-rc2 |
369 370 |
} break; |
8c979c26a [VLAN]: Fix MAC a... |
371 372 |
case NETDEV_CHANGEADDR: /* Adjust unicast filters on underlying device */ |
b738127df vlan: Rename VLAN... |
373 |
for (i = 0; i < VLAN_N_VID; i++) { |
8c979c26a [VLAN]: Fix MAC a... |
374 375 376 |
vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; |
d932e04a5 [VLAN]: Don't syn... |
377 378 379 |
flgs = vlandev->flags; if (!(flgs & IFF_UP)) continue; |
8c979c26a [VLAN]: Fix MAC a... |
380 381 |
vlan_sync_address(dev, vlandev); } |
2e477c9bd vlan: Propagate p... |
382 383 384 |
break; case NETDEV_CHANGEMTU: |
b738127df vlan: Rename VLAN... |
385 |
for (i = 0; i < VLAN_N_VID; i++) { |
2e477c9bd vlan: Propagate p... |
386 387 388 389 390 391 392 393 394 |
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... |
395 |
break; |
5fb135705 [VLAN]: Propagate... |
396 397 |
case NETDEV_FEAT_CHANGE: /* Propagate device features to underlying device */ |
b738127df vlan: Rename VLAN... |
398 |
for (i = 0; i < VLAN_N_VID; i++) { |
5fb135705 [VLAN]: Propagate... |
399 400 401 402 403 404 405 406 |
vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; vlan_transfer_features(dev, vlandev); } break; |
1da177e4c Linux-2.6.12-rc2 |
407 408 |
case NETDEV_DOWN: /* Put all VLANs for this dev in the down state too. */ |
b738127df vlan: Rename VLAN... |
409 |
for (i = 0; i < VLAN_N_VID; i++) { |
5c15bdec5 [VLAN]: Avoid a 4... |
410 |
vlandev = vlan_group_get_device(grp, i); |
1da177e4c Linux-2.6.12-rc2 |
411 412 413 414 415 416 |
if (!vlandev) continue; flgs = vlandev->flags; if (!(flgs & IFF_UP)) continue; |
5e7565930 vlan: support "lo... |
417 418 419 |
vlan = vlan_dev_info(vlandev); if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) dev_change_flags(vlandev, flgs & ~IFF_UP); |
fc4a74896 netdevice: provid... |
420 |
netif_stacked_transfer_operstate(dev, vlandev); |
1da177e4c Linux-2.6.12-rc2 |
421 422 423 424 425 |
} break; case NETDEV_UP: /* Put all VLANs for this dev in the up state too. */ |
b738127df vlan: Rename VLAN... |
426 |
for (i = 0; i < VLAN_N_VID; i++) { |
5c15bdec5 [VLAN]: Avoid a 4... |
427 |
vlandev = vlan_group_get_device(grp, i); |
1da177e4c Linux-2.6.12-rc2 |
428 429 |
if (!vlandev) continue; |
122952fc2 [NET] 8021Q: Fix ... |
430 |
|
1da177e4c Linux-2.6.12-rc2 |
431 432 433 |
flgs = vlandev->flags; if (flgs & IFF_UP) continue; |
5e7565930 vlan: support "lo... |
434 435 436 |
vlan = vlan_dev_info(vlandev); if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) dev_change_flags(vlandev, flgs | IFF_UP); |
fc4a74896 netdevice: provid... |
437 |
netif_stacked_transfer_operstate(dev, vlandev); |
1da177e4c Linux-2.6.12-rc2 |
438 439 |
} break; |
122952fc2 [NET] 8021Q: Fix ... |
440 |
|
1da177e4c Linux-2.6.12-rc2 |
441 |
case NETDEV_UNREGISTER: |
3b27e1055 netns: keep vlan ... |
442 443 444 |
/* twiddle thumbs on netns device moves */ if (dev->reg_state != NETREG_UNREGISTERING) break; |
b738127df vlan: Rename VLAN... |
445 |
for (i = 0; i < VLAN_N_VID; i++) { |
29906f6a4 vlan: cleanup mul... |
446 447 448 449 450 451 452 |
vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; /* unregistration of last vlan destroys group, abort * afterwards */ if (grp->nr_vlans == 1) |
b738127df vlan: Rename VLAN... |
453 |
i = VLAN_N_VID; |
29906f6a4 vlan: cleanup mul... |
454 455 456 457 |
unregister_vlan_dev(vlandev, &list); } unregister_netdevice_many(&list); |
1da177e4c Linux-2.6.12-rc2 |
458 |
break; |
1c01fe14a net: forbid under... |
459 460 461 462 |
case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ return NOTIFY_BAD; |
99606477a vlan: Propagate N... |
463 464 |
case NETDEV_NOTIFY_PEERS: |
7c8994323 bonding, ipv4, ip... |
465 |
case NETDEV_BONDING_FAILOVER: |
99606477a vlan: Propagate N... |
466 467 468 469 470 |
/* 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... |
471 |
call_netdevice_notifiers(event, vlandev); |
99606477a vlan: Propagate N... |
472 473 |
} break; |
3ff50b799 [NET]: cleanup ex... |
474 |
} |
1da177e4c Linux-2.6.12-rc2 |
475 476 477 478 |
out: return NOTIFY_DONE; } |
69ab4b7d6 [VLAN]: Clean up ... |
479 480 481 |
static struct notifier_block vlan_notifier_block __read_mostly = { .notifier_call = vlan_device_event, }; |
1da177e4c Linux-2.6.12-rc2 |
482 483 484 485 486 |
/* * 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... |
487 |
static int vlan_ioctl_handler(struct net *net, void __user *arg) |
1da177e4c Linux-2.6.12-rc2 |
488 |
{ |
c17d8874f [VLAN]: Convert n... |
489 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
490 |
struct vlan_ioctl_args args; |
c17d8874f [VLAN]: Convert n... |
491 |
struct net_device *dev = NULL; |
1da177e4c Linux-2.6.12-rc2 |
492 493 494 495 496 497 498 |
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... |
499 |
rtnl_lock(); |
1da177e4c Linux-2.6.12-rc2 |
500 501 |
switch (args.cmd) { case SET_VLAN_INGRESS_PRIORITY_CMD: |
c17d8874f [VLAN]: Convert n... |
502 503 504 505 506 507 508 |
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... |
509 |
dev = __dev_get_by_name(net, args.device1); |
c17d8874f [VLAN]: Convert n... |
510 511 512 513 |
if (!dev) goto out; err = -EINVAL; |
26a25239d vlan: Use is_vlan... |
514 |
if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev)) |
c17d8874f [VLAN]: Convert n... |
515 516 517 518 519 520 |
goto out; } switch (args.cmd) { case SET_VLAN_INGRESS_PRIORITY_CMD: err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
521 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
522 523 524 525 |
break; vlan_dev_set_ingress_priority(dev, args.u.skb_priority, args.vlan_qos); |
fffe470a8 [VLAN]: Fix SET_V... |
526 |
err = 0; |
1da177e4c Linux-2.6.12-rc2 |
527 528 529 |
break; case SET_VLAN_EGRESS_PRIORITY_CMD: |
c17d8874f [VLAN]: Convert n... |
530 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
531 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
532 533 |
break; err = vlan_dev_set_egress_priority(dev, |
1da177e4c Linux-2.6.12-rc2 |
534 535 536 537 538 |
args.u.skb_priority, args.vlan_qos); break; case SET_VLAN_FLAG_CMD: |
c17d8874f [VLAN]: Convert n... |
539 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
540 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
541 |
break; |
b3ce0325f vlan: Change vlan... |
542 543 544 |
err = vlan_dev_change_flags(dev, args.vlan_qos ? args.u.flag : 0, args.u.flag); |
1da177e4c Linux-2.6.12-rc2 |
545 546 547 |
break; case SET_VLAN_NAME_TYPE_CMD: |
c17d8874f [VLAN]: Convert n... |
548 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
549 |
if (!capable(CAP_NET_ADMIN)) |
e35de0261 [VLAN]: Lost rtnl... |
550 |
break; |
c17d8874f [VLAN]: Convert n... |
551 552 |
if ((args.u.name_type >= 0) && (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { |
7a17a2f79 [VLAN]: Make the ... |
553 554 555 556 |
struct vlan_net *vn; vn = net_generic(net, vlan_net_id); vn->name_type = args.u.name_type; |
1da177e4c Linux-2.6.12-rc2 |
557 558 559 560 561 562 563 |
err = 0; } else { err = -EINVAL; } break; case ADD_VLAN_CMD: |
c17d8874f [VLAN]: Convert n... |
564 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
565 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
566 |
break; |
2ae0bf69b [VLAN]: Return pr... |
567 |
err = register_vlan_device(dev, args.u.VID); |
1da177e4c Linux-2.6.12-rc2 |
568 569 570 |
break; case DEL_VLAN_CMD: |
c17d8874f [VLAN]: Convert n... |
571 |
err = -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
572 |
if (!capable(CAP_NET_ADMIN)) |
c17d8874f [VLAN]: Convert n... |
573 |
break; |
23289a37e net: add a list_h... |
574 |
unregister_vlan_dev(dev, NULL); |
af3015170 [VLAN]: Simplify ... |
575 |
err = 0; |
1da177e4c Linux-2.6.12-rc2 |
576 |
break; |
1da177e4c Linux-2.6.12-rc2 |
577 |
case GET_VLAN_REALDEV_NAME_CMD: |
3f5f4346b [8021Q]: vlan_ioc... |
578 |
err = 0; |
c17d8874f [VLAN]: Convert n... |
579 |
vlan_dev_get_realdev_name(dev, args.u.device2); |
1da177e4c Linux-2.6.12-rc2 |
580 |
if (copy_to_user(arg, &args, |
2029cc2c8 [VLAN]: checkpatc... |
581 |
sizeof(struct vlan_ioctl_args))) |
1da177e4c Linux-2.6.12-rc2 |
582 |
err = -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
583 584 585 |
break; case GET_VLAN_VID_CMD: |
3f5f4346b [8021Q]: vlan_ioc... |
586 |
err = 0; |
22d1ba74b vlan: move struct... |
587 |
args.u.VID = vlan_dev_vlan_id(dev); |
1da177e4c Linux-2.6.12-rc2 |
588 |
if (copy_to_user(arg, &args, |
2029cc2c8 [VLAN]: checkpatc... |
589 |
sizeof(struct vlan_ioctl_args))) |
122952fc2 [NET] 8021Q: Fix ... |
590 |
err = -EFAULT; |
1da177e4c Linux-2.6.12-rc2 |
591 592 593 |
break; default: |
198a291ce [VLAN]: Remove no... |
594 |
err = -EOPNOTSUPP; |
c17d8874f [VLAN]: Convert n... |
595 |
break; |
3ff50b799 [NET]: cleanup ex... |
596 |
} |
7eb1b3d37 [VLAN]: Add two m... |
597 |
out: |
c17d8874f [VLAN]: Convert n... |
598 |
rtnl_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
599 600 |
return err; } |
2c8c1e729 net: spread __net... |
601 |
static int __net_init vlan_init_net(struct net *net) |
d9ed0f0e2 [VLAN]: Introduce... |
602 |
{ |
946d1a929 net: Simplify vla... |
603 |
struct vlan_net *vn = net_generic(net, vlan_net_id); |
d9ed0f0e2 [VLAN]: Introduce... |
604 |
int err; |
d9ed0f0e2 [VLAN]: Introduce... |
605 |
|
7a17a2f79 [VLAN]: Make the ... |
606 |
vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD; |
cd1c70143 [VLAN]: Add a net... |
607 |
err = vlan_proc_init(net); |
cd1c70143 [VLAN]: Add a net... |
608 |
|
d9ed0f0e2 [VLAN]: Introduce... |
609 610 |
return err; } |
2c8c1e729 net: spread __net... |
611 |
static void __net_exit vlan_exit_net(struct net *net) |
d9ed0f0e2 [VLAN]: Introduce... |
612 |
{ |
cd1c70143 [VLAN]: Add a net... |
613 |
vlan_proc_cleanup(net); |
d9ed0f0e2 [VLAN]: Introduce... |
614 615 616 617 618 |
} static struct pernet_operations vlan_net_ops = { .init = vlan_init_net, .exit = vlan_exit_net, |
946d1a929 net: Simplify vla... |
619 620 |
.id = &vlan_net_id, .size = sizeof(struct vlan_net), |
d9ed0f0e2 [VLAN]: Introduce... |
621 |
}; |
69ab4b7d6 [VLAN]: Clean up ... |
622 623 624 |
static int __init vlan_proto_init(void) { int err; |
da7c06c4a net:8021q:vlan.c ... |
625 626 |
pr_info("%s v%s ", vlan_fullname, vlan_version); |
69ab4b7d6 [VLAN]: Clean up ... |
627 |
|
91e2ff352 net: Teach vlans ... |
628 |
err = register_pernet_subsys(&vlan_net_ops); |
d9ed0f0e2 [VLAN]: Introduce... |
629 630 |
if (err < 0) goto err0; |
69ab4b7d6 [VLAN]: Clean up ... |
631 632 633 |
err = register_netdevice_notifier(&vlan_notifier_block); if (err < 0) goto err2; |
70c03b49b vlan: Add GVRP su... |
634 |
err = vlan_gvrp_init(); |
69ab4b7d6 [VLAN]: Clean up ... |
635 636 |
if (err < 0) goto err3; |
70c03b49b vlan: Add GVRP su... |
637 638 639 |
err = vlan_netlink_init(); if (err < 0) goto err4; |
69ab4b7d6 [VLAN]: Clean up ... |
640 641 |
vlan_ioctl_set(vlan_ioctl_handler); return 0; |
70c03b49b vlan: Add GVRP su... |
642 643 |
err4: vlan_gvrp_uninit(); |
69ab4b7d6 [VLAN]: Clean up ... |
644 645 646 |
err3: unregister_netdevice_notifier(&vlan_notifier_block); err2: |
91e2ff352 net: Teach vlans ... |
647 |
unregister_pernet_subsys(&vlan_net_ops); |
d9ed0f0e2 [VLAN]: Introduce... |
648 |
err0: |
69ab4b7d6 [VLAN]: Clean up ... |
649 650 651 652 653 |
return err; } static void __exit vlan_cleanup_module(void) { |
69ab4b7d6 [VLAN]: Clean up ... |
654 655 656 657 |
vlan_ioctl_set(NULL); vlan_netlink_fini(); unregister_netdevice_notifier(&vlan_notifier_block); |
91e2ff352 net: Teach vlans ... |
658 |
unregister_pernet_subsys(&vlan_net_ops); |
6e327c11a 8021q: Vlan drive... |
659 |
rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
70c03b49b vlan: Add GVRP su... |
660 661 |
vlan_gvrp_uninit(); |
69ab4b7d6 [VLAN]: Clean up ... |
662 663 664 665 |
} module_init(vlan_proto_init); module_exit(vlan_cleanup_module); |
1da177e4c Linux-2.6.12-rc2 |
666 667 |
MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); |