Blame view

net/8021q/vlan.c 16.6 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. */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
50
51
  static int vlan_group_prealloc_vid(struct vlan_group *vg,
  				   __be16 vlan_proto, u16 vlan_id)
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
52
53
  {
  	struct net_device **array;
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
54
  	unsigned int pidx, vidx;
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
55
56
57
  	unsigned int size;
  
  	ASSERT_RTNL();
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
58
59
60
  	pidx  = vlan_proto_idx(vlan_proto);
  	vidx  = vlan_id / VLAN_GROUP_ARRAY_PART_LEN;
  	array = vg->vlan_devices_arrays[pidx][vidx];
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
61
62
63
64
65
66
67
  	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;
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
68
  	vg->vlan_devices_arrays[pidx][vidx] = array;
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
69
  	return 0;
42429aaee   Patrick McHardy   [VLAN]: Move vlan...
70
  }
23289a37e   Eric Dumazet   net: add a list_h...
71
  void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  {
7da82c06d   Jiri Pirko   vlan: rename vlan...
73
  	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
af3015170   Patrick McHardy   [VLAN]: Simplify ...
74
  	struct net_device *real_dev = vlan->real_dev;
5b9ea6e02   Jiri Pirko   vlan: introduce v...
75
  	struct vlan_info *vlan_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
  	struct vlan_group *grp;
9bb8582ef   Patrick McHardy   vlan: TCI related...
77
  	u16 vlan_id = vlan->vlan_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
  
  	ASSERT_RTNL();
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
80

5b9ea6e02   Jiri Pirko   vlan: introduce v...
81
82
83
84
  	vlan_info = rtnl_dereference(real_dev->vlan_info);
  	BUG_ON(!vlan_info);
  
  	grp = &vlan_info->grp;
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
85

5b9ea6e02   Jiri Pirko   vlan: introduce v...
86
  	grp->nr_vlan_devs--;
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
87

86fbe9bb5   David Ward   net/8021q: Implem...
88
89
  	if (vlan->flags & VLAN_FLAG_MVRP)
  		vlan_mvrp_request_leave(dev);
55aee10de   Eric Dumazet   vlan: fix GVRP at...
90
91
  	if (vlan->flags & VLAN_FLAG_GVRP)
  		vlan_gvrp_request_leave(dev);
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
92
  	vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, NULL);
47701a36a   Veaceslav Falico   vlan: unlink the ...
93
94
  
  	netdev_upper_dev_unlink(real_dev, dev);
48752e1b1   Eric Dumazet   vlan: remove one ...
95
96
97
98
  	/* 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...
99
  	unregister_netdevice_queue(dev, head);
ce305002e   Patrick McHardy   vlan: Move device...
100

86fbe9bb5   David Ward   net/8021q: Implem...
101
102
  	if (grp->nr_vlan_devs == 0) {
  		vlan_mvrp_uninit_applicant(real_dev);
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
103
  		vlan_gvrp_uninit_applicant(real_dev);
86fbe9bb5   David Ward   net/8021q: Implem...
104
  	}
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
105

4a7df340e   Cong Wang   8021q: fix a pote...
106
107
108
109
110
  	/* Take it out of our own structures, but be sure to interlock with
  	 * HW accelerating devices or SW vlan input packet processing if
  	 * VLAN is not 0 (leave it there for 802.1p).
  	 */
  	if (vlan_id)
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
111
  		vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id);
4a7df340e   Cong Wang   8021q: fix a pote...
112

af3015170   Patrick McHardy   [VLAN]: Simplify ...
113
114
  	/* Get rid of the vlan's reference to real_dev */
  	dev_put(real_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  }
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
116
117
  int vlan_check_real_dev(struct net_device *real_dev,
  			__be16 protocol, u16 vlan_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  {
656299f70   Stephen Hemminger   vlan: convert to ...
119
  	const char *name = real_dev->name;
40f98e1af   Patrick McHardy   [VLAN]: Clean up ...
120

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
afab2d299   Joe Perches   net: 8021q: Add p...
122
123
  		pr_info("VLANs not supported on %s
  ", name);
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
124
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  	}
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
126
  	if (vlan_find_dev(real_dev, protocol, vlan_id) != NULL)
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
127
  		return -EEXIST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128

c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
129
130
  	return 0;
  }
07b5b17e1   Patrick McHardy   [VLAN]: Use rtnl_...
131
  int register_vlan_dev(struct net_device *dev)
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
132
  {
7da82c06d   Jiri Pirko   vlan: rename vlan...
133
  	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
134
  	struct net_device *real_dev = vlan->real_dev;
9bb8582ef   Patrick McHardy   vlan: TCI related...
135
  	u16 vlan_id = vlan->vlan_id;
5b9ea6e02   Jiri Pirko   vlan: introduce v...
136
137
  	struct vlan_info *vlan_info;
  	struct vlan_group *grp;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
138
  	int err;
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
139
  	err = vlan_vid_add(real_dev, vlan->vlan_proto, vlan_id);
5b9ea6e02   Jiri Pirko   vlan: introduce v...
140
141
142
143
144
145
146
147
148
  	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   Patrick McHardy   vlan: Add GVRP su...
149
150
  		err = vlan_gvrp_init_applicant(real_dev);
  		if (err < 0)
5b9ea6e02   Jiri Pirko   vlan: introduce v...
151
  			goto out_vid_del;
86fbe9bb5   David Ward   net/8021q: Implem...
152
153
154
  		err = vlan_mvrp_init_applicant(real_dev);
  		if (err < 0)
  			goto out_uninit_gvrp;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
155
  	}
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
156
  	err = vlan_group_prealloc_vid(grp, vlan->vlan_proto, vlan_id);
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
157
  	if (err < 0)
86fbe9bb5   David Ward   net/8021q: Implem...
158
  		goto out_uninit_mvrp;
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
159

d38569ab2   Vlad Yasevich   vlan: Fix lockdep...
160
  	vlan->nest_level = dev_get_nest_level(real_dev, is_vlan_dev) + 1;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
161
162
  	err = register_netdevice(dev);
  	if (err < 0)
5df27e6cb   Veaceslav Falico   vlan: link the up...
163
164
165
166
167
  		goto out_uninit_mvrp;
  
  	err = netdev_upper_dev_link(real_dev, dev);
  	if (err)
  		goto out_unregister_netdev;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
168

7da82c06d   Jiri Pirko   vlan: rename vlan...
169
  	/* Account for reference in struct vlan_dev_priv */
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
170
  	dev_hold(real_dev);
fc4a74896   Patrick Mullaney   netdevice: provid...
171
  	netif_stacked_transfer_operstate(real_dev, dev);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
172
173
174
175
176
  	linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
  
  	/* So, got the sucker initialized, now lets place
  	 * it into our local structure.
  	 */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
177
  	vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, dev);
5b9ea6e02   Jiri Pirko   vlan: introduce v...
178
  	grp->nr_vlan_devs++;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
179

e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
180
  	return 0;
5df27e6cb   Veaceslav Falico   vlan: link the up...
181
182
  out_unregister_netdev:
  	unregister_netdevice(dev);
86fbe9bb5   David Ward   net/8021q: Implem...
183
184
185
186
  out_uninit_mvrp:
  	if (grp->nr_vlan_devs == 0)
  		vlan_mvrp_uninit_applicant(real_dev);
  out_uninit_gvrp:
5b9ea6e02   Jiri Pirko   vlan: introduce v...
187
  	if (grp->nr_vlan_devs == 0)
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
188
  		vlan_gvrp_uninit_applicant(real_dev);
5b9ea6e02   Jiri Pirko   vlan: introduce v...
189
  out_vid_del:
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
190
  	vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
191
192
  	return err;
  }
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
193
  /*  Attach a VLAN device to a mac address (ie Ethernet Card).
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
194
   *  Returns 0 if the device was created or a negative error code otherwise.
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
195
   */
9bb8582ef   Patrick McHardy   vlan: TCI related...
196
  static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
197
  {
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
198
  	struct net_device *new_dev;
0c0667a85   Wang Sheng-Hui   vlan: cleanup the...
199
  	struct vlan_dev_priv *vlan;
7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
200
201
  	struct net *net = dev_net(real_dev);
  	struct vlan_net *vn = net_generic(net, vlan_net_id);
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
202
  	char name[IFNAMSIZ];
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
203
  	int err;
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
204

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

1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
208
  	err = vlan_check_real_dev(real_dev, htons(ETH_P_8021Q), vlan_id);
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
209
210
  	if (err < 0)
  		return err;
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
211

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  	/* Gotta set up the fields for the device. */
7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
213
  	switch (vn->name_type) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
  	case VLAN_NAME_TYPE_RAW_PLUS_VID:
  		/* name will look like:	 eth1.0005 */
9bb8582ef   Patrick McHardy   vlan: TCI related...
216
  		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
220
221
  		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...
222
  		snprintf(name, IFNAMSIZ, "vlan%i", vlan_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
227
  		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...
228
  		snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229
230
231
232
233
234
  		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...
235
  		snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
236
  	}
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
237

c835a6773   Tom Gundersen   net: set name_ass...
238
239
  	new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name,
  			       NET_NAME_UNKNOWN, vlan_setup);
5dd8d1e9e   Arjan van de Ven   [PATCH] lockdep: ...
240

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

65d292a2e   Pavel Emelyanov   [VLAN]: Allow vla...
244
  	dev_net_set(new_dev, net);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
  	/* need 4 bytes for extra VLAN header info,
  	 * hope the underlying device can handle it.
  	 */
  	new_dev->mtu = real_dev->mtu;
6e22ce2c6   Yi Zou   8021q: fix vlan d...
249
  	new_dev->priv_flags |= (real_dev->priv_flags & IFF_UNICAST_FLT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250

0c0667a85   Wang Sheng-Hui   vlan: cleanup the...
251
252
253
254
255
256
  	vlan = vlan_dev_priv(new_dev);
  	vlan->vlan_proto = htons(ETH_P_8021Q);
  	vlan->vlan_id = vlan_id;
  	vlan->real_dev = real_dev;
  	vlan->dent = NULL;
  	vlan->flags = VLAN_FLAG_REORDER_HDR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
  out_free_newdev:
  	free_netdev(new_dev);
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
267
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  }
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
269
270
271
  static void vlan_sync_address(struct net_device *dev,
  			      struct net_device *vlandev)
  {
7da82c06d   Jiri Pirko   vlan: rename vlan...
272
  	struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
273
274
  
  	/* May be called without an actual change */
53a2b3a18   Joe Perches   8021q: Convert co...
275
  	if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr))
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
276
277
278
279
  		return;
  
  	/* vlan address was different from the old address and is equal to
  	 * the new address */
53a2b3a18   Joe Perches   8021q: Convert co...
280
281
  	if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
  	    ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
a748ee242   Jiri Pirko   net: move address...
282
  		dev_uc_del(dev, vlandev->dev_addr);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
283
284
285
  
  	/* vlan address was equal to the old address and is different from
  	 * the new address */
53a2b3a18   Joe Perches   8021q: Convert co...
286
287
  	if (ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
  	    !ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
a748ee242   Jiri Pirko   net: move address...
288
  		dev_uc_add(dev, vlandev->dev_addr);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
289

07fc67bef   Joe Perches   8021q: Use ether_...
290
  	ether_addr_copy(vlan->real_dev_addr, dev->dev_addr);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
291
  }
5fb135705   Patrick McHardy   [VLAN]: Propagate...
292
293
294
  static void vlan_transfer_features(struct net_device *dev,
  				   struct net_device *vlandev)
  {
fc0d48b8f   Vlad Yasevich   vlan: Set hard_he...
295
  	struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
1ae4be22f   Alexander Duyck   vlan: vlan device...
296
  	vlandev->gso_max_size = dev->gso_max_size;
029f5fc31   John Fastabend   8021q: set hard_h...
297

fc0d48b8f   Vlad Yasevich   vlan: Set hard_he...
298
  	if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
029f5fc31   John Fastabend   8021q: set hard_h...
299
300
301
  		vlandev->hard_header_len = dev->hard_header_len;
  	else
  		vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
f4d5392e5   Amerigo Wang   vlan: use IS_ENAB...
302
  #if IS_ENABLED(CONFIG_FCOE)
b85daa532   Vasu Dev   vlan: adds fcoe o...
303
304
  	vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
  #endif
8a0427bb6   MichaÅ‚ MirosÅ‚aw   vlan: convert VLA...
305
306
  
  	netdev_update_features(vlandev);
5fb135705   Patrick McHardy   [VLAN]: Propagate...
307
  }
9c5ff24f9   WANG Cong   vlan: fail early ...
308
  static int __vlan_device_event(struct net_device *dev, unsigned long event)
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
309
  {
9c5ff24f9   WANG Cong   vlan: fail early ...
310
  	int err = 0;
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
311
312
313
  	switch (event) {
  	case NETDEV_CHANGENAME:
  		vlan_proc_rem_dev(dev);
9c5ff24f9   WANG Cong   vlan: fail early ...
314
  		err = vlan_proc_add_dev(dev);
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
315
  		break;
30688a9a3   Pavel Emelyanov   [VLAN]: Handle vl...
316
  	case NETDEV_REGISTER:
9c5ff24f9   WANG Cong   vlan: fail early ...
317
  		err = vlan_proc_add_dev(dev);
30688a9a3   Pavel Emelyanov   [VLAN]: Handle vl...
318
319
320
321
  		break;
  	case NETDEV_UNREGISTER:
  		vlan_proc_rem_dev(dev);
  		break;
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
322
  	}
9c5ff24f9   WANG Cong   vlan: fail early ...
323
324
  
  	return err;
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
325
  }
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
326
327
  static int vlan_device_event(struct notifier_block *unused, unsigned long event,
  			     void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
  {
351638e7d   Jiri Pirko   net: pass info st...
329
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
330
  	struct vlan_group *grp;
5b9ea6e02   Jiri Pirko   vlan: introduce v...
331
  	struct vlan_info *vlan_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
  	int i, flgs;
  	struct net_device *vlandev;
7da82c06d   Jiri Pirko   vlan: rename vlan...
334
  	struct vlan_dev_priv *vlan;
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
335
  	bool last = false;
29906f6a4   Patrick McHardy   vlan: cleanup mul...
336
  	LIST_HEAD(list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337

9c5ff24f9   WANG Cong   vlan: fail early ...
338
339
340
341
342
343
  	if (is_vlan_dev(dev)) {
  		int err = __vlan_device_event(dev, event);
  
  		if (err)
  			return notifier_from_errno(err);
  	}
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
344

ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
345
  	if ((event == NETDEV_UP) &&
f646968f8   Patrick McHardy   net: vlan: rename...
346
  	    (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
afab2d299   Joe Perches   net: 8021q: Add p...
347
348
  		pr_info("adding VLAN 0 to HW filter on device %s
  ",
ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
349
  			dev->name);
80d5c3689   Patrick McHardy   net: vlan: prepar...
350
  		vlan_vid_add(dev, htons(ETH_P_8021Q), 0);
ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
351
  	}
5b9ea6e02   Jiri Pirko   vlan: introduce v...
352
353
  	vlan_info = rtnl_dereference(dev->vlan_info);
  	if (!vlan_info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
  		goto out;
5b9ea6e02   Jiri Pirko   vlan: introduce v...
355
  	grp = &vlan_info->grp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
358
359
360
361
362
363
  
  	/* 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 */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
364
  		vlan_group_for_each_dev(grp, i, vlandev)
fc4a74896   Patrick Mullaney   netdevice: provid...
365
  			netif_stacked_transfer_operstate(dev, vlandev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
  		break;
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
367
368
  	case NETDEV_CHANGEADDR:
  		/* Adjust unicast filters on underlying device */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
369
  		vlan_group_for_each_dev(grp, i, vlandev) {
d932e04a5   Patrick McHardy   [VLAN]: Don't syn...
370
371
372
  			flgs = vlandev->flags;
  			if (!(flgs & IFF_UP))
  				continue;
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
373
374
  			vlan_sync_address(dev, vlandev);
  		}
2e477c9bd   Herbert Xu   vlan: Propagate p...
375
376
377
  		break;
  
  	case NETDEV_CHANGEMTU:
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
378
  		vlan_group_for_each_dev(grp, i, vlandev) {
2e477c9bd   Herbert Xu   vlan: Propagate p...
379
380
381
382
383
  			if (vlandev->mtu <= dev->mtu)
  				continue;
  
  			dev_set_mtu(vlandev, dev->mtu);
  		}
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
384
  		break;
5fb135705   Patrick McHardy   [VLAN]: Propagate...
385
386
  	case NETDEV_FEAT_CHANGE:
  		/* Propagate device features to underlying device */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
387
  		vlan_group_for_each_dev(grp, i, vlandev)
5fb135705   Patrick McHardy   [VLAN]: Propagate...
388
  			vlan_transfer_features(dev, vlandev);
5fb135705   Patrick McHardy   [VLAN]: Propagate...
389
  		break;
99c4a26a1   David S. Miller   net: Fix high ove...
390
391
392
  	case NETDEV_DOWN: {
  		struct net_device *tmp;
  		LIST_HEAD(close_list);
f646968f8   Patrick McHardy   net: vlan: rename...
393
  		if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
80d5c3689   Patrick McHardy   net: vlan: prepar...
394
  			vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
efc73f4bb   Amir Hanania   net: Fix memory l...
395

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
  		/* Put all VLANs for this dev in the down state too.  */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
397
  		vlan_group_for_each_dev(grp, i, vlandev) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
  			flgs = vlandev->flags;
  			if (!(flgs & IFF_UP))
  				continue;
7da82c06d   Jiri Pirko   vlan: rename vlan...
401
  			vlan = vlan_dev_priv(vlandev);
5e7565930   Patrick McHardy   vlan: support "lo...
402
  			if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
99c4a26a1   David S. Miller   net: Fix high ove...
403
404
405
406
407
408
  				list_add(&vlandev->close_list, &close_list);
  		}
  
  		dev_close_many(&close_list, false);
  
  		list_for_each_entry_safe(vlandev, tmp, &close_list, close_list) {
fc4a74896   Patrick Mullaney   netdevice: provid...
409
  			netif_stacked_transfer_operstate(dev, vlandev);
99c4a26a1   David S. Miller   net: Fix high ove...
410
  			list_del_init(&vlandev->close_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  		}
99c4a26a1   David S. Miller   net: Fix high ove...
412
  		list_del(&close_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
  		break;
99c4a26a1   David S. Miller   net: Fix high ove...
414
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
  	case NETDEV_UP:
  		/* Put all VLANs for this dev in the up state too.  */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
417
  		vlan_group_for_each_dev(grp, i, vlandev) {
be346ffaa   Vlad Yasevich   vlan: Correctly p...
418
  			flgs = dev_get_flags(vlandev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
  			if (flgs & IFF_UP)
  				continue;
7da82c06d   Jiri Pirko   vlan: rename vlan...
421
  			vlan = vlan_dev_priv(vlandev);
5e7565930   Patrick McHardy   vlan: support "lo...
422
423
  			if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
  				dev_change_flags(vlandev, flgs | IFF_UP);
fc4a74896   Patrick Mullaney   netdevice: provid...
424
  			netif_stacked_transfer_operstate(dev, vlandev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
  		}
  		break;
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
427

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  	case NETDEV_UNREGISTER:
3b27e1055   David Lamparter   netns: keep vlan ...
429
430
431
  		/* twiddle thumbs on netns device moves */
  		if (dev->reg_state != NETREG_UNREGISTERING)
  			break;
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
432
  		vlan_group_for_each_dev(grp, i, vlandev) {
5b9ea6e02   Jiri Pirko   vlan: introduce v...
433
  			/* removal of last vid destroys vlan_info, abort
29906f6a4   Patrick McHardy   vlan: cleanup mul...
434
  			 * afterwards */
5b9ea6e02   Jiri Pirko   vlan: introduce v...
435
  			if (vlan_info->nr_vids == 1)
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
436
  				last = true;
29906f6a4   Patrick McHardy   vlan: cleanup mul...
437
438
  
  			unregister_vlan_dev(vlandev, &list);
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
439
440
  			if (last)
  				break;
29906f6a4   Patrick McHardy   vlan: cleanup mul...
441
442
  		}
  		unregister_netdevice_many(&list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  		break;
1c01fe14a   Jiri Pirko   net: forbid under...
444
445
446
  
  	case NETDEV_PRE_TYPE_CHANGE:
  		/* Forbid underlaying device to change its type. */
18c22a03a   Jiri Pirko   vlan: allow to ch...
447
448
449
  		if (vlan_uses_dev(dev))
  			return NOTIFY_BAD;
  		break;
99606477a   Ben Hutchings   vlan: Propagate N...
450
451
  
  	case NETDEV_NOTIFY_PEERS:
7c8994323   Ben Hutchings   bonding, ipv4, ip...
452
  	case NETDEV_BONDING_FAILOVER:
4aa5dee4d   Jiri Pirko   net: convert rese...
453
  	case NETDEV_RESEND_IGMP:
99606477a   Ben Hutchings   vlan: Propagate N...
454
  		/* Propagate to vlan devices */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
455
  		vlan_group_for_each_dev(grp, i, vlandev)
7c8994323   Ben Hutchings   bonding, ipv4, ip...
456
  			call_netdevice_notifiers(event, vlandev);
99606477a   Ben Hutchings   vlan: Propagate N...
457
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
458
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
462
  
  out:
  	return NOTIFY_DONE;
  }
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
463
464
465
  static struct notifier_block vlan_notifier_block __read_mostly = {
  	.notifier_call = vlan_device_event,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
467
468
469
470
  /*
   *	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...
471
  static int vlan_ioctl_handler(struct net *net, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
  {
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
473
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  	struct vlan_ioctl_args args;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
475
  	struct net_device *dev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
479
480
481
482
  
  	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...
483
  	rtnl_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
  	switch (args.cmd) {
  	case SET_VLAN_INGRESS_PRIORITY_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
486
487
488
489
490
491
492
  	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...
493
  		dev = __dev_get_by_name(net, args.device1);
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
494
495
496
497
  		if (!dev)
  			goto out;
  
  		err = -EINVAL;
26a25239d   Joonwoo Park   vlan: Use is_vlan...
498
  		if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
499
500
501
502
503
504
  			goto out;
  	}
  
  	switch (args.cmd) {
  	case SET_VLAN_INGRESS_PRIORITY_CMD:
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
505
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
506
507
508
509
  			break;
  		vlan_dev_set_ingress_priority(dev,
  					      args.u.skb_priority,
  					      args.vlan_qos);
fffe470a8   Patrick McHardy   [VLAN]: Fix SET_V...
510
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
512
513
  		break;
  
  	case SET_VLAN_EGRESS_PRIORITY_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
514
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
515
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
516
517
  			break;
  		err = vlan_dev_set_egress_priority(dev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
521
522
  						   args.u.skb_priority,
  						   args.vlan_qos);
  		break;
  
  	case SET_VLAN_FLAG_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
523
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
524
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
525
  			break;
b3ce0325f   Patrick McHardy   vlan: Change vlan...
526
527
528
  		err = vlan_dev_change_flags(dev,
  					    args.vlan_qos ? args.u.flag : 0,
  					    args.u.flag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
  		break;
  
  	case SET_VLAN_NAME_TYPE_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
532
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
533
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
e35de0261   Pavel Emelyanov   [VLAN]: Lost rtnl...
534
  			break;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
535
536
  		if ((args.u.name_type >= 0) &&
  		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
537
538
539
540
  			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
541
542
543
544
545
546
547
  			err = 0;
  		} else {
  			err = -EINVAL;
  		}
  		break;
  
  	case ADD_VLAN_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
548
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
549
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
550
  			break;
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
551
  		err = register_vlan_device(dev, args.u.VID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552
553
554
  		break;
  
  	case DEL_VLAN_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
555
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
556
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
557
  			break;
23289a37e   Eric Dumazet   net: add a list_h...
558
  		unregister_vlan_dev(dev, NULL);
af3015170   Patrick McHardy   [VLAN]: Simplify ...
559
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
560
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
  	case GET_VLAN_REALDEV_NAME_CMD:
3f5f4346b   Andrew Morton   [8021Q]: vlan_ioc...
562
  		err = 0;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
563
  		vlan_dev_get_realdev_name(dev, args.u.device2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  		if (copy_to_user(arg, &args,
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
565
  				 sizeof(struct vlan_ioctl_args)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
  			err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
  		break;
  
  	case GET_VLAN_VID_CMD:
3f5f4346b   Andrew Morton   [8021Q]: vlan_ioc...
570
  		err = 0;
22d1ba74b   Patrick McHardy   vlan: move struct...
571
  		args.u.VID = vlan_dev_vlan_id(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
  		if (copy_to_user(arg, &args,
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
573
  				 sizeof(struct vlan_ioctl_args)))
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
574
  		      err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
576
577
  		break;
  
  	default:
198a291ce   Patrick McHardy   [VLAN]: Remove no...
578
  		err = -EOPNOTSUPP;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
579
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
580
  	}
7eb1b3d37   Mika Kukkonen   [VLAN]: Add two m...
581
  out:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
582
  	rtnl_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
  	return err;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
585
  static int __net_init vlan_init_net(struct net *net)
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
586
  {
946d1a929   Eric W. Biederman   net: Simplify vla...
587
  	struct vlan_net *vn = net_generic(net, vlan_net_id);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
588
  	int err;
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
589

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

d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
593
594
  	return err;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
595
  static void __net_exit vlan_exit_net(struct net *net)
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
596
  {
cd1c70143   Pavel Emelyanov   [VLAN]: Add a net...
597
  	vlan_proc_cleanup(net);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
598
599
600
601
602
  }
  
  static struct pernet_operations vlan_net_ops = {
  	.init = vlan_init_net,
  	.exit = vlan_exit_net,
946d1a929   Eric W. Biederman   net: Simplify vla...
603
604
  	.id   = &vlan_net_id,
  	.size = sizeof(struct vlan_net),
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
605
  };
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
606
607
608
  static int __init vlan_proto_init(void)
  {
  	int err;
da7c06c4a   Justin Mattock   net:8021q:vlan.c ...
609
610
  	pr_info("%s v%s
  ", vlan_fullname, vlan_version);
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
611

91e2ff352   Eric W. Biederman   net: Teach vlans ...
612
  	err = register_pernet_subsys(&vlan_net_ops);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
613
614
  	if (err < 0)
  		goto err0;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
615
616
617
  	err = register_netdevice_notifier(&vlan_notifier_block);
  	if (err < 0)
  		goto err2;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
618
  	err = vlan_gvrp_init();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
619
620
  	if (err < 0)
  		goto err3;
86fbe9bb5   David Ward   net/8021q: Implem...
621
  	err = vlan_mvrp_init();
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
622
623
  	if (err < 0)
  		goto err4;
86fbe9bb5   David Ward   net/8021q: Implem...
624
625
626
  	err = vlan_netlink_init();
  	if (err < 0)
  		goto err5;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
627
628
  	vlan_ioctl_set(vlan_ioctl_handler);
  	return 0;
86fbe9bb5   David Ward   net/8021q: Implem...
629
630
  err5:
  	vlan_mvrp_uninit();
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
631
632
  err4:
  	vlan_gvrp_uninit();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
633
634
635
  err3:
  	unregister_netdevice_notifier(&vlan_notifier_block);
  err2:
91e2ff352   Eric W. Biederman   net: Teach vlans ...
636
  	unregister_pernet_subsys(&vlan_net_ops);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
637
  err0:
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
638
639
640
641
642
  	return err;
  }
  
  static void __exit vlan_cleanup_module(void)
  {
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
643
644
645
646
  	vlan_ioctl_set(NULL);
  	vlan_netlink_fini();
  
  	unregister_netdevice_notifier(&vlan_notifier_block);
91e2ff352   Eric W. Biederman   net: Teach vlans ...
647
  	unregister_pernet_subsys(&vlan_net_ops);
6e327c11a   Jesper Dangaard Brouer   8021q: Vlan drive...
648
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
649

86fbe9bb5   David Ward   net/8021q: Implem...
650
  	vlan_mvrp_uninit();
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
651
  	vlan_gvrp_uninit();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
652
653
654
655
  }
  
  module_init(vlan_proto_init);
  module_exit(vlan_cleanup_module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);