Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
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     /* When this function is called for a port then the br pointer is
0363      * invalid, therefor set the br to point correctly
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 }