linux/net/bridge/br_mrp_netlink.c
<<
>>
Prefs
   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}
 572