1 // SPDX-License-Identifier: GPL-2.0-or-later
3 #include <net/genetlink.h>
5 #include <uapi/linux/mrp_bridge.h>
6 #include "br_private.h"
7 #include "br_private_mrp.h"
9 static 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
},
19 static const struct nla_policy
20 br_mrp_instance_policy
[IFLA_BRIDGE_MRP_INSTANCE_MAX
+ 1] = {
21 [IFLA_BRIDGE_MRP_INSTANCE_UNSPEC
] = { .type
= NLA_REJECT
},
22 [IFLA_BRIDGE_MRP_INSTANCE_RING_ID
] = { .type
= NLA_U32
},
23 [IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX
] = { .type
= NLA_U32
},
24 [IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX
] = { .type
= NLA_U32
},
25 [IFLA_BRIDGE_MRP_INSTANCE_PRIO
] = { .type
= NLA_U16
},
28 static int br_mrp_instance_parse(struct net_bridge
*br
, struct nlattr
*attr
,
29 int cmd
, struct netlink_ext_ack
*extack
)
31 struct nlattr
*tb
[IFLA_BRIDGE_MRP_INSTANCE_MAX
+ 1];
32 struct br_mrp_instance inst
;
35 err
= nla_parse_nested(tb
, IFLA_BRIDGE_MRP_INSTANCE_MAX
, attr
,
36 br_mrp_instance_policy
, extack
);
40 if (!tb
[IFLA_BRIDGE_MRP_INSTANCE_RING_ID
] ||
41 !tb
[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX
] ||
42 !tb
[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX
]) {
43 NL_SET_ERR_MSG_MOD(extack
,
44 "Missing attribute: RING_ID or P_IFINDEX or S_IFINDEX");
48 memset(&inst
, 0, sizeof(inst
));
50 inst
.ring_id
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_INSTANCE_RING_ID
]);
51 inst
.p_ifindex
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX
]);
52 inst
.s_ifindex
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX
]);
53 inst
.prio
= MRP_DEFAULT_PRIO
;
55 if (tb
[IFLA_BRIDGE_MRP_INSTANCE_PRIO
])
56 inst
.prio
= nla_get_u16(tb
[IFLA_BRIDGE_MRP_INSTANCE_PRIO
]);
58 if (cmd
== RTM_SETLINK
)
59 return br_mrp_add(br
, &inst
);
61 return br_mrp_del(br
, &inst
);
66 static const struct nla_policy
67 br_mrp_port_state_policy
[IFLA_BRIDGE_MRP_PORT_STATE_MAX
+ 1] = {
68 [IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC
] = { .type
= NLA_REJECT
},
69 [IFLA_BRIDGE_MRP_PORT_STATE_STATE
] = { .type
= NLA_U32
},
72 static int br_mrp_port_state_parse(struct net_bridge_port
*p
,
74 struct netlink_ext_ack
*extack
)
76 struct nlattr
*tb
[IFLA_BRIDGE_MRP_PORT_STATE_MAX
+ 1];
77 enum br_mrp_port_state_type state
;
80 err
= nla_parse_nested(tb
, IFLA_BRIDGE_MRP_PORT_STATE_MAX
, attr
,
81 br_mrp_port_state_policy
, extack
);
85 if (!tb
[IFLA_BRIDGE_MRP_PORT_STATE_STATE
]) {
86 NL_SET_ERR_MSG_MOD(extack
, "Missing attribute: STATE");
90 state
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_PORT_STATE_STATE
]);
92 return br_mrp_set_port_state(p
, state
);
95 static const struct nla_policy
96 br_mrp_port_role_policy
[IFLA_BRIDGE_MRP_PORT_ROLE_MAX
+ 1] = {
97 [IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC
] = { .type
= NLA_REJECT
},
98 [IFLA_BRIDGE_MRP_PORT_ROLE_ROLE
] = { .type
= NLA_U32
},
101 static int br_mrp_port_role_parse(struct net_bridge_port
*p
,
103 struct netlink_ext_ack
*extack
)
105 struct nlattr
*tb
[IFLA_BRIDGE_MRP_PORT_ROLE_MAX
+ 1];
106 enum br_mrp_port_role_type role
;
109 err
= nla_parse_nested(tb
, IFLA_BRIDGE_MRP_PORT_ROLE_MAX
, attr
,
110 br_mrp_port_role_policy
, extack
);
114 if (!tb
[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE
]) {
115 NL_SET_ERR_MSG_MOD(extack
, "Missing attribute: ROLE");
119 role
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_PORT_ROLE_ROLE
]);
121 return br_mrp_set_port_role(p
, role
);
124 static const struct nla_policy
125 br_mrp_ring_state_policy
[IFLA_BRIDGE_MRP_RING_STATE_MAX
+ 1] = {
126 [IFLA_BRIDGE_MRP_RING_STATE_UNSPEC
] = { .type
= NLA_REJECT
},
127 [IFLA_BRIDGE_MRP_RING_STATE_RING_ID
] = { .type
= NLA_U32
},
128 [IFLA_BRIDGE_MRP_RING_STATE_STATE
] = { .type
= NLA_U32
},
131 static int br_mrp_ring_state_parse(struct net_bridge
*br
, struct nlattr
*attr
,
132 struct netlink_ext_ack
*extack
)
134 struct nlattr
*tb
[IFLA_BRIDGE_MRP_RING_STATE_MAX
+ 1];
135 struct br_mrp_ring_state state
;
138 err
= nla_parse_nested(tb
, IFLA_BRIDGE_MRP_RING_STATE_MAX
, attr
,
139 br_mrp_ring_state_policy
, extack
);
143 if (!tb
[IFLA_BRIDGE_MRP_RING_STATE_RING_ID
] ||
144 !tb
[IFLA_BRIDGE_MRP_RING_STATE_STATE
]) {
145 NL_SET_ERR_MSG_MOD(extack
,
146 "Missing attribute: RING_ID or STATE");
150 memset(&state
, 0x0, sizeof(state
));
152 state
.ring_id
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_RING_STATE_RING_ID
]);
153 state
.ring_state
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_RING_STATE_STATE
]);
155 return br_mrp_set_ring_state(br
, &state
);
158 static const struct nla_policy
159 br_mrp_ring_role_policy
[IFLA_BRIDGE_MRP_RING_ROLE_MAX
+ 1] = {
160 [IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC
] = { .type
= NLA_REJECT
},
161 [IFLA_BRIDGE_MRP_RING_ROLE_RING_ID
] = { .type
= NLA_U32
},
162 [IFLA_BRIDGE_MRP_RING_ROLE_ROLE
] = { .type
= NLA_U32
},
165 static int br_mrp_ring_role_parse(struct net_bridge
*br
, struct nlattr
*attr
,
166 struct netlink_ext_ack
*extack
)
168 struct nlattr
*tb
[IFLA_BRIDGE_MRP_RING_ROLE_MAX
+ 1];
169 struct br_mrp_ring_role role
;
172 err
= nla_parse_nested(tb
, IFLA_BRIDGE_MRP_RING_ROLE_MAX
, attr
,
173 br_mrp_ring_role_policy
, extack
);
177 if (!tb
[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID
] ||
178 !tb
[IFLA_BRIDGE_MRP_RING_ROLE_ROLE
]) {
179 NL_SET_ERR_MSG_MOD(extack
,
180 "Missing attribute: RING_ID or ROLE");
184 memset(&role
, 0x0, sizeof(role
));
186 role
.ring_id
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_RING_ROLE_RING_ID
]);
187 role
.ring_role
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_RING_ROLE_ROLE
]);
189 return br_mrp_set_ring_role(br
, &role
);
192 static const struct nla_policy
193 br_mrp_start_test_policy
[IFLA_BRIDGE_MRP_START_TEST_MAX
+ 1] = {
194 [IFLA_BRIDGE_MRP_START_TEST_UNSPEC
] = { .type
= NLA_REJECT
},
195 [IFLA_BRIDGE_MRP_START_TEST_RING_ID
] = { .type
= NLA_U32
},
196 [IFLA_BRIDGE_MRP_START_TEST_INTERVAL
] = { .type
= NLA_U32
},
197 [IFLA_BRIDGE_MRP_START_TEST_MAX_MISS
] = { .type
= NLA_U32
},
198 [IFLA_BRIDGE_MRP_START_TEST_PERIOD
] = { .type
= NLA_U32
},
199 [IFLA_BRIDGE_MRP_START_TEST_MONITOR
] = { .type
= NLA_U32
},
202 static int br_mrp_start_test_parse(struct net_bridge
*br
, struct nlattr
*attr
,
203 struct netlink_ext_ack
*extack
)
205 struct nlattr
*tb
[IFLA_BRIDGE_MRP_START_TEST_MAX
+ 1];
206 struct br_mrp_start_test test
;
209 err
= nla_parse_nested(tb
, IFLA_BRIDGE_MRP_START_TEST_MAX
, attr
,
210 br_mrp_start_test_policy
, extack
);
214 if (!tb
[IFLA_BRIDGE_MRP_START_TEST_RING_ID
] ||
215 !tb
[IFLA_BRIDGE_MRP_START_TEST_INTERVAL
] ||
216 !tb
[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS
] ||
217 !tb
[IFLA_BRIDGE_MRP_START_TEST_PERIOD
]) {
218 NL_SET_ERR_MSG_MOD(extack
,
219 "Missing attribute: RING_ID or INTERVAL or MAX_MISS or PERIOD");
223 memset(&test
, 0x0, sizeof(test
));
225 test
.ring_id
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_START_TEST_RING_ID
]);
226 test
.interval
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_START_TEST_INTERVAL
]);
227 test
.max_miss
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS
]);
228 test
.period
= nla_get_u32(tb
[IFLA_BRIDGE_MRP_START_TEST_PERIOD
]);
229 test
.monitor
= false;
231 if (tb
[IFLA_BRIDGE_MRP_START_TEST_MONITOR
])
233 nla_get_u32(tb
[IFLA_BRIDGE_MRP_START_TEST_MONITOR
]);
235 return br_mrp_start_test(br
, &test
);
238 int br_mrp_parse(struct net_bridge
*br
, struct net_bridge_port
*p
,
239 struct nlattr
*attr
, int cmd
, struct netlink_ext_ack
*extack
)
241 struct nlattr
*tb
[IFLA_BRIDGE_MRP_MAX
+ 1];
244 /* When this function is called for a port then the br pointer is
245 * invalid, therefor set the br to point correctly
250 if (br
->stp_enabled
!= BR_NO_STP
) {
251 NL_SET_ERR_MSG_MOD(extack
, "MRP can't be enabled if STP is already enabled");
255 err
= nla_parse_nested(tb
, IFLA_BRIDGE_MRP_MAX
, attr
,
256 br_mrp_policy
, extack
);
260 if (tb
[IFLA_BRIDGE_MRP_INSTANCE
]) {
261 err
= br_mrp_instance_parse(br
, tb
[IFLA_BRIDGE_MRP_INSTANCE
],
267 if (tb
[IFLA_BRIDGE_MRP_PORT_STATE
]) {
268 err
= br_mrp_port_state_parse(p
, tb
[IFLA_BRIDGE_MRP_PORT_STATE
],
274 if (tb
[IFLA_BRIDGE_MRP_PORT_ROLE
]) {
275 err
= br_mrp_port_role_parse(p
, tb
[IFLA_BRIDGE_MRP_PORT_ROLE
],
281 if (tb
[IFLA_BRIDGE_MRP_RING_STATE
]) {
282 err
= br_mrp_ring_state_parse(br
,
283 tb
[IFLA_BRIDGE_MRP_RING_STATE
],
289 if (tb
[IFLA_BRIDGE_MRP_RING_ROLE
]) {
290 err
= br_mrp_ring_role_parse(br
, tb
[IFLA_BRIDGE_MRP_RING_ROLE
],
296 if (tb
[IFLA_BRIDGE_MRP_START_TEST
]) {
297 err
= br_mrp_start_test_parse(br
,
298 tb
[IFLA_BRIDGE_MRP_START_TEST
],
307 int br_mrp_port_open(struct net_device
*dev
, u8 loc
)
309 struct net_bridge_port
*p
;
312 p
= br_port_get_rcu(dev
);
319 p
->flags
|= BR_MRP_LOST_CONT
;
321 p
->flags
&= ~BR_MRP_LOST_CONT
;
323 br_ifinfo_notify(RTM_NEWLINK
, NULL
, p
);