net/8021q: Implement Multiple VLAN Registration Protocol (MVRP)
Initial implementation of the Multiple VLAN Registration Protocol
(MVRP) from IEEE 802.1Q-2011, based on the existing implementation
of the GARP VLAN Registration Protocol (GVRP).
Signed-off-by: David Ward <david.ward@ll.mit.edu>
Acked-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index addc578..a187144 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -95,6 +95,8 @@
grp->nr_vlan_devs--;
+ if (vlan->flags & VLAN_FLAG_MVRP)
+ vlan_mvrp_request_leave(dev);
if (vlan->flags & VLAN_FLAG_GVRP)
vlan_gvrp_request_leave(dev);
@@ -107,8 +109,10 @@
netdev_upper_dev_unlink(real_dev, dev);
- if (grp->nr_vlan_devs == 0)
+ if (grp->nr_vlan_devs == 0) {
+ vlan_mvrp_uninit_applicant(real_dev);
vlan_gvrp_uninit_applicant(real_dev);
+ }
/* Get rid of the vlan's reference to real_dev */
dev_put(real_dev);
@@ -151,15 +155,18 @@
err = vlan_gvrp_init_applicant(real_dev);
if (err < 0)
goto out_vid_del;
+ err = vlan_mvrp_init_applicant(real_dev);
+ if (err < 0)
+ goto out_uninit_gvrp;
}
err = vlan_group_prealloc_vid(grp, vlan_id);
if (err < 0)
- goto out_uninit_applicant;
+ goto out_uninit_mvrp;
err = netdev_upper_dev_link(real_dev, dev);
if (err)
- goto out_uninit_applicant;
+ goto out_uninit_mvrp;
err = register_netdevice(dev);
if (err < 0)
@@ -181,7 +188,10 @@
out_upper_dev_unlink:
netdev_upper_dev_unlink(real_dev, dev);
-out_uninit_applicant:
+out_uninit_mvrp:
+ if (grp->nr_vlan_devs == 0)
+ vlan_mvrp_uninit_applicant(real_dev);
+out_uninit_gvrp:
if (grp->nr_vlan_devs == 0)
vlan_gvrp_uninit_applicant(real_dev);
out_vid_del:
@@ -655,13 +665,19 @@
if (err < 0)
goto err3;
- err = vlan_netlink_init();
+ err = vlan_mvrp_init();
if (err < 0)
goto err4;
+ err = vlan_netlink_init();
+ if (err < 0)
+ goto err5;
+
vlan_ioctl_set(vlan_ioctl_handler);
return 0;
+err5:
+ vlan_mvrp_uninit();
err4:
vlan_gvrp_uninit();
err3:
@@ -682,6 +698,7 @@
unregister_pernet_subsys(&vlan_net_ops);
rcu_barrier(); /* Wait for completion of call_rcu()'s */
+ vlan_mvrp_uninit();
vlan_gvrp_uninit();
}