186fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward/*
286fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *	IEEE 802.1Q Multiple VLAN Registration Protocol (MVRP)
386fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *
486fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *	Copyright (c) 2012 Massachusetts Institute of Technology
586fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *
686fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *	Adapted from code in net/8021q/vlan_gvrp.c
786fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *	Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
886fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *
986fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *	This program is free software; you can redistribute it and/or
1086fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *	modify it under the terms of the GNU General Public License
1186fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward *	version 2 as published by the Free Software Foundation.
1286fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward */
1386fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward#include <linux/types.h>
1486fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward#include <linux/if_ether.h>
1586fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward#include <linux/if_vlan.h>
1686fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward#include <net/mrp.h>
1786fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward#include "vlan.h"
1886fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
1986fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward#define MRP_MVRP_ADDRESS	{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x21 }
2086fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
2186fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Wardenum mvrp_attributes {
2286fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	MVRP_ATTR_INVALID,
2386fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	MVRP_ATTR_VID,
2486fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	__MVRP_ATTR_MAX
2586fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward};
2686fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward#define MVRP_ATTR_MAX	(__MVRP_ATTR_MAX - 1)
2786fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
2886fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Wardstatic struct mrp_application vlan_mrp_app __read_mostly = {
2986fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	.type		= MRP_APPLICATION_MVRP,
3086fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	.maxattr	= MVRP_ATTR_MAX,
3186fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	.pkttype.type	= htons(ETH_P_MVRP),
3286fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	.group_address	= MRP_MVRP_ADDRESS,
3386fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	.version	= 0,
3486fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward};
3586fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
3686fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Wardint vlan_mvrp_request_join(const struct net_device *dev)
3786fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward{
3886fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
3986fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	__be16 vlan_id = htons(vlan->vlan_id);
4086fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
411fd9b1fc310314911f66d2f14a8e4f0ef37bf47bPatrick McHardy	if (vlan->vlan_proto != htons(ETH_P_8021Q))
421fd9b1fc310314911f66d2f14a8e4f0ef37bf47bPatrick McHardy		return 0;
4386fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	return mrp_request_join(vlan->real_dev, &vlan_mrp_app,
4486fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward				&vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
4586fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward}
4686fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
4786fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Wardvoid vlan_mvrp_request_leave(const struct net_device *dev)
4886fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward{
4986fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
5086fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	__be16 vlan_id = htons(vlan->vlan_id);
5186fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
521fd9b1fc310314911f66d2f14a8e4f0ef37bf47bPatrick McHardy	if (vlan->vlan_proto != htons(ETH_P_8021Q))
531fd9b1fc310314911f66d2f14a8e4f0ef37bf47bPatrick McHardy		return;
5486fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	mrp_request_leave(vlan->real_dev, &vlan_mrp_app,
5586fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward			  &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
5686fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward}
5786fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
5886fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Wardint vlan_mvrp_init_applicant(struct net_device *dev)
5986fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward{
6086fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	return mrp_init_applicant(dev, &vlan_mrp_app);
6186fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward}
6286fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
6386fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Wardvoid vlan_mvrp_uninit_applicant(struct net_device *dev)
6486fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward{
6586fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	mrp_uninit_applicant(dev, &vlan_mrp_app);
6686fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward}
6786fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
6886fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Wardint __init vlan_mvrp_init(void)
6986fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward{
7086fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	return mrp_register_application(&vlan_mrp_app);
7186fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward}
7286fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward
7386fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Wardvoid vlan_mvrp_uninit(void)
7486fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward{
7586fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward	mrp_unregister_application(&vlan_mrp_app);
7686fbe9bb599fcaf7e92e38dbfdad0414a2d68f7dDavid Ward}
77