cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

br_mrp_netlink.c (16331B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2
      3#include <net/genetlink.h>
      4
      5#include <uapi/linux/mrp_bridge.h>
      6#include "br_private.h"
      7#include "br_private_mrp.h"
      8
      9static const struct nla_policy br_mrp_policy[IFLA_BRIDGE_MRP_MAX + 1] = {
     10	[IFLA_BRIDGE_MRP_UNSPEC]	= { .type = NLA_REJECT },
     11	[IFLA_BRIDGE_MRP_INSTANCE]	= { .type = NLA_NESTED },
     12	[IFLA_BRIDGE_MRP_PORT_STATE]	= { .type = NLA_NESTED },
     13	[IFLA_BRIDGE_MRP_PORT_ROLE]	= { .type = NLA_NESTED },
     14	[IFLA_BRIDGE_MRP_RING_STATE]	= { .type = NLA_NESTED },
     15	[IFLA_BRIDGE_MRP_RING_ROLE]	= { .type = NLA_NESTED },
     16	[IFLA_BRIDGE_MRP_START_TEST]	= { .type = NLA_NESTED },
     17	[IFLA_BRIDGE_MRP_IN_ROLE]	= { .type = NLA_NESTED },
     18	[IFLA_BRIDGE_MRP_IN_STATE]	= { .type = NLA_NESTED },
     19	[IFLA_BRIDGE_MRP_START_IN_TEST]	= { .type = NLA_NESTED },
     20};
     21
     22static const struct nla_policy
     23br_mrp_instance_policy[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1] = {
     24	[IFLA_BRIDGE_MRP_INSTANCE_UNSPEC]	= { .type = NLA_REJECT },
     25	[IFLA_BRIDGE_MRP_INSTANCE_RING_ID]	= { .type = NLA_U32 },
     26	[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]	= { .type = NLA_U32 },
     27	[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]	= { .type = NLA_U32 },
     28	[IFLA_BRIDGE_MRP_INSTANCE_PRIO]		= { .type = NLA_U16 },
     29};
     30
     31static int br_mrp_instance_parse(struct net_bridge *br, struct nlattr *attr,
     32				 int cmd, struct netlink_ext_ack *extack)
     33{
     34	struct nlattr *tb[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1];
     35	struct br_mrp_instance inst;
     36	int err;
     37
     38	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_INSTANCE_MAX, attr,
     39			       br_mrp_instance_policy, extack);
     40	if (err)
     41		return err;
     42
     43	if (!tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID] ||
     44	    !tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX] ||
     45	    !tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]) {
     46		NL_SET_ERR_MSG_MOD(extack,
     47				   "Missing attribute: RING_ID or P_IFINDEX or S_IFINDEX");
     48		return -EINVAL;
     49	}
     50
     51	memset(&inst, 0, sizeof(inst));
     52
     53	inst.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID]);
     54	inst.p_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]);
     55	inst.s_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]);
     56	inst.prio = MRP_DEFAULT_PRIO;
     57
     58	if (tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO])
     59		inst.prio = nla_get_u16(tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO]);
     60
     61	if (cmd == RTM_SETLINK)
     62		return br_mrp_add(br, &inst);
     63	else
     64		return br_mrp_del(br, &inst);
     65
     66	return 0;
     67}
     68
     69static const struct nla_policy
     70br_mrp_port_state_policy[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1] = {
     71	[IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC]	= { .type = NLA_REJECT },
     72	[IFLA_BRIDGE_MRP_PORT_STATE_STATE]	= { .type = NLA_U32 },
     73};
     74
     75static int br_mrp_port_state_parse(struct net_bridge_port *p,
     76				   struct nlattr *attr,
     77				   struct netlink_ext_ack *extack)
     78{
     79	struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1];
     80	enum br_mrp_port_state_type state;
     81	int err;
     82
     83	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_STATE_MAX, attr,
     84			       br_mrp_port_state_policy, extack);
     85	if (err)
     86		return err;
     87
     88	if (!tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]) {
     89		NL_SET_ERR_MSG_MOD(extack, "Missing attribute: STATE");
     90		return -EINVAL;
     91	}
     92
     93	state = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]);
     94
     95	return br_mrp_set_port_state(p, state);
     96}
     97
     98static const struct nla_policy
     99br_mrp_port_role_policy[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1] = {
    100	[IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC]	= { .type = NLA_REJECT },
    101	[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]	= { .type = NLA_U32 },
    102};
    103
    104static int br_mrp_port_role_parse(struct net_bridge_port *p,
    105				  struct nlattr *attr,
    106				  struct netlink_ext_ack *extack)
    107{
    108	struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1];
    109	enum br_mrp_port_role_type role;
    110	int err;
    111
    112	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_ROLE_MAX, attr,
    113			       br_mrp_port_role_policy, extack);
    114	if (err)
    115		return err;
    116
    117	if (!tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]) {
    118		NL_SET_ERR_MSG_MOD(extack, "Missing attribute: ROLE");
    119		return -EINVAL;
    120	}
    121
    122	role = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]);
    123
    124	return br_mrp_set_port_role(p, role);
    125}
    126
    127static const struct nla_policy
    128br_mrp_ring_state_policy[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1] = {
    129	[IFLA_BRIDGE_MRP_RING_STATE_UNSPEC]	= { .type = NLA_REJECT },
    130	[IFLA_BRIDGE_MRP_RING_STATE_RING_ID]	= { .type = NLA_U32 },
    131	[IFLA_BRIDGE_MRP_RING_STATE_STATE]	= { .type = NLA_U32 },
    132};
    133
    134static int br_mrp_ring_state_parse(struct net_bridge *br, struct nlattr *attr,
    135				   struct netlink_ext_ack *extack)
    136{
    137	struct nlattr *tb[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1];
    138	struct br_mrp_ring_state state;
    139	int err;
    140
    141	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_STATE_MAX, attr,
    142			       br_mrp_ring_state_policy, extack);
    143	if (err)
    144		return err;
    145
    146	if (!tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID] ||
    147	    !tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]) {
    148		NL_SET_ERR_MSG_MOD(extack,
    149				   "Missing attribute: RING_ID or STATE");
    150		return -EINVAL;
    151	}
    152
    153	memset(&state, 0x0, sizeof(state));
    154
    155	state.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID]);
    156	state.ring_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]);
    157
    158	return br_mrp_set_ring_state(br, &state);
    159}
    160
    161static const struct nla_policy
    162br_mrp_ring_role_policy[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1] = {
    163	[IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC]	= { .type = NLA_REJECT },
    164	[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]	= { .type = NLA_U32 },
    165	[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]	= { .type = NLA_U32 },
    166};
    167
    168static int br_mrp_ring_role_parse(struct net_bridge *br, struct nlattr *attr,
    169				  struct netlink_ext_ack *extack)
    170{
    171	struct nlattr *tb[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1];
    172	struct br_mrp_ring_role role;
    173	int err;
    174
    175	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_ROLE_MAX, attr,
    176			       br_mrp_ring_role_policy, extack);
    177	if (err)
    178		return err;
    179
    180	if (!tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID] ||
    181	    !tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]) {
    182		NL_SET_ERR_MSG_MOD(extack,
    183				   "Missing attribute: RING_ID or ROLE");
    184		return -EINVAL;
    185	}
    186
    187	memset(&role, 0x0, sizeof(role));
    188
    189	role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]);
    190	role.ring_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]);
    191
    192	return br_mrp_set_ring_role(br, &role);
    193}
    194
    195static const struct nla_policy
    196br_mrp_start_test_policy[IFLA_BRIDGE_MRP_START_TEST_MAX + 1] = {
    197	[IFLA_BRIDGE_MRP_START_TEST_UNSPEC]	= { .type = NLA_REJECT },
    198	[IFLA_BRIDGE_MRP_START_TEST_RING_ID]	= { .type = NLA_U32 },
    199	[IFLA_BRIDGE_MRP_START_TEST_INTERVAL]	= { .type = NLA_U32 },
    200	[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]	= { .type = NLA_U32 },
    201	[IFLA_BRIDGE_MRP_START_TEST_PERIOD]	= { .type = NLA_U32 },
    202	[IFLA_BRIDGE_MRP_START_TEST_MONITOR]	= { .type = NLA_U32 },
    203};
    204
    205static int br_mrp_start_test_parse(struct net_bridge *br, struct nlattr *attr,
    206				   struct netlink_ext_ack *extack)
    207{
    208	struct nlattr *tb[IFLA_BRIDGE_MRP_START_TEST_MAX + 1];
    209	struct br_mrp_start_test test;
    210	int err;
    211
    212	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_TEST_MAX, attr,
    213			       br_mrp_start_test_policy, extack);
    214	if (err)
    215		return err;
    216
    217	if (!tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID] ||
    218	    !tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL] ||
    219	    !tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] ||
    220	    !tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]) {
    221		NL_SET_ERR_MSG_MOD(extack,
    222				   "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
    223		return -EINVAL;
    224	}
    225
    226	memset(&test, 0x0, sizeof(test));
    227
    228	test.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID]);
    229	test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL]);
    230	test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]);
    231	test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]);
    232	test.monitor = false;
    233
    234	if (tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR])
    235		test.monitor =
    236			nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR]);
    237
    238	return br_mrp_start_test(br, &test);
    239}
    240
    241static const struct nla_policy
    242br_mrp_in_state_policy[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1] = {
    243	[IFLA_BRIDGE_MRP_IN_STATE_UNSPEC]	= { .type = NLA_REJECT },
    244	[IFLA_BRIDGE_MRP_IN_STATE_IN_ID]	= { .type = NLA_U32 },
    245	[IFLA_BRIDGE_MRP_IN_STATE_STATE]	= { .type = NLA_U32 },
    246};
    247
    248static int br_mrp_in_state_parse(struct net_bridge *br, struct nlattr *attr,
    249				 struct netlink_ext_ack *extack)
    250{
    251	struct nlattr *tb[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1];
    252	struct br_mrp_in_state state;
    253	int err;
    254
    255	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_STATE_MAX, attr,
    256			       br_mrp_in_state_policy, extack);
    257	if (err)
    258		return err;
    259
    260	if (!tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID] ||
    261	    !tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]) {
    262		NL_SET_ERR_MSG_MOD(extack,
    263				   "Missing attribute: IN_ID or STATE");
    264		return -EINVAL;
    265	}
    266
    267	memset(&state, 0x0, sizeof(state));
    268
    269	state.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID]);
    270	state.in_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]);
    271
    272	return br_mrp_set_in_state(br, &state);
    273}
    274
    275static const struct nla_policy
    276br_mrp_in_role_policy[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1] = {
    277	[IFLA_BRIDGE_MRP_IN_ROLE_UNSPEC]	= { .type = NLA_REJECT },
    278	[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]	= { .type = NLA_U32 },
    279	[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]		= { .type = NLA_U16 },
    280	[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]		= { .type = NLA_U32 },
    281	[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]	= { .type = NLA_U32 },
    282};
    283
    284static int br_mrp_in_role_parse(struct net_bridge *br, struct nlattr *attr,
    285				struct netlink_ext_ack *extack)
    286{
    287	struct nlattr *tb[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1];
    288	struct br_mrp_in_role role;
    289	int err;
    290
    291	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_ROLE_MAX, attr,
    292			       br_mrp_in_role_policy, extack);
    293	if (err)
    294		return err;
    295
    296	if (!tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID] ||
    297	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID] ||
    298	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX] ||
    299	    !tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]) {
    300		NL_SET_ERR_MSG_MOD(extack,
    301				   "Missing attribute: RING_ID or ROLE or IN_ID or I_IFINDEX");
    302		return -EINVAL;
    303	}
    304
    305	memset(&role, 0x0, sizeof(role));
    306
    307	role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]);
    308	role.in_id = nla_get_u16(tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]);
    309	role.i_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]);
    310	role.in_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]);
    311
    312	return br_mrp_set_in_role(br, &role);
    313}
    314
    315static const struct nla_policy
    316br_mrp_start_in_test_policy[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1] = {
    317	[IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC]	= { .type = NLA_REJECT },
    318	[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]	= { .type = NLA_U32 },
    319	[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL]	= { .type = NLA_U32 },
    320	[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS]	= { .type = NLA_U32 },
    321	[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]	= { .type = NLA_U32 },
    322};
    323
    324static int br_mrp_start_in_test_parse(struct net_bridge *br,
    325				      struct nlattr *attr,
    326				      struct netlink_ext_ack *extack)
    327{
    328	struct nlattr *tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1];
    329	struct br_mrp_start_in_test test;
    330	int err;
    331
    332	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_IN_TEST_MAX, attr,
    333			       br_mrp_start_in_test_policy, extack);
    334	if (err)
    335		return err;
    336
    337	if (!tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] ||
    338	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] ||
    339	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] ||
    340	    !tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]) {
    341		NL_SET_ERR_MSG_MOD(extack,
    342				   "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
    343		return -EINVAL;
    344	}
    345
    346	memset(&test, 0x0, sizeof(test));
    347
    348	test.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]);
    349	test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL]);
    350	test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS]);
    351	test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]);
    352
    353	return br_mrp_start_in_test(br, &test);
    354}
    355
    356int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
    357		 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
    358{
    359	struct nlattr *tb[IFLA_BRIDGE_MRP_MAX + 1];
    360	int err;
    361
    362	/* When this function is called for a port then the br pointer is
    363	 * invalid, therefor set the br to point correctly
    364	 */
    365	if (p)
    366		br = p->br;
    367
    368	if (br->stp_enabled != BR_NO_STP) {
    369		NL_SET_ERR_MSG_MOD(extack, "MRP can't be enabled if STP is already enabled");
    370		return -EINVAL;
    371	}
    372
    373	err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_MAX, attr,
    374			       br_mrp_policy, extack);
    375	if (err)
    376		return err;
    377
    378	if (tb[IFLA_BRIDGE_MRP_INSTANCE]) {
    379		err = br_mrp_instance_parse(br, tb[IFLA_BRIDGE_MRP_INSTANCE],
    380					    cmd, extack);
    381		if (err)
    382			return err;
    383	}
    384
    385	if (tb[IFLA_BRIDGE_MRP_PORT_STATE]) {
    386		err = br_mrp_port_state_parse(p, tb[IFLA_BRIDGE_MRP_PORT_STATE],
    387					      extack);
    388		if (err)
    389			return err;
    390	}
    391
    392	if (tb[IFLA_BRIDGE_MRP_PORT_ROLE]) {
    393		err = br_mrp_port_role_parse(p, tb[IFLA_BRIDGE_MRP_PORT_ROLE],
    394					     extack);
    395		if (err)
    396			return err;
    397	}
    398
    399	if (tb[IFLA_BRIDGE_MRP_RING_STATE]) {
    400		err = br_mrp_ring_state_parse(br,
    401					      tb[IFLA_BRIDGE_MRP_RING_STATE],
    402					      extack);
    403		if (err)
    404			return err;
    405	}
    406
    407	if (tb[IFLA_BRIDGE_MRP_RING_ROLE]) {
    408		err = br_mrp_ring_role_parse(br, tb[IFLA_BRIDGE_MRP_RING_ROLE],
    409					     extack);
    410		if (err)
    411			return err;
    412	}
    413
    414	if (tb[IFLA_BRIDGE_MRP_START_TEST]) {
    415		err = br_mrp_start_test_parse(br,
    416					      tb[IFLA_BRIDGE_MRP_START_TEST],
    417					      extack);
    418		if (err)
    419			return err;
    420	}
    421
    422	if (tb[IFLA_BRIDGE_MRP_IN_STATE]) {
    423		err = br_mrp_in_state_parse(br, tb[IFLA_BRIDGE_MRP_IN_STATE],
    424					    extack);
    425		if (err)
    426			return err;
    427	}
    428
    429	if (tb[IFLA_BRIDGE_MRP_IN_ROLE]) {
    430		err = br_mrp_in_role_parse(br, tb[IFLA_BRIDGE_MRP_IN_ROLE],
    431					   extack);
    432		if (err)
    433			return err;
    434	}
    435
    436	if (tb[IFLA_BRIDGE_MRP_START_IN_TEST]) {
    437		err = br_mrp_start_in_test_parse(br,
    438						 tb[IFLA_BRIDGE_MRP_START_IN_TEST],
    439						 extack);
    440		if (err)
    441			return err;
    442	}
    443
    444	return 0;
    445}
    446
    447int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br)
    448{
    449	struct nlattr *tb, *mrp_tb;
    450	struct br_mrp *mrp;
    451
    452	mrp_tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP);
    453	if (!mrp_tb)
    454		return -EMSGSIZE;
    455
    456	hlist_for_each_entry_rcu(mrp, &br->mrp_list, list) {
    457		struct net_bridge_port *p;
    458
    459		tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP_INFO);
    460		if (!tb)
    461			goto nla_info_failure;
    462
    463		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ID,
    464				mrp->ring_id))
    465			goto nla_put_failure;
    466
    467		p = rcu_dereference(mrp->p_port);
    468		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_P_IFINDEX,
    469				     p->dev->ifindex))
    470			goto nla_put_failure;
    471
    472		p = rcu_dereference(mrp->s_port);
    473		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_S_IFINDEX,
    474				     p->dev->ifindex))
    475			goto nla_put_failure;
    476
    477		p = rcu_dereference(mrp->i_port);
    478		if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_I_IFINDEX,
    479				     p->dev->ifindex))
    480			goto nla_put_failure;
    481
    482		if (nla_put_u16(skb, IFLA_BRIDGE_MRP_INFO_PRIO,
    483				mrp->prio))
    484			goto nla_put_failure;
    485		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_STATE,
    486				mrp->ring_state))
    487			goto nla_put_failure;
    488		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ROLE,
    489				mrp->ring_role))
    490			goto nla_put_failure;
    491		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL,
    492				mrp->test_interval))
    493			goto nla_put_failure;
    494		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS,
    495				mrp->test_max_miss))
    496			goto nla_put_failure;
    497		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MONITOR,
    498				mrp->test_monitor))
    499			goto nla_put_failure;
    500
    501		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_STATE,
    502				mrp->in_state))
    503			goto nla_put_failure;
    504		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_ROLE,
    505				mrp->in_role))
    506			goto nla_put_failure;
    507		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL,
    508				mrp->in_test_interval))
    509			goto nla_put_failure;
    510		if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS,
    511				mrp->in_test_max_miss))
    512			goto nla_put_failure;
    513
    514		nla_nest_end(skb, tb);
    515	}
    516	nla_nest_end(skb, mrp_tb);
    517
    518	return 0;
    519
    520nla_put_failure:
    521	nla_nest_cancel(skb, tb);
    522
    523nla_info_failure:
    524	nla_nest_cancel(skb, mrp_tb);
    525
    526	return -EMSGSIZE;
    527}
    528
    529int br_mrp_ring_port_open(struct net_device *dev, u8 loc)
    530{
    531	struct net_bridge_port *p;
    532	int err = 0;
    533
    534	p = br_port_get_rcu(dev);
    535	if (!p) {
    536		err = -EINVAL;
    537		goto out;
    538	}
    539
    540	if (loc)
    541		p->flags |= BR_MRP_LOST_CONT;
    542	else
    543		p->flags &= ~BR_MRP_LOST_CONT;
    544
    545	br_ifinfo_notify(RTM_NEWLINK, NULL, p);
    546
    547out:
    548	return err;
    549}
    550
    551int br_mrp_in_port_open(struct net_device *dev, u8 loc)
    552{
    553	struct net_bridge_port *p;
    554	int err = 0;
    555
    556	p = br_port_get_rcu(dev);
    557	if (!p) {
    558		err = -EINVAL;
    559		goto out;
    560	}
    561
    562	if (loc)
    563		p->flags |= BR_MRP_LOST_IN_CONT;
    564	else
    565		p->flags &= ~BR_MRP_LOST_IN_CONT;
    566
    567	br_ifinfo_notify(RTM_NEWLINK, NULL, p);
    568
    569out:
    570	return err;
    571}