0001
0002
0003 #include <net/genetlink.h>
0004
0005 #include <uapi/linux/mrp_bridge.h>
0006 #include "br_private.h"
0007 #include "br_private_mrp.h"
0008
0009 static const struct nla_policy br_mrp_policy[IFLA_BRIDGE_MRP_MAX + 1] = {
0010 [IFLA_BRIDGE_MRP_UNSPEC] = { .type = NLA_REJECT },
0011 [IFLA_BRIDGE_MRP_INSTANCE] = { .type = NLA_NESTED },
0012 [IFLA_BRIDGE_MRP_PORT_STATE] = { .type = NLA_NESTED },
0013 [IFLA_BRIDGE_MRP_PORT_ROLE] = { .type = NLA_NESTED },
0014 [IFLA_BRIDGE_MRP_RING_STATE] = { .type = NLA_NESTED },
0015 [IFLA_BRIDGE_MRP_RING_ROLE] = { .type = NLA_NESTED },
0016 [IFLA_BRIDGE_MRP_START_TEST] = { .type = NLA_NESTED },
0017 [IFLA_BRIDGE_MRP_IN_ROLE] = { .type = NLA_NESTED },
0018 [IFLA_BRIDGE_MRP_IN_STATE] = { .type = NLA_NESTED },
0019 [IFLA_BRIDGE_MRP_START_IN_TEST] = { .type = NLA_NESTED },
0020 };
0021
0022 static const struct nla_policy
0023 br_mrp_instance_policy[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1] = {
0024 [IFLA_BRIDGE_MRP_INSTANCE_UNSPEC] = { .type = NLA_REJECT },
0025 [IFLA_BRIDGE_MRP_INSTANCE_RING_ID] = { .type = NLA_U32 },
0026 [IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX] = { .type = NLA_U32 },
0027 [IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX] = { .type = NLA_U32 },
0028 [IFLA_BRIDGE_MRP_INSTANCE_PRIO] = { .type = NLA_U16 },
0029 };
0030
0031 static int br_mrp_instance_parse(struct net_bridge *br, struct nlattr *attr,
0032 int cmd, struct netlink_ext_ack *extack)
0033 {
0034 struct nlattr *tb[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1];
0035 struct br_mrp_instance inst;
0036 int err;
0037
0038 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_INSTANCE_MAX, attr,
0039 br_mrp_instance_policy, extack);
0040 if (err)
0041 return err;
0042
0043 if (!tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID] ||
0044 !tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX] ||
0045 !tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]) {
0046 NL_SET_ERR_MSG_MOD(extack,
0047 "Missing attribute: RING_ID or P_IFINDEX or S_IFINDEX");
0048 return -EINVAL;
0049 }
0050
0051 memset(&inst, 0, sizeof(inst));
0052
0053 inst.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID]);
0054 inst.p_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]);
0055 inst.s_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]);
0056 inst.prio = MRP_DEFAULT_PRIO;
0057
0058 if (tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO])
0059 inst.prio = nla_get_u16(tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO]);
0060
0061 if (cmd == RTM_SETLINK)
0062 return br_mrp_add(br, &inst);
0063 else
0064 return br_mrp_del(br, &inst);
0065
0066 return 0;
0067 }
0068
0069 static const struct nla_policy
0070 br_mrp_port_state_policy[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1] = {
0071 [IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC] = { .type = NLA_REJECT },
0072 [IFLA_BRIDGE_MRP_PORT_STATE_STATE] = { .type = NLA_U32 },
0073 };
0074
0075 static int br_mrp_port_state_parse(struct net_bridge_port *p,
0076 struct nlattr *attr,
0077 struct netlink_ext_ack *extack)
0078 {
0079 struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1];
0080 enum br_mrp_port_state_type state;
0081 int err;
0082
0083 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_STATE_MAX, attr,
0084 br_mrp_port_state_policy, extack);
0085 if (err)
0086 return err;
0087
0088 if (!tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]) {
0089 NL_SET_ERR_MSG_MOD(extack, "Missing attribute: STATE");
0090 return -EINVAL;
0091 }
0092
0093 state = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]);
0094
0095 return br_mrp_set_port_state(p, state);
0096 }
0097
0098 static const struct nla_policy
0099 br_mrp_port_role_policy[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1] = {
0100 [IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC] = { .type = NLA_REJECT },
0101 [IFLA_BRIDGE_MRP_PORT_ROLE_ROLE] = { .type = NLA_U32 },
0102 };
0103
0104 static int br_mrp_port_role_parse(struct net_bridge_port *p,
0105 struct nlattr *attr,
0106 struct netlink_ext_ack *extack)
0107 {
0108 struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1];
0109 enum br_mrp_port_role_type role;
0110 int err;
0111
0112 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_ROLE_MAX, attr,
0113 br_mrp_port_role_policy, extack);
0114 if (err)
0115 return err;
0116
0117 if (!tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]) {
0118 NL_SET_ERR_MSG_MOD(extack, "Missing attribute: ROLE");
0119 return -EINVAL;
0120 }
0121
0122 role = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]);
0123
0124 return br_mrp_set_port_role(p, role);
0125 }
0126
0127 static const struct nla_policy
0128 br_mrp_ring_state_policy[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1] = {
0129 [IFLA_BRIDGE_MRP_RING_STATE_UNSPEC] = { .type = NLA_REJECT },
0130 [IFLA_BRIDGE_MRP_RING_STATE_RING_ID] = { .type = NLA_U32 },
0131 [IFLA_BRIDGE_MRP_RING_STATE_STATE] = { .type = NLA_U32 },
0132 };
0133
0134 static int br_mrp_ring_state_parse(struct net_bridge *br, struct nlattr *attr,
0135 struct netlink_ext_ack *extack)
0136 {
0137 struct nlattr *tb[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1];
0138 struct br_mrp_ring_state state;
0139 int err;
0140
0141 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_STATE_MAX, attr,
0142 br_mrp_ring_state_policy, extack);
0143 if (err)
0144 return err;
0145
0146 if (!tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID] ||
0147 !tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]) {
0148 NL_SET_ERR_MSG_MOD(extack,
0149 "Missing attribute: RING_ID or STATE");
0150 return -EINVAL;
0151 }
0152
0153 memset(&state, 0x0, sizeof(state));
0154
0155 state.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID]);
0156 state.ring_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]);
0157
0158 return br_mrp_set_ring_state(br, &state);
0159 }
0160
0161 static const struct nla_policy
0162 br_mrp_ring_role_policy[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1] = {
0163 [IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC] = { .type = NLA_REJECT },
0164 [IFLA_BRIDGE_MRP_RING_ROLE_RING_ID] = { .type = NLA_U32 },
0165 [IFLA_BRIDGE_MRP_RING_ROLE_ROLE] = { .type = NLA_U32 },
0166 };
0167
0168 static int br_mrp_ring_role_parse(struct net_bridge *br, struct nlattr *attr,
0169 struct netlink_ext_ack *extack)
0170 {
0171 struct nlattr *tb[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1];
0172 struct br_mrp_ring_role role;
0173 int err;
0174
0175 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_ROLE_MAX, attr,
0176 br_mrp_ring_role_policy, extack);
0177 if (err)
0178 return err;
0179
0180 if (!tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID] ||
0181 !tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]) {
0182 NL_SET_ERR_MSG_MOD(extack,
0183 "Missing attribute: RING_ID or ROLE");
0184 return -EINVAL;
0185 }
0186
0187 memset(&role, 0x0, sizeof(role));
0188
0189 role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]);
0190 role.ring_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]);
0191
0192 return br_mrp_set_ring_role(br, &role);
0193 }
0194
0195 static const struct nla_policy
0196 br_mrp_start_test_policy[IFLA_BRIDGE_MRP_START_TEST_MAX + 1] = {
0197 [IFLA_BRIDGE_MRP_START_TEST_UNSPEC] = { .type = NLA_REJECT },
0198 [IFLA_BRIDGE_MRP_START_TEST_RING_ID] = { .type = NLA_U32 },
0199 [IFLA_BRIDGE_MRP_START_TEST_INTERVAL] = { .type = NLA_U32 },
0200 [IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] = { .type = NLA_U32 },
0201 [IFLA_BRIDGE_MRP_START_TEST_PERIOD] = { .type = NLA_U32 },
0202 [IFLA_BRIDGE_MRP_START_TEST_MONITOR] = { .type = NLA_U32 },
0203 };
0204
0205 static int br_mrp_start_test_parse(struct net_bridge *br, struct nlattr *attr,
0206 struct netlink_ext_ack *extack)
0207 {
0208 struct nlattr *tb[IFLA_BRIDGE_MRP_START_TEST_MAX + 1];
0209 struct br_mrp_start_test test;
0210 int err;
0211
0212 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_TEST_MAX, attr,
0213 br_mrp_start_test_policy, extack);
0214 if (err)
0215 return err;
0216
0217 if (!tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID] ||
0218 !tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL] ||
0219 !tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] ||
0220 !tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]) {
0221 NL_SET_ERR_MSG_MOD(extack,
0222 "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
0223 return -EINVAL;
0224 }
0225
0226 memset(&test, 0x0, sizeof(test));
0227
0228 test.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID]);
0229 test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL]);
0230 test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]);
0231 test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]);
0232 test.monitor = false;
0233
0234 if (tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR])
0235 test.monitor =
0236 nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR]);
0237
0238 return br_mrp_start_test(br, &test);
0239 }
0240
0241 static const struct nla_policy
0242 br_mrp_in_state_policy[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1] = {
0243 [IFLA_BRIDGE_MRP_IN_STATE_UNSPEC] = { .type = NLA_REJECT },
0244 [IFLA_BRIDGE_MRP_IN_STATE_IN_ID] = { .type = NLA_U32 },
0245 [IFLA_BRIDGE_MRP_IN_STATE_STATE] = { .type = NLA_U32 },
0246 };
0247
0248 static int br_mrp_in_state_parse(struct net_bridge *br, struct nlattr *attr,
0249 struct netlink_ext_ack *extack)
0250 {
0251 struct nlattr *tb[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1];
0252 struct br_mrp_in_state state;
0253 int err;
0254
0255 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_STATE_MAX, attr,
0256 br_mrp_in_state_policy, extack);
0257 if (err)
0258 return err;
0259
0260 if (!tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID] ||
0261 !tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]) {
0262 NL_SET_ERR_MSG_MOD(extack,
0263 "Missing attribute: IN_ID or STATE");
0264 return -EINVAL;
0265 }
0266
0267 memset(&state, 0x0, sizeof(state));
0268
0269 state.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID]);
0270 state.in_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]);
0271
0272 return br_mrp_set_in_state(br, &state);
0273 }
0274
0275 static const struct nla_policy
0276 br_mrp_in_role_policy[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1] = {
0277 [IFLA_BRIDGE_MRP_IN_ROLE_UNSPEC] = { .type = NLA_REJECT },
0278 [IFLA_BRIDGE_MRP_IN_ROLE_RING_ID] = { .type = NLA_U32 },
0279 [IFLA_BRIDGE_MRP_IN_ROLE_IN_ID] = { .type = NLA_U16 },
0280 [IFLA_BRIDGE_MRP_IN_ROLE_ROLE] = { .type = NLA_U32 },
0281 [IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX] = { .type = NLA_U32 },
0282 };
0283
0284 static int br_mrp_in_role_parse(struct net_bridge *br, struct nlattr *attr,
0285 struct netlink_ext_ack *extack)
0286 {
0287 struct nlattr *tb[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1];
0288 struct br_mrp_in_role role;
0289 int err;
0290
0291 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_ROLE_MAX, attr,
0292 br_mrp_in_role_policy, extack);
0293 if (err)
0294 return err;
0295
0296 if (!tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID] ||
0297 !tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID] ||
0298 !tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX] ||
0299 !tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]) {
0300 NL_SET_ERR_MSG_MOD(extack,
0301 "Missing attribute: RING_ID or ROLE or IN_ID or I_IFINDEX");
0302 return -EINVAL;
0303 }
0304
0305 memset(&role, 0x0, sizeof(role));
0306
0307 role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]);
0308 role.in_id = nla_get_u16(tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]);
0309 role.i_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]);
0310 role.in_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]);
0311
0312 return br_mrp_set_in_role(br, &role);
0313 }
0314
0315 static const struct nla_policy
0316 br_mrp_start_in_test_policy[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1] = {
0317 [IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC] = { .type = NLA_REJECT },
0318 [IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] = { .type = NLA_U32 },
0319 [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = { .type = NLA_U32 },
0320 [IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] = { .type = NLA_U32 },
0321 [IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD] = { .type = NLA_U32 },
0322 };
0323
0324 static int br_mrp_start_in_test_parse(struct net_bridge *br,
0325 struct nlattr *attr,
0326 struct netlink_ext_ack *extack)
0327 {
0328 struct nlattr *tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1];
0329 struct br_mrp_start_in_test test;
0330 int err;
0331
0332 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_IN_TEST_MAX, attr,
0333 br_mrp_start_in_test_policy, extack);
0334 if (err)
0335 return err;
0336
0337 if (!tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] ||
0338 !tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] ||
0339 !tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] ||
0340 !tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]) {
0341 NL_SET_ERR_MSG_MOD(extack,
0342 "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
0343 return -EINVAL;
0344 }
0345
0346 memset(&test, 0x0, sizeof(test));
0347
0348 test.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]);
0349 test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL]);
0350 test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS]);
0351 test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]);
0352
0353 return br_mrp_start_in_test(br, &test);
0354 }
0355
0356 int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
0357 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
0358 {
0359 struct nlattr *tb[IFLA_BRIDGE_MRP_MAX + 1];
0360 int err;
0361
0362
0363
0364
0365 if (p)
0366 br = p->br;
0367
0368 if (br->stp_enabled != BR_NO_STP) {
0369 NL_SET_ERR_MSG_MOD(extack, "MRP can't be enabled if STP is already enabled");
0370 return -EINVAL;
0371 }
0372
0373 err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_MAX, attr,
0374 br_mrp_policy, extack);
0375 if (err)
0376 return err;
0377
0378 if (tb[IFLA_BRIDGE_MRP_INSTANCE]) {
0379 err = br_mrp_instance_parse(br, tb[IFLA_BRIDGE_MRP_INSTANCE],
0380 cmd, extack);
0381 if (err)
0382 return err;
0383 }
0384
0385 if (tb[IFLA_BRIDGE_MRP_PORT_STATE]) {
0386 err = br_mrp_port_state_parse(p, tb[IFLA_BRIDGE_MRP_PORT_STATE],
0387 extack);
0388 if (err)
0389 return err;
0390 }
0391
0392 if (tb[IFLA_BRIDGE_MRP_PORT_ROLE]) {
0393 err = br_mrp_port_role_parse(p, tb[IFLA_BRIDGE_MRP_PORT_ROLE],
0394 extack);
0395 if (err)
0396 return err;
0397 }
0398
0399 if (tb[IFLA_BRIDGE_MRP_RING_STATE]) {
0400 err = br_mrp_ring_state_parse(br,
0401 tb[IFLA_BRIDGE_MRP_RING_STATE],
0402 extack);
0403 if (err)
0404 return err;
0405 }
0406
0407 if (tb[IFLA_BRIDGE_MRP_RING_ROLE]) {
0408 err = br_mrp_ring_role_parse(br, tb[IFLA_BRIDGE_MRP_RING_ROLE],
0409 extack);
0410 if (err)
0411 return err;
0412 }
0413
0414 if (tb[IFLA_BRIDGE_MRP_START_TEST]) {
0415 err = br_mrp_start_test_parse(br,
0416 tb[IFLA_BRIDGE_MRP_START_TEST],
0417 extack);
0418 if (err)
0419 return err;
0420 }
0421
0422 if (tb[IFLA_BRIDGE_MRP_IN_STATE]) {
0423 err = br_mrp_in_state_parse(br, tb[IFLA_BRIDGE_MRP_IN_STATE],
0424 extack);
0425 if (err)
0426 return err;
0427 }
0428
0429 if (tb[IFLA_BRIDGE_MRP_IN_ROLE]) {
0430 err = br_mrp_in_role_parse(br, tb[IFLA_BRIDGE_MRP_IN_ROLE],
0431 extack);
0432 if (err)
0433 return err;
0434 }
0435
0436 if (tb[IFLA_BRIDGE_MRP_START_IN_TEST]) {
0437 err = br_mrp_start_in_test_parse(br,
0438 tb[IFLA_BRIDGE_MRP_START_IN_TEST],
0439 extack);
0440 if (err)
0441 return err;
0442 }
0443
0444 return 0;
0445 }
0446
0447 int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br)
0448 {
0449 struct nlattr *tb, *mrp_tb;
0450 struct br_mrp *mrp;
0451
0452 mrp_tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP);
0453 if (!mrp_tb)
0454 return -EMSGSIZE;
0455
0456 hlist_for_each_entry_rcu(mrp, &br->mrp_list, list) {
0457 struct net_bridge_port *p;
0458
0459 tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP_INFO);
0460 if (!tb)
0461 goto nla_info_failure;
0462
0463 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ID,
0464 mrp->ring_id))
0465 goto nla_put_failure;
0466
0467 p = rcu_dereference(mrp->p_port);
0468 if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_P_IFINDEX,
0469 p->dev->ifindex))
0470 goto nla_put_failure;
0471
0472 p = rcu_dereference(mrp->s_port);
0473 if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_S_IFINDEX,
0474 p->dev->ifindex))
0475 goto nla_put_failure;
0476
0477 p = rcu_dereference(mrp->i_port);
0478 if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_I_IFINDEX,
0479 p->dev->ifindex))
0480 goto nla_put_failure;
0481
0482 if (nla_put_u16(skb, IFLA_BRIDGE_MRP_INFO_PRIO,
0483 mrp->prio))
0484 goto nla_put_failure;
0485 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_STATE,
0486 mrp->ring_state))
0487 goto nla_put_failure;
0488 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ROLE,
0489 mrp->ring_role))
0490 goto nla_put_failure;
0491 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL,
0492 mrp->test_interval))
0493 goto nla_put_failure;
0494 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS,
0495 mrp->test_max_miss))
0496 goto nla_put_failure;
0497 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MONITOR,
0498 mrp->test_monitor))
0499 goto nla_put_failure;
0500
0501 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_STATE,
0502 mrp->in_state))
0503 goto nla_put_failure;
0504 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_ROLE,
0505 mrp->in_role))
0506 goto nla_put_failure;
0507 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL,
0508 mrp->in_test_interval))
0509 goto nla_put_failure;
0510 if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS,
0511 mrp->in_test_max_miss))
0512 goto nla_put_failure;
0513
0514 nla_nest_end(skb, tb);
0515 }
0516 nla_nest_end(skb, mrp_tb);
0517
0518 return 0;
0519
0520 nla_put_failure:
0521 nla_nest_cancel(skb, tb);
0522
0523 nla_info_failure:
0524 nla_nest_cancel(skb, mrp_tb);
0525
0526 return -EMSGSIZE;
0527 }
0528
0529 int br_mrp_ring_port_open(struct net_device *dev, u8 loc)
0530 {
0531 struct net_bridge_port *p;
0532 int err = 0;
0533
0534 p = br_port_get_rcu(dev);
0535 if (!p) {
0536 err = -EINVAL;
0537 goto out;
0538 }
0539
0540 if (loc)
0541 p->flags |= BR_MRP_LOST_CONT;
0542 else
0543 p->flags &= ~BR_MRP_LOST_CONT;
0544
0545 br_ifinfo_notify(RTM_NEWLINK, NULL, p);
0546
0547 out:
0548 return err;
0549 }
0550
0551 int br_mrp_in_port_open(struct net_device *dev, u8 loc)
0552 {
0553 struct net_bridge_port *p;
0554 int err = 0;
0555
0556 p = br_port_get_rcu(dev);
0557 if (!p) {
0558 err = -EINVAL;
0559 goto out;
0560 }
0561
0562 if (loc)
0563 p->flags |= BR_MRP_LOST_IN_CONT;
0564 else
0565 p->flags &= ~BR_MRP_LOST_IN_CONT;
0566
0567 br_ifinfo_notify(RTM_NEWLINK, NULL, p);
0568
0569 out:
0570 return err;
0571 }