1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5 */
6
7 #include "devl_internal.h"
8
9 static inline bool
devlink_rate_is_leaf(struct devlink_rate * devlink_rate)10 devlink_rate_is_leaf(struct devlink_rate *devlink_rate)
11 {
12 return devlink_rate->type == DEVLINK_RATE_TYPE_LEAF;
13 }
14
devlink_rate_is_node(const struct devlink_rate * devlink_rate)15 bool devlink_rate_is_node(const struct devlink_rate *devlink_rate)
16 {
17 return devlink_rate->type == DEVLINK_RATE_TYPE_NODE;
18 }
19
20 static struct devlink_rate *
devlink_rate_leaf_get_from_info(struct devlink * devlink,struct genl_info * info)21 devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info)
22 {
23 struct devlink_rate *devlink_rate;
24 struct devlink_port *devlink_port;
25
26 devlink_port = devlink_port_get_from_attrs(devlink, info->attrs);
27 if (IS_ERR(devlink_port))
28 return ERR_CAST(devlink_port);
29 devlink_rate = devlink_port->devlink_rate;
30 return devlink_rate ?: ERR_PTR(-ENODEV);
31 }
32
33 static struct devlink_rate *
devlink_rate_node_get_by_name(struct devlink * devlink,const char * node_name)34 devlink_rate_node_get_by_name(struct devlink *devlink, const char *node_name)
35 {
36 struct devlink_rate *devlink_rate;
37
38 list_for_each_entry(devlink_rate, &devlink->rate_list, list) {
39 if (devlink_rate_is_node(devlink_rate) &&
40 !strcmp(node_name, devlink_rate->name))
41 return devlink_rate;
42 }
43 return ERR_PTR(-ENODEV);
44 }
45
46 static struct devlink_rate *
devlink_rate_node_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)47 devlink_rate_node_get_from_attrs(struct devlink *devlink, struct nlattr **attrs)
48 {
49 const char *rate_node_name;
50 size_t len;
51
52 if (!attrs[DEVLINK_ATTR_RATE_NODE_NAME])
53 return ERR_PTR(-EINVAL);
54 rate_node_name = nla_data(attrs[DEVLINK_ATTR_RATE_NODE_NAME]);
55 len = strlen(rate_node_name);
56 /* Name cannot be empty or decimal number */
57 if (!len || strspn(rate_node_name, "0123456789") == len)
58 return ERR_PTR(-EINVAL);
59
60 return devlink_rate_node_get_by_name(devlink, rate_node_name);
61 }
62
63 static struct devlink_rate *
devlink_rate_node_get_from_info(struct devlink * devlink,struct genl_info * info)64 devlink_rate_node_get_from_info(struct devlink *devlink, struct genl_info *info)
65 {
66 return devlink_rate_node_get_from_attrs(devlink, info->attrs);
67 }
68
69 static struct devlink_rate *
devlink_rate_get_from_info(struct devlink * devlink,struct genl_info * info)70 devlink_rate_get_from_info(struct devlink *devlink, struct genl_info *info)
71 {
72 struct nlattr **attrs = info->attrs;
73
74 if (attrs[DEVLINK_ATTR_PORT_INDEX])
75 return devlink_rate_leaf_get_from_info(devlink, info);
76 else if (attrs[DEVLINK_ATTR_RATE_NODE_NAME])
77 return devlink_rate_node_get_from_info(devlink, info);
78 else
79 return ERR_PTR(-EINVAL);
80 }
81
devlink_rate_put_tc_bws(struct sk_buff * msg,u32 * tc_bw)82 static int devlink_rate_put_tc_bws(struct sk_buff *msg, u32 *tc_bw)
83 {
84 struct nlattr *nla_tc_bw;
85 int i;
86
87 for (i = 0; i < DEVLINK_RATE_TCS_MAX; i++) {
88 nla_tc_bw = nla_nest_start(msg, DEVLINK_ATTR_RATE_TC_BWS);
89 if (!nla_tc_bw)
90 return -EMSGSIZE;
91
92 if (nla_put_u8(msg, DEVLINK_RATE_TC_ATTR_INDEX, i) ||
93 nla_put_u32(msg, DEVLINK_RATE_TC_ATTR_BW, tc_bw[i]))
94 goto nla_put_failure;
95
96 nla_nest_end(msg, nla_tc_bw);
97 }
98 return 0;
99
100 nla_put_failure:
101 nla_nest_cancel(msg, nla_tc_bw);
102 return -EMSGSIZE;
103 }
104
devlink_nl_rate_fill(struct sk_buff * msg,struct devlink_rate * devlink_rate,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct netlink_ext_ack * extack)105 static int devlink_nl_rate_fill(struct sk_buff *msg,
106 struct devlink_rate *devlink_rate,
107 enum devlink_command cmd, u32 portid, u32 seq,
108 int flags, struct netlink_ext_ack *extack)
109 {
110 struct devlink *devlink = devlink_rate->devlink;
111 void *hdr;
112
113 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
114 if (!hdr)
115 return -EMSGSIZE;
116
117 if (devlink_nl_put_handle(msg, devlink))
118 goto nla_put_failure;
119
120 if (nla_put_u16(msg, DEVLINK_ATTR_RATE_TYPE, devlink_rate->type))
121 goto nla_put_failure;
122
123 if (devlink_rate_is_leaf(devlink_rate)) {
124 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
125 devlink_rate->devlink_port->index))
126 goto nla_put_failure;
127 } else if (devlink_rate_is_node(devlink_rate)) {
128 if (nla_put_string(msg, DEVLINK_ATTR_RATE_NODE_NAME,
129 devlink_rate->name))
130 goto nla_put_failure;
131 }
132
133 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_RATE_TX_SHARE,
134 devlink_rate->tx_share))
135 goto nla_put_failure;
136
137 if (devlink_nl_put_u64(msg, DEVLINK_ATTR_RATE_TX_MAX,
138 devlink_rate->tx_max))
139 goto nla_put_failure;
140
141 if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_PRIORITY,
142 devlink_rate->tx_priority))
143 goto nla_put_failure;
144
145 if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_WEIGHT,
146 devlink_rate->tx_weight))
147 goto nla_put_failure;
148
149 if (devlink_rate->parent)
150 if (nla_put_string(msg, DEVLINK_ATTR_RATE_PARENT_NODE_NAME,
151 devlink_rate->parent->name))
152 goto nla_put_failure;
153
154 if (devlink_rate_put_tc_bws(msg, devlink_rate->tc_bw))
155 goto nla_put_failure;
156
157 genlmsg_end(msg, hdr);
158 return 0;
159
160 nla_put_failure:
161 genlmsg_cancel(msg, hdr);
162 return -EMSGSIZE;
163 }
164
devlink_rate_notify(struct devlink_rate * devlink_rate,enum devlink_command cmd)165 static void devlink_rate_notify(struct devlink_rate *devlink_rate,
166 enum devlink_command cmd)
167 {
168 struct devlink *devlink = devlink_rate->devlink;
169 struct sk_buff *msg;
170 int err;
171
172 WARN_ON(cmd != DEVLINK_CMD_RATE_NEW && cmd != DEVLINK_CMD_RATE_DEL);
173
174 if (!devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
175 return;
176
177 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
178 if (!msg)
179 return;
180
181 err = devlink_nl_rate_fill(msg, devlink_rate, cmd, 0, 0, 0, NULL);
182 if (err) {
183 nlmsg_free(msg);
184 return;
185 }
186
187 devlink_nl_notify_send(devlink, msg);
188 }
189
devlink_rates_notify_register(struct devlink * devlink)190 void devlink_rates_notify_register(struct devlink *devlink)
191 {
192 struct devlink_rate *rate_node;
193
194 list_for_each_entry(rate_node, &devlink->rate_list, list)
195 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW);
196 }
197
devlink_rates_notify_unregister(struct devlink * devlink)198 void devlink_rates_notify_unregister(struct devlink *devlink)
199 {
200 struct devlink_rate *rate_node;
201
202 list_for_each_entry_reverse(rate_node, &devlink->rate_list, list)
203 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL);
204 }
205
206 static int
devlink_nl_rate_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)207 devlink_nl_rate_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
208 struct netlink_callback *cb, int flags)
209 {
210 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
211 struct devlink_rate *devlink_rate;
212 int idx = 0;
213 int err = 0;
214
215 list_for_each_entry(devlink_rate, &devlink->rate_list, list) {
216 enum devlink_command cmd = DEVLINK_CMD_RATE_NEW;
217 u32 id = NETLINK_CB(cb->skb).portid;
218
219 if (idx < state->idx) {
220 idx++;
221 continue;
222 }
223 err = devlink_nl_rate_fill(msg, devlink_rate, cmd, id,
224 cb->nlh->nlmsg_seq, flags, NULL);
225 if (err) {
226 state->idx = idx;
227 break;
228 }
229 idx++;
230 }
231
232 return err;
233 }
234
devlink_nl_rate_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)235 int devlink_nl_rate_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
236 {
237 return devlink_nl_dumpit(skb, cb, devlink_nl_rate_get_dump_one);
238 }
239
devlink_nl_rate_get_doit(struct sk_buff * skb,struct genl_info * info)240 int devlink_nl_rate_get_doit(struct sk_buff *skb, struct genl_info *info)
241 {
242 struct devlink *devlink = info->user_ptr[0];
243 struct devlink_rate *devlink_rate;
244 struct sk_buff *msg;
245 int err;
246
247 devlink_rate = devlink_rate_get_from_info(devlink, info);
248 if (IS_ERR(devlink_rate))
249 return PTR_ERR(devlink_rate);
250
251 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
252 if (!msg)
253 return -ENOMEM;
254
255 err = devlink_nl_rate_fill(msg, devlink_rate, DEVLINK_CMD_RATE_NEW,
256 info->snd_portid, info->snd_seq, 0,
257 info->extack);
258 if (err) {
259 nlmsg_free(msg);
260 return err;
261 }
262
263 return genlmsg_reply(msg, info);
264 }
265
266 static bool
devlink_rate_is_parent_node(struct devlink_rate * devlink_rate,struct devlink_rate * parent)267 devlink_rate_is_parent_node(struct devlink_rate *devlink_rate,
268 struct devlink_rate *parent)
269 {
270 while (parent) {
271 if (parent == devlink_rate)
272 return true;
273 parent = parent->parent;
274 }
275 return false;
276 }
277
278 static int
devlink_nl_rate_parent_node_set(struct devlink_rate * devlink_rate,struct genl_info * info,struct nlattr * nla_parent)279 devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate,
280 struct genl_info *info,
281 struct nlattr *nla_parent)
282 {
283 struct devlink *devlink = devlink_rate->devlink;
284 const char *parent_name = nla_data(nla_parent);
285 const struct devlink_ops *ops = devlink->ops;
286 size_t len = strlen(parent_name);
287 struct devlink_rate *parent;
288 int err = -EOPNOTSUPP;
289
290 parent = devlink_rate->parent;
291
292 if (parent && !len) {
293 if (devlink_rate_is_leaf(devlink_rate))
294 err = ops->rate_leaf_parent_set(devlink_rate, NULL,
295 devlink_rate->priv, NULL,
296 info->extack);
297 else if (devlink_rate_is_node(devlink_rate))
298 err = ops->rate_node_parent_set(devlink_rate, NULL,
299 devlink_rate->priv, NULL,
300 info->extack);
301 if (err)
302 return err;
303
304 refcount_dec(&parent->refcnt);
305 devlink_rate->parent = NULL;
306 } else if (len) {
307 parent = devlink_rate_node_get_by_name(devlink, parent_name);
308 if (IS_ERR(parent))
309 return -ENODEV;
310
311 if (parent == devlink_rate) {
312 NL_SET_ERR_MSG(info->extack, "Parent to self is not allowed");
313 return -EINVAL;
314 }
315
316 if (devlink_rate_is_node(devlink_rate) &&
317 devlink_rate_is_parent_node(devlink_rate, parent->parent)) {
318 NL_SET_ERR_MSG(info->extack, "Node is already a parent of parent node.");
319 return -EEXIST;
320 }
321
322 if (devlink_rate_is_leaf(devlink_rate))
323 err = ops->rate_leaf_parent_set(devlink_rate, parent,
324 devlink_rate->priv, parent->priv,
325 info->extack);
326 else if (devlink_rate_is_node(devlink_rate))
327 err = ops->rate_node_parent_set(devlink_rate, parent,
328 devlink_rate->priv, parent->priv,
329 info->extack);
330 if (err)
331 return err;
332
333 if (devlink_rate->parent)
334 /* we're reassigning to other parent in this case */
335 refcount_dec(&devlink_rate->parent->refcnt);
336
337 refcount_inc(&parent->refcnt);
338 devlink_rate->parent = parent;
339 }
340
341 return 0;
342 }
343
devlink_nl_rate_tc_bw_parse(struct nlattr * parent_nest,u32 * tc_bw,unsigned long * bitmap,struct netlink_ext_ack * extack)344 static int devlink_nl_rate_tc_bw_parse(struct nlattr *parent_nest, u32 *tc_bw,
345 unsigned long *bitmap,
346 struct netlink_ext_ack *extack)
347 {
348 struct nlattr *tb[DEVLINK_RATE_TC_ATTR_MAX + 1];
349 u8 tc_index;
350 int err;
351
352 err = nla_parse_nested(tb, DEVLINK_RATE_TC_ATTR_MAX, parent_nest,
353 devlink_dl_rate_tc_bws_nl_policy, extack);
354 if (err)
355 return err;
356
357 if (!tb[DEVLINK_RATE_TC_ATTR_INDEX]) {
358 NL_SET_ERR_ATTR_MISS(extack, parent_nest,
359 DEVLINK_RATE_TC_ATTR_INDEX);
360 return -EINVAL;
361 }
362
363 tc_index = nla_get_u8(tb[DEVLINK_RATE_TC_ATTR_INDEX]);
364
365 if (!tb[DEVLINK_RATE_TC_ATTR_BW]) {
366 NL_SET_ERR_ATTR_MISS(extack, parent_nest,
367 DEVLINK_RATE_TC_ATTR_BW);
368 return -EINVAL;
369 }
370
371 if (test_and_set_bit(tc_index, bitmap)) {
372 NL_SET_ERR_MSG_FMT(extack,
373 "Duplicate traffic class index specified (%u)",
374 tc_index);
375 return -EINVAL;
376 }
377
378 tc_bw[tc_index] = nla_get_u32(tb[DEVLINK_RATE_TC_ATTR_BW]);
379
380 return 0;
381 }
382
devlink_nl_rate_tc_bw_set(struct devlink_rate * devlink_rate,struct genl_info * info)383 static int devlink_nl_rate_tc_bw_set(struct devlink_rate *devlink_rate,
384 struct genl_info *info)
385 {
386 DECLARE_BITMAP(bitmap, DEVLINK_RATE_TCS_MAX) = {};
387 struct devlink *devlink = devlink_rate->devlink;
388 const struct devlink_ops *ops = devlink->ops;
389 u32 tc_bw[DEVLINK_RATE_TCS_MAX] = {};
390 int rem, err = -EOPNOTSUPP, i;
391 struct nlattr *attr;
392
393 nlmsg_for_each_attr_type(attr, DEVLINK_ATTR_RATE_TC_BWS, info->nlhdr,
394 GENL_HDRLEN, rem) {
395 err = devlink_nl_rate_tc_bw_parse(attr, tc_bw, bitmap,
396 info->extack);
397 if (err)
398 return err;
399 }
400
401 for (i = 0; i < DEVLINK_RATE_TCS_MAX; i++) {
402 if (!test_bit(i, bitmap)) {
403 NL_SET_ERR_MSG_FMT(info->extack,
404 "Bandwidth values must be specified for all %u traffic classes",
405 DEVLINK_RATE_TCS_MAX);
406 return -EINVAL;
407 }
408 }
409
410 if (devlink_rate_is_leaf(devlink_rate))
411 err = ops->rate_leaf_tc_bw_set(devlink_rate, devlink_rate->priv,
412 tc_bw, info->extack);
413 else if (devlink_rate_is_node(devlink_rate))
414 err = ops->rate_node_tc_bw_set(devlink_rate, devlink_rate->priv,
415 tc_bw, info->extack);
416
417 if (err)
418 return err;
419
420 memcpy(devlink_rate->tc_bw, tc_bw, sizeof(tc_bw));
421
422 return 0;
423 }
424
devlink_nl_rate_set(struct devlink_rate * devlink_rate,const struct devlink_ops * ops,struct genl_info * info)425 static int devlink_nl_rate_set(struct devlink_rate *devlink_rate,
426 const struct devlink_ops *ops,
427 struct genl_info *info)
428 {
429 struct nlattr *nla_parent, **attrs = info->attrs;
430 int err = -EOPNOTSUPP;
431 u32 priority;
432 u32 weight;
433 u64 rate;
434
435 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE]) {
436 rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_SHARE]);
437 if (devlink_rate_is_leaf(devlink_rate))
438 err = ops->rate_leaf_tx_share_set(devlink_rate, devlink_rate->priv,
439 rate, info->extack);
440 else if (devlink_rate_is_node(devlink_rate))
441 err = ops->rate_node_tx_share_set(devlink_rate, devlink_rate->priv,
442 rate, info->extack);
443 if (err)
444 return err;
445 devlink_rate->tx_share = rate;
446 }
447
448 if (attrs[DEVLINK_ATTR_RATE_TX_MAX]) {
449 rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_MAX]);
450 if (devlink_rate_is_leaf(devlink_rate))
451 err = ops->rate_leaf_tx_max_set(devlink_rate, devlink_rate->priv,
452 rate, info->extack);
453 else if (devlink_rate_is_node(devlink_rate))
454 err = ops->rate_node_tx_max_set(devlink_rate, devlink_rate->priv,
455 rate, info->extack);
456 if (err)
457 return err;
458 devlink_rate->tx_max = rate;
459 }
460
461 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]) {
462 priority = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]);
463 if (devlink_rate_is_leaf(devlink_rate))
464 err = ops->rate_leaf_tx_priority_set(devlink_rate, devlink_rate->priv,
465 priority, info->extack);
466 else if (devlink_rate_is_node(devlink_rate))
467 err = ops->rate_node_tx_priority_set(devlink_rate, devlink_rate->priv,
468 priority, info->extack);
469
470 if (err)
471 return err;
472 devlink_rate->tx_priority = priority;
473 }
474
475 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]) {
476 weight = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]);
477 if (devlink_rate_is_leaf(devlink_rate))
478 err = ops->rate_leaf_tx_weight_set(devlink_rate, devlink_rate->priv,
479 weight, info->extack);
480 else if (devlink_rate_is_node(devlink_rate))
481 err = ops->rate_node_tx_weight_set(devlink_rate, devlink_rate->priv,
482 weight, info->extack);
483
484 if (err)
485 return err;
486 devlink_rate->tx_weight = weight;
487 }
488
489 nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME];
490 if (nla_parent) {
491 err = devlink_nl_rate_parent_node_set(devlink_rate, info,
492 nla_parent);
493 if (err)
494 return err;
495 }
496
497 if (attrs[DEVLINK_ATTR_RATE_TC_BWS]) {
498 err = devlink_nl_rate_tc_bw_set(devlink_rate, info);
499 if (err)
500 return err;
501 }
502
503 return 0;
504 }
505
devlink_rate_set_ops_supported(const struct devlink_ops * ops,struct genl_info * info,enum devlink_rate_type type)506 static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops,
507 struct genl_info *info,
508 enum devlink_rate_type type)
509 {
510 struct nlattr **attrs = info->attrs;
511
512 if (type == DEVLINK_RATE_TYPE_LEAF) {
513 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_leaf_tx_share_set) {
514 NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the leafs");
515 return false;
516 }
517 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_leaf_tx_max_set) {
518 NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the leafs");
519 return false;
520 }
521 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] &&
522 !ops->rate_leaf_parent_set) {
523 NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the leafs");
524 return false;
525 }
526 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_leaf_tx_priority_set) {
527 NL_SET_ERR_MSG_ATTR(info->extack,
528 attrs[DEVLINK_ATTR_RATE_TX_PRIORITY],
529 "TX priority set isn't supported for the leafs");
530 return false;
531 }
532 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_leaf_tx_weight_set) {
533 NL_SET_ERR_MSG_ATTR(info->extack,
534 attrs[DEVLINK_ATTR_RATE_TX_WEIGHT],
535 "TX weight set isn't supported for the leafs");
536 return false;
537 }
538 if (attrs[DEVLINK_ATTR_RATE_TC_BWS] &&
539 !ops->rate_leaf_tc_bw_set) {
540 NL_SET_ERR_MSG_ATTR(info->extack,
541 attrs[DEVLINK_ATTR_RATE_TC_BWS],
542 "TC bandwidth set isn't supported for the leafs");
543 return false;
544 }
545 } else if (type == DEVLINK_RATE_TYPE_NODE) {
546 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_node_tx_share_set) {
547 NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the nodes");
548 return false;
549 }
550 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_node_tx_max_set) {
551 NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the nodes");
552 return false;
553 }
554 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] &&
555 !ops->rate_node_parent_set) {
556 NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the nodes");
557 return false;
558 }
559 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_node_tx_priority_set) {
560 NL_SET_ERR_MSG_ATTR(info->extack,
561 attrs[DEVLINK_ATTR_RATE_TX_PRIORITY],
562 "TX priority set isn't supported for the nodes");
563 return false;
564 }
565 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_node_tx_weight_set) {
566 NL_SET_ERR_MSG_ATTR(info->extack,
567 attrs[DEVLINK_ATTR_RATE_TX_WEIGHT],
568 "TX weight set isn't supported for the nodes");
569 return false;
570 }
571 if (attrs[DEVLINK_ATTR_RATE_TC_BWS] &&
572 !ops->rate_node_tc_bw_set) {
573 NL_SET_ERR_MSG_ATTR(info->extack,
574 attrs[DEVLINK_ATTR_RATE_TC_BWS],
575 "TC bandwidth set isn't supported for the nodes");
576 return false;
577 }
578 } else {
579 WARN(1, "Unknown type of rate object");
580 return false;
581 }
582
583 return true;
584 }
585
devlink_nl_rate_set_doit(struct sk_buff * skb,struct genl_info * info)586 int devlink_nl_rate_set_doit(struct sk_buff *skb, struct genl_info *info)
587 {
588 struct devlink *devlink = info->user_ptr[0];
589 struct devlink_rate *devlink_rate;
590 const struct devlink_ops *ops;
591 int err;
592
593 devlink_rate = devlink_rate_get_from_info(devlink, info);
594 if (IS_ERR(devlink_rate))
595 return PTR_ERR(devlink_rate);
596
597 ops = devlink->ops;
598 if (!ops || !devlink_rate_set_ops_supported(ops, info, devlink_rate->type))
599 return -EOPNOTSUPP;
600
601 err = devlink_nl_rate_set(devlink_rate, ops, info);
602
603 if (!err)
604 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW);
605 return err;
606 }
607
devlink_nl_rate_new_doit(struct sk_buff * skb,struct genl_info * info)608 int devlink_nl_rate_new_doit(struct sk_buff *skb, struct genl_info *info)
609 {
610 struct devlink *devlink = info->user_ptr[0];
611 struct devlink_rate *rate_node;
612 const struct devlink_ops *ops;
613 int err;
614
615 ops = devlink->ops;
616 if (!ops || !ops->rate_node_new || !ops->rate_node_del) {
617 NL_SET_ERR_MSG(info->extack, "Rate nodes aren't supported");
618 return -EOPNOTSUPP;
619 }
620
621 if (!devlink_rate_set_ops_supported(ops, info, DEVLINK_RATE_TYPE_NODE))
622 return -EOPNOTSUPP;
623
624 rate_node = devlink_rate_node_get_from_attrs(devlink, info->attrs);
625 if (!IS_ERR(rate_node))
626 return -EEXIST;
627 else if (rate_node == ERR_PTR(-EINVAL))
628 return -EINVAL;
629
630 rate_node = kzalloc_obj(*rate_node);
631 if (!rate_node)
632 return -ENOMEM;
633
634 rate_node->devlink = devlink;
635 rate_node->type = DEVLINK_RATE_TYPE_NODE;
636 rate_node->name = nla_strdup(info->attrs[DEVLINK_ATTR_RATE_NODE_NAME], GFP_KERNEL);
637 if (!rate_node->name) {
638 err = -ENOMEM;
639 goto err_strdup;
640 }
641
642 err = ops->rate_node_new(rate_node, &rate_node->priv, info->extack);
643 if (err)
644 goto err_node_new;
645
646 err = devlink_nl_rate_set(rate_node, ops, info);
647 if (err)
648 goto err_rate_set;
649
650 refcount_set(&rate_node->refcnt, 1);
651 list_add(&rate_node->list, &devlink->rate_list);
652 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW);
653 return 0;
654
655 err_rate_set:
656 ops->rate_node_del(rate_node, rate_node->priv, info->extack);
657 err_node_new:
658 kfree(rate_node->name);
659 err_strdup:
660 kfree(rate_node);
661 return err;
662 }
663
devlink_nl_rate_del_doit(struct sk_buff * skb,struct genl_info * info)664 int devlink_nl_rate_del_doit(struct sk_buff *skb, struct genl_info *info)
665 {
666 struct devlink *devlink = info->user_ptr[0];
667 struct devlink_rate *rate_node;
668 int err;
669
670 rate_node = devlink_rate_node_get_from_info(devlink, info);
671 if (IS_ERR(rate_node))
672 return PTR_ERR(rate_node);
673
674 if (refcount_read(&rate_node->refcnt) > 1) {
675 NL_SET_ERR_MSG(info->extack, "Node has children. Cannot delete node.");
676 return -EBUSY;
677 }
678
679 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL);
680 err = devlink->ops->rate_node_del(rate_node, rate_node->priv,
681 info->extack);
682 if (rate_node->parent)
683 refcount_dec(&rate_node->parent->refcnt);
684 list_del(&rate_node->list);
685 kfree(rate_node->name);
686 kfree(rate_node);
687 return err;
688 }
689
devlink_rates_check(struct devlink * devlink,bool (* rate_filter)(const struct devlink_rate *),struct netlink_ext_ack * extack)690 int devlink_rates_check(struct devlink *devlink,
691 bool (*rate_filter)(const struct devlink_rate *),
692 struct netlink_ext_ack *extack)
693 {
694 struct devlink_rate *devlink_rate;
695
696 list_for_each_entry(devlink_rate, &devlink->rate_list, list)
697 if (!rate_filter || rate_filter(devlink_rate)) {
698 if (extack)
699 NL_SET_ERR_MSG(extack, "Rate node(s) exists.");
700 return -EBUSY;
701 }
702 return 0;
703 }
704
705 /**
706 * devl_rate_node_create - create devlink rate node
707 * @devlink: devlink instance
708 * @priv: driver private data
709 * @node_name: name of the resulting node
710 * @parent: parent devlink_rate struct
711 *
712 * Create devlink rate object of type node
713 */
714 struct devlink_rate *
devl_rate_node_create(struct devlink * devlink,void * priv,char * node_name,struct devlink_rate * parent)715 devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name,
716 struct devlink_rate *parent)
717 {
718 struct devlink_rate *rate_node;
719
720 rate_node = devlink_rate_node_get_by_name(devlink, node_name);
721 if (!IS_ERR(rate_node))
722 return ERR_PTR(-EEXIST);
723
724 rate_node = kzalloc_obj(*rate_node);
725 if (!rate_node)
726 return ERR_PTR(-ENOMEM);
727
728 if (parent) {
729 rate_node->parent = parent;
730 refcount_inc(&rate_node->parent->refcnt);
731 }
732
733 rate_node->type = DEVLINK_RATE_TYPE_NODE;
734 rate_node->devlink = devlink;
735 rate_node->priv = priv;
736
737 rate_node->name = kstrdup(node_name, GFP_KERNEL);
738 if (!rate_node->name) {
739 kfree(rate_node);
740 return ERR_PTR(-ENOMEM);
741 }
742
743 refcount_set(&rate_node->refcnt, 1);
744 list_add(&rate_node->list, &devlink->rate_list);
745 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW);
746 return rate_node;
747 }
748 EXPORT_SYMBOL_GPL(devl_rate_node_create);
749
750 /**
751 * devl_rate_leaf_create - create devlink rate leaf
752 * @devlink_port: devlink port object to create rate object on
753 * @priv: driver private data
754 * @parent: parent devlink_rate struct
755 *
756 * Create devlink rate object of type leaf on provided @devlink_port.
757 */
devl_rate_leaf_create(struct devlink_port * devlink_port,void * priv,struct devlink_rate * parent)758 int devl_rate_leaf_create(struct devlink_port *devlink_port, void *priv,
759 struct devlink_rate *parent)
760 {
761 struct devlink *devlink = devlink_port->devlink;
762 struct devlink_rate *devlink_rate;
763
764 devl_assert_locked(devlink_port->devlink);
765
766 if (WARN_ON(devlink_port->devlink_rate))
767 return -EBUSY;
768
769 devlink_rate = kzalloc_obj(*devlink_rate);
770 if (!devlink_rate)
771 return -ENOMEM;
772
773 if (parent) {
774 devlink_rate->parent = parent;
775 refcount_inc(&devlink_rate->parent->refcnt);
776 }
777
778 devlink_rate->type = DEVLINK_RATE_TYPE_LEAF;
779 devlink_rate->devlink = devlink;
780 devlink_rate->devlink_port = devlink_port;
781 devlink_rate->priv = priv;
782 list_add_tail(&devlink_rate->list, &devlink->rate_list);
783 devlink_port->devlink_rate = devlink_rate;
784 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW);
785
786 return 0;
787 }
788 EXPORT_SYMBOL_GPL(devl_rate_leaf_create);
789
790 /**
791 * devl_rate_leaf_destroy - destroy devlink rate leaf
792 *
793 * @devlink_port: devlink port linked to the rate object
794 *
795 * Destroy the devlink rate object of type leaf on provided @devlink_port.
796 */
devl_rate_leaf_destroy(struct devlink_port * devlink_port)797 void devl_rate_leaf_destroy(struct devlink_port *devlink_port)
798 {
799 struct devlink_rate *devlink_rate = devlink_port->devlink_rate;
800
801 devl_assert_locked(devlink_port->devlink);
802 if (!devlink_rate)
803 return;
804
805 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL);
806 if (devlink_rate->parent)
807 refcount_dec(&devlink_rate->parent->refcnt);
808 list_del(&devlink_rate->list);
809 devlink_port->devlink_rate = NULL;
810 kfree(devlink_rate);
811 }
812 EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy);
813
814 /**
815 * devl_rate_nodes_destroy - destroy all devlink rate nodes on device
816 * @devlink: devlink instance
817 *
818 * Unset parent for all rate objects and destroy all rate nodes
819 * on specified device.
820 */
devl_rate_nodes_destroy(struct devlink * devlink)821 void devl_rate_nodes_destroy(struct devlink *devlink)
822 {
823 const struct devlink_ops *ops = devlink->ops;
824 struct devlink_rate *devlink_rate, *tmp;
825
826 devl_assert_locked(devlink);
827
828 list_for_each_entry(devlink_rate, &devlink->rate_list, list) {
829 if (!devlink_rate->parent)
830 continue;
831
832 if (devlink_rate_is_leaf(devlink_rate))
833 ops->rate_leaf_parent_set(devlink_rate, NULL, devlink_rate->priv,
834 NULL, NULL);
835 else if (devlink_rate_is_node(devlink_rate))
836 ops->rate_node_parent_set(devlink_rate, NULL, devlink_rate->priv,
837 NULL, NULL);
838
839 refcount_dec(&devlink_rate->parent->refcnt);
840 devlink_rate->parent = NULL;
841 }
842 list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) {
843 if (devlink_rate_is_node(devlink_rate)) {
844 ops->rate_node_del(devlink_rate, devlink_rate->priv, NULL);
845 list_del(&devlink_rate->list);
846 kfree(devlink_rate->name);
847 kfree(devlink_rate);
848 }
849 }
850 }
851 EXPORT_SYMBOL_GPL(devl_rate_nodes_destroy);
852