18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#include <net/genetlink.h>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#include <uapi/linux/mrp_bridge.h>
68c2ecf20Sopenharmony_ci#include "br_private.h"
78c2ecf20Sopenharmony_ci#include "br_private_mrp.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistatic const struct nla_policy br_mrp_policy[IFLA_BRIDGE_MRP_MAX + 1] = {
108c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_UNSPEC]	= { .type = NLA_REJECT },
118c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_INSTANCE]	= { .type = NLA_NESTED },
128c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_PORT_STATE]	= { .type = NLA_NESTED },
138c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_PORT_ROLE]	= { .type = NLA_NESTED },
148c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_RING_STATE]	= { .type = NLA_NESTED },
158c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_RING_ROLE]	= { .type = NLA_NESTED },
168c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_TEST]	= { .type = NLA_NESTED },
178c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_ROLE]	= { .type = NLA_NESTED },
188c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_STATE]	= { .type = NLA_NESTED },
198c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_IN_TEST]	= { .type = NLA_NESTED },
208c2ecf20Sopenharmony_ci};
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic const struct nla_policy
238c2ecf20Sopenharmony_cibr_mrp_instance_policy[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1] = {
248c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_INSTANCE_UNSPEC]	= { .type = NLA_REJECT },
258c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_INSTANCE_RING_ID]	= { .type = NLA_U32 },
268c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]	= { .type = NLA_U32 },
278c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]	= { .type = NLA_U32 },
288c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_INSTANCE_PRIO]		= { .type = NLA_U16 },
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic int br_mrp_instance_parse(struct net_bridge *br, struct nlattr *attr,
328c2ecf20Sopenharmony_ci				 int cmd, struct netlink_ext_ack *extack)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1];
358c2ecf20Sopenharmony_ci	struct br_mrp_instance inst;
368c2ecf20Sopenharmony_ci	int err;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_INSTANCE_MAX, attr,
398c2ecf20Sopenharmony_ci			       br_mrp_instance_policy, extack);
408c2ecf20Sopenharmony_ci	if (err)
418c2ecf20Sopenharmony_ci		return err;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID] ||
448c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX] ||
458c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]) {
468c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack,
478c2ecf20Sopenharmony_ci				   "Missing attribute: RING_ID or P_IFINDEX or S_IFINDEX");
488c2ecf20Sopenharmony_ci		return -EINVAL;
498c2ecf20Sopenharmony_ci	}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	memset(&inst, 0, sizeof(inst));
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	inst.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID]);
548c2ecf20Sopenharmony_ci	inst.p_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]);
558c2ecf20Sopenharmony_ci	inst.s_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]);
568c2ecf20Sopenharmony_ci	inst.prio = MRP_DEFAULT_PRIO;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO])
598c2ecf20Sopenharmony_ci		inst.prio = nla_get_u16(tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO]);
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	if (cmd == RTM_SETLINK)
628c2ecf20Sopenharmony_ci		return br_mrp_add(br, &inst);
638c2ecf20Sopenharmony_ci	else
648c2ecf20Sopenharmony_ci		return br_mrp_del(br, &inst);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	return 0;
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic const struct nla_policy
708c2ecf20Sopenharmony_cibr_mrp_port_state_policy[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1] = {
718c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC]	= { .type = NLA_REJECT },
728c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_PORT_STATE_STATE]	= { .type = NLA_U32 },
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic int br_mrp_port_state_parse(struct net_bridge_port *p,
768c2ecf20Sopenharmony_ci				   struct nlattr *attr,
778c2ecf20Sopenharmony_ci				   struct netlink_ext_ack *extack)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1];
808c2ecf20Sopenharmony_ci	enum br_mrp_port_state_type state;
818c2ecf20Sopenharmony_ci	int err;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_STATE_MAX, attr,
848c2ecf20Sopenharmony_ci			       br_mrp_port_state_policy, extack);
858c2ecf20Sopenharmony_ci	if (err)
868c2ecf20Sopenharmony_ci		return err;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]) {
898c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing attribute: STATE");
908c2ecf20Sopenharmony_ci		return -EINVAL;
918c2ecf20Sopenharmony_ci	}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	state = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	return br_mrp_set_port_state(p, state);
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic const struct nla_policy
998c2ecf20Sopenharmony_cibr_mrp_port_role_policy[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1] = {
1008c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC]	= { .type = NLA_REJECT },
1018c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]	= { .type = NLA_U32 },
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic int br_mrp_port_role_parse(struct net_bridge_port *p,
1058c2ecf20Sopenharmony_ci				  struct nlattr *attr,
1068c2ecf20Sopenharmony_ci				  struct netlink_ext_ack *extack)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1];
1098c2ecf20Sopenharmony_ci	enum br_mrp_port_role_type role;
1108c2ecf20Sopenharmony_ci	int err;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_ROLE_MAX, attr,
1138c2ecf20Sopenharmony_ci			       br_mrp_port_role_policy, extack);
1148c2ecf20Sopenharmony_ci	if (err)
1158c2ecf20Sopenharmony_ci		return err;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]) {
1188c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "Missing attribute: ROLE");
1198c2ecf20Sopenharmony_ci		return -EINVAL;
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	role = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	return br_mrp_set_port_role(p, role);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic const struct nla_policy
1288c2ecf20Sopenharmony_cibr_mrp_ring_state_policy[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1] = {
1298c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_RING_STATE_UNSPEC]	= { .type = NLA_REJECT },
1308c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_RING_STATE_RING_ID]	= { .type = NLA_U32 },
1318c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_RING_STATE_STATE]	= { .type = NLA_U32 },
1328c2ecf20Sopenharmony_ci};
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic int br_mrp_ring_state_parse(struct net_bridge *br, struct nlattr *attr,
1358c2ecf20Sopenharmony_ci				   struct netlink_ext_ack *extack)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1];
1388c2ecf20Sopenharmony_ci	struct br_mrp_ring_state state;
1398c2ecf20Sopenharmony_ci	int err;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_STATE_MAX, attr,
1428c2ecf20Sopenharmony_ci			       br_mrp_ring_state_policy, extack);
1438c2ecf20Sopenharmony_ci	if (err)
1448c2ecf20Sopenharmony_ci		return err;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID] ||
1478c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]) {
1488c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack,
1498c2ecf20Sopenharmony_ci				   "Missing attribute: RING_ID or STATE");
1508c2ecf20Sopenharmony_ci		return -EINVAL;
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	memset(&state, 0x0, sizeof(state));
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	state.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID]);
1568c2ecf20Sopenharmony_ci	state.ring_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	return br_mrp_set_ring_state(br, &state);
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic const struct nla_policy
1628c2ecf20Sopenharmony_cibr_mrp_ring_role_policy[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1] = {
1638c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC]	= { .type = NLA_REJECT },
1648c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]	= { .type = NLA_U32 },
1658c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]	= { .type = NLA_U32 },
1668c2ecf20Sopenharmony_ci};
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic int br_mrp_ring_role_parse(struct net_bridge *br, struct nlattr *attr,
1698c2ecf20Sopenharmony_ci				  struct netlink_ext_ack *extack)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1];
1728c2ecf20Sopenharmony_ci	struct br_mrp_ring_role role;
1738c2ecf20Sopenharmony_ci	int err;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_ROLE_MAX, attr,
1768c2ecf20Sopenharmony_ci			       br_mrp_ring_role_policy, extack);
1778c2ecf20Sopenharmony_ci	if (err)
1788c2ecf20Sopenharmony_ci		return err;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID] ||
1818c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]) {
1828c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack,
1838c2ecf20Sopenharmony_ci				   "Missing attribute: RING_ID or ROLE");
1848c2ecf20Sopenharmony_ci		return -EINVAL;
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	memset(&role, 0x0, sizeof(role));
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]);
1908c2ecf20Sopenharmony_ci	role.ring_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	return br_mrp_set_ring_role(br, &role);
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_cistatic const struct nla_policy
1968c2ecf20Sopenharmony_cibr_mrp_start_test_policy[IFLA_BRIDGE_MRP_START_TEST_MAX + 1] = {
1978c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_TEST_UNSPEC]	= { .type = NLA_REJECT },
1988c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_TEST_RING_ID]	= { .type = NLA_U32 },
1998c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_TEST_INTERVAL]	= { .type = NLA_U32 },
2008c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]	= { .type = NLA_U32 },
2018c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_TEST_PERIOD]	= { .type = NLA_U32 },
2028c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_TEST_MONITOR]	= { .type = NLA_U32 },
2038c2ecf20Sopenharmony_ci};
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_cistatic int br_mrp_start_test_parse(struct net_bridge *br, struct nlattr *attr,
2068c2ecf20Sopenharmony_ci				   struct netlink_ext_ack *extack)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_START_TEST_MAX + 1];
2098c2ecf20Sopenharmony_ci	struct br_mrp_start_test test;
2108c2ecf20Sopenharmony_ci	int err;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_TEST_MAX, attr,
2138c2ecf20Sopenharmony_ci			       br_mrp_start_test_policy, extack);
2148c2ecf20Sopenharmony_ci	if (err)
2158c2ecf20Sopenharmony_ci		return err;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID] ||
2188c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL] ||
2198c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] ||
2208c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]) {
2218c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack,
2228c2ecf20Sopenharmony_ci				   "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
2238c2ecf20Sopenharmony_ci		return -EINVAL;
2248c2ecf20Sopenharmony_ci	}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	memset(&test, 0x0, sizeof(test));
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	test.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID]);
2298c2ecf20Sopenharmony_ci	test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL]);
2308c2ecf20Sopenharmony_ci	test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]);
2318c2ecf20Sopenharmony_ci	test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]);
2328c2ecf20Sopenharmony_ci	test.monitor = false;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR])
2358c2ecf20Sopenharmony_ci		test.monitor =
2368c2ecf20Sopenharmony_ci			nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR]);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	return br_mrp_start_test(br, &test);
2398c2ecf20Sopenharmony_ci}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_cistatic const struct nla_policy
2428c2ecf20Sopenharmony_cibr_mrp_in_state_policy[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1] = {
2438c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_STATE_UNSPEC]	= { .type = NLA_REJECT },
2448c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_STATE_IN_ID]	= { .type = NLA_U32 },
2458c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_STATE_STATE]	= { .type = NLA_U32 },
2468c2ecf20Sopenharmony_ci};
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_cistatic int br_mrp_in_state_parse(struct net_bridge *br, struct nlattr *attr,
2498c2ecf20Sopenharmony_ci				 struct netlink_ext_ack *extack)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1];
2528c2ecf20Sopenharmony_ci	struct br_mrp_in_state state;
2538c2ecf20Sopenharmony_ci	int err;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_STATE_MAX, attr,
2568c2ecf20Sopenharmony_ci			       br_mrp_in_state_policy, extack);
2578c2ecf20Sopenharmony_ci	if (err)
2588c2ecf20Sopenharmony_ci		return err;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID] ||
2618c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]) {
2628c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack,
2638c2ecf20Sopenharmony_ci				   "Missing attribute: IN_ID or STATE");
2648c2ecf20Sopenharmony_ci		return -EINVAL;
2658c2ecf20Sopenharmony_ci	}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	memset(&state, 0x0, sizeof(state));
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	state.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID]);
2708c2ecf20Sopenharmony_ci	state.in_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]);
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	return br_mrp_set_in_state(br, &state);
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic const struct nla_policy
2768c2ecf20Sopenharmony_cibr_mrp_in_role_policy[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1] = {
2778c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_ROLE_UNSPEC]	= { .type = NLA_REJECT },
2788c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]	= { .type = NLA_U32 },
2798c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]		= { .type = NLA_U16 },
2808c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]		= { .type = NLA_U32 },
2818c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]	= { .type = NLA_U32 },
2828c2ecf20Sopenharmony_ci};
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_cistatic int br_mrp_in_role_parse(struct net_bridge *br, struct nlattr *attr,
2858c2ecf20Sopenharmony_ci				struct netlink_ext_ack *extack)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1];
2888c2ecf20Sopenharmony_ci	struct br_mrp_in_role role;
2898c2ecf20Sopenharmony_ci	int err;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_ROLE_MAX, attr,
2928c2ecf20Sopenharmony_ci			       br_mrp_in_role_policy, extack);
2938c2ecf20Sopenharmony_ci	if (err)
2948c2ecf20Sopenharmony_ci		return err;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID] ||
2978c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID] ||
2988c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX] ||
2998c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]) {
3008c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack,
3018c2ecf20Sopenharmony_ci				   "Missing attribute: RING_ID or ROLE or IN_ID or I_IFINDEX");
3028c2ecf20Sopenharmony_ci		return -EINVAL;
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	memset(&role, 0x0, sizeof(role));
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]);
3088c2ecf20Sopenharmony_ci	role.in_id = nla_get_u16(tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]);
3098c2ecf20Sopenharmony_ci	role.i_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]);
3108c2ecf20Sopenharmony_ci	role.in_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	return br_mrp_set_in_role(br, &role);
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic const struct nla_policy
3168c2ecf20Sopenharmony_cibr_mrp_start_in_test_policy[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1] = {
3178c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC]	= { .type = NLA_REJECT },
3188c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]	= { .type = NLA_U32 },
3198c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL]	= { .type = NLA_U32 },
3208c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS]	= { .type = NLA_U32 },
3218c2ecf20Sopenharmony_ci	[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]	= { .type = NLA_U32 },
3228c2ecf20Sopenharmony_ci};
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistatic int br_mrp_start_in_test_parse(struct net_bridge *br,
3258c2ecf20Sopenharmony_ci				      struct nlattr *attr,
3268c2ecf20Sopenharmony_ci				      struct netlink_ext_ack *extack)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1];
3298c2ecf20Sopenharmony_ci	struct br_mrp_start_in_test test;
3308c2ecf20Sopenharmony_ci	int err;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_IN_TEST_MAX, attr,
3338c2ecf20Sopenharmony_ci			       br_mrp_start_in_test_policy, extack);
3348c2ecf20Sopenharmony_ci	if (err)
3358c2ecf20Sopenharmony_ci		return err;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	if (!tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] ||
3388c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] ||
3398c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] ||
3408c2ecf20Sopenharmony_ci	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]) {
3418c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack,
3428c2ecf20Sopenharmony_ci				   "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
3438c2ecf20Sopenharmony_ci		return -EINVAL;
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	memset(&test, 0x0, sizeof(test));
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	test.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]);
3498c2ecf20Sopenharmony_ci	test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL]);
3508c2ecf20Sopenharmony_ci	test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS]);
3518c2ecf20Sopenharmony_ci	test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]);
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	return br_mrp_start_in_test(br, &test);
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ciint br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
3578c2ecf20Sopenharmony_ci		 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
3588c2ecf20Sopenharmony_ci{
3598c2ecf20Sopenharmony_ci	struct nlattr *tb[IFLA_BRIDGE_MRP_MAX + 1];
3608c2ecf20Sopenharmony_ci	int err;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	/* When this function is called for a port then the br pointer is
3638c2ecf20Sopenharmony_ci	 * invalid, therefor set the br to point correctly
3648c2ecf20Sopenharmony_ci	 */
3658c2ecf20Sopenharmony_ci	if (p)
3668c2ecf20Sopenharmony_ci		br = p->br;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	if (br->stp_enabled != BR_NO_STP) {
3698c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "MRP can't be enabled if STP is already enabled");
3708c2ecf20Sopenharmony_ci		return -EINVAL;
3718c2ecf20Sopenharmony_ci	}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_MAX, attr,
3748c2ecf20Sopenharmony_ci			       br_mrp_policy, extack);
3758c2ecf20Sopenharmony_ci	if (err)
3768c2ecf20Sopenharmony_ci		return err;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_INSTANCE]) {
3798c2ecf20Sopenharmony_ci		err = br_mrp_instance_parse(br, tb[IFLA_BRIDGE_MRP_INSTANCE],
3808c2ecf20Sopenharmony_ci					    cmd, extack);
3818c2ecf20Sopenharmony_ci		if (err)
3828c2ecf20Sopenharmony_ci			return err;
3838c2ecf20Sopenharmony_ci	}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_PORT_STATE]) {
3868c2ecf20Sopenharmony_ci		err = br_mrp_port_state_parse(p, tb[IFLA_BRIDGE_MRP_PORT_STATE],
3878c2ecf20Sopenharmony_ci					      extack);
3888c2ecf20Sopenharmony_ci		if (err)
3898c2ecf20Sopenharmony_ci			return err;
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_PORT_ROLE]) {
3938c2ecf20Sopenharmony_ci		err = br_mrp_port_role_parse(p, tb[IFLA_BRIDGE_MRP_PORT_ROLE],
3948c2ecf20Sopenharmony_ci					     extack);
3958c2ecf20Sopenharmony_ci		if (err)
3968c2ecf20Sopenharmony_ci			return err;
3978c2ecf20Sopenharmony_ci	}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_RING_STATE]) {
4008c2ecf20Sopenharmony_ci		err = br_mrp_ring_state_parse(br,
4018c2ecf20Sopenharmony_ci					      tb[IFLA_BRIDGE_MRP_RING_STATE],
4028c2ecf20Sopenharmony_ci					      extack);
4038c2ecf20Sopenharmony_ci		if (err)
4048c2ecf20Sopenharmony_ci			return err;
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_RING_ROLE]) {
4088c2ecf20Sopenharmony_ci		err = br_mrp_ring_role_parse(br, tb[IFLA_BRIDGE_MRP_RING_ROLE],
4098c2ecf20Sopenharmony_ci					     extack);
4108c2ecf20Sopenharmony_ci		if (err)
4118c2ecf20Sopenharmony_ci			return err;
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_START_TEST]) {
4158c2ecf20Sopenharmony_ci		err = br_mrp_start_test_parse(br,
4168c2ecf20Sopenharmony_ci					      tb[IFLA_BRIDGE_MRP_START_TEST],
4178c2ecf20Sopenharmony_ci					      extack);
4188c2ecf20Sopenharmony_ci		if (err)
4198c2ecf20Sopenharmony_ci			return err;
4208c2ecf20Sopenharmony_ci	}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_IN_STATE]) {
4238c2ecf20Sopenharmony_ci		err = br_mrp_in_state_parse(br, tb[IFLA_BRIDGE_MRP_IN_STATE],
4248c2ecf20Sopenharmony_ci					    extack);
4258c2ecf20Sopenharmony_ci		if (err)
4268c2ecf20Sopenharmony_ci			return err;
4278c2ecf20Sopenharmony_ci	}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_IN_ROLE]) {
4308c2ecf20Sopenharmony_ci		err = br_mrp_in_role_parse(br, tb[IFLA_BRIDGE_MRP_IN_ROLE],
4318c2ecf20Sopenharmony_ci					   extack);
4328c2ecf20Sopenharmony_ci		if (err)
4338c2ecf20Sopenharmony_ci			return err;
4348c2ecf20Sopenharmony_ci	}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	if (tb[IFLA_BRIDGE_MRP_START_IN_TEST]) {
4378c2ecf20Sopenharmony_ci		err = br_mrp_start_in_test_parse(br,
4388c2ecf20Sopenharmony_ci						 tb[IFLA_BRIDGE_MRP_START_IN_TEST],
4398c2ecf20Sopenharmony_ci						 extack);
4408c2ecf20Sopenharmony_ci		if (err)
4418c2ecf20Sopenharmony_ci			return err;
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	return 0;
4458c2ecf20Sopenharmony_ci}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ciint br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br)
4488c2ecf20Sopenharmony_ci{
4498c2ecf20Sopenharmony_ci	struct nlattr *tb, *mrp_tb;
4508c2ecf20Sopenharmony_ci	struct br_mrp *mrp;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	mrp_tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP);
4538c2ecf20Sopenharmony_ci	if (!mrp_tb)
4548c2ecf20Sopenharmony_ci		return -EMSGSIZE;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(mrp, &br->mrp_list, list) {
4578c2ecf20Sopenharmony_ci		struct net_bridge_port *p;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci		tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP_INFO);
4608c2ecf20Sopenharmony_ci		if (!tb)
4618c2ecf20Sopenharmony_ci			goto nla_info_failure;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ID,
4648c2ecf20Sopenharmony_ci				mrp->ring_id))
4658c2ecf20Sopenharmony_ci			goto nla_put_failure;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci		p = rcu_dereference(mrp->p_port);
4688c2ecf20Sopenharmony_ci		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_P_IFINDEX,
4698c2ecf20Sopenharmony_ci				     p->dev->ifindex))
4708c2ecf20Sopenharmony_ci			goto nla_put_failure;
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		p = rcu_dereference(mrp->s_port);
4738c2ecf20Sopenharmony_ci		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_S_IFINDEX,
4748c2ecf20Sopenharmony_ci				     p->dev->ifindex))
4758c2ecf20Sopenharmony_ci			goto nla_put_failure;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci		p = rcu_dereference(mrp->i_port);
4788c2ecf20Sopenharmony_ci		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_I_IFINDEX,
4798c2ecf20Sopenharmony_ci				     p->dev->ifindex))
4808c2ecf20Sopenharmony_ci			goto nla_put_failure;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci		if (nla_put_u16(skb, IFLA_BRIDGE_MRP_INFO_PRIO,
4838c2ecf20Sopenharmony_ci				mrp->prio))
4848c2ecf20Sopenharmony_ci			goto nla_put_failure;
4858c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_STATE,
4868c2ecf20Sopenharmony_ci				mrp->ring_state))
4878c2ecf20Sopenharmony_ci			goto nla_put_failure;
4888c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ROLE,
4898c2ecf20Sopenharmony_ci				mrp->ring_role))
4908c2ecf20Sopenharmony_ci			goto nla_put_failure;
4918c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL,
4928c2ecf20Sopenharmony_ci				mrp->test_interval))
4938c2ecf20Sopenharmony_ci			goto nla_put_failure;
4948c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS,
4958c2ecf20Sopenharmony_ci				mrp->test_max_miss))
4968c2ecf20Sopenharmony_ci			goto nla_put_failure;
4978c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MONITOR,
4988c2ecf20Sopenharmony_ci				mrp->test_monitor))
4998c2ecf20Sopenharmony_ci			goto nla_put_failure;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_STATE,
5028c2ecf20Sopenharmony_ci				mrp->in_state))
5038c2ecf20Sopenharmony_ci			goto nla_put_failure;
5048c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_ROLE,
5058c2ecf20Sopenharmony_ci				mrp->in_role))
5068c2ecf20Sopenharmony_ci			goto nla_put_failure;
5078c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL,
5088c2ecf20Sopenharmony_ci				mrp->in_test_interval))
5098c2ecf20Sopenharmony_ci			goto nla_put_failure;
5108c2ecf20Sopenharmony_ci		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS,
5118c2ecf20Sopenharmony_ci				mrp->in_test_max_miss))
5128c2ecf20Sopenharmony_ci			goto nla_put_failure;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci		nla_nest_end(skb, tb);
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci	nla_nest_end(skb, mrp_tb);
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	return 0;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_cinla_put_failure:
5218c2ecf20Sopenharmony_ci	nla_nest_cancel(skb, tb);
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_cinla_info_failure:
5248c2ecf20Sopenharmony_ci	nla_nest_cancel(skb, mrp_tb);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	return -EMSGSIZE;
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ciint br_mrp_ring_port_open(struct net_device *dev, u8 loc)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	struct net_bridge_port *p;
5328c2ecf20Sopenharmony_ci	int err = 0;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	p = br_port_get_rcu(dev);
5358c2ecf20Sopenharmony_ci	if (!p) {
5368c2ecf20Sopenharmony_ci		err = -EINVAL;
5378c2ecf20Sopenharmony_ci		goto out;
5388c2ecf20Sopenharmony_ci	}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	if (loc)
5418c2ecf20Sopenharmony_ci		p->flags |= BR_MRP_LOST_CONT;
5428c2ecf20Sopenharmony_ci	else
5438c2ecf20Sopenharmony_ci		p->flags &= ~BR_MRP_LOST_CONT;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	br_ifinfo_notify(RTM_NEWLINK, NULL, p);
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ciout:
5488c2ecf20Sopenharmony_ci	return err;
5498c2ecf20Sopenharmony_ci}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ciint br_mrp_in_port_open(struct net_device *dev, u8 loc)
5528c2ecf20Sopenharmony_ci{
5538c2ecf20Sopenharmony_ci	struct net_bridge_port *p;
5548c2ecf20Sopenharmony_ci	int err = 0;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	p = br_port_get_rcu(dev);
5578c2ecf20Sopenharmony_ci	if (!p) {
5588c2ecf20Sopenharmony_ci		err = -EINVAL;
5598c2ecf20Sopenharmony_ci		goto out;
5608c2ecf20Sopenharmony_ci	}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	if (loc)
5638c2ecf20Sopenharmony_ci		p->flags |= BR_MRP_LOST_IN_CONT;
5648c2ecf20Sopenharmony_ci	else
5658c2ecf20Sopenharmony_ci		p->flags &= ~BR_MRP_LOST_IN_CONT;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	br_ifinfo_notify(RTM_NEWLINK, NULL, p);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ciout:
5708c2ecf20Sopenharmony_ci	return err;
5718c2ecf20Sopenharmony_ci}
572