Blame view

net/8021q/vlan.c 16.7 KB
1da177e4c   Linus Torvalds   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   Patrick McHardy   [VLAN]: Update li...
6
   *              Please send support related email to: netdev@vger.kernel.org
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
   *              VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
8
   *
1da177e4c   Linus Torvalds   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   Joe Perches   net: 8021q: Add p...
20
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
4fc268d24   Randy Dunlap   [PATCH] capable/c...
21
  #include <linux/capability.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
  #include <linux/module.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
25
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <linux/init.h>
82524746c   Franck Bui-Huu   rcu: split list.h...
27
  #include <linux/rculist.h>
1da177e4c   Linus Torvalds   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   Patrick McHardy   vlan: remove unne...
32
  #include <net/rtnetlink.h>
e9dc86534   Eric W. Biederman   [NET]: Make devic...
33
  #include <net/net_namespace.h>
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
34
  #include <net/netns/generic.h>
61362766d   Patrick McHardy   vlan: remove unne...
35
  #include <asm/uaccess.h>
1da177e4c   Linus Torvalds   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   Eric Dumazet   netns: net_identi...
44
  int vlan_net_id __read_mostly;
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
45

b30200616   Stephen Hemminger   vlan: propogate e...
46
47
  const char vlan_fullname[] = "802.1Q VLAN Support";
  const char vlan_version[] = DRV_VERSION;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  /* End of global variables definitions. */
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
50
51
52
  static void vlan_group_free(struct vlan_group *grp)
  {
  	int i;
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
53
  	for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++)
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
54
55
56
  		kfree(grp->vlan_devices_arrays[i]);
  	kfree(grp);
  }
a9fde2607   Pavel Emelyanov   [VLAN]: Tag vlan_...
57
  static struct vlan_group *vlan_group_alloc(struct net_device *real_dev)
42429aaee   Patrick McHardy   [VLAN]: Move vlan...
58
59
  {
  	struct vlan_group *grp;
42429aaee   Patrick McHardy   [VLAN]: Move vlan...
60
61
62
63
  
  	grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
  	if (!grp)
  		return NULL;
a9fde2607   Pavel Emelyanov   [VLAN]: Tag vlan_...
64
  	grp->real_dev = real_dev;
42429aaee   Patrick McHardy   [VLAN]: Move vlan...
65
  	return grp;
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
66
  }
42429aaee   Patrick McHardy   [VLAN]: Move vlan...
67

9bb8582ef   Patrick McHardy   vlan: TCI related...
68
  static int vlan_group_prealloc_vid(struct vlan_group *vg, u16 vlan_id)
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
69
70
71
72
73
  {
  	struct net_device **array;
  	unsigned int size;
  
  	ASSERT_RTNL();
9bb8582ef   Patrick McHardy   vlan: TCI related...
74
  	array = vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN];
67727184f   Pavel Emelyanov   [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   Patrick McHardy   vlan: TCI related...
82
  	vg->vlan_devices_arrays[vlan_id / VLAN_GROUP_ARRAY_PART_LEN] = array;
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
83
  	return 0;
42429aaee   Patrick McHardy   [VLAN]: Move vlan...
84
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  static void vlan_rcu_free(struct rcu_head *rcu)
  {
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
87
  	vlan_group_free(container_of(rcu, struct vlan_group, rcu));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  }
23289a37e   Eric Dumazet   net: add a list_h...
89
  void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  {
9dfebcc64   Patrick McHardy   [VLAN]: Turn VLAN...
91
  	struct vlan_dev_info *vlan = vlan_dev_info(dev);
af3015170   Patrick McHardy   [VLAN]: Simplify ...
92
  	struct net_device *real_dev = vlan->real_dev;
656299f70   Stephen Hemminger   vlan: convert to ...
93
  	const struct net_device_ops *ops = real_dev->netdev_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
  	struct vlan_group *grp;
9bb8582ef   Patrick McHardy   vlan: TCI related...
95
  	u16 vlan_id = vlan->vlan_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
  
  	ASSERT_RTNL();
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
98

b616b09af   Eric Dumazet   vlan: rcu annotat...
99
  	grp = rtnl_dereference(real_dev->vlgrp);
af3015170   Patrick McHardy   [VLAN]: Simplify ...
100
  	BUG_ON(!grp);
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
101

acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
102
  	/* Take it out of our own structures, but be sure to interlock with
ad1afb003   Pedro Garcia   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   Patrick McHardy   [VLAN]: Clean up ...
105
  	 */
ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
106
  	if (vlan_id && (real_dev->features & NETIF_F_HW_VLAN_FILTER))
656299f70   Stephen Hemminger   vlan: convert to ...
107
  		ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108

af3015170   Patrick McHardy   [VLAN]: Simplify ...
109
  	grp->nr_vlans--;
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
110

55aee10de   Eric Dumazet   vlan: fix GVRP at...
111
112
  	if (vlan->flags & VLAN_FLAG_GVRP)
  		vlan_gvrp_request_leave(dev);
29906f6a4   Patrick McHardy   vlan: cleanup mul...
113
  	vlan_group_set_device(grp, vlan_id, NULL);
48752e1b1   Eric Dumazet   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   Eric Dumazet   net: add a list_h...
118
  	unregister_netdevice_queue(dev, head);
ce305002e   Patrick McHardy   vlan: Move device...
119

acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
120
  	/* If the group is now empty, kill off the group. */
af3015170   Patrick McHardy   [VLAN]: Simplify ...
121
  	if (grp->nr_vlans == 0) {
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
122
  		vlan_gvrp_uninit_applicant(real_dev);
a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
123
  		RCU_INIT_POINTER(real_dev->vlgrp, NULL);
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
124

acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
125
126
  		/* Free the group, after all cpu's are done. */
  		call_rcu(&grp->rcu, vlan_rcu_free);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
  	}
af3015170   Patrick McHardy   [VLAN]: Simplify ...
128
129
  	/* Get rid of the vlan's reference to real_dev */
  	dev_put(real_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  }
9bb8582ef   Patrick McHardy   vlan: TCI related...
131
  int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  {
656299f70   Stephen Hemminger   vlan: convert to ...
133
134
  	const char *name = real_dev->name;
  	const struct net_device_ops *ops = real_dev->netdev_ops;
40f98e1af   Patrick McHardy   [VLAN]: Clean up ...
135

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
  	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
afab2d299   Joe Perches   net: 8021q: Add p...
137
138
  		pr_info("VLANs not supported on %s
  ", name);
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
139
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
656299f70   Stephen Hemminger   vlan: convert to ...
142
  	    (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
afab2d299   Joe Perches   net: 8021q: Add p...
143
144
  		pr_info("Device %s has buggy VLAN hw accel
  ", name);
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
145
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  	}
65ac6a5fa   Jesse Gross   vlan: Avoid hash ...
147
  	if (vlan_find_dev(real_dev, vlan_id) != NULL)
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
148
  		return -EEXIST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149

c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
150
151
  	return 0;
  }
07b5b17e1   Patrick McHardy   [VLAN]: Use rtnl_...
152
  int register_vlan_dev(struct net_device *dev)
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
153
  {
9dfebcc64   Patrick McHardy   [VLAN]: Turn VLAN...
154
  	struct vlan_dev_info *vlan = vlan_dev_info(dev);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
155
  	struct net_device *real_dev = vlan->real_dev;
656299f70   Stephen Hemminger   vlan: convert to ...
156
  	const struct net_device_ops *ops = real_dev->netdev_ops;
9bb8582ef   Patrick McHardy   vlan: TCI related...
157
  	u16 vlan_id = vlan->vlan_id;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
158
159
  	struct vlan_group *grp, *ngrp = NULL;
  	int err;
b616b09af   Eric Dumazet   vlan: rcu annotat...
160
  	grp = rtnl_dereference(real_dev->vlgrp);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
161
  	if (!grp) {
a9fde2607   Pavel Emelyanov   [VLAN]: Tag vlan_...
162
  		ngrp = grp = vlan_group_alloc(real_dev);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
163
164
  		if (!grp)
  			return -ENOBUFS;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
165
166
167
  		err = vlan_gvrp_init_applicant(real_dev);
  		if (err < 0)
  			goto out_free_group;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
168
  	}
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
169
170
  	err = vlan_group_prealloc_vid(grp, vlan_id);
  	if (err < 0)
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
171
  		goto out_uninit_applicant;
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
172

e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
173
174
  	err = register_netdevice(dev);
  	if (err < 0)
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
175
  		goto out_uninit_applicant;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
176
177
178
  
  	/* Account for reference in struct vlan_dev_info */
  	dev_hold(real_dev);
fc4a74896   Patrick Mullaney   netdevice: provid...
179
  	netif_stacked_transfer_operstate(real_dev, dev);
e89fe42cd   Patrick McHardy   [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   Patrick McHardy   [VLAN]: Simplify ...
186
  	grp->nr_vlans++;
65ac6a5fa   Jesse Gross   vlan: Avoid hash ...
187
  	if (ngrp) {
65ac6a5fa   Jesse Gross   vlan: Avoid hash ...
188
189
  		rcu_assign_pointer(real_dev->vlgrp, ngrp);
  	}
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
190
  	if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
656299f70   Stephen Hemminger   vlan: convert to ...
191
  		ops->ndo_vlan_rx_add_vid(real_dev, vlan_id);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
192

e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
193
  	return 0;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
194
195
196
  out_uninit_applicant:
  	if (ngrp)
  		vlan_gvrp_uninit_applicant(real_dev);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
197
  out_free_group:
6b863d1d3   Eric Dumazet   vlan: Fix registe...
198
  	if (ngrp) {
6b863d1d3   Eric Dumazet   vlan: Fix registe...
199
200
201
  		/* Free the group, after all cpu's are done. */
  		call_rcu(&ngrp->rcu, vlan_rcu_free);
  	}
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
202
203
  	return err;
  }
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
204
  /*  Attach a VLAN device to a mac address (ie Ethernet Card).
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
205
   *  Returns 0 if the device was created or a negative error code otherwise.
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
206
   */
9bb8582ef   Patrick McHardy   vlan: TCI related...
207
  static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
208
  {
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
209
  	struct net_device *new_dev;
7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
210
211
  	struct net *net = dev_net(real_dev);
  	struct vlan_net *vn = net_generic(net, vlan_net_id);
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
212
  	char name[IFNAMSIZ];
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
213
  	int err;
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
214

9bb8582ef   Patrick McHardy   vlan: TCI related...
215
  	if (vlan_id >= VLAN_VID_MASK)
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
216
  		return -ERANGE;
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
217

9bb8582ef   Patrick McHardy   vlan: TCI related...
218
  	err = vlan_check_real_dev(real_dev, vlan_id);
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
219
220
  	if (err < 0)
  		return err;
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
221

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  	/* Gotta set up the fields for the device. */
7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
223
  	switch (vn->name_type) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
  	case VLAN_NAME_TYPE_RAW_PLUS_VID:
  		/* name will look like:	 eth1.0005 */
9bb8582ef   Patrick McHardy   vlan: TCI related...
226
  		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id);
1da177e4c   Linus Torvalds   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   Patrick McHardy   vlan: TCI related...
232
  		snprintf(name, IFNAMSIZ, "vlan%i", vlan_id);
1da177e4c   Linus Torvalds   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   Patrick McHardy   vlan: TCI related...
238
  		snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
1da177e4c   Linus Torvalds   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   Patrick McHardy   vlan: TCI related...
245
  		snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
246
  	}
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
247

4af429d29   Eric Dumazet   vlan: lockless tr...
248
  	new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name, vlan_setup);
5dd8d1e9e   Arjan van de Ven   [PATCH] lockdep: ...
249

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
  	if (new_dev == NULL)
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
251
  		return -ENOBUFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252

65d292a2e   Pavel Emelyanov   [VLAN]: Allow vla...
253
  	dev_net_set(new_dev, net);
1da177e4c   Linus Torvalds   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   Patrick McHardy   vlan: TCI related...
258
  	vlan_dev_info(new_dev)->vlan_id = vlan_id;
9dfebcc64   Patrick McHardy   [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   Linus Torvalds   Linux-2.6.12-rc2
262

07b5b17e1   Patrick McHardy   [VLAN]: Use rtnl_...
263
  	new_dev->rtnl_link_ops = &vlan_link_ops;
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
264
265
  	err = register_vlan_dev(new_dev);
  	if (err < 0)
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
266
  		goto out_free_newdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267

2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
268
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
  out_free_newdev:
  	free_netdev(new_dev);
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
272
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  }
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
274
275
276
  static void vlan_sync_address(struct net_device *dev,
  			      struct net_device *vlandev)
  {
9dfebcc64   Patrick McHardy   [VLAN]: Turn VLAN...
277
  	struct vlan_dev_info *vlan = vlan_dev_info(vlandev);
8c979c26a   Patrick McHardy   [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   Jiri Pirko   net: move address...
287
  		dev_uc_del(dev, vlandev->dev_addr);
8c979c26a   Patrick McHardy   [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   Jiri Pirko   net: move address...
293
  		dev_uc_add(dev, vlandev->dev_addr);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
294
295
296
  
  	memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN);
  }
5fb135705   Patrick McHardy   [VLAN]: Propagate...
297
298
299
  static void vlan_transfer_features(struct net_device *dev,
  				   struct net_device *vlandev)
  {
1ae4be22f   Alexander Duyck   vlan: vlan device...
300
  	vlandev->gso_max_size = dev->gso_max_size;
029f5fc31   John Fastabend   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   Vasu Dev   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   MichaÅ‚ MirosÅ‚aw   vlan: convert VLA...
309
310
  
  	netdev_update_features(vlandev);
5fb135705   Patrick McHardy   [VLAN]: Propagate...
311
  }
802fb176d   Pavel Emelyanov   [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   Joe Perches   net: 8021q: Add p...
318
319
320
  			pr_warn("failed to change proc name for %s
  ",
  				dev->name);
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
321
  		break;
30688a9a3   Pavel Emelyanov   [VLAN]: Handle vl...
322
323
  	case NETDEV_REGISTER:
  		if (vlan_proc_add_dev(dev) < 0)
afab2d299   Joe Perches   net: 8021q: Add p...
324
325
  			pr_warn("failed to add proc entry for %s
  ", dev->name);
30688a9a3   Pavel Emelyanov   [VLAN]: Handle vl...
326
327
328
329
  		break;
  	case NETDEV_UNREGISTER:
  		vlan_proc_rem_dev(dev);
  		break;
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
330
331
  	}
  }
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
332
333
  static int vlan_device_event(struct notifier_block *unused, unsigned long event,
  			     void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
  {
  	struct net_device *dev = ptr;
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
336
  	struct vlan_group *grp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
  	int i, flgs;
  	struct net_device *vlandev;
5e7565930   Patrick McHardy   vlan: support "lo...
339
  	struct vlan_dev_info *vlan;
29906f6a4   Patrick McHardy   vlan: cleanup mul...
340
  	LIST_HEAD(list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341

81d85346b   Patrick McHardy   vlan: Correctly h...
342
  	if (is_vlan_dev(dev))
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
343
  		__vlan_device_event(dev, event);
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
344

ad1afb003   Pedro Garcia   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   Joe Perches   net: 8021q: Add p...
348
349
  		pr_info("adding VLAN 0 to HW filter on device %s
  ",
ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
350
351
352
  			dev->name);
  		dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
  	}
b616b09af   Eric Dumazet   vlan: rcu annotat...
353
  	grp = rtnl_dereference(dev->vlgrp);
1da177e4c   Linus Torvalds   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   Jesse Gross   vlan: Rename VLAN...
364
  		for (i = 0; i < VLAN_N_VID; i++) {
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
365
  			vlandev = vlan_group_get_device(grp, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
  			if (!vlandev)
  				continue;
fc4a74896   Patrick Mullaney   netdevice: provid...
368
  			netif_stacked_transfer_operstate(dev, vlandev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
  		}
  		break;
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
371
372
  	case NETDEV_CHANGEADDR:
  		/* Adjust unicast filters on underlying device */
b738127df   Jesse Gross   vlan: Rename VLAN...
373
  		for (i = 0; i < VLAN_N_VID; i++) {
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
374
375
376
  			vlandev = vlan_group_get_device(grp, i);
  			if (!vlandev)
  				continue;
d932e04a5   Patrick McHardy   [VLAN]: Don't syn...
377
378
379
  			flgs = vlandev->flags;
  			if (!(flgs & IFF_UP))
  				continue;
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
380
381
  			vlan_sync_address(dev, vlandev);
  		}
2e477c9bd   Herbert Xu   vlan: Propagate p...
382
383
384
  		break;
  
  	case NETDEV_CHANGEMTU:
b738127df   Jesse Gross   vlan: Rename VLAN...
385
  		for (i = 0; i < VLAN_N_VID; i++) {
2e477c9bd   Herbert Xu   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   Patrick McHardy   [VLAN]: Fix MAC a...
395
  		break;
5fb135705   Patrick McHardy   [VLAN]: Propagate...
396
397
  	case NETDEV_FEAT_CHANGE:
  		/* Propagate device features to underlying device */
b738127df   Jesse Gross   vlan: Rename VLAN...
398
  		for (i = 0; i < VLAN_N_VID; i++) {
5fb135705   Patrick McHardy   [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   Linus Torvalds   Linux-2.6.12-rc2
407
408
  	case NETDEV_DOWN:
  		/* Put all VLANs for this dev in the down state too.  */
b738127df   Jesse Gross   vlan: Rename VLAN...
409
  		for (i = 0; i < VLAN_N_VID; i++) {
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
410
  			vlandev = vlan_group_get_device(grp, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
414
415
416
  			if (!vlandev)
  				continue;
  
  			flgs = vlandev->flags;
  			if (!(flgs & IFF_UP))
  				continue;
5e7565930   Patrick McHardy   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   Patrick Mullaney   netdevice: provid...
420
  			netif_stacked_transfer_operstate(dev, vlandev);
1da177e4c   Linus Torvalds   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   Jesse Gross   vlan: Rename VLAN...
426
  		for (i = 0; i < VLAN_N_VID; i++) {
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
427
  			vlandev = vlan_group_get_device(grp, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
  			if (!vlandev)
  				continue;
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
430

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
432
433
  			flgs = vlandev->flags;
  			if (flgs & IFF_UP)
  				continue;
5e7565930   Patrick McHardy   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   Patrick Mullaney   netdevice: provid...
437
  			netif_stacked_transfer_operstate(dev, vlandev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
  		}
  		break;
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
440

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  	case NETDEV_UNREGISTER:
3b27e1055   David Lamparter   netns: keep vlan ...
442
443
444
  		/* twiddle thumbs on netns device moves */
  		if (dev->reg_state != NETREG_UNREGISTERING)
  			break;
b738127df   Jesse Gross   vlan: Rename VLAN...
445
  		for (i = 0; i < VLAN_N_VID; i++) {
29906f6a4   Patrick McHardy   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   Jesse Gross   vlan: Rename VLAN...
453
  				i = VLAN_N_VID;
29906f6a4   Patrick McHardy   vlan: cleanup mul...
454
455
456
457
  
  			unregister_vlan_dev(vlandev, &list);
  		}
  		unregister_netdevice_many(&list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  		break;
1c01fe14a   Jiri Pirko   net: forbid under...
459
460
461
462
  
  	case NETDEV_PRE_TYPE_CHANGE:
  		/* Forbid underlaying device to change its type. */
  		return NOTIFY_BAD;
99606477a   Ben Hutchings   vlan: Propagate N...
463
464
  
  	case NETDEV_NOTIFY_PEERS:
7c8994323   Ben Hutchings   bonding, ipv4, ip...
465
  	case NETDEV_BONDING_FAILOVER:
99606477a   Ben Hutchings   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   Ben Hutchings   bonding, ipv4, ip...
471
  			call_netdevice_notifiers(event, vlandev);
99606477a   Ben Hutchings   vlan: Propagate N...
472
473
  		}
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
474
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
477
478
  
  out:
  	return NOTIFY_DONE;
  }
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
479
480
481
  static struct notifier_block vlan_notifier_block __read_mostly = {
  	.notifier_call = vlan_device_event,
  };
1da177e4c   Linus Torvalds   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   Eric W. Biederman   [NET]: Make the d...
487
  static int vlan_ioctl_handler(struct net *net, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
  {
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
489
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  	struct vlan_ioctl_args args;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
491
  	struct net_device *dev = NULL;
1da177e4c   Linus Torvalds   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   Patrick McHardy   [VLAN]: Convert n...
499
  	rtnl_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
  	switch (args.cmd) {
  	case SET_VLAN_INGRESS_PRIORITY_CMD:
c17d8874f   Patrick McHardy   [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   Pavel Emelyanov   [VLAN]: Allow vla...
509
  		dev = __dev_get_by_name(net, args.device1);
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
510
511
512
513
  		if (!dev)
  			goto out;
  
  		err = -EINVAL;
26a25239d   Joonwoo Park   vlan: Use is_vlan...
514
  		if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
515
516
517
518
519
520
  			goto out;
  	}
  
  	switch (args.cmd) {
  	case SET_VLAN_INGRESS_PRIORITY_CMD:
  		err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
  		if (!capable(CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
522
523
524
525
  			break;
  		vlan_dev_set_ingress_priority(dev,
  					      args.u.skb_priority,
  					      args.vlan_qos);
fffe470a8   Patrick McHardy   [VLAN]: Fix SET_V...
526
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
  		break;
  
  	case SET_VLAN_EGRESS_PRIORITY_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
530
  		err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  		if (!capable(CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
532
533
  			break;
  		err = vlan_dev_set_egress_priority(dev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
  						   args.u.skb_priority,
  						   args.vlan_qos);
  		break;
  
  	case SET_VLAN_FLAG_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
539
  		err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
  		if (!capable(CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
541
  			break;
b3ce0325f   Patrick McHardy   vlan: Change vlan...
542
543
544
  		err = vlan_dev_change_flags(dev,
  					    args.vlan_qos ? args.u.flag : 0,
  					    args.u.flag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
547
  		break;
  
  	case SET_VLAN_NAME_TYPE_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
548
  		err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
  		if (!capable(CAP_NET_ADMIN))
e35de0261   Pavel Emelyanov   [VLAN]: Lost rtnl...
550
  			break;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
551
552
  		if ((args.u.name_type >= 0) &&
  		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
7a17a2f79   Pavel Emelyanov   [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   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
561
562
563
  			err = 0;
  		} else {
  			err = -EINVAL;
  		}
  		break;
  
  	case ADD_VLAN_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
564
  		err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565
  		if (!capable(CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
566
  			break;
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
567
  		err = register_vlan_device(dev, args.u.VID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
569
570
  		break;
  
  	case DEL_VLAN_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
571
  		err = -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
  		if (!capable(CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
573
  			break;
23289a37e   Eric Dumazet   net: add a list_h...
574
  		unregister_vlan_dev(dev, NULL);
af3015170   Patrick McHardy   [VLAN]: Simplify ...
575
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  	case GET_VLAN_REALDEV_NAME_CMD:
3f5f4346b   Andrew Morton   [8021Q]: vlan_ioc...
578
  		err = 0;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
579
  		vlan_dev_get_realdev_name(dev, args.u.device2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
  		if (copy_to_user(arg, &args,
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
581
  				 sizeof(struct vlan_ioctl_args)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  			err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
585
  		break;
  
  	case GET_VLAN_VID_CMD:
3f5f4346b   Andrew Morton   [8021Q]: vlan_ioc...
586
  		err = 0;
22d1ba74b   Patrick McHardy   vlan: move struct...
587
  		args.u.VID = vlan_dev_vlan_id(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
  		if (copy_to_user(arg, &args,
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
589
  				 sizeof(struct vlan_ioctl_args)))
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
590
  		      err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
  		break;
  
  	default:
198a291ce   Patrick McHardy   [VLAN]: Remove no...
594
  		err = -EOPNOTSUPP;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
595
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
596
  	}
7eb1b3d37   Mika Kukkonen   [VLAN]: Add two m...
597
  out:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
598
  	rtnl_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
  	return err;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
601
  static int __net_init vlan_init_net(struct net *net)
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
602
  {
946d1a929   Eric W. Biederman   net: Simplify vla...
603
  	struct vlan_net *vn = net_generic(net, vlan_net_id);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
604
  	int err;
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
605

7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
606
  	vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
cd1c70143   Pavel Emelyanov   [VLAN]: Add a net...
607
  	err = vlan_proc_init(net);
cd1c70143   Pavel Emelyanov   [VLAN]: Add a net...
608

d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
609
610
  	return err;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
611
  static void __net_exit vlan_exit_net(struct net *net)
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
612
  {
cd1c70143   Pavel Emelyanov   [VLAN]: Add a net...
613
  	vlan_proc_cleanup(net);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
614
615
616
617
618
  }
  
  static struct pernet_operations vlan_net_ops = {
  	.init = vlan_init_net,
  	.exit = vlan_exit_net,
946d1a929   Eric W. Biederman   net: Simplify vla...
619
620
  	.id   = &vlan_net_id,
  	.size = sizeof(struct vlan_net),
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
621
  };
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
622
623
624
  static int __init vlan_proto_init(void)
  {
  	int err;
da7c06c4a   Justin Mattock   net:8021q:vlan.c ...
625
626
  	pr_info("%s v%s
  ", vlan_fullname, vlan_version);
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
627

91e2ff352   Eric W. Biederman   net: Teach vlans ...
628
  	err = register_pernet_subsys(&vlan_net_ops);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
629
630
  	if (err < 0)
  		goto err0;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
631
632
633
  	err = register_netdevice_notifier(&vlan_notifier_block);
  	if (err < 0)
  		goto err2;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
634
  	err = vlan_gvrp_init();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
635
636
  	if (err < 0)
  		goto err3;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
637
638
639
  	err = vlan_netlink_init();
  	if (err < 0)
  		goto err4;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
640
641
  	vlan_ioctl_set(vlan_ioctl_handler);
  	return 0;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
642
643
  err4:
  	vlan_gvrp_uninit();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
644
645
646
  err3:
  	unregister_netdevice_notifier(&vlan_notifier_block);
  err2:
91e2ff352   Eric W. Biederman   net: Teach vlans ...
647
  	unregister_pernet_subsys(&vlan_net_ops);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
648
  err0:
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
649
650
651
652
653
  	return err;
  }
  
  static void __exit vlan_cleanup_module(void)
  {
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
654
655
656
657
  	vlan_ioctl_set(NULL);
  	vlan_netlink_fini();
  
  	unregister_netdevice_notifier(&vlan_notifier_block);
91e2ff352   Eric W. Biederman   net: Teach vlans ...
658
  	unregister_pernet_subsys(&vlan_net_ops);
6e327c11a   Jesper Dangaard Brouer   8021q: Vlan drive...
659
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
660
661
  
  	vlan_gvrp_uninit();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
662
663
664
665
  }
  
  module_init(vlan_proto_init);
  module_exit(vlan_cleanup_module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);