19a9f26e8SHoratiu Vultur // SPDX-License-Identifier: GPL-2.0-or-later
29a9f26e8SHoratiu Vultur
39a9f26e8SHoratiu Vultur #include <net/genetlink.h>
49a9f26e8SHoratiu Vultur
59a9f26e8SHoratiu Vultur #include <uapi/linux/mrp_bridge.h>
69a9f26e8SHoratiu Vultur #include "br_private.h"
79a9f26e8SHoratiu Vultur #include "br_private_mrp.h"
89a9f26e8SHoratiu Vultur
94d02b8f0SHoratiu Vultur static const struct nla_policy br_mrp_policy[IFLA_BRIDGE_MRP_MAX + 1] = {
104d02b8f0SHoratiu Vultur [IFLA_BRIDGE_MRP_UNSPEC] = { .type = NLA_REJECT },
1120f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_INSTANCE] = { .type = NLA_NESTED },
1220f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_PORT_STATE] = { .type = NLA_NESTED },
1320f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_PORT_ROLE] = { .type = NLA_NESTED },
1420f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_RING_STATE] = { .type = NLA_NESTED },
1520f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_RING_ROLE] = { .type = NLA_NESTED },
1620f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_TEST] = { .type = NLA_NESTED },
177ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_ROLE] = { .type = NLA_NESTED },
187ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_STATE] = { .type = NLA_NESTED },
197ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_IN_TEST] = { .type = NLA_NESTED },
204d02b8f0SHoratiu Vultur };
214d02b8f0SHoratiu Vultur
2220f6a05eSHoratiu Vultur static const struct nla_policy
2320f6a05eSHoratiu Vultur br_mrp_instance_policy[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1] = {
2420f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_INSTANCE_UNSPEC] = { .type = NLA_REJECT },
2520f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_INSTANCE_RING_ID] = { .type = NLA_U32 },
2620f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX] = { .type = NLA_U32 },
2720f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX] = { .type = NLA_U32 },
284b3a61b0SHoratiu Vultur [IFLA_BRIDGE_MRP_INSTANCE_PRIO] = { .type = NLA_U16 },
2920f6a05eSHoratiu Vultur };
3020f6a05eSHoratiu Vultur
br_mrp_instance_parse(struct net_bridge * br,struct nlattr * attr,int cmd,struct netlink_ext_ack * extack)3120f6a05eSHoratiu Vultur static int br_mrp_instance_parse(struct net_bridge *br, struct nlattr *attr,
3220f6a05eSHoratiu Vultur int cmd, struct netlink_ext_ack *extack)
3320f6a05eSHoratiu Vultur {
3420f6a05eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_INSTANCE_MAX + 1];
3520f6a05eSHoratiu Vultur struct br_mrp_instance inst;
3620f6a05eSHoratiu Vultur int err;
3720f6a05eSHoratiu Vultur
3820f6a05eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_INSTANCE_MAX, attr,
3920f6a05eSHoratiu Vultur br_mrp_instance_policy, extack);
4020f6a05eSHoratiu Vultur if (err)
4120f6a05eSHoratiu Vultur return err;
4220f6a05eSHoratiu Vultur
4320f6a05eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID] ||
4420f6a05eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX] ||
4520f6a05eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]) {
4620f6a05eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack,
4720f6a05eSHoratiu Vultur "Missing attribute: RING_ID or P_IFINDEX or S_IFINDEX");
4820f6a05eSHoratiu Vultur return -EINVAL;
4920f6a05eSHoratiu Vultur }
5020f6a05eSHoratiu Vultur
5120f6a05eSHoratiu Vultur memset(&inst, 0, sizeof(inst));
5220f6a05eSHoratiu Vultur
5320f6a05eSHoratiu Vultur inst.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_RING_ID]);
5420f6a05eSHoratiu Vultur inst.p_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX]);
5520f6a05eSHoratiu Vultur inst.s_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX]);
564b3a61b0SHoratiu Vultur inst.prio = MRP_DEFAULT_PRIO;
574b3a61b0SHoratiu Vultur
584b3a61b0SHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO])
594b3a61b0SHoratiu Vultur inst.prio = nla_get_u16(tb[IFLA_BRIDGE_MRP_INSTANCE_PRIO]);
6020f6a05eSHoratiu Vultur
6120f6a05eSHoratiu Vultur if (cmd == RTM_SETLINK)
6220f6a05eSHoratiu Vultur return br_mrp_add(br, &inst);
6320f6a05eSHoratiu Vultur else
6420f6a05eSHoratiu Vultur return br_mrp_del(br, &inst);
6520f6a05eSHoratiu Vultur
6620f6a05eSHoratiu Vultur return 0;
6720f6a05eSHoratiu Vultur }
6820f6a05eSHoratiu Vultur
6920f6a05eSHoratiu Vultur static const struct nla_policy
7020f6a05eSHoratiu Vultur br_mrp_port_state_policy[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1] = {
7120f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC] = { .type = NLA_REJECT },
7220f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_PORT_STATE_STATE] = { .type = NLA_U32 },
7320f6a05eSHoratiu Vultur };
7420f6a05eSHoratiu Vultur
br_mrp_port_state_parse(struct net_bridge_port * p,struct nlattr * attr,struct netlink_ext_ack * extack)7520f6a05eSHoratiu Vultur static int br_mrp_port_state_parse(struct net_bridge_port *p,
7620f6a05eSHoratiu Vultur struct nlattr *attr,
7720f6a05eSHoratiu Vultur struct netlink_ext_ack *extack)
7820f6a05eSHoratiu Vultur {
7920f6a05eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_STATE_MAX + 1];
8020f6a05eSHoratiu Vultur enum br_mrp_port_state_type state;
8120f6a05eSHoratiu Vultur int err;
8220f6a05eSHoratiu Vultur
8320f6a05eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_STATE_MAX, attr,
8420f6a05eSHoratiu Vultur br_mrp_port_state_policy, extack);
8520f6a05eSHoratiu Vultur if (err)
8620f6a05eSHoratiu Vultur return err;
8720f6a05eSHoratiu Vultur
8820f6a05eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]) {
8920f6a05eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack, "Missing attribute: STATE");
9020f6a05eSHoratiu Vultur return -EINVAL;
9120f6a05eSHoratiu Vultur }
9220f6a05eSHoratiu Vultur
9320f6a05eSHoratiu Vultur state = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_STATE_STATE]);
9420f6a05eSHoratiu Vultur
9520f6a05eSHoratiu Vultur return br_mrp_set_port_state(p, state);
9620f6a05eSHoratiu Vultur }
9720f6a05eSHoratiu Vultur
9820f6a05eSHoratiu Vultur static const struct nla_policy
9920f6a05eSHoratiu Vultur br_mrp_port_role_policy[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1] = {
10020f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC] = { .type = NLA_REJECT },
10120f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_PORT_ROLE_ROLE] = { .type = NLA_U32 },
10220f6a05eSHoratiu Vultur };
10320f6a05eSHoratiu Vultur
br_mrp_port_role_parse(struct net_bridge_port * p,struct nlattr * attr,struct netlink_ext_ack * extack)10420f6a05eSHoratiu Vultur static int br_mrp_port_role_parse(struct net_bridge_port *p,
10520f6a05eSHoratiu Vultur struct nlattr *attr,
10620f6a05eSHoratiu Vultur struct netlink_ext_ack *extack)
10720f6a05eSHoratiu Vultur {
10820f6a05eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_PORT_ROLE_MAX + 1];
10920f6a05eSHoratiu Vultur enum br_mrp_port_role_type role;
11020f6a05eSHoratiu Vultur int err;
11120f6a05eSHoratiu Vultur
11220f6a05eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_PORT_ROLE_MAX, attr,
11320f6a05eSHoratiu Vultur br_mrp_port_role_policy, extack);
11420f6a05eSHoratiu Vultur if (err)
11520f6a05eSHoratiu Vultur return err;
11620f6a05eSHoratiu Vultur
11720f6a05eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]) {
11820f6a05eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack, "Missing attribute: ROLE");
11920f6a05eSHoratiu Vultur return -EINVAL;
12020f6a05eSHoratiu Vultur }
12120f6a05eSHoratiu Vultur
12220f6a05eSHoratiu Vultur role = nla_get_u32(tb[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE]);
12320f6a05eSHoratiu Vultur
12420f6a05eSHoratiu Vultur return br_mrp_set_port_role(p, role);
12520f6a05eSHoratiu Vultur }
12620f6a05eSHoratiu Vultur
12720f6a05eSHoratiu Vultur static const struct nla_policy
12820f6a05eSHoratiu Vultur br_mrp_ring_state_policy[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1] = {
12920f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_RING_STATE_UNSPEC] = { .type = NLA_REJECT },
13020f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_RING_STATE_RING_ID] = { .type = NLA_U32 },
13120f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_RING_STATE_STATE] = { .type = NLA_U32 },
13220f6a05eSHoratiu Vultur };
13320f6a05eSHoratiu Vultur
br_mrp_ring_state_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)13420f6a05eSHoratiu Vultur static int br_mrp_ring_state_parse(struct net_bridge *br, struct nlattr *attr,
13520f6a05eSHoratiu Vultur struct netlink_ext_ack *extack)
13620f6a05eSHoratiu Vultur {
13720f6a05eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_RING_STATE_MAX + 1];
13820f6a05eSHoratiu Vultur struct br_mrp_ring_state state;
13920f6a05eSHoratiu Vultur int err;
14020f6a05eSHoratiu Vultur
14120f6a05eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_STATE_MAX, attr,
14220f6a05eSHoratiu Vultur br_mrp_ring_state_policy, extack);
14320f6a05eSHoratiu Vultur if (err)
14420f6a05eSHoratiu Vultur return err;
14520f6a05eSHoratiu Vultur
14620f6a05eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID] ||
14720f6a05eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]) {
14820f6a05eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack,
14920f6a05eSHoratiu Vultur "Missing attribute: RING_ID or STATE");
15020f6a05eSHoratiu Vultur return -EINVAL;
15120f6a05eSHoratiu Vultur }
15220f6a05eSHoratiu Vultur
15320f6a05eSHoratiu Vultur memset(&state, 0x0, sizeof(state));
15420f6a05eSHoratiu Vultur
15520f6a05eSHoratiu Vultur state.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_RING_ID]);
15620f6a05eSHoratiu Vultur state.ring_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_STATE_STATE]);
15720f6a05eSHoratiu Vultur
15820f6a05eSHoratiu Vultur return br_mrp_set_ring_state(br, &state);
15920f6a05eSHoratiu Vultur }
16020f6a05eSHoratiu Vultur
16120f6a05eSHoratiu Vultur static const struct nla_policy
16220f6a05eSHoratiu Vultur br_mrp_ring_role_policy[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1] = {
16320f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC] = { .type = NLA_REJECT },
16420f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_RING_ROLE_RING_ID] = { .type = NLA_U32 },
16520f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_RING_ROLE_ROLE] = { .type = NLA_U32 },
16620f6a05eSHoratiu Vultur };
16720f6a05eSHoratiu Vultur
br_mrp_ring_role_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)16820f6a05eSHoratiu Vultur static int br_mrp_ring_role_parse(struct net_bridge *br, struct nlattr *attr,
16920f6a05eSHoratiu Vultur struct netlink_ext_ack *extack)
17020f6a05eSHoratiu Vultur {
17120f6a05eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_RING_ROLE_MAX + 1];
17220f6a05eSHoratiu Vultur struct br_mrp_ring_role role;
17320f6a05eSHoratiu Vultur int err;
17420f6a05eSHoratiu Vultur
17520f6a05eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_RING_ROLE_MAX, attr,
17620f6a05eSHoratiu Vultur br_mrp_ring_role_policy, extack);
17720f6a05eSHoratiu Vultur if (err)
17820f6a05eSHoratiu Vultur return err;
17920f6a05eSHoratiu Vultur
18020f6a05eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID] ||
18120f6a05eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]) {
18220f6a05eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack,
18320f6a05eSHoratiu Vultur "Missing attribute: RING_ID or ROLE");
18420f6a05eSHoratiu Vultur return -EINVAL;
18520f6a05eSHoratiu Vultur }
18620f6a05eSHoratiu Vultur
18720f6a05eSHoratiu Vultur memset(&role, 0x0, sizeof(role));
18820f6a05eSHoratiu Vultur
18920f6a05eSHoratiu Vultur role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID]);
19020f6a05eSHoratiu Vultur role.ring_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_RING_ROLE_ROLE]);
19120f6a05eSHoratiu Vultur
19220f6a05eSHoratiu Vultur return br_mrp_set_ring_role(br, &role);
19320f6a05eSHoratiu Vultur }
19420f6a05eSHoratiu Vultur
19520f6a05eSHoratiu Vultur static const struct nla_policy
19620f6a05eSHoratiu Vultur br_mrp_start_test_policy[IFLA_BRIDGE_MRP_START_TEST_MAX + 1] = {
19720f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_TEST_UNSPEC] = { .type = NLA_REJECT },
19820f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_TEST_RING_ID] = { .type = NLA_U32 },
19920f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_TEST_INTERVAL] = { .type = NLA_U32 },
20020f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] = { .type = NLA_U32 },
20120f6a05eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_TEST_PERIOD] = { .type = NLA_U32 },
202c6676e7dSHoratiu Vultur [IFLA_BRIDGE_MRP_START_TEST_MONITOR] = { .type = NLA_U32 },
20320f6a05eSHoratiu Vultur };
20420f6a05eSHoratiu Vultur
br_mrp_start_test_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)20520f6a05eSHoratiu Vultur static int br_mrp_start_test_parse(struct net_bridge *br, struct nlattr *attr,
20620f6a05eSHoratiu Vultur struct netlink_ext_ack *extack)
20720f6a05eSHoratiu Vultur {
20820f6a05eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_START_TEST_MAX + 1];
20920f6a05eSHoratiu Vultur struct br_mrp_start_test test;
21020f6a05eSHoratiu Vultur int err;
21120f6a05eSHoratiu Vultur
21220f6a05eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_TEST_MAX, attr,
21320f6a05eSHoratiu Vultur br_mrp_start_test_policy, extack);
21420f6a05eSHoratiu Vultur if (err)
21520f6a05eSHoratiu Vultur return err;
21620f6a05eSHoratiu Vultur
21720f6a05eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID] ||
21820f6a05eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL] ||
21920f6a05eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] ||
22020f6a05eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]) {
22120f6a05eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack,
22220f6a05eSHoratiu Vultur "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
22320f6a05eSHoratiu Vultur return -EINVAL;
22420f6a05eSHoratiu Vultur }
22520f6a05eSHoratiu Vultur
22620f6a05eSHoratiu Vultur memset(&test, 0x0, sizeof(test));
22720f6a05eSHoratiu Vultur
22820f6a05eSHoratiu Vultur test.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_RING_ID]);
22920f6a05eSHoratiu Vultur test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_INTERVAL]);
23020f6a05eSHoratiu Vultur test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS]);
23120f6a05eSHoratiu Vultur test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_PERIOD]);
232c6676e7dSHoratiu Vultur test.monitor = false;
233c6676e7dSHoratiu Vultur
234c6676e7dSHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR])
235c6676e7dSHoratiu Vultur test.monitor =
236c6676e7dSHoratiu Vultur nla_get_u32(tb[IFLA_BRIDGE_MRP_START_TEST_MONITOR]);
23720f6a05eSHoratiu Vultur
23820f6a05eSHoratiu Vultur return br_mrp_start_test(br, &test);
23920f6a05eSHoratiu Vultur }
24020f6a05eSHoratiu Vultur
2417ab1748eSHoratiu Vultur static const struct nla_policy
2427ab1748eSHoratiu Vultur br_mrp_in_state_policy[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1] = {
2437ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_STATE_UNSPEC] = { .type = NLA_REJECT },
2447ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_STATE_IN_ID] = { .type = NLA_U32 },
2457ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_STATE_STATE] = { .type = NLA_U32 },
2467ab1748eSHoratiu Vultur };
2477ab1748eSHoratiu Vultur
br_mrp_in_state_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)2487ab1748eSHoratiu Vultur static int br_mrp_in_state_parse(struct net_bridge *br, struct nlattr *attr,
2497ab1748eSHoratiu Vultur struct netlink_ext_ack *extack)
2507ab1748eSHoratiu Vultur {
2517ab1748eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_IN_STATE_MAX + 1];
2527ab1748eSHoratiu Vultur struct br_mrp_in_state state;
2537ab1748eSHoratiu Vultur int err;
2547ab1748eSHoratiu Vultur
2557ab1748eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_STATE_MAX, attr,
2567ab1748eSHoratiu Vultur br_mrp_in_state_policy, extack);
2577ab1748eSHoratiu Vultur if (err)
2587ab1748eSHoratiu Vultur return err;
2597ab1748eSHoratiu Vultur
2607ab1748eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID] ||
2617ab1748eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]) {
2627ab1748eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack,
2637ab1748eSHoratiu Vultur "Missing attribute: IN_ID or STATE");
2647ab1748eSHoratiu Vultur return -EINVAL;
2657ab1748eSHoratiu Vultur }
2667ab1748eSHoratiu Vultur
2677ab1748eSHoratiu Vultur memset(&state, 0x0, sizeof(state));
2687ab1748eSHoratiu Vultur
2697ab1748eSHoratiu Vultur state.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_IN_ID]);
2707ab1748eSHoratiu Vultur state.in_state = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_STATE_STATE]);
2717ab1748eSHoratiu Vultur
2727ab1748eSHoratiu Vultur return br_mrp_set_in_state(br, &state);
2737ab1748eSHoratiu Vultur }
2747ab1748eSHoratiu Vultur
2757ab1748eSHoratiu Vultur static const struct nla_policy
2767ab1748eSHoratiu Vultur br_mrp_in_role_policy[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1] = {
2777ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_ROLE_UNSPEC] = { .type = NLA_REJECT },
2787ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_ROLE_RING_ID] = { .type = NLA_U32 },
2797ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_ROLE_IN_ID] = { .type = NLA_U16 },
2807ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_ROLE_ROLE] = { .type = NLA_U32 },
2817ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX] = { .type = NLA_U32 },
2827ab1748eSHoratiu Vultur };
2837ab1748eSHoratiu Vultur
br_mrp_in_role_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)2847ab1748eSHoratiu Vultur static int br_mrp_in_role_parse(struct net_bridge *br, struct nlattr *attr,
2857ab1748eSHoratiu Vultur struct netlink_ext_ack *extack)
2867ab1748eSHoratiu Vultur {
2877ab1748eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_IN_ROLE_MAX + 1];
2887ab1748eSHoratiu Vultur struct br_mrp_in_role role;
2897ab1748eSHoratiu Vultur int err;
2907ab1748eSHoratiu Vultur
2917ab1748eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_IN_ROLE_MAX, attr,
2927ab1748eSHoratiu Vultur br_mrp_in_role_policy, extack);
2937ab1748eSHoratiu Vultur if (err)
2947ab1748eSHoratiu Vultur return err;
2957ab1748eSHoratiu Vultur
2967ab1748eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID] ||
2977ab1748eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID] ||
2987ab1748eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX] ||
2997ab1748eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]) {
3007ab1748eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack,
3017ab1748eSHoratiu Vultur "Missing attribute: RING_ID or ROLE or IN_ID or I_IFINDEX");
3027ab1748eSHoratiu Vultur return -EINVAL;
3037ab1748eSHoratiu Vultur }
3047ab1748eSHoratiu Vultur
3057ab1748eSHoratiu Vultur memset(&role, 0x0, sizeof(role));
3067ab1748eSHoratiu Vultur
3077ab1748eSHoratiu Vultur role.ring_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_RING_ID]);
3087ab1748eSHoratiu Vultur role.in_id = nla_get_u16(tb[IFLA_BRIDGE_MRP_IN_ROLE_IN_ID]);
3097ab1748eSHoratiu Vultur role.i_ifindex = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX]);
3107ab1748eSHoratiu Vultur role.in_role = nla_get_u32(tb[IFLA_BRIDGE_MRP_IN_ROLE_ROLE]);
3117ab1748eSHoratiu Vultur
3127ab1748eSHoratiu Vultur return br_mrp_set_in_role(br, &role);
3137ab1748eSHoratiu Vultur }
3147ab1748eSHoratiu Vultur
3157ab1748eSHoratiu Vultur static const struct nla_policy
3167ab1748eSHoratiu Vultur br_mrp_start_in_test_policy[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1] = {
3177ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC] = { .type = NLA_REJECT },
3187ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] = { .type = NLA_U32 },
3197ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = { .type = NLA_U32 },
3207ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] = { .type = NLA_U32 },
3217ab1748eSHoratiu Vultur [IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD] = { .type = NLA_U32 },
3227ab1748eSHoratiu Vultur };
3237ab1748eSHoratiu Vultur
br_mrp_start_in_test_parse(struct net_bridge * br,struct nlattr * attr,struct netlink_ext_ack * extack)3247ab1748eSHoratiu Vultur static int br_mrp_start_in_test_parse(struct net_bridge *br,
3257ab1748eSHoratiu Vultur struct nlattr *attr,
3267ab1748eSHoratiu Vultur struct netlink_ext_ack *extack)
3277ab1748eSHoratiu Vultur {
3287ab1748eSHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1];
3297ab1748eSHoratiu Vultur struct br_mrp_start_in_test test;
3307ab1748eSHoratiu Vultur int err;
3317ab1748eSHoratiu Vultur
3327ab1748eSHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_START_IN_TEST_MAX, attr,
3337ab1748eSHoratiu Vultur br_mrp_start_in_test_policy, extack);
3347ab1748eSHoratiu Vultur if (err)
3357ab1748eSHoratiu Vultur return err;
3367ab1748eSHoratiu Vultur
3377ab1748eSHoratiu Vultur if (!tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] ||
3387ab1748eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] ||
3397ab1748eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] ||
3407ab1748eSHoratiu Vultur !tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]) {
3417ab1748eSHoratiu Vultur NL_SET_ERR_MSG_MOD(extack,
3427ab1748eSHoratiu Vultur "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
3437ab1748eSHoratiu Vultur return -EINVAL;
3447ab1748eSHoratiu Vultur }
3457ab1748eSHoratiu Vultur
3467ab1748eSHoratiu Vultur memset(&test, 0x0, sizeof(test));
3477ab1748eSHoratiu Vultur
3487ab1748eSHoratiu Vultur test.in_id = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID]);
3497ab1748eSHoratiu Vultur test.interval = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL]);
3507ab1748eSHoratiu Vultur test.max_miss = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS]);
3517ab1748eSHoratiu Vultur test.period = nla_get_u32(tb[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD]);
3527ab1748eSHoratiu Vultur
3537ab1748eSHoratiu Vultur return br_mrp_start_in_test(br, &test);
3547ab1748eSHoratiu Vultur }
3557ab1748eSHoratiu Vultur
br_mrp_parse(struct net_bridge * br,struct net_bridge_port * p,struct nlattr * attr,int cmd,struct netlink_ext_ack * extack)3564d02b8f0SHoratiu Vultur int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
3574d02b8f0SHoratiu Vultur struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
3584d02b8f0SHoratiu Vultur {
3594d02b8f0SHoratiu Vultur struct nlattr *tb[IFLA_BRIDGE_MRP_MAX + 1];
3604d02b8f0SHoratiu Vultur int err;
3614d02b8f0SHoratiu Vultur
362617504c6SHoratiu Vultur /* When this function is called for a port then the br pointer is
363617504c6SHoratiu Vultur * invalid, therefor set the br to point correctly
364617504c6SHoratiu Vultur */
365617504c6SHoratiu Vultur if (p)
366617504c6SHoratiu Vultur br = p->br;
367617504c6SHoratiu Vultur
3684d02b8f0SHoratiu Vultur if (br->stp_enabled != BR_NO_STP) {
369c75a33c8SJacob Keller NL_SET_ERR_MSG_MOD(extack, "MRP can't be enabled if STP is already enabled");
3704d02b8f0SHoratiu Vultur return -EINVAL;
3714d02b8f0SHoratiu Vultur }
3724d02b8f0SHoratiu Vultur
3734d02b8f0SHoratiu Vultur err = nla_parse_nested(tb, IFLA_BRIDGE_MRP_MAX, attr,
3744d02b8f0SHoratiu Vultur br_mrp_policy, extack);
3754d02b8f0SHoratiu Vultur if (err)
3764d02b8f0SHoratiu Vultur return err;
3774d02b8f0SHoratiu Vultur
3784d02b8f0SHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_INSTANCE]) {
37920f6a05eSHoratiu Vultur err = br_mrp_instance_parse(br, tb[IFLA_BRIDGE_MRP_INSTANCE],
38020f6a05eSHoratiu Vultur cmd, extack);
3814d02b8f0SHoratiu Vultur if (err)
3824d02b8f0SHoratiu Vultur return err;
3834d02b8f0SHoratiu Vultur }
3844d02b8f0SHoratiu Vultur
3854d02b8f0SHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_PORT_STATE]) {
38620f6a05eSHoratiu Vultur err = br_mrp_port_state_parse(p, tb[IFLA_BRIDGE_MRP_PORT_STATE],
38720f6a05eSHoratiu Vultur extack);
3884d02b8f0SHoratiu Vultur if (err)
3894d02b8f0SHoratiu Vultur return err;
3904d02b8f0SHoratiu Vultur }
3914d02b8f0SHoratiu Vultur
3924d02b8f0SHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_PORT_ROLE]) {
39320f6a05eSHoratiu Vultur err = br_mrp_port_role_parse(p, tb[IFLA_BRIDGE_MRP_PORT_ROLE],
39420f6a05eSHoratiu Vultur extack);
3954d02b8f0SHoratiu Vultur if (err)
3964d02b8f0SHoratiu Vultur return err;
3974d02b8f0SHoratiu Vultur }
3984d02b8f0SHoratiu Vultur
3994d02b8f0SHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_RING_STATE]) {
40020f6a05eSHoratiu Vultur err = br_mrp_ring_state_parse(br,
40120f6a05eSHoratiu Vultur tb[IFLA_BRIDGE_MRP_RING_STATE],
40220f6a05eSHoratiu Vultur extack);
4034d02b8f0SHoratiu Vultur if (err)
4044d02b8f0SHoratiu Vultur return err;
4054d02b8f0SHoratiu Vultur }
4064d02b8f0SHoratiu Vultur
4074d02b8f0SHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_RING_ROLE]) {
40820f6a05eSHoratiu Vultur err = br_mrp_ring_role_parse(br, tb[IFLA_BRIDGE_MRP_RING_ROLE],
40920f6a05eSHoratiu Vultur extack);
4104d02b8f0SHoratiu Vultur if (err)
4114d02b8f0SHoratiu Vultur return err;
4124d02b8f0SHoratiu Vultur }
4134d02b8f0SHoratiu Vultur
4144d02b8f0SHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_START_TEST]) {
41520f6a05eSHoratiu Vultur err = br_mrp_start_test_parse(br,
41620f6a05eSHoratiu Vultur tb[IFLA_BRIDGE_MRP_START_TEST],
41720f6a05eSHoratiu Vultur extack);
4184d02b8f0SHoratiu Vultur if (err)
4194d02b8f0SHoratiu Vultur return err;
4204d02b8f0SHoratiu Vultur }
4214d02b8f0SHoratiu Vultur
4227ab1748eSHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_IN_STATE]) {
4237ab1748eSHoratiu Vultur err = br_mrp_in_state_parse(br, tb[IFLA_BRIDGE_MRP_IN_STATE],
4247ab1748eSHoratiu Vultur extack);
4257ab1748eSHoratiu Vultur if (err)
4267ab1748eSHoratiu Vultur return err;
4277ab1748eSHoratiu Vultur }
4287ab1748eSHoratiu Vultur
4297ab1748eSHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_IN_ROLE]) {
4307ab1748eSHoratiu Vultur err = br_mrp_in_role_parse(br, tb[IFLA_BRIDGE_MRP_IN_ROLE],
4317ab1748eSHoratiu Vultur extack);
4327ab1748eSHoratiu Vultur if (err)
4337ab1748eSHoratiu Vultur return err;
4347ab1748eSHoratiu Vultur }
4357ab1748eSHoratiu Vultur
4367ab1748eSHoratiu Vultur if (tb[IFLA_BRIDGE_MRP_START_IN_TEST]) {
4377ab1748eSHoratiu Vultur err = br_mrp_start_in_test_parse(br,
4387ab1748eSHoratiu Vultur tb[IFLA_BRIDGE_MRP_START_IN_TEST],
4397ab1748eSHoratiu Vultur extack);
4407ab1748eSHoratiu Vultur if (err)
4417ab1748eSHoratiu Vultur return err;
4427ab1748eSHoratiu Vultur }
4437ab1748eSHoratiu Vultur
4444d02b8f0SHoratiu Vultur return 0;
4454d02b8f0SHoratiu Vultur }
4464d02b8f0SHoratiu Vultur
br_mrp_fill_info(struct sk_buff * skb,struct net_bridge * br)447df42ef22SHoratiu Vultur int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br)
448df42ef22SHoratiu Vultur {
449df42ef22SHoratiu Vultur struct nlattr *tb, *mrp_tb;
450df42ef22SHoratiu Vultur struct br_mrp *mrp;
451df42ef22SHoratiu Vultur
452df42ef22SHoratiu Vultur mrp_tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP);
453df42ef22SHoratiu Vultur if (!mrp_tb)
454df42ef22SHoratiu Vultur return -EMSGSIZE;
455df42ef22SHoratiu Vultur
456*0169b820SHoratiu Vultur hlist_for_each_entry_rcu(mrp, &br->mrp_list, list) {
457df42ef22SHoratiu Vultur struct net_bridge_port *p;
458df42ef22SHoratiu Vultur
459df42ef22SHoratiu Vultur tb = nla_nest_start_noflag(skb, IFLA_BRIDGE_MRP_INFO);
460df42ef22SHoratiu Vultur if (!tb)
461df42ef22SHoratiu Vultur goto nla_info_failure;
462df42ef22SHoratiu Vultur
463df42ef22SHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ID,
464df42ef22SHoratiu Vultur mrp->ring_id))
465df42ef22SHoratiu Vultur goto nla_put_failure;
466df42ef22SHoratiu Vultur
467df42ef22SHoratiu Vultur p = rcu_dereference(mrp->p_port);
468df42ef22SHoratiu Vultur if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_P_IFINDEX,
469df42ef22SHoratiu Vultur p->dev->ifindex))
470df42ef22SHoratiu Vultur goto nla_put_failure;
471df42ef22SHoratiu Vultur
472df42ef22SHoratiu Vultur p = rcu_dereference(mrp->s_port);
473df42ef22SHoratiu Vultur if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_S_IFINDEX,
474df42ef22SHoratiu Vultur p->dev->ifindex))
475df42ef22SHoratiu Vultur goto nla_put_failure;
476df42ef22SHoratiu Vultur
4774fc4871fSHoratiu Vultur p = rcu_dereference(mrp->i_port);
4784fc4871fSHoratiu Vultur if (p && nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_I_IFINDEX,
4794fc4871fSHoratiu Vultur p->dev->ifindex))
4804fc4871fSHoratiu Vultur goto nla_put_failure;
4814fc4871fSHoratiu Vultur
482df42ef22SHoratiu Vultur if (nla_put_u16(skb, IFLA_BRIDGE_MRP_INFO_PRIO,
483df42ef22SHoratiu Vultur mrp->prio))
484df42ef22SHoratiu Vultur goto nla_put_failure;
485df42ef22SHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_STATE,
486df42ef22SHoratiu Vultur mrp->ring_state))
487df42ef22SHoratiu Vultur goto nla_put_failure;
488df42ef22SHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_RING_ROLE,
489df42ef22SHoratiu Vultur mrp->ring_role))
490df42ef22SHoratiu Vultur goto nla_put_failure;
491df42ef22SHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL,
492df42ef22SHoratiu Vultur mrp->test_interval))
493df42ef22SHoratiu Vultur goto nla_put_failure;
494df42ef22SHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS,
495df42ef22SHoratiu Vultur mrp->test_max_miss))
496df42ef22SHoratiu Vultur goto nla_put_failure;
497df42ef22SHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_TEST_MONITOR,
498df42ef22SHoratiu Vultur mrp->test_monitor))
499df42ef22SHoratiu Vultur goto nla_put_failure;
500df42ef22SHoratiu Vultur
5014fc4871fSHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_STATE,
5024fc4871fSHoratiu Vultur mrp->in_state))
5034fc4871fSHoratiu Vultur goto nla_put_failure;
5044fc4871fSHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_ROLE,
5054fc4871fSHoratiu Vultur mrp->in_role))
5064fc4871fSHoratiu Vultur goto nla_put_failure;
5074fc4871fSHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL,
5084fc4871fSHoratiu Vultur mrp->in_test_interval))
5094fc4871fSHoratiu Vultur goto nla_put_failure;
5104fc4871fSHoratiu Vultur if (nla_put_u32(skb, IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS,
5114fc4871fSHoratiu Vultur mrp->in_test_max_miss))
5124fc4871fSHoratiu Vultur goto nla_put_failure;
5134fc4871fSHoratiu Vultur
514df42ef22SHoratiu Vultur nla_nest_end(skb, tb);
515df42ef22SHoratiu Vultur }
516df42ef22SHoratiu Vultur nla_nest_end(skb, mrp_tb);
517df42ef22SHoratiu Vultur
518df42ef22SHoratiu Vultur return 0;
519df42ef22SHoratiu Vultur
520df42ef22SHoratiu Vultur nla_put_failure:
521df42ef22SHoratiu Vultur nla_nest_cancel(skb, tb);
522df42ef22SHoratiu Vultur
523df42ef22SHoratiu Vultur nla_info_failure:
524df42ef22SHoratiu Vultur nla_nest_cancel(skb, mrp_tb);
525df42ef22SHoratiu Vultur
526df42ef22SHoratiu Vultur return -EMSGSIZE;
527df42ef22SHoratiu Vultur }
528df42ef22SHoratiu Vultur
br_mrp_ring_port_open(struct net_device * dev,u8 loc)5294cc625c6SHoratiu Vultur int br_mrp_ring_port_open(struct net_device *dev, u8 loc)
5309a9f26e8SHoratiu Vultur {
5319a9f26e8SHoratiu Vultur struct net_bridge_port *p;
5329a9f26e8SHoratiu Vultur int err = 0;
5339a9f26e8SHoratiu Vultur
5349a9f26e8SHoratiu Vultur p = br_port_get_rcu(dev);
5359a9f26e8SHoratiu Vultur if (!p) {
5369a9f26e8SHoratiu Vultur err = -EINVAL;
5379a9f26e8SHoratiu Vultur goto out;
5389a9f26e8SHoratiu Vultur }
5399a9f26e8SHoratiu Vultur
5409a9f26e8SHoratiu Vultur if (loc)
5419a9f26e8SHoratiu Vultur p->flags |= BR_MRP_LOST_CONT;
5429a9f26e8SHoratiu Vultur else
5439a9f26e8SHoratiu Vultur p->flags &= ~BR_MRP_LOST_CONT;
5449a9f26e8SHoratiu Vultur
5459a9f26e8SHoratiu Vultur br_ifinfo_notify(RTM_NEWLINK, NULL, p);
5469a9f26e8SHoratiu Vultur
5479a9f26e8SHoratiu Vultur out:
5489a9f26e8SHoratiu Vultur return err;
5499a9f26e8SHoratiu Vultur }
5504139d4b5SHoratiu Vultur
br_mrp_in_port_open(struct net_device * dev,u8 loc)5514139d4b5SHoratiu Vultur int br_mrp_in_port_open(struct net_device *dev, u8 loc)
5524139d4b5SHoratiu Vultur {
5534139d4b5SHoratiu Vultur struct net_bridge_port *p;
5544139d4b5SHoratiu Vultur int err = 0;
5554139d4b5SHoratiu Vultur
5564139d4b5SHoratiu Vultur p = br_port_get_rcu(dev);
5574139d4b5SHoratiu Vultur if (!p) {
5584139d4b5SHoratiu Vultur err = -EINVAL;
5594139d4b5SHoratiu Vultur goto out;
5604139d4b5SHoratiu Vultur }
5614139d4b5SHoratiu Vultur
5624139d4b5SHoratiu Vultur if (loc)
5634139d4b5SHoratiu Vultur p->flags |= BR_MRP_LOST_IN_CONT;
5644139d4b5SHoratiu Vultur else
5654139d4b5SHoratiu Vultur p->flags &= ~BR_MRP_LOST_IN_CONT;
5664139d4b5SHoratiu Vultur
5674139d4b5SHoratiu Vultur br_ifinfo_notify(RTM_NEWLINK, NULL, p);
5684139d4b5SHoratiu Vultur
5694139d4b5SHoratiu Vultur out:
5704139d4b5SHoratiu Vultur return err;
5714139d4b5SHoratiu Vultur }
572