Blame view

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

5b9ea6e02   Jiri Pirko   vlan: introduce v...
77
78
79
80
  	vlan_info = rtnl_dereference(real_dev->vlan_info);
  	BUG_ON(!vlan_info);
  
  	grp = &vlan_info->grp;
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
81

acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
82
  	/* Take it out of our own structures, but be sure to interlock with
ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
83
84
  	 * HW accelerating devices or SW vlan input packet processing if
  	 * VLAN is not 0 (leave it there for 802.1p).
acc5efbcd   Patrick McHardy   [VLAN]: Clean up ...
85
  	 */
87002b03b   Jiri Pirko   net: introduce vl...
86
87
  	if (vlan_id)
  		vlan_vid_del(real_dev, vlan_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88

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

55aee10de   Eric Dumazet   vlan: fix GVRP at...
91
92
  	if (vlan->flags & VLAN_FLAG_GVRP)
  		vlan_gvrp_request_leave(dev);
29906f6a4   Patrick McHardy   vlan: cleanup mul...
93
  	vlan_group_set_device(grp, vlan_id, NULL);
48752e1b1   Eric Dumazet   vlan: remove one ...
94
95
96
97
  	/* Because unregister_netdevice_queue() makes sure at least one rcu
  	 * grace period is respected before device freeing,
  	 * we dont need to call synchronize_net() here.
  	 */
23289a37e   Eric Dumazet   net: add a list_h...
98
  	unregister_netdevice_queue(dev, head);
ce305002e   Patrick McHardy   vlan: Move device...
99

5b9ea6e02   Jiri Pirko   vlan: introduce v...
100
  	if (grp->nr_vlan_devs == 0)
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
101
  		vlan_gvrp_uninit_applicant(real_dev);
af3015170   Patrick McHardy   [VLAN]: Simplify ...
102
103
  	/* Get rid of the vlan's reference to real_dev */
  	dev_put(real_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  }
9bb8582ef   Patrick McHardy   vlan: TCI related...
105
  int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
  {
656299f70   Stephen Hemminger   vlan: convert to ...
107
108
  	const char *name = real_dev->name;
  	const struct net_device_ops *ops = real_dev->netdev_ops;
40f98e1af   Patrick McHardy   [VLAN]: Clean up ...
109

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
afab2d299   Joe Perches   net: 8021q: Add p...
111
112
  		pr_info("VLANs not supported on %s
  ", name);
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
113
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
  	if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
656299f70   Stephen Hemminger   vlan: convert to ...
116
  	    (!ops->ndo_vlan_rx_add_vid || !ops->ndo_vlan_rx_kill_vid)) {
afab2d299   Joe Perches   net: 8021q: Add p...
117
118
  		pr_info("Device %s has buggy VLAN hw accel
  ", name);
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
119
  		return -EOPNOTSUPP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  	}
65ac6a5fa   Jesse Gross   vlan: Avoid hash ...
121
  	if (vlan_find_dev(real_dev, vlan_id) != NULL)
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
122
  		return -EEXIST;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123

c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
124
125
  	return 0;
  }
07b5b17e1   Patrick McHardy   [VLAN]: Use rtnl_...
126
  int register_vlan_dev(struct net_device *dev)
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
127
  {
7da82c06d   Jiri Pirko   vlan: rename vlan...
128
  	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
129
  	struct net_device *real_dev = vlan->real_dev;
9bb8582ef   Patrick McHardy   vlan: TCI related...
130
  	u16 vlan_id = vlan->vlan_id;
5b9ea6e02   Jiri Pirko   vlan: introduce v...
131
132
  	struct vlan_info *vlan_info;
  	struct vlan_group *grp;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
133
  	int err;
5b9ea6e02   Jiri Pirko   vlan: introduce v...
134
135
136
137
138
139
140
141
142
143
  	err = vlan_vid_add(real_dev, vlan_id);
  	if (err)
  		return err;
  
  	vlan_info = rtnl_dereference(real_dev->vlan_info);
  	/* vlan_info should be there now. vlan_vid_add took care of it */
  	BUG_ON(!vlan_info);
  
  	grp = &vlan_info->grp;
  	if (grp->nr_vlan_devs == 0) {
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
144
145
  		err = vlan_gvrp_init_applicant(real_dev);
  		if (err < 0)
5b9ea6e02   Jiri Pirko   vlan: introduce v...
146
  			goto out_vid_del;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
147
  	}
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
148
149
  	err = vlan_group_prealloc_vid(grp, vlan_id);
  	if (err < 0)
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
150
  		goto out_uninit_applicant;
67727184f   Pavel Emelyanov   [VLAN]: Reduce me...
151

e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
152
153
  	err = register_netdevice(dev);
  	if (err < 0)
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
154
  		goto out_uninit_applicant;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
155

7da82c06d   Jiri Pirko   vlan: rename vlan...
156
  	/* Account for reference in struct vlan_dev_priv */
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
157
  	dev_hold(real_dev);
fc4a74896   Patrick Mullaney   netdevice: provid...
158
  	netif_stacked_transfer_operstate(real_dev, dev);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
159
160
161
162
163
164
  	linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
  
  	/* So, got the sucker initialized, now lets place
  	 * it into our local structure.
  	 */
  	vlan_group_set_device(grp, vlan_id, dev);
5b9ea6e02   Jiri Pirko   vlan: introduce v...
165
  	grp->nr_vlan_devs++;
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
166

e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
167
  	return 0;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
168
  out_uninit_applicant:
5b9ea6e02   Jiri Pirko   vlan: introduce v...
169
  	if (grp->nr_vlan_devs == 0)
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
170
  		vlan_gvrp_uninit_applicant(real_dev);
5b9ea6e02   Jiri Pirko   vlan: introduce v...
171
172
  out_vid_del:
  	vlan_vid_del(real_dev, vlan_id);
e89fe42cd   Patrick McHardy   [VLAN]: Move devi...
173
174
  	return err;
  }
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
175
  /*  Attach a VLAN device to a mac address (ie Ethernet Card).
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
176
   *  Returns 0 if the device was created or a negative error code otherwise.
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
177
   */
9bb8582ef   Patrick McHardy   vlan: TCI related...
178
  static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
179
  {
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
180
  	struct net_device *new_dev;
7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
181
182
  	struct net *net = dev_net(real_dev);
  	struct vlan_net *vn = net_generic(net, vlan_net_id);
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
183
  	char name[IFNAMSIZ];
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
184
  	int err;
c1d3ee992   Patrick McHardy   [VLAN]: Split up ...
185

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
  	/* Gotta set up the fields for the device. */
7a17a2f79   Pavel Emelyanov   [VLAN]: Make the ...
194
  	switch (vn->name_type) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
  	case VLAN_NAME_TYPE_RAW_PLUS_VID:
  		/* name will look like:	 eth1.0005 */
9bb8582ef   Patrick McHardy   vlan: TCI related...
197
  		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
200
201
202
  		break;
  	case VLAN_NAME_TYPE_PLUS_VID_NO_PAD:
  		/* Put our vlan.VID in the name.
  		 * Name will look like:	 vlan5
  		 */
9bb8582ef   Patrick McHardy   vlan: TCI related...
203
  		snprintf(name, IFNAMSIZ, "vlan%i", vlan_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
207
208
  		break;
  	case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD:
  		/* Put our vlan.VID in the name.
  		 * Name will look like:	 eth0.5
  		 */
9bb8582ef   Patrick McHardy   vlan: TCI related...
209
  		snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
213
214
215
  		break;
  	case VLAN_NAME_TYPE_PLUS_VID:
  		/* Put our vlan.VID in the name.
  		 * Name will look like:	 vlan0005
  		 */
  	default:
9bb8582ef   Patrick McHardy   vlan: TCI related...
216
  		snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
3ff50b799   Stephen Hemminger   [NET]: cleanup ex...
217
  	}
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
218

7da82c06d   Jiri Pirko   vlan: rename vlan...
219
  	new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name, vlan_setup);
5dd8d1e9e   Arjan van de Ven   [PATCH] lockdep: ...
220

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

65d292a2e   Pavel Emelyanov   [VLAN]: Allow vla...
224
  	dev_net_set(new_dev, net);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
  	/* need 4 bytes for extra VLAN header info,
  	 * hope the underlying device can handle it.
  	 */
  	new_dev->mtu = real_dev->mtu;
7da82c06d   Jiri Pirko   vlan: rename vlan...
229
230
231
232
  	vlan_dev_priv(new_dev)->vlan_id = vlan_id;
  	vlan_dev_priv(new_dev)->real_dev = real_dev;
  	vlan_dev_priv(new_dev)->dent = NULL;
  	vlan_dev_priv(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233

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

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
242
  out_free_newdev:
  	free_netdev(new_dev);
2ae0bf69b   Patrick McHardy   [VLAN]: Return pr...
243
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
  }
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
245
246
247
  static void vlan_sync_address(struct net_device *dev,
  			      struct net_device *vlandev)
  {
7da82c06d   Jiri Pirko   vlan: rename vlan...
248
  	struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
249
250
251
252
253
254
255
256
257
  
  	/* May be called without an actual change */
  	if (!compare_ether_addr(vlan->real_dev_addr, dev->dev_addr))
  		return;
  
  	/* vlan address was different from the old address and is equal to
  	 * the new address */
  	if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
  	    !compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
a748ee242   Jiri Pirko   net: move address...
258
  		dev_uc_del(dev, vlandev->dev_addr);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
259
260
261
262
263
  
  	/* vlan address was equal to the old address and is different from
  	 * the new address */
  	if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
  	    compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
a748ee242   Jiri Pirko   net: move address...
264
  		dev_uc_add(dev, vlandev->dev_addr);
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
265
266
267
  
  	memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN);
  }
5fb135705   Patrick McHardy   [VLAN]: Propagate...
268
269
270
  static void vlan_transfer_features(struct net_device *dev,
  				   struct net_device *vlandev)
  {
1ae4be22f   Alexander Duyck   vlan: vlan device...
271
  	vlandev->gso_max_size = dev->gso_max_size;
029f5fc31   John Fastabend   8021q: set hard_h...
272
273
274
275
276
  
  	if (dev->features & NETIF_F_HW_VLAN_TX)
  		vlandev->hard_header_len = dev->hard_header_len;
  	else
  		vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
b85daa532   Vasu Dev   vlan: adds fcoe o...
277
278
279
  #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
  	vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
  #endif
8a0427bb6   MichaÅ‚ MirosÅ‚aw   vlan: convert VLA...
280
281
  
  	netdev_update_features(vlandev);
5fb135705   Patrick McHardy   [VLAN]: Propagate...
282
  }
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
283
284
285
286
287
288
  static void __vlan_device_event(struct net_device *dev, unsigned long event)
  {
  	switch (event) {
  	case NETDEV_CHANGENAME:
  		vlan_proc_rem_dev(dev);
  		if (vlan_proc_add_dev(dev) < 0)
afab2d299   Joe Perches   net: 8021q: Add p...
289
290
291
  			pr_warn("failed to change proc name for %s
  ",
  				dev->name);
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
292
  		break;
30688a9a3   Pavel Emelyanov   [VLAN]: Handle vl...
293
294
  	case NETDEV_REGISTER:
  		if (vlan_proc_add_dev(dev) < 0)
afab2d299   Joe Perches   net: 8021q: Add p...
295
296
  			pr_warn("failed to add proc entry for %s
  ", dev->name);
30688a9a3   Pavel Emelyanov   [VLAN]: Handle vl...
297
298
299
300
  		break;
  	case NETDEV_UNREGISTER:
  		vlan_proc_rem_dev(dev);
  		break;
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
301
302
  	}
  }
2029cc2c8   Patrick McHardy   [VLAN]: checkpatc...
303
304
  static int vlan_device_event(struct notifier_block *unused, unsigned long event,
  			     void *ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
  {
  	struct net_device *dev = ptr;
802fb176d   Pavel Emelyanov   [VLAN]: Proc entr...
307
  	struct vlan_group *grp;
5b9ea6e02   Jiri Pirko   vlan: introduce v...
308
  	struct vlan_info *vlan_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
  	int i, flgs;
  	struct net_device *vlandev;
7da82c06d   Jiri Pirko   vlan: rename vlan...
311
  	struct vlan_dev_priv *vlan;
29906f6a4   Patrick McHardy   vlan: cleanup mul...
312
  	LIST_HEAD(list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313

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

ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
317
  	if ((event == NETDEV_UP) &&
87002b03b   Jiri Pirko   net: introduce vl...
318
  	    (dev->features & NETIF_F_HW_VLAN_FILTER)) {
afab2d299   Joe Perches   net: 8021q: Add p...
319
320
  		pr_info("adding VLAN 0 to HW filter on device %s
  ",
ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
321
  			dev->name);
87002b03b   Jiri Pirko   net: introduce vl...
322
  		vlan_vid_add(dev, 0);
ad1afb003   Pedro Garcia   vlan_dev: VLAN 0 ...
323
  	}
5b9ea6e02   Jiri Pirko   vlan: introduce v...
324
325
  	vlan_info = rtnl_dereference(dev->vlan_info);
  	if (!vlan_info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  		goto out;
5b9ea6e02   Jiri Pirko   vlan: introduce v...
327
  	grp = &vlan_info->grp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
331
332
333
334
335
  
  	/* It is OK that we do not hold the group lock right now,
  	 * as we run under the RTNL lock.
  	 */
  
  	switch (event) {
  	case NETDEV_CHANGE:
  		/* Propagate real device state to vlan devices */
b738127df   Jesse Gross   vlan: Rename VLAN...
336
  		for (i = 0; i < VLAN_N_VID; i++) {
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
337
  			vlandev = vlan_group_get_device(grp, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
339
  			if (!vlandev)
  				continue;
fc4a74896   Patrick Mullaney   netdevice: provid...
340
  			netif_stacked_transfer_operstate(dev, vlandev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
  		}
  		break;
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
343
344
  	case NETDEV_CHANGEADDR:
  		/* Adjust unicast filters on underlying device */
b738127df   Jesse Gross   vlan: Rename VLAN...
345
  		for (i = 0; i < VLAN_N_VID; i++) {
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
346
347
348
  			vlandev = vlan_group_get_device(grp, i);
  			if (!vlandev)
  				continue;
d932e04a5   Patrick McHardy   [VLAN]: Don't syn...
349
350
351
  			flgs = vlandev->flags;
  			if (!(flgs & IFF_UP))
  				continue;
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
352
353
  			vlan_sync_address(dev, vlandev);
  		}
2e477c9bd   Herbert Xu   vlan: Propagate p...
354
355
356
  		break;
  
  	case NETDEV_CHANGEMTU:
b738127df   Jesse Gross   vlan: Rename VLAN...
357
  		for (i = 0; i < VLAN_N_VID; i++) {
2e477c9bd   Herbert Xu   vlan: Propagate p...
358
359
360
361
362
363
364
365
366
  			vlandev = vlan_group_get_device(grp, i);
  			if (!vlandev)
  				continue;
  
  			if (vlandev->mtu <= dev->mtu)
  				continue;
  
  			dev_set_mtu(vlandev, dev->mtu);
  		}
8c979c26a   Patrick McHardy   [VLAN]: Fix MAC a...
367
  		break;
5fb135705   Patrick McHardy   [VLAN]: Propagate...
368
369
  	case NETDEV_FEAT_CHANGE:
  		/* Propagate device features to underlying device */
b738127df   Jesse Gross   vlan: Rename VLAN...
370
  		for (i = 0; i < VLAN_N_VID; i++) {
5fb135705   Patrick McHardy   [VLAN]: Propagate...
371
372
373
374
375
376
377
378
  			vlandev = vlan_group_get_device(grp, i);
  			if (!vlandev)
  				continue;
  
  			vlan_transfer_features(dev, vlandev);
  		}
  
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
  	case NETDEV_DOWN:
  		/* Put all VLANs for this dev in the down state too.  */
b738127df   Jesse Gross   vlan: Rename VLAN...
381
  		for (i = 0; i < VLAN_N_VID; i++) {
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
382
  			vlandev = vlan_group_get_device(grp, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
384
385
386
387
388
  			if (!vlandev)
  				continue;
  
  			flgs = vlandev->flags;
  			if (!(flgs & IFF_UP))
  				continue;
7da82c06d   Jiri Pirko   vlan: rename vlan...
389
  			vlan = vlan_dev_priv(vlandev);
5e7565930   Patrick McHardy   vlan: support "lo...
390
391
  			if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
  				dev_change_flags(vlandev, flgs & ~IFF_UP);
fc4a74896   Patrick Mullaney   netdevice: provid...
392
  			netif_stacked_transfer_operstate(dev, vlandev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
397
  		}
  		break;
  
  	case NETDEV_UP:
  		/* Put all VLANs for this dev in the up state too.  */
b738127df   Jesse Gross   vlan: Rename VLAN...
398
  		for (i = 0; i < VLAN_N_VID; i++) {
5c15bdec5   Dan Aloni   [VLAN]: Avoid a 4...
399
  			vlandev = vlan_group_get_device(grp, i);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
400
401
  			if (!vlandev)
  				continue;
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
402

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
  			flgs = vlandev->flags;
  			if (flgs & IFF_UP)
  				continue;
7da82c06d   Jiri Pirko   vlan: rename vlan...
406
  			vlan = vlan_dev_priv(vlandev);
5e7565930   Patrick McHardy   vlan: support "lo...
407
408
  			if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
  				dev_change_flags(vlandev, flgs | IFF_UP);
fc4a74896   Patrick Mullaney   netdevice: provid...
409
  			netif_stacked_transfer_operstate(dev, vlandev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
411
  		}
  		break;
122952fc2   YOSHIFUJI Hideaki   [NET] 8021Q: Fix ...
412

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

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

d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
580
581
  	return err;
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
582
  static void __net_exit vlan_exit_net(struct net *net)
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
583
  {
cd1c70143   Pavel Emelyanov   [VLAN]: Add a net...
584
  	vlan_proc_cleanup(net);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
585
586
587
588
589
  }
  
  static struct pernet_operations vlan_net_ops = {
  	.init = vlan_init_net,
  	.exit = vlan_exit_net,
946d1a929   Eric W. Biederman   net: Simplify vla...
590
591
  	.id   = &vlan_net_id,
  	.size = sizeof(struct vlan_net),
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
592
  };
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
593
594
595
  static int __init vlan_proto_init(void)
  {
  	int err;
da7c06c4a   Justin Mattock   net:8021q:vlan.c ...
596
597
  	pr_info("%s v%s
  ", vlan_fullname, vlan_version);
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
598

91e2ff352   Eric W. Biederman   net: Teach vlans ...
599
  	err = register_pernet_subsys(&vlan_net_ops);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
600
601
  	if (err < 0)
  		goto err0;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
602
603
604
  	err = register_netdevice_notifier(&vlan_notifier_block);
  	if (err < 0)
  		goto err2;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
605
  	err = vlan_gvrp_init();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
606
607
  	if (err < 0)
  		goto err3;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
608
609
610
  	err = vlan_netlink_init();
  	if (err < 0)
  		goto err4;
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
611
612
  	vlan_ioctl_set(vlan_ioctl_handler);
  	return 0;
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
613
614
  err4:
  	vlan_gvrp_uninit();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
615
616
617
  err3:
  	unregister_netdevice_notifier(&vlan_notifier_block);
  err2:
91e2ff352   Eric W. Biederman   net: Teach vlans ...
618
  	unregister_pernet_subsys(&vlan_net_ops);
d9ed0f0e2   Pavel Emelyanov   [VLAN]: Introduce...
619
  err0:
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
620
621
622
623
624
  	return err;
  }
  
  static void __exit vlan_cleanup_module(void)
  {
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
625
626
627
628
  	vlan_ioctl_set(NULL);
  	vlan_netlink_fini();
  
  	unregister_netdevice_notifier(&vlan_notifier_block);
91e2ff352   Eric W. Biederman   net: Teach vlans ...
629
  	unregister_pernet_subsys(&vlan_net_ops);
6e327c11a   Jesper Dangaard Brouer   8021q: Vlan drive...
630
  	rcu_barrier(); /* Wait for completion of call_rcu()'s */
70c03b49b   Patrick McHardy   vlan: Add GVRP su...
631
632
  
  	vlan_gvrp_uninit();
69ab4b7d6   Patrick McHardy   [VLAN]: Clean up ...
633
634
635
636
  }
  
  module_init(vlan_proto_init);
  module_exit(vlan_cleanup_module);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
638
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);