162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *	IEEE 802.1Q Multiple VLAN Registration Protocol (MVRP)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *	Copyright (c) 2012 Massachusetts Institute of Technology
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *	Adapted from code in net/8021q/vlan_gvrp.c
862306a36Sopenharmony_ci *	Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci#include <linux/types.h>
1162306a36Sopenharmony_ci#include <linux/if_ether.h>
1262306a36Sopenharmony_ci#include <linux/if_vlan.h>
1362306a36Sopenharmony_ci#include <net/mrp.h>
1462306a36Sopenharmony_ci#include "vlan.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define MRP_MVRP_ADDRESS	{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x21 }
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cienum mvrp_attributes {
1962306a36Sopenharmony_ci	MVRP_ATTR_INVALID,
2062306a36Sopenharmony_ci	MVRP_ATTR_VID,
2162306a36Sopenharmony_ci	__MVRP_ATTR_MAX
2262306a36Sopenharmony_ci};
2362306a36Sopenharmony_ci#define MVRP_ATTR_MAX	(__MVRP_ATTR_MAX - 1)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic struct mrp_application vlan_mrp_app __read_mostly = {
2662306a36Sopenharmony_ci	.type		= MRP_APPLICATION_MVRP,
2762306a36Sopenharmony_ci	.maxattr	= MVRP_ATTR_MAX,
2862306a36Sopenharmony_ci	.pkttype.type	= htons(ETH_P_MVRP),
2962306a36Sopenharmony_ci	.group_address	= MRP_MVRP_ADDRESS,
3062306a36Sopenharmony_ci	.version	= 0,
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciint vlan_mvrp_request_join(const struct net_device *dev)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
3662306a36Sopenharmony_ci	__be16 vlan_id = htons(vlan->vlan_id);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (vlan->vlan_proto != htons(ETH_P_8021Q))
3962306a36Sopenharmony_ci		return 0;
4062306a36Sopenharmony_ci	return mrp_request_join(vlan->real_dev, &vlan_mrp_app,
4162306a36Sopenharmony_ci				&vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_civoid vlan_mvrp_request_leave(const struct net_device *dev)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	const struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
4762306a36Sopenharmony_ci	__be16 vlan_id = htons(vlan->vlan_id);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	if (vlan->vlan_proto != htons(ETH_P_8021Q))
5062306a36Sopenharmony_ci		return;
5162306a36Sopenharmony_ci	mrp_request_leave(vlan->real_dev, &vlan_mrp_app,
5262306a36Sopenharmony_ci			  &vlan_id, sizeof(vlan_id), MVRP_ATTR_VID);
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ciint vlan_mvrp_init_applicant(struct net_device *dev)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	return mrp_init_applicant(dev, &vlan_mrp_app);
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_civoid vlan_mvrp_uninit_applicant(struct net_device *dev)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	mrp_uninit_applicant(dev, &vlan_mrp_app);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ciint __init vlan_mvrp_init(void)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	return mrp_register_application(&vlan_mrp_app);
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_civoid vlan_mvrp_uninit(void)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	mrp_unregister_application(&vlan_mrp_app);
7362306a36Sopenharmony_ci}
74