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}