Blame view

net/8021q/vlan.c 18.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. */
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

952fcfd08   Sabrina Dubroca   net: remove type_...
160
  	vlan->nest_level = dev_get_nest_level(real_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;
0c0667a85   Wang Sheng-Hui   vlan: cleanup the...
249
250
251
252
253
254
  	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
255

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
  out_free_newdev:
  	free_netdev(new_dev);
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
265
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  }
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
267
268
269
  static void vlan_sync_address(struct net_device *dev,
  			      struct net_device *vlandev)
  {
7da82c06d   Jiri Pirko   vlan: rename vlan...
270
  	struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
271
272
  
  	/* May be called without an actual change */
53a2b3a18   Joe Perches   8021q: Convert co...
273
  	if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr))
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
274
  		return;
308453aa9   Mike Manning   vlan: Propagate M...
275
276
277
  	/* vlan continues to inherit address of lower device */
  	if (vlan_dev_inherit_address(vlandev, dev))
  		goto out;
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
278
279
  	/* 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

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

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

9c5ff24f9   WANG Cong   vlan: fail early ...
340
341
342
343
344
345
  	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...
346

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  	case NETDEV_UNREGISTER:
3b27e1055   David Lamparter   netns: keep vlan ...
431
432
433
  		/* twiddle thumbs on netns device moves */
  		if (dev->reg_state != NETREG_UNREGISTERING)
  			break;
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
434
  		vlan_group_for_each_dev(grp, i, vlandev) {
5b9ea6e02   Jiri Pirko   vlan: introduce v...
435
  			/* removal of last vid destroys vlan_info, abort
29906f6a4   Patrick McHardy   vlan: cleanup mul...
436
  			 * afterwards */
5b9ea6e02   Jiri Pirko   vlan: introduce v...
437
  			if (vlan_info->nr_vids == 1)
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
438
  				last = true;
29906f6a4   Patrick McHardy   vlan: cleanup mul...
439
440
  
  			unregister_vlan_dev(vlandev, &list);
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
441
442
  			if (last)
  				break;
29906f6a4   Patrick McHardy   vlan: cleanup mul...
443
444
  		}
  		unregister_netdevice_many(&list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  		break;
1c01fe14a   Jiri Pirko   net: forbid under...
446
447
448
  
  	case NETDEV_PRE_TYPE_CHANGE:
  		/* Forbid underlaying device to change its type. */
18c22a03a   Jiri Pirko   vlan: allow to ch...
449
450
451
  		if (vlan_uses_dev(dev))
  			return NOTIFY_BAD;
  		break;
99606477a   Ben Hutchings   vlan: Propagate N...
452
453
  
  	case NETDEV_NOTIFY_PEERS:
7c8994323   Ben Hutchings   bonding, ipv4, ip...
454
  	case NETDEV_BONDING_FAILOVER:
4aa5dee4d   Jiri Pirko   net: convert rese...
455
  	case NETDEV_RESEND_IGMP:
99606477a   Ben Hutchings   vlan: Propagate N...
456
  		/* Propagate to vlan devices */
1fd9b1fc3   Patrick McHardy   net: vlan: prepar...
457
  		vlan_group_for_each_dev(grp, i, vlandev)
7c8994323   Ben Hutchings   bonding, ipv4, ip...
458
  			call_netdevice_notifiers(event, vlandev);
99606477a   Ben Hutchings   vlan: Propagate N...
459
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
460
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
463
464
  
  out:
  	return NOTIFY_DONE;
  }
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
465
466
467
  static struct notifier_block vlan_notifier_block __read_mostly = {
  	.notifier_call = vlan_device_event,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
472
  /*
   *	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...
473
  static int vlan_ioctl_handler(struct net *net, void __user *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  {
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
475
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  	struct vlan_ioctl_args args;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
477
  	struct net_device *dev = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
481
482
483
484
  
  	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...
485
  	rtnl_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
  	switch (args.cmd) {
  	case SET_VLAN_INGRESS_PRIORITY_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
488
489
490
491
492
493
494
  	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...
495
  		dev = __dev_get_by_name(net, args.device1);
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
496
497
498
499
  		if (!dev)
  			goto out;
  
  		err = -EINVAL;
26a25239d   Joonwoo Park   vlan: Use is_vlan...
500
  		if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
501
502
503
504
505
506
  			goto out;
  	}
  
  	switch (args.cmd) {
  	case SET_VLAN_INGRESS_PRIORITY_CMD:
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
507
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
508
509
510
511
  			break;
  		vlan_dev_set_ingress_priority(dev,
  					      args.u.skb_priority,
  					      args.vlan_qos);
fffe470a8   Patrick McHardy   [VLAN]: Fix SET_V...
512
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
515
  		break;
  
  	case SET_VLAN_EGRESS_PRIORITY_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
516
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
517
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
518
519
  			break;
  		err = vlan_dev_set_egress_priority(dev,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
522
523
524
  						   args.u.skb_priority,
  						   args.vlan_qos);
  		break;
  
  	case SET_VLAN_FLAG_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
525
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
526
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
527
  			break;
b3ce0325f   Patrick McHardy   vlan: Change vlan...
528
529
530
  		err = vlan_dev_change_flags(dev,
  					    args.vlan_qos ? args.u.flag : 0,
  					    args.u.flag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
532
533
  		break;
  
  	case SET_VLAN_NAME_TYPE_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
534
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
535
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
e35de0261   Pavel Emelyanov   [VLAN]: Lost rtnl...
536
  			break;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
537
538
  		if ((args.u.name_type >= 0) &&
  		    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
539
540
541
542
  			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
543
544
545
546
547
548
549
  			err = 0;
  		} else {
  			err = -EINVAL;
  		}
  		break;
  
  	case ADD_VLAN_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
550
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
551
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
552
  			break;
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
553
  		err = register_vlan_device(dev, args.u.VID);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
556
  		break;
  
  	case DEL_VLAN_CMD:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
557
  		err = -EPERM;
276996fda   Eric W. Biederman   net: Allow the us...
558
  		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
559
  			break;
23289a37e   Eric Dumazet   net: add a list_h...
560
  		unregister_vlan_dev(dev, NULL);
af3015170   Patrick McHardy   [VLAN]: Simplify ...
561
  		err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
  	case GET_VLAN_REALDEV_NAME_CMD:
3f5f4346b   Andrew Morton   [8021Q]: vlan_ioc...
564
  		err = 0;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
565
  		vlan_dev_get_realdev_name(dev, args.u.device2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
  		if (copy_to_user(arg, &args,
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
567
  				 sizeof(struct vlan_ioctl_args)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
  			err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
570
571
  		break;
  
  	case GET_VLAN_VID_CMD:
3f5f4346b   Andrew Morton   [8021Q]: vlan_ioc...
572
  		err = 0;
22d1ba74b   Patrick McHardy   vlan: move struct...
573
  		args.u.VID = vlan_dev_vlan_id(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
  		if (copy_to_user(arg, &args,
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
575
  				 sizeof(struct vlan_ioctl_args)))
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
576
  		      err = -EFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
579
  		break;
  
  	default:
198a291ce   Patrick McHardy   [VLAN]: Remove no...
580
  		err = -EOPNOTSUPP;
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
581
  		break;
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
582
  	}
7eb1b3d37   Mika Kukkonen   [VLAN]: Add two m...
583
  out:
c17d8874f   Patrick McHardy   [VLAN]: Convert n...
584
  	rtnl_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
  	return err;
  }
66e5133f1   Toshiaki Makita   vlan: Add GRO sup...
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  static struct sk_buff **vlan_gro_receive(struct sk_buff **head,
  					 struct sk_buff *skb)
  {
  	struct sk_buff *p, **pp = NULL;
  	struct vlan_hdr *vhdr;
  	unsigned int hlen, off_vlan;
  	const struct packet_offload *ptype;
  	__be16 type;
  	int flush = 1;
  
  	off_vlan = skb_gro_offset(skb);
  	hlen = off_vlan + sizeof(*vhdr);
  	vhdr = skb_gro_header_fast(skb, off_vlan);
  	if (skb_gro_header_hard(skb, hlen)) {
  		vhdr = skb_gro_header_slow(skb, hlen, off_vlan);
  		if (unlikely(!vhdr))
  			goto out;
  	}
  
  	type = vhdr->h_vlan_encapsulated_proto;
  
  	rcu_read_lock();
  	ptype = gro_find_receive_by_type(type);
  	if (!ptype)
  		goto out_unlock;
  
  	flush = 0;
  
  	for (p = *head; p; p = p->next) {
  		struct vlan_hdr *vhdr2;
  
  		if (!NAPI_GRO_CB(p)->same_flow)
  			continue;
  
  		vhdr2 = (struct vlan_hdr *)(p->data + off_vlan);
  		if (compare_vlan_header(vhdr, vhdr2))
  			NAPI_GRO_CB(p)->same_flow = 0;
  	}
  
  	skb_gro_pull(skb, sizeof(*vhdr));
  	skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr));
fcd91dd44   Sabrina Dubroca   net: add recursio...
628
  	pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
66e5133f1   Toshiaki Makita   vlan: Add GRO sup...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
  
  out_unlock:
  	rcu_read_unlock();
  out:
  	NAPI_GRO_CB(skb)->flush |= flush;
  
  	return pp;
  }
  
  static int vlan_gro_complete(struct sk_buff *skb, int nhoff)
  {
  	struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data + nhoff);
  	__be16 type = vhdr->h_vlan_encapsulated_proto;
  	struct packet_offload *ptype;
  	int err = -ENOENT;
  
  	rcu_read_lock();
  	ptype = gro_find_complete_by_type(type);
  	if (ptype)
  		err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(*vhdr));
  
  	rcu_read_unlock();
  	return err;
  }
  
  static struct packet_offload vlan_packet_offloads[] __read_mostly = {
  	{
  		.type = cpu_to_be16(ETH_P_8021Q),
  		.priority = 10,
  		.callbacks = {
  			.gro_receive = vlan_gro_receive,
  			.gro_complete = vlan_gro_complete,
  		},
  	},
  	{
  		.type = cpu_to_be16(ETH_P_8021AD),
  		.priority = 10,
  		.callbacks = {
  			.gro_receive = vlan_gro_receive,
  			.gro_complete = vlan_gro_complete,
  		},
  	},
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
672
  static int __net_init vlan_init_net(struct net *net)
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
673
  {
946d1a929   Eric W. Biederman   net: Simplify vla...
674
  	struct vlan_net *vn = net_generic(net, vlan_net_id);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
675
  	int err;
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
676

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

d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
680
681
  	return err;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
682
  static void __net_exit vlan_exit_net(struct net *net)
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
683
  {
cd1c70143   Pavel Emelyanov   [VLAN]: Add a net...
684
  	vlan_proc_cleanup(net);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
685
686
687
688
689
  }
  
  static struct pernet_operations vlan_net_ops = {
  	.init = vlan_init_net,
  	.exit = vlan_exit_net,
946d1a929   Eric W. Biederman   net: Simplify vla...
690
691
  	.id   = &vlan_net_id,
  	.size = sizeof(struct vlan_net),
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
692
  };
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
693
694
695
  static int __init vlan_proto_init(void)
  {
  	int err;
66e5133f1   Toshiaki Makita   vlan: Add GRO sup...
696
  	unsigned int i;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
697

da7c06c4a   Justin Mattock   net:8021q:vlan.c ...
698
699
  	pr_info("%s v%s
  ", vlan_fullname, vlan_version);
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
700

91e2ff352   Eric W. Biederman   net: Teach vlans ...
701
  	err = register_pernet_subsys(&vlan_net_ops);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
702
703
  	if (err < 0)
  		goto err0;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
704
705
706
  	err = register_netdevice_notifier(&vlan_notifier_block);
  	if (err < 0)
  		goto err2;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
707
  	err = vlan_gvrp_init();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
708
709
  	if (err < 0)
  		goto err3;
86fbe9bb5   David Ward   net/8021q: Implem...
710
  	err = vlan_mvrp_init();
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
711
712
  	if (err < 0)
  		goto err4;
86fbe9bb5   David Ward   net/8021q: Implem...
713
714
715
  	err = vlan_netlink_init();
  	if (err < 0)
  		goto err5;
66e5133f1   Toshiaki Makita   vlan: Add GRO sup...
716
717
  	for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++)
  		dev_add_offload(&vlan_packet_offloads[i]);
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
718
719
  	vlan_ioctl_set(vlan_ioctl_handler);
  	return 0;
86fbe9bb5   David Ward   net/8021q: Implem...
720
721
  err5:
  	vlan_mvrp_uninit();
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
722
723
  err4:
  	vlan_gvrp_uninit();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
724
725
726
  err3:
  	unregister_netdevice_notifier(&vlan_notifier_block);
  err2:
91e2ff352   Eric W. Biederman   net: Teach vlans ...
727
  	unregister_pernet_subsys(&vlan_net_ops);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
728
  err0:
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
729
730
731
732
733
  	return err;
  }
  
  static void __exit vlan_cleanup_module(void)
  {
66e5133f1   Toshiaki Makita   vlan: Add GRO sup...
734
  	unsigned int i;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
735
  	vlan_ioctl_set(NULL);
66e5133f1   Toshiaki Makita   vlan: Add GRO sup...
736
737
738
  
  	for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++)
  		dev_remove_offload(&vlan_packet_offloads[i]);
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
739
740
741
  	vlan_netlink_fini();
  
  	unregister_netdevice_notifier(&vlan_notifier_block);
91e2ff352   Eric W. Biederman   net: Teach vlans ...
742
  	unregister_pernet_subsys(&vlan_net_ops);
6e327c11a   Jesper Dangaard Brouer   8021q: Vlan drive...
743
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
744

86fbe9bb5   David Ward   net/8021q: Implem...
745
  	vlan_mvrp_uninit();
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
746
  	vlan_gvrp_uninit();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
747
748
749
750
  }
  
  module_init(vlan_proto_init);
  module_exit(vlan_cleanup_module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
752
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);