vlan.c 19.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * INET		802.1Q VLAN
 *		Ethernet-type device handling.
 *
 * Authors:	Ben Greear <greearb@candelatech.com>
P
Patrick McHardy 已提交
6
 *              Please send support related email to: netdev@vger.kernel.org
L
Linus Torvalds 已提交
7
 *              VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
8
 *
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20
 * 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.
 */

J
Joe Perches 已提交
21 22
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

23
#include <linux/capability.h>
L
Linus Torvalds 已提交
24 25 26
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
27
#include <linux/slab.h>
L
Linus Torvalds 已提交
28
#include <linux/init.h>
29
#include <linux/rculist.h>
L
Linus Torvalds 已提交
30 31 32 33
#include <net/p8022.h>
#include <net/arp.h>
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
34
#include <net/rtnetlink.h>
35
#include <net/net_namespace.h>
36
#include <net/netns/generic.h>
37
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
38 39 40 41 42 43 44 45 46

#include <linux/if_vlan.h>
#include "vlan.h"
#include "vlanproc.h"

#define DRV_VERSION "1.8"

/* Global VLAN variables */

47
unsigned int vlan_net_id __read_mostly;
48

49 50
const char vlan_fullname[] = "802.1Q VLAN Support";
const char vlan_version[] = DRV_VERSION;
L
Linus Torvalds 已提交
51 52 53

/* End of global variables definitions. */

54 55
static int vlan_group_prealloc_vid(struct vlan_group *vg,
				   __be16 vlan_proto, u16 vlan_id)
56 57
{
	struct net_device **array;
58
	unsigned int pidx, vidx;
59 60 61 62
	unsigned int size;

	ASSERT_RTNL();

63 64 65
	pidx  = vlan_proto_idx(vlan_proto);
	vidx  = vlan_id / VLAN_GROUP_ARRAY_PART_LEN;
	array = vg->vlan_devices_arrays[pidx][vidx];
66 67 68 69 70 71 72 73
	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;

74
	vg->vlan_devices_arrays[pidx][vidx] = array;
75
	return 0;
76 77
}

78
void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
L
Linus Torvalds 已提交
79
{
80
	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
81
	struct net_device *real_dev = vlan->real_dev;
82
	struct vlan_info *vlan_info;
L
Linus Torvalds 已提交
83
	struct vlan_group *grp;
84
	u16 vlan_id = vlan->vlan_id;
L
Linus Torvalds 已提交
85 86

	ASSERT_RTNL();
87

88 89 90 91
	vlan_info = rtnl_dereference(real_dev->vlan_info);
	BUG_ON(!vlan_info);

	grp = &vlan_info->grp;
92

93
	grp->nr_vlan_devs--;
94

95 96
	if (vlan->flags & VLAN_FLAG_MVRP)
		vlan_mvrp_request_leave(dev);
E
Eric Dumazet 已提交
97 98 99
	if (vlan->flags & VLAN_FLAG_GVRP)
		vlan_gvrp_request_leave(dev);

100
	vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, NULL);
101 102

	netdev_upper_dev_unlink(real_dev, dev);
103 104 105 106
	/* 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.
	 */
107
	unregister_netdevice_queue(dev, head);
108

109 110
	if (grp->nr_vlan_devs == 0) {
		vlan_mvrp_uninit_applicant(real_dev);
P
Patrick McHardy 已提交
111
		vlan_gvrp_uninit_applicant(real_dev);
112
	}
P
Patrick McHardy 已提交
113

114 115 116 117 118
	/* 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)
119
		vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id);
120

121 122
	/* Get rid of the vlan's reference to real_dev */
	dev_put(real_dev);
L
Linus Torvalds 已提交
123 124
}

125 126
int vlan_check_real_dev(struct net_device *real_dev,
			__be16 protocol, u16 vlan_id)
L
Linus Torvalds 已提交
127
{
128
	const char *name = real_dev->name;
129

L
Linus Torvalds 已提交
130
	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
J
Joe Perches 已提交
131
		pr_info("VLANs not supported on %s\n", name);
P
Patrick McHardy 已提交
132
		return -EOPNOTSUPP;
L
Linus Torvalds 已提交
133 134
	}

135
	if (vlan_find_dev(real_dev, protocol, vlan_id) != NULL)
P
Patrick McHardy 已提交
136
		return -EEXIST;
L
Linus Torvalds 已提交
137

P
Patrick McHardy 已提交
138 139 140
	return 0;
}

141
int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack)
142
{
143
	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
144
	struct net_device *real_dev = vlan->real_dev;
145
	u16 vlan_id = vlan->vlan_id;
146 147
	struct vlan_info *vlan_info;
	struct vlan_group *grp;
148 149
	int err;

150
	err = vlan_vid_add(real_dev, vlan->vlan_proto, vlan_id);
151 152 153 154 155 156 157 158 159
	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) {
P
Patrick McHardy 已提交
160 161
		err = vlan_gvrp_init_applicant(real_dev);
		if (err < 0)
162
			goto out_vid_del;
163 164 165
		err = vlan_mvrp_init_applicant(real_dev);
		if (err < 0)
			goto out_uninit_gvrp;
166 167
	}

168
	err = vlan_group_prealloc_vid(grp, vlan->vlan_proto, vlan_id);
169
	if (err < 0)
170
		goto out_uninit_mvrp;
171

172
	vlan->nest_level = dev_get_nest_level(real_dev) + 1;
173 174
	err = register_netdevice(dev);
	if (err < 0)
175 176
		goto out_uninit_mvrp;

177
	err = netdev_upper_dev_link(real_dev, dev, extack);
178 179
	if (err)
		goto out_unregister_netdev;
180

181
	/* Account for reference in struct vlan_dev_priv */
182 183
	dev_hold(real_dev);

184
	netif_stacked_transfer_operstate(real_dev, dev);
185 186 187 188 189
	linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */

	/* So, got the sucker initialized, now lets place
	 * it into our local structure.
	 */
190
	vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, dev);
191
	grp->nr_vlan_devs++;
192 193 194

	return 0;

195 196
out_unregister_netdev:
	unregister_netdevice(dev);
197 198 199 200
out_uninit_mvrp:
	if (grp->nr_vlan_devs == 0)
		vlan_mvrp_uninit_applicant(real_dev);
out_uninit_gvrp:
201
	if (grp->nr_vlan_devs == 0)
P
Patrick McHardy 已提交
202
		vlan_gvrp_uninit_applicant(real_dev);
203
out_vid_del:
204
	vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id);
205 206 207
	return err;
}

P
Patrick McHardy 已提交
208
/*  Attach a VLAN device to a mac address (ie Ethernet Card).
209
 *  Returns 0 if the device was created or a negative error code otherwise.
P
Patrick McHardy 已提交
210
 */
211
static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
P
Patrick McHardy 已提交
212 213
{
	struct net_device *new_dev;
214
	struct vlan_dev_priv *vlan;
215 216
	struct net *net = dev_net(real_dev);
	struct vlan_net *vn = net_generic(net, vlan_net_id);
P
Patrick McHardy 已提交
217
	char name[IFNAMSIZ];
218
	int err;
P
Patrick McHardy 已提交
219

220
	if (vlan_id >= VLAN_VID_MASK)
221
		return -ERANGE;
P
Patrick McHardy 已提交
222

223
	err = vlan_check_real_dev(real_dev, htons(ETH_P_8021Q), vlan_id);
224 225
	if (err < 0)
		return err;
P
Patrick McHardy 已提交
226

L
Linus Torvalds 已提交
227
	/* Gotta set up the fields for the device. */
228
	switch (vn->name_type) {
L
Linus Torvalds 已提交
229 230
	case VLAN_NAME_TYPE_RAW_PLUS_VID:
		/* name will look like:	 eth1.0005 */
231
		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id);
L
Linus Torvalds 已提交
232 233 234 235 236
		break;
	case VLAN_NAME_TYPE_PLUS_VID_NO_PAD:
		/* Put our vlan.VID in the name.
		 * Name will look like:	 vlan5
		 */
237
		snprintf(name, IFNAMSIZ, "vlan%i", vlan_id);
L
Linus Torvalds 已提交
238 239 240 241 242
		break;
	case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD:
		/* Put our vlan.VID in the name.
		 * Name will look like:	 eth0.5
		 */
243
		snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
L
Linus Torvalds 已提交
244 245 246 247 248 249
		break;
	case VLAN_NAME_TYPE_PLUS_VID:
		/* Put our vlan.VID in the name.
		 * Name will look like:	 vlan0005
		 */
	default:
250
		snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
251
	}
252

253 254
	new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name,
			       NET_NAME_UNKNOWN, vlan_setup);
255

L
Linus Torvalds 已提交
256
	if (new_dev == NULL)
257
		return -ENOBUFS;
L
Linus Torvalds 已提交
258

259
	dev_net_set(new_dev, net);
L
Linus Torvalds 已提交
260 261 262 263 264
	/* need 4 bytes for extra VLAN header info,
	 * hope the underlying device can handle it.
	 */
	new_dev->mtu = real_dev->mtu;

265 266 267 268 269 270
	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;
L
Linus Torvalds 已提交
271

P
Patrick McHardy 已提交
272
	new_dev->rtnl_link_ops = &vlan_link_ops;
273
	err = register_vlan_dev(new_dev, NULL);
274
	if (err < 0)
275
		goto out_free_newdev;
L
Linus Torvalds 已提交
276

277
	return 0;
L
Linus Torvalds 已提交
278 279

out_free_newdev:
280 281
	if (new_dev->reg_state == NETREG_UNINITIALIZED)
		free_netdev(new_dev);
282
	return err;
L
Linus Torvalds 已提交
283 284
}

285 286 287
static void vlan_sync_address(struct net_device *dev,
			      struct net_device *vlandev)
{
288
	struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
289 290

	/* May be called without an actual change */
291
	if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr))
292 293
		return;

294 295 296 297
	/* vlan continues to inherit address of lower device */
	if (vlan_dev_inherit_address(vlandev, dev))
		goto out;

298 299
	/* vlan address was different from the old address and is equal to
	 * the new address */
300 301
	if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
	    ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
302
		dev_uc_del(dev, vlandev->dev_addr);
303 304 305

	/* vlan address was equal to the old address and is different from
	 * the new address */
306 307
	if (ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
	    !ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
308
		dev_uc_add(dev, vlandev->dev_addr);
309

310
out:
J
Joe Perches 已提交
311
	ether_addr_copy(vlan->real_dev_addr, dev->dev_addr);
312 313
}

314 315 316
static void vlan_transfer_features(struct net_device *dev,
				   struct net_device *vlandev)
{
317 318
	struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);

319
	vlandev->gso_max_size = dev->gso_max_size;
E
Eric Dumazet 已提交
320
	vlandev->gso_max_segs = dev->gso_max_segs;
321

322
	if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
323 324 325 326
		vlandev->hard_header_len = dev->hard_header_len;
	else
		vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;

A
Amerigo Wang 已提交
327
#if IS_ENABLED(CONFIG_FCOE)
328 329
	vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
#endif
330

331 332 333
	vlandev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
	vlandev->priv_flags |= (vlan->real_dev->priv_flags & IFF_XMIT_DST_RELEASE);

334
	netdev_update_features(vlandev);
335 336
}

337
static int __vlan_device_event(struct net_device *dev, unsigned long event)
338
{
339 340
	int err = 0;

341 342 343
	switch (event) {
	case NETDEV_CHANGENAME:
		vlan_proc_rem_dev(dev);
344
		err = vlan_proc_add_dev(dev);
345
		break;
346
	case NETDEV_REGISTER:
347
		err = vlan_proc_add_dev(dev);
348 349 350 351
		break;
	case NETDEV_UNREGISTER:
		vlan_proc_rem_dev(dev);
		break;
352
	}
353 354

	return err;
355 356
}

P
Patrick McHardy 已提交
357 358
static int vlan_device_event(struct notifier_block *unused, unsigned long event,
			     void *ptr)
L
Linus Torvalds 已提交
359
{
360
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
361
	struct vlan_group *grp;
362
	struct vlan_info *vlan_info;
L
Linus Torvalds 已提交
363 364
	int i, flgs;
	struct net_device *vlandev;
365
	struct vlan_dev_priv *vlan;
366
	bool last = false;
367
	LIST_HEAD(list);
L
Linus Torvalds 已提交
368

369 370 371 372 373 374
	if (is_vlan_dev(dev)) {
		int err = __vlan_device_event(dev, event);

		if (err)
			return notifier_from_errno(err);
	}
375

376
	if ((event == NETDEV_UP) &&
377
	    (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
J
Joe Perches 已提交
378
		pr_info("adding VLAN 0 to HW filter on device %s\n",
379
			dev->name);
380
		vlan_vid_add(dev, htons(ETH_P_8021Q), 0);
381
	}
382 383 384
	if (event == NETDEV_DOWN &&
	    (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
		vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
385

386 387
	vlan_info = rtnl_dereference(dev->vlan_info);
	if (!vlan_info)
L
Linus Torvalds 已提交
388
		goto out;
389
	grp = &vlan_info->grp;
L
Linus Torvalds 已提交
390 391 392 393 394 395 396 397

	/* 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 */
398
		vlan_group_for_each_dev(grp, i, vlandev)
399
			netif_stacked_transfer_operstate(dev, vlandev);
L
Linus Torvalds 已提交
400 401
		break;

402 403
	case NETDEV_CHANGEADDR:
		/* Adjust unicast filters on underlying device */
404
		vlan_group_for_each_dev(grp, i, vlandev) {
405 406 407 408
			flgs = vlandev->flags;
			if (!(flgs & IFF_UP))
				continue;

409 410
			vlan_sync_address(dev, vlandev);
		}
411 412 413
		break;

	case NETDEV_CHANGEMTU:
414
		vlan_group_for_each_dev(grp, i, vlandev) {
415 416 417 418 419
			if (vlandev->mtu <= dev->mtu)
				continue;

			dev_set_mtu(vlandev, dev->mtu);
		}
420 421
		break;

422 423
	case NETDEV_FEAT_CHANGE:
		/* Propagate device features to underlying device */
424
		vlan_group_for_each_dev(grp, i, vlandev)
425 426 427
			vlan_transfer_features(dev, vlandev);
		break;

428 429 430 431
	case NETDEV_DOWN: {
		struct net_device *tmp;
		LIST_HEAD(close_list);

L
Linus Torvalds 已提交
432
		/* Put all VLANs for this dev in the down state too.  */
433
		vlan_group_for_each_dev(grp, i, vlandev) {
L
Linus Torvalds 已提交
434 435 436 437
			flgs = vlandev->flags;
			if (!(flgs & IFF_UP))
				continue;

438
			vlan = vlan_dev_priv(vlandev);
439
			if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
440 441 442 443 444 445
				list_add(&vlandev->close_list, &close_list);
		}

		dev_close_many(&close_list, false);

		list_for_each_entry_safe(vlandev, tmp, &close_list, close_list) {
446
			netif_stacked_transfer_operstate(dev, vlandev);
447
			list_del_init(&vlandev->close_list);
L
Linus Torvalds 已提交
448
		}
449
		list_del(&close_list);
L
Linus Torvalds 已提交
450
		break;
451
	}
L
Linus Torvalds 已提交
452 453
	case NETDEV_UP:
		/* Put all VLANs for this dev in the up state too.  */
454
		vlan_group_for_each_dev(grp, i, vlandev) {
455
			flgs = dev_get_flags(vlandev);
L
Linus Torvalds 已提交
456 457 458
			if (flgs & IFF_UP)
				continue;

459
			vlan = vlan_dev_priv(vlandev);
460 461
			if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
				dev_change_flags(vlandev, flgs | IFF_UP);
462
			netif_stacked_transfer_operstate(dev, vlandev);
L
Linus Torvalds 已提交
463 464
		}
		break;
465

L
Linus Torvalds 已提交
466
	case NETDEV_UNREGISTER:
467 468 469 470
		/* twiddle thumbs on netns device moves */
		if (dev->reg_state != NETREG_UNREGISTERING)
			break;

471
		vlan_group_for_each_dev(grp, i, vlandev) {
472
			/* removal of last vid destroys vlan_info, abort
473
			 * afterwards */
474
			if (vlan_info->nr_vids == 1)
475
				last = true;
476 477

			unregister_vlan_dev(vlandev, &list);
478 479
			if (last)
				break;
480 481
		}
		unregister_netdevice_many(&list);
L
Linus Torvalds 已提交
482
		break;
483 484 485

	case NETDEV_PRE_TYPE_CHANGE:
		/* Forbid underlaying device to change its type. */
486 487 488
		if (vlan_uses_dev(dev))
			return NOTIFY_BAD;
		break;
489 490

	case NETDEV_NOTIFY_PEERS:
491
	case NETDEV_BONDING_FAILOVER:
492
	case NETDEV_RESEND_IGMP:
493
		/* Propagate to vlan devices */
494
		vlan_group_for_each_dev(grp, i, vlandev)
495
			call_netdevice_notifiers(event, vlandev);
496
		break;
497
	}
L
Linus Torvalds 已提交
498 499 500 501 502

out:
	return NOTIFY_DONE;
}

503 504 505 506
static struct notifier_block vlan_notifier_block __read_mostly = {
	.notifier_call = vlan_device_event,
};

L
Linus Torvalds 已提交
507 508 509 510 511
/*
 *	VLAN IOCTL handler.
 *	o execute requested action or pass command to the device driver
 *   arg is really a struct vlan_ioctl_args __user *.
 */
512
static int vlan_ioctl_handler(struct net *net, void __user *arg)
L
Linus Torvalds 已提交
513
{
514
	int err;
L
Linus Torvalds 已提交
515
	struct vlan_ioctl_args args;
516
	struct net_device *dev = NULL;
L
Linus Torvalds 已提交
517 518 519 520 521

	if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
		return -EFAULT;

	/* Null terminate this sucker, just in case. */
522 523
	args.device1[sizeof(args.device1) - 1] = 0;
	args.u.device2[sizeof(args.u.device2) - 1] = 0;
L
Linus Torvalds 已提交
524

525 526
	rtnl_lock();

L
Linus Torvalds 已提交
527 528
	switch (args.cmd) {
	case SET_VLAN_INGRESS_PRIORITY_CMD:
529 530 531 532 533 534 535
	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;
536
		dev = __dev_get_by_name(net, args.device1);
537 538 539 540
		if (!dev)
			goto out;

		err = -EINVAL;
J
Joonwoo Park 已提交
541
		if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev))
542 543 544 545 546 547
			goto out;
	}

	switch (args.cmd) {
	case SET_VLAN_INGRESS_PRIORITY_CMD:
		err = -EPERM;
548
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
549 550 551 552
			break;
		vlan_dev_set_ingress_priority(dev,
					      args.u.skb_priority,
					      args.vlan_qos);
553
		err = 0;
L
Linus Torvalds 已提交
554 555 556
		break;

	case SET_VLAN_EGRESS_PRIORITY_CMD:
557
		err = -EPERM;
558
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
559 560
			break;
		err = vlan_dev_set_egress_priority(dev,
L
Linus Torvalds 已提交
561 562 563 564 565
						   args.u.skb_priority,
						   args.vlan_qos);
		break;

	case SET_VLAN_FLAG_CMD:
566
		err = -EPERM;
567
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
568
			break;
569 570 571
		err = vlan_dev_change_flags(dev,
					    args.vlan_qos ? args.u.flag : 0,
					    args.u.flag);
L
Linus Torvalds 已提交
572 573 574
		break;

	case SET_VLAN_NAME_TYPE_CMD:
575
		err = -EPERM;
576
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
577
			break;
578
		if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) {
579 580 581 582
			struct vlan_net *vn;

			vn = net_generic(net, vlan_net_id);
			vn->name_type = args.u.name_type;
L
Linus Torvalds 已提交
583 584 585 586 587 588 589
			err = 0;
		} else {
			err = -EINVAL;
		}
		break;

	case ADD_VLAN_CMD:
590
		err = -EPERM;
591
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
592
			break;
593
		err = register_vlan_device(dev, args.u.VID);
L
Linus Torvalds 已提交
594 595 596
		break;

	case DEL_VLAN_CMD:
597
		err = -EPERM;
598
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
599
			break;
600
		unregister_vlan_dev(dev, NULL);
601
		err = 0;
L
Linus Torvalds 已提交
602 603 604
		break;

	case GET_VLAN_REALDEV_NAME_CMD:
605
		err = 0;
606
		vlan_dev_get_realdev_name(dev, args.u.device2);
L
Linus Torvalds 已提交
607
		if (copy_to_user(arg, &args,
P
Patrick McHardy 已提交
608
				 sizeof(struct vlan_ioctl_args)))
L
Linus Torvalds 已提交
609 610 611 612
			err = -EFAULT;
		break;

	case GET_VLAN_VID_CMD:
613
		err = 0;
614
		args.u.VID = vlan_dev_vlan_id(dev);
L
Linus Torvalds 已提交
615
		if (copy_to_user(arg, &args,
P
Patrick McHardy 已提交
616
				 sizeof(struct vlan_ioctl_args)))
617
		      err = -EFAULT;
L
Linus Torvalds 已提交
618 619 620
		break;

	default:
621
		err = -EOPNOTSUPP;
622
		break;
623
	}
624
out:
625
	rtnl_unlock();
L
Linus Torvalds 已提交
626 627 628
	return err;
}

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
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));
S
Sabrina Dubroca 已提交
670
	pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714

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,
		},
	},
};

715
static int __net_init vlan_init_net(struct net *net)
716
{
717
	struct vlan_net *vn = net_generic(net, vlan_net_id);
718 719
	int err;

720 721
	vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;

722 723
	err = vlan_proc_init(net);

724 725 726
	return err;
}

727
static void __net_exit vlan_exit_net(struct net *net)
728
{
729
	vlan_proc_cleanup(net);
730 731 732 733 734
}

static struct pernet_operations vlan_net_ops = {
	.init = vlan_init_net,
	.exit = vlan_exit_net,
735 736
	.id   = &vlan_net_id,
	.size = sizeof(struct vlan_net),
737 738
};

739 740 741
static int __init vlan_proto_init(void)
{
	int err;
742
	unsigned int i;
743

744
	pr_info("%s v%s\n", vlan_fullname, vlan_version);
745

746
	err = register_pernet_subsys(&vlan_net_ops);
747 748 749
	if (err < 0)
		goto err0;

750 751 752 753
	err = register_netdevice_notifier(&vlan_notifier_block);
	if (err < 0)
		goto err2;

P
Patrick McHardy 已提交
754
	err = vlan_gvrp_init();
755 756 757
	if (err < 0)
		goto err3;

758
	err = vlan_mvrp_init();
P
Patrick McHardy 已提交
759 760 761
	if (err < 0)
		goto err4;

762 763 764 765
	err = vlan_netlink_init();
	if (err < 0)
		goto err5;

766 767 768
	for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++)
		dev_add_offload(&vlan_packet_offloads[i]);

769 770 771
	vlan_ioctl_set(vlan_ioctl_handler);
	return 0;

772 773
err5:
	vlan_mvrp_uninit();
P
Patrick McHardy 已提交
774 775
err4:
	vlan_gvrp_uninit();
776 777 778
err3:
	unregister_netdevice_notifier(&vlan_notifier_block);
err2:
779
	unregister_pernet_subsys(&vlan_net_ops);
780
err0:
781 782 783 784 785
	return err;
}

static void __exit vlan_cleanup_module(void)
{
786 787
	unsigned int i;

788
	vlan_ioctl_set(NULL);
789 790 791 792

	for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++)
		dev_remove_offload(&vlan_packet_offloads[i]);

793 794 795 796
	vlan_netlink_fini();

	unregister_netdevice_notifier(&vlan_notifier_block);

797
	unregister_pernet_subsys(&vlan_net_ops);
798
	rcu_barrier(); /* Wait for completion of call_rcu()'s */
P
Patrick McHardy 已提交
799

800
	vlan_mvrp_uninit();
P
Patrick McHardy 已提交
801
	vlan_gvrp_uninit();
802 803 804 805 806
}

module_init(vlan_proto_init);
module_exit(vlan_cleanup_module);

L
Linus Torvalds 已提交
807 808
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);