Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
[deliverable/linux.git] / net / core / devlink.c
1 /*
2 * net/core/devlink.c - Network physical/parent device Netlink interface
3 *
4 * Heavily inspired by net/wireless/
5 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
6 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/slab.h>
18 #include <linux/gfp.h>
19 #include <linux/device.h>
20 #include <linux/list.h>
21 #include <linux/netdevice.h>
22 #include <rdma/ib_verbs.h>
23 #include <net/netlink.h>
24 #include <net/genetlink.h>
25 #include <net/rtnetlink.h>
26 #include <net/net_namespace.h>
27 #include <net/sock.h>
28 #include <net/devlink.h>
29
30 static LIST_HEAD(devlink_list);
31
32 /* devlink_mutex
33 *
34 * An overall lock guarding every operation coming from userspace.
35 * It also guards devlink devices list and it is taken when
36 * driver registers/unregisters it.
37 */
38 static DEFINE_MUTEX(devlink_mutex);
39
40 /* devlink_port_mutex
41 *
42 * Shared lock to guard lists of ports in all devlink devices.
43 */
44 static DEFINE_MUTEX(devlink_port_mutex);
45
46 static struct net *devlink_net(const struct devlink *devlink)
47 {
48 return read_pnet(&devlink->_net);
49 }
50
51 static void devlink_net_set(struct devlink *devlink, struct net *net)
52 {
53 write_pnet(&devlink->_net, net);
54 }
55
56 static struct devlink *devlink_get_from_attrs(struct net *net,
57 struct nlattr **attrs)
58 {
59 struct devlink *devlink;
60 char *busname;
61 char *devname;
62
63 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
64 return ERR_PTR(-EINVAL);
65
66 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
67 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
68
69 list_for_each_entry(devlink, &devlink_list, list) {
70 if (strcmp(devlink->dev->bus->name, busname) == 0 &&
71 strcmp(dev_name(devlink->dev), devname) == 0 &&
72 net_eq(devlink_net(devlink), net))
73 return devlink;
74 }
75
76 return ERR_PTR(-ENODEV);
77 }
78
79 static struct devlink *devlink_get_from_info(struct genl_info *info)
80 {
81 return devlink_get_from_attrs(genl_info_net(info), info->attrs);
82 }
83
84 static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
85 int port_index)
86 {
87 struct devlink_port *devlink_port;
88
89 list_for_each_entry(devlink_port, &devlink->port_list, list) {
90 if (devlink_port->index == port_index)
91 return devlink_port;
92 }
93 return NULL;
94 }
95
96 static bool devlink_port_index_exists(struct devlink *devlink, int port_index)
97 {
98 return devlink_port_get_by_index(devlink, port_index);
99 }
100
101 static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
102 struct nlattr **attrs)
103 {
104 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
105 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
106 struct devlink_port *devlink_port;
107
108 devlink_port = devlink_port_get_by_index(devlink, port_index);
109 if (!devlink_port)
110 return ERR_PTR(-ENODEV);
111 return devlink_port;
112 }
113 return ERR_PTR(-EINVAL);
114 }
115
116 static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
117 struct genl_info *info)
118 {
119 return devlink_port_get_from_attrs(devlink, info->attrs);
120 }
121
122 struct devlink_sb {
123 struct list_head list;
124 unsigned int index;
125 u32 size;
126 u16 ingress_pools_count;
127 u16 egress_pools_count;
128 u16 ingress_tc_count;
129 u16 egress_tc_count;
130 };
131
132 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
133 {
134 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
135 }
136
137 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
138 unsigned int sb_index)
139 {
140 struct devlink_sb *devlink_sb;
141
142 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
143 if (devlink_sb->index == sb_index)
144 return devlink_sb;
145 }
146 return NULL;
147 }
148
149 static bool devlink_sb_index_exists(struct devlink *devlink,
150 unsigned int sb_index)
151 {
152 return devlink_sb_get_by_index(devlink, sb_index);
153 }
154
155 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
156 struct nlattr **attrs)
157 {
158 if (attrs[DEVLINK_ATTR_SB_INDEX]) {
159 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
160 struct devlink_sb *devlink_sb;
161
162 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
163 if (!devlink_sb)
164 return ERR_PTR(-ENODEV);
165 return devlink_sb;
166 }
167 return ERR_PTR(-EINVAL);
168 }
169
170 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
171 struct genl_info *info)
172 {
173 return devlink_sb_get_from_attrs(devlink, info->attrs);
174 }
175
176 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
177 struct nlattr **attrs,
178 u16 *p_pool_index)
179 {
180 u16 val;
181
182 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
183 return -EINVAL;
184
185 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
186 if (val >= devlink_sb_pool_count(devlink_sb))
187 return -EINVAL;
188 *p_pool_index = val;
189 return 0;
190 }
191
192 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
193 struct genl_info *info,
194 u16 *p_pool_index)
195 {
196 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
197 p_pool_index);
198 }
199
200 static int
201 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
202 enum devlink_sb_pool_type *p_pool_type)
203 {
204 u8 val;
205
206 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
207 return -EINVAL;
208
209 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
210 if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
211 val != DEVLINK_SB_POOL_TYPE_EGRESS)
212 return -EINVAL;
213 *p_pool_type = val;
214 return 0;
215 }
216
217 static int
218 devlink_sb_pool_type_get_from_info(struct genl_info *info,
219 enum devlink_sb_pool_type *p_pool_type)
220 {
221 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
222 }
223
224 static int
225 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
226 enum devlink_sb_threshold_type *p_th_type)
227 {
228 u8 val;
229
230 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
231 return -EINVAL;
232
233 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
234 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
235 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
236 return -EINVAL;
237 *p_th_type = val;
238 return 0;
239 }
240
241 static int
242 devlink_sb_th_type_get_from_info(struct genl_info *info,
243 enum devlink_sb_threshold_type *p_th_type)
244 {
245 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
246 }
247
248 static int
249 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
250 struct nlattr **attrs,
251 enum devlink_sb_pool_type pool_type,
252 u16 *p_tc_index)
253 {
254 u16 val;
255
256 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
257 return -EINVAL;
258
259 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
260 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
261 val >= devlink_sb->ingress_tc_count)
262 return -EINVAL;
263 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
264 val >= devlink_sb->egress_tc_count)
265 return -EINVAL;
266 *p_tc_index = val;
267 return 0;
268 }
269
270 static int
271 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
272 struct genl_info *info,
273 enum devlink_sb_pool_type pool_type,
274 u16 *p_tc_index)
275 {
276 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
277 pool_type, p_tc_index);
278 }
279
280 #define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
281 #define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
282 #define DEVLINK_NL_FLAG_NEED_SB BIT(2)
283 #define DEVLINK_NL_FLAG_LOCK_PORTS BIT(3)
284 /* port is not needed but we need to ensure they don't
285 * change in the middle of command
286 */
287
288 static int devlink_nl_pre_doit(const struct genl_ops *ops,
289 struct sk_buff *skb, struct genl_info *info)
290 {
291 struct devlink *devlink;
292
293 mutex_lock(&devlink_mutex);
294 devlink = devlink_get_from_info(info);
295 if (IS_ERR(devlink)) {
296 mutex_unlock(&devlink_mutex);
297 return PTR_ERR(devlink);
298 }
299 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
300 info->user_ptr[0] = devlink;
301 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
302 struct devlink_port *devlink_port;
303
304 mutex_lock(&devlink_port_mutex);
305 devlink_port = devlink_port_get_from_info(devlink, info);
306 if (IS_ERR(devlink_port)) {
307 mutex_unlock(&devlink_port_mutex);
308 mutex_unlock(&devlink_mutex);
309 return PTR_ERR(devlink_port);
310 }
311 info->user_ptr[0] = devlink_port;
312 }
313 if (ops->internal_flags & DEVLINK_NL_FLAG_LOCK_PORTS) {
314 mutex_lock(&devlink_port_mutex);
315 }
316 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
317 struct devlink_sb *devlink_sb;
318
319 devlink_sb = devlink_sb_get_from_info(devlink, info);
320 if (IS_ERR(devlink_sb)) {
321 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT)
322 mutex_unlock(&devlink_port_mutex);
323 mutex_unlock(&devlink_mutex);
324 return PTR_ERR(devlink_sb);
325 }
326 info->user_ptr[1] = devlink_sb;
327 }
328 return 0;
329 }
330
331 static void devlink_nl_post_doit(const struct genl_ops *ops,
332 struct sk_buff *skb, struct genl_info *info)
333 {
334 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT ||
335 ops->internal_flags & DEVLINK_NL_FLAG_LOCK_PORTS)
336 mutex_unlock(&devlink_port_mutex);
337 mutex_unlock(&devlink_mutex);
338 }
339
340 static struct genl_family devlink_nl_family = {
341 .id = GENL_ID_GENERATE,
342 .name = DEVLINK_GENL_NAME,
343 .version = DEVLINK_GENL_VERSION,
344 .maxattr = DEVLINK_ATTR_MAX,
345 .netnsok = true,
346 .pre_doit = devlink_nl_pre_doit,
347 .post_doit = devlink_nl_post_doit,
348 };
349
350 enum devlink_multicast_groups {
351 DEVLINK_MCGRP_CONFIG,
352 };
353
354 static const struct genl_multicast_group devlink_nl_mcgrps[] = {
355 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
356 };
357
358 static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
359 {
360 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
361 return -EMSGSIZE;
362 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
363 return -EMSGSIZE;
364 return 0;
365 }
366
367 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
368 enum devlink_command cmd, u32 portid,
369 u32 seq, int flags)
370 {
371 void *hdr;
372
373 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
374 if (!hdr)
375 return -EMSGSIZE;
376
377 if (devlink_nl_put_handle(msg, devlink))
378 goto nla_put_failure;
379
380 genlmsg_end(msg, hdr);
381 return 0;
382
383 nla_put_failure:
384 genlmsg_cancel(msg, hdr);
385 return -EMSGSIZE;
386 }
387
388 static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
389 {
390 struct sk_buff *msg;
391 int err;
392
393 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
394
395 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
396 if (!msg)
397 return;
398
399 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
400 if (err) {
401 nlmsg_free(msg);
402 return;
403 }
404
405 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
406 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
407 }
408
409 static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
410 struct devlink_port *devlink_port,
411 enum devlink_command cmd, u32 portid,
412 u32 seq, int flags)
413 {
414 void *hdr;
415
416 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
417 if (!hdr)
418 return -EMSGSIZE;
419
420 if (devlink_nl_put_handle(msg, devlink))
421 goto nla_put_failure;
422 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
423 goto nla_put_failure;
424 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
425 goto nla_put_failure;
426 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
427 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
428 devlink_port->desired_type))
429 goto nla_put_failure;
430 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
431 struct net_device *netdev = devlink_port->type_dev;
432
433 if (netdev &&
434 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
435 netdev->ifindex) ||
436 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
437 netdev->name)))
438 goto nla_put_failure;
439 }
440 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
441 struct ib_device *ibdev = devlink_port->type_dev;
442
443 if (ibdev &&
444 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
445 ibdev->name))
446 goto nla_put_failure;
447 }
448 if (devlink_port->split &&
449 nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
450 devlink_port->split_group))
451 goto nla_put_failure;
452
453 genlmsg_end(msg, hdr);
454 return 0;
455
456 nla_put_failure:
457 genlmsg_cancel(msg, hdr);
458 return -EMSGSIZE;
459 }
460
461 static void devlink_port_notify(struct devlink_port *devlink_port,
462 enum devlink_command cmd)
463 {
464 struct devlink *devlink = devlink_port->devlink;
465 struct sk_buff *msg;
466 int err;
467
468 if (!devlink_port->registered)
469 return;
470
471 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
472
473 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
474 if (!msg)
475 return;
476
477 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
478 if (err) {
479 nlmsg_free(msg);
480 return;
481 }
482
483 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
484 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
485 }
486
487 static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
488 {
489 struct devlink *devlink = info->user_ptr[0];
490 struct sk_buff *msg;
491 int err;
492
493 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
494 if (!msg)
495 return -ENOMEM;
496
497 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
498 info->snd_portid, info->snd_seq, 0);
499 if (err) {
500 nlmsg_free(msg);
501 return err;
502 }
503
504 return genlmsg_reply(msg, info);
505 }
506
507 static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
508 struct netlink_callback *cb)
509 {
510 struct devlink *devlink;
511 int start = cb->args[0];
512 int idx = 0;
513 int err;
514
515 mutex_lock(&devlink_mutex);
516 list_for_each_entry(devlink, &devlink_list, list) {
517 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
518 continue;
519 if (idx < start) {
520 idx++;
521 continue;
522 }
523 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
524 NETLINK_CB(cb->skb).portid,
525 cb->nlh->nlmsg_seq, NLM_F_MULTI);
526 if (err)
527 goto out;
528 idx++;
529 }
530 out:
531 mutex_unlock(&devlink_mutex);
532
533 cb->args[0] = idx;
534 return msg->len;
535 }
536
537 static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
538 struct genl_info *info)
539 {
540 struct devlink_port *devlink_port = info->user_ptr[0];
541 struct devlink *devlink = devlink_port->devlink;
542 struct sk_buff *msg;
543 int err;
544
545 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
546 if (!msg)
547 return -ENOMEM;
548
549 err = devlink_nl_port_fill(msg, devlink, devlink_port,
550 DEVLINK_CMD_PORT_NEW,
551 info->snd_portid, info->snd_seq, 0);
552 if (err) {
553 nlmsg_free(msg);
554 return err;
555 }
556
557 return genlmsg_reply(msg, info);
558 }
559
560 static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
561 struct netlink_callback *cb)
562 {
563 struct devlink *devlink;
564 struct devlink_port *devlink_port;
565 int start = cb->args[0];
566 int idx = 0;
567 int err;
568
569 mutex_lock(&devlink_mutex);
570 mutex_lock(&devlink_port_mutex);
571 list_for_each_entry(devlink, &devlink_list, list) {
572 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
573 continue;
574 list_for_each_entry(devlink_port, &devlink->port_list, list) {
575 if (idx < start) {
576 idx++;
577 continue;
578 }
579 err = devlink_nl_port_fill(msg, devlink, devlink_port,
580 DEVLINK_CMD_NEW,
581 NETLINK_CB(cb->skb).portid,
582 cb->nlh->nlmsg_seq,
583 NLM_F_MULTI);
584 if (err)
585 goto out;
586 idx++;
587 }
588 }
589 out:
590 mutex_unlock(&devlink_port_mutex);
591 mutex_unlock(&devlink_mutex);
592
593 cb->args[0] = idx;
594 return msg->len;
595 }
596
597 static int devlink_port_type_set(struct devlink *devlink,
598 struct devlink_port *devlink_port,
599 enum devlink_port_type port_type)
600
601 {
602 int err;
603
604 if (devlink->ops && devlink->ops->port_type_set) {
605 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
606 return -EINVAL;
607 err = devlink->ops->port_type_set(devlink_port, port_type);
608 if (err)
609 return err;
610 devlink_port->desired_type = port_type;
611 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
612 return 0;
613 }
614 return -EOPNOTSUPP;
615 }
616
617 static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
618 struct genl_info *info)
619 {
620 struct devlink_port *devlink_port = info->user_ptr[0];
621 struct devlink *devlink = devlink_port->devlink;
622 int err;
623
624 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
625 enum devlink_port_type port_type;
626
627 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
628 err = devlink_port_type_set(devlink, devlink_port, port_type);
629 if (err)
630 return err;
631 }
632 return 0;
633 }
634
635 static int devlink_port_split(struct devlink *devlink,
636 u32 port_index, u32 count)
637
638 {
639 if (devlink->ops && devlink->ops->port_split)
640 return devlink->ops->port_split(devlink, port_index, count);
641 return -EOPNOTSUPP;
642 }
643
644 static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
645 struct genl_info *info)
646 {
647 struct devlink *devlink = info->user_ptr[0];
648 u32 port_index;
649 u32 count;
650
651 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
652 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
653 return -EINVAL;
654
655 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
656 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
657 return devlink_port_split(devlink, port_index, count);
658 }
659
660 static int devlink_port_unsplit(struct devlink *devlink, u32 port_index)
661
662 {
663 if (devlink->ops && devlink->ops->port_unsplit)
664 return devlink->ops->port_unsplit(devlink, port_index);
665 return -EOPNOTSUPP;
666 }
667
668 static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
669 struct genl_info *info)
670 {
671 struct devlink *devlink = info->user_ptr[0];
672 u32 port_index;
673
674 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
675 return -EINVAL;
676
677 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
678 return devlink_port_unsplit(devlink, port_index);
679 }
680
681 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
682 struct devlink_sb *devlink_sb,
683 enum devlink_command cmd, u32 portid,
684 u32 seq, int flags)
685 {
686 void *hdr;
687
688 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
689 if (!hdr)
690 return -EMSGSIZE;
691
692 if (devlink_nl_put_handle(msg, devlink))
693 goto nla_put_failure;
694 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
695 goto nla_put_failure;
696 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
697 goto nla_put_failure;
698 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
699 devlink_sb->ingress_pools_count))
700 goto nla_put_failure;
701 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
702 devlink_sb->egress_pools_count))
703 goto nla_put_failure;
704 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
705 devlink_sb->ingress_tc_count))
706 goto nla_put_failure;
707 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
708 devlink_sb->egress_tc_count))
709 goto nla_put_failure;
710
711 genlmsg_end(msg, hdr);
712 return 0;
713
714 nla_put_failure:
715 genlmsg_cancel(msg, hdr);
716 return -EMSGSIZE;
717 }
718
719 static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
720 struct genl_info *info)
721 {
722 struct devlink *devlink = info->user_ptr[0];
723 struct devlink_sb *devlink_sb = info->user_ptr[1];
724 struct sk_buff *msg;
725 int err;
726
727 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
728 if (!msg)
729 return -ENOMEM;
730
731 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
732 DEVLINK_CMD_SB_NEW,
733 info->snd_portid, info->snd_seq, 0);
734 if (err) {
735 nlmsg_free(msg);
736 return err;
737 }
738
739 return genlmsg_reply(msg, info);
740 }
741
742 static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
743 struct netlink_callback *cb)
744 {
745 struct devlink *devlink;
746 struct devlink_sb *devlink_sb;
747 int start = cb->args[0];
748 int idx = 0;
749 int err;
750
751 mutex_lock(&devlink_mutex);
752 list_for_each_entry(devlink, &devlink_list, list) {
753 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
754 continue;
755 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
756 if (idx < start) {
757 idx++;
758 continue;
759 }
760 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
761 DEVLINK_CMD_SB_NEW,
762 NETLINK_CB(cb->skb).portid,
763 cb->nlh->nlmsg_seq,
764 NLM_F_MULTI);
765 if (err)
766 goto out;
767 idx++;
768 }
769 }
770 out:
771 mutex_unlock(&devlink_mutex);
772
773 cb->args[0] = idx;
774 return msg->len;
775 }
776
777 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
778 struct devlink_sb *devlink_sb,
779 u16 pool_index, enum devlink_command cmd,
780 u32 portid, u32 seq, int flags)
781 {
782 struct devlink_sb_pool_info pool_info;
783 void *hdr;
784 int err;
785
786 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
787 pool_index, &pool_info);
788 if (err)
789 return err;
790
791 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
792 if (!hdr)
793 return -EMSGSIZE;
794
795 if (devlink_nl_put_handle(msg, devlink))
796 goto nla_put_failure;
797 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
798 goto nla_put_failure;
799 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
800 goto nla_put_failure;
801 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
802 goto nla_put_failure;
803 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
804 goto nla_put_failure;
805 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
806 pool_info.threshold_type))
807 goto nla_put_failure;
808
809 genlmsg_end(msg, hdr);
810 return 0;
811
812 nla_put_failure:
813 genlmsg_cancel(msg, hdr);
814 return -EMSGSIZE;
815 }
816
817 static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
818 struct genl_info *info)
819 {
820 struct devlink *devlink = info->user_ptr[0];
821 struct devlink_sb *devlink_sb = info->user_ptr[1];
822 struct sk_buff *msg;
823 u16 pool_index;
824 int err;
825
826 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
827 &pool_index);
828 if (err)
829 return err;
830
831 if (!devlink->ops || !devlink->ops->sb_pool_get)
832 return -EOPNOTSUPP;
833
834 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
835 if (!msg)
836 return -ENOMEM;
837
838 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
839 DEVLINK_CMD_SB_POOL_NEW,
840 info->snd_portid, info->snd_seq, 0);
841 if (err) {
842 nlmsg_free(msg);
843 return err;
844 }
845
846 return genlmsg_reply(msg, info);
847 }
848
849 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
850 struct devlink *devlink,
851 struct devlink_sb *devlink_sb,
852 u32 portid, u32 seq)
853 {
854 u16 pool_count = devlink_sb_pool_count(devlink_sb);
855 u16 pool_index;
856 int err;
857
858 for (pool_index = 0; pool_index < pool_count; pool_index++) {
859 if (*p_idx < start) {
860 (*p_idx)++;
861 continue;
862 }
863 err = devlink_nl_sb_pool_fill(msg, devlink,
864 devlink_sb,
865 pool_index,
866 DEVLINK_CMD_SB_POOL_NEW,
867 portid, seq, NLM_F_MULTI);
868 if (err)
869 return err;
870 (*p_idx)++;
871 }
872 return 0;
873 }
874
875 static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
876 struct netlink_callback *cb)
877 {
878 struct devlink *devlink;
879 struct devlink_sb *devlink_sb;
880 int start = cb->args[0];
881 int idx = 0;
882 int err;
883
884 mutex_lock(&devlink_mutex);
885 list_for_each_entry(devlink, &devlink_list, list) {
886 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
887 !devlink->ops || !devlink->ops->sb_pool_get)
888 continue;
889 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
890 err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
891 devlink_sb,
892 NETLINK_CB(cb->skb).portid,
893 cb->nlh->nlmsg_seq);
894 if (err && err != -EOPNOTSUPP)
895 goto out;
896 }
897 }
898 out:
899 mutex_unlock(&devlink_mutex);
900
901 cb->args[0] = idx;
902 return msg->len;
903 }
904
905 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
906 u16 pool_index, u32 size,
907 enum devlink_sb_threshold_type threshold_type)
908
909 {
910 const struct devlink_ops *ops = devlink->ops;
911
912 if (ops && ops->sb_pool_set)
913 return ops->sb_pool_set(devlink, sb_index, pool_index,
914 size, threshold_type);
915 return -EOPNOTSUPP;
916 }
917
918 static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
919 struct genl_info *info)
920 {
921 struct devlink *devlink = info->user_ptr[0];
922 struct devlink_sb *devlink_sb = info->user_ptr[1];
923 enum devlink_sb_threshold_type threshold_type;
924 u16 pool_index;
925 u32 size;
926 int err;
927
928 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
929 &pool_index);
930 if (err)
931 return err;
932
933 err = devlink_sb_th_type_get_from_info(info, &threshold_type);
934 if (err)
935 return err;
936
937 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
938 return -EINVAL;
939
940 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
941 return devlink_sb_pool_set(devlink, devlink_sb->index,
942 pool_index, size, threshold_type);
943 }
944
945 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
946 struct devlink *devlink,
947 struct devlink_port *devlink_port,
948 struct devlink_sb *devlink_sb,
949 u16 pool_index,
950 enum devlink_command cmd,
951 u32 portid, u32 seq, int flags)
952 {
953 const struct devlink_ops *ops = devlink->ops;
954 u32 threshold;
955 void *hdr;
956 int err;
957
958 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
959 pool_index, &threshold);
960 if (err)
961 return err;
962
963 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
964 if (!hdr)
965 return -EMSGSIZE;
966
967 if (devlink_nl_put_handle(msg, devlink))
968 goto nla_put_failure;
969 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
970 goto nla_put_failure;
971 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
972 goto nla_put_failure;
973 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
974 goto nla_put_failure;
975 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
976 goto nla_put_failure;
977
978 if (ops->sb_occ_port_pool_get) {
979 u32 cur;
980 u32 max;
981
982 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
983 pool_index, &cur, &max);
984 if (err && err != -EOPNOTSUPP)
985 return err;
986 if (!err) {
987 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
988 goto nla_put_failure;
989 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
990 goto nla_put_failure;
991 }
992 }
993
994 genlmsg_end(msg, hdr);
995 return 0;
996
997 nla_put_failure:
998 genlmsg_cancel(msg, hdr);
999 return -EMSGSIZE;
1000 }
1001
1002 static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1003 struct genl_info *info)
1004 {
1005 struct devlink_port *devlink_port = info->user_ptr[0];
1006 struct devlink *devlink = devlink_port->devlink;
1007 struct devlink_sb *devlink_sb = info->user_ptr[1];
1008 struct sk_buff *msg;
1009 u16 pool_index;
1010 int err;
1011
1012 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1013 &pool_index);
1014 if (err)
1015 return err;
1016
1017 if (!devlink->ops || !devlink->ops->sb_port_pool_get)
1018 return -EOPNOTSUPP;
1019
1020 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1021 if (!msg)
1022 return -ENOMEM;
1023
1024 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1025 devlink_sb, pool_index,
1026 DEVLINK_CMD_SB_PORT_POOL_NEW,
1027 info->snd_portid, info->snd_seq, 0);
1028 if (err) {
1029 nlmsg_free(msg);
1030 return err;
1031 }
1032
1033 return genlmsg_reply(msg, info);
1034 }
1035
1036 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1037 struct devlink *devlink,
1038 struct devlink_sb *devlink_sb,
1039 u32 portid, u32 seq)
1040 {
1041 struct devlink_port *devlink_port;
1042 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1043 u16 pool_index;
1044 int err;
1045
1046 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1047 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1048 if (*p_idx < start) {
1049 (*p_idx)++;
1050 continue;
1051 }
1052 err = devlink_nl_sb_port_pool_fill(msg, devlink,
1053 devlink_port,
1054 devlink_sb,
1055 pool_index,
1056 DEVLINK_CMD_SB_PORT_POOL_NEW,
1057 portid, seq,
1058 NLM_F_MULTI);
1059 if (err)
1060 return err;
1061 (*p_idx)++;
1062 }
1063 }
1064 return 0;
1065 }
1066
1067 static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1068 struct netlink_callback *cb)
1069 {
1070 struct devlink *devlink;
1071 struct devlink_sb *devlink_sb;
1072 int start = cb->args[0];
1073 int idx = 0;
1074 int err;
1075
1076 mutex_lock(&devlink_mutex);
1077 mutex_lock(&devlink_port_mutex);
1078 list_for_each_entry(devlink, &devlink_list, list) {
1079 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1080 !devlink->ops || !devlink->ops->sb_port_pool_get)
1081 continue;
1082 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1083 err = __sb_port_pool_get_dumpit(msg, start, &idx,
1084 devlink, devlink_sb,
1085 NETLINK_CB(cb->skb).portid,
1086 cb->nlh->nlmsg_seq);
1087 if (err && err != -EOPNOTSUPP)
1088 goto out;
1089 }
1090 }
1091 out:
1092 mutex_unlock(&devlink_port_mutex);
1093 mutex_unlock(&devlink_mutex);
1094
1095 cb->args[0] = idx;
1096 return msg->len;
1097 }
1098
1099 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1100 unsigned int sb_index, u16 pool_index,
1101 u32 threshold)
1102
1103 {
1104 const struct devlink_ops *ops = devlink_port->devlink->ops;
1105
1106 if (ops && ops->sb_port_pool_set)
1107 return ops->sb_port_pool_set(devlink_port, sb_index,
1108 pool_index, threshold);
1109 return -EOPNOTSUPP;
1110 }
1111
1112 static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1113 struct genl_info *info)
1114 {
1115 struct devlink_port *devlink_port = info->user_ptr[0];
1116 struct devlink_sb *devlink_sb = info->user_ptr[1];
1117 u16 pool_index;
1118 u32 threshold;
1119 int err;
1120
1121 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1122 &pool_index);
1123 if (err)
1124 return err;
1125
1126 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1127 return -EINVAL;
1128
1129 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1130 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1131 pool_index, threshold);
1132 }
1133
1134 static int
1135 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1136 struct devlink_port *devlink_port,
1137 struct devlink_sb *devlink_sb, u16 tc_index,
1138 enum devlink_sb_pool_type pool_type,
1139 enum devlink_command cmd,
1140 u32 portid, u32 seq, int flags)
1141 {
1142 const struct devlink_ops *ops = devlink->ops;
1143 u16 pool_index;
1144 u32 threshold;
1145 void *hdr;
1146 int err;
1147
1148 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1149 tc_index, pool_type,
1150 &pool_index, &threshold);
1151 if (err)
1152 return err;
1153
1154 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1155 if (!hdr)
1156 return -EMSGSIZE;
1157
1158 if (devlink_nl_put_handle(msg, devlink))
1159 goto nla_put_failure;
1160 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1161 goto nla_put_failure;
1162 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1163 goto nla_put_failure;
1164 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1165 goto nla_put_failure;
1166 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1167 goto nla_put_failure;
1168 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1169 goto nla_put_failure;
1170 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1171 goto nla_put_failure;
1172
1173 if (ops->sb_occ_tc_port_bind_get) {
1174 u32 cur;
1175 u32 max;
1176
1177 err = ops->sb_occ_tc_port_bind_get(devlink_port,
1178 devlink_sb->index,
1179 tc_index, pool_type,
1180 &cur, &max);
1181 if (err && err != -EOPNOTSUPP)
1182 return err;
1183 if (!err) {
1184 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1185 goto nla_put_failure;
1186 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1187 goto nla_put_failure;
1188 }
1189 }
1190
1191 genlmsg_end(msg, hdr);
1192 return 0;
1193
1194 nla_put_failure:
1195 genlmsg_cancel(msg, hdr);
1196 return -EMSGSIZE;
1197 }
1198
1199 static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1200 struct genl_info *info)
1201 {
1202 struct devlink_port *devlink_port = info->user_ptr[0];
1203 struct devlink *devlink = devlink_port->devlink;
1204 struct devlink_sb *devlink_sb = info->user_ptr[1];
1205 struct sk_buff *msg;
1206 enum devlink_sb_pool_type pool_type;
1207 u16 tc_index;
1208 int err;
1209
1210 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1211 if (err)
1212 return err;
1213
1214 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1215 pool_type, &tc_index);
1216 if (err)
1217 return err;
1218
1219 if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get)
1220 return -EOPNOTSUPP;
1221
1222 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1223 if (!msg)
1224 return -ENOMEM;
1225
1226 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1227 devlink_sb, tc_index, pool_type,
1228 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1229 info->snd_portid,
1230 info->snd_seq, 0);
1231 if (err) {
1232 nlmsg_free(msg);
1233 return err;
1234 }
1235
1236 return genlmsg_reply(msg, info);
1237 }
1238
1239 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1240 int start, int *p_idx,
1241 struct devlink *devlink,
1242 struct devlink_sb *devlink_sb,
1243 u32 portid, u32 seq)
1244 {
1245 struct devlink_port *devlink_port;
1246 u16 tc_index;
1247 int err;
1248
1249 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1250 for (tc_index = 0;
1251 tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1252 if (*p_idx < start) {
1253 (*p_idx)++;
1254 continue;
1255 }
1256 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1257 devlink_port,
1258 devlink_sb,
1259 tc_index,
1260 DEVLINK_SB_POOL_TYPE_INGRESS,
1261 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1262 portid, seq,
1263 NLM_F_MULTI);
1264 if (err)
1265 return err;
1266 (*p_idx)++;
1267 }
1268 for (tc_index = 0;
1269 tc_index < devlink_sb->egress_tc_count; tc_index++) {
1270 if (*p_idx < start) {
1271 (*p_idx)++;
1272 continue;
1273 }
1274 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1275 devlink_port,
1276 devlink_sb,
1277 tc_index,
1278 DEVLINK_SB_POOL_TYPE_EGRESS,
1279 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1280 portid, seq,
1281 NLM_F_MULTI);
1282 if (err)
1283 return err;
1284 (*p_idx)++;
1285 }
1286 }
1287 return 0;
1288 }
1289
1290 static int
1291 devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1292 struct netlink_callback *cb)
1293 {
1294 struct devlink *devlink;
1295 struct devlink_sb *devlink_sb;
1296 int start = cb->args[0];
1297 int idx = 0;
1298 int err;
1299
1300 mutex_lock(&devlink_mutex);
1301 mutex_lock(&devlink_port_mutex);
1302 list_for_each_entry(devlink, &devlink_list, list) {
1303 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1304 !devlink->ops || !devlink->ops->sb_tc_pool_bind_get)
1305 continue;
1306 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1307 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1308 devlink,
1309 devlink_sb,
1310 NETLINK_CB(cb->skb).portid,
1311 cb->nlh->nlmsg_seq);
1312 if (err && err != -EOPNOTSUPP)
1313 goto out;
1314 }
1315 }
1316 out:
1317 mutex_unlock(&devlink_port_mutex);
1318 mutex_unlock(&devlink_mutex);
1319
1320 cb->args[0] = idx;
1321 return msg->len;
1322 }
1323
1324 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1325 unsigned int sb_index, u16 tc_index,
1326 enum devlink_sb_pool_type pool_type,
1327 u16 pool_index, u32 threshold)
1328
1329 {
1330 const struct devlink_ops *ops = devlink_port->devlink->ops;
1331
1332 if (ops && ops->sb_tc_pool_bind_set)
1333 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1334 tc_index, pool_type,
1335 pool_index, threshold);
1336 return -EOPNOTSUPP;
1337 }
1338
1339 static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1340 struct genl_info *info)
1341 {
1342 struct devlink_port *devlink_port = info->user_ptr[0];
1343 struct devlink_sb *devlink_sb = info->user_ptr[1];
1344 enum devlink_sb_pool_type pool_type;
1345 u16 tc_index;
1346 u16 pool_index;
1347 u32 threshold;
1348 int err;
1349
1350 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1351 if (err)
1352 return err;
1353
1354 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1355 pool_type, &tc_index);
1356 if (err)
1357 return err;
1358
1359 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1360 &pool_index);
1361 if (err)
1362 return err;
1363
1364 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1365 return -EINVAL;
1366
1367 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1368 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1369 tc_index, pool_type,
1370 pool_index, threshold);
1371 }
1372
1373 static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1374 struct genl_info *info)
1375 {
1376 struct devlink *devlink = info->user_ptr[0];
1377 struct devlink_sb *devlink_sb = info->user_ptr[1];
1378 const struct devlink_ops *ops = devlink->ops;
1379
1380 if (ops && ops->sb_occ_snapshot)
1381 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1382 return -EOPNOTSUPP;
1383 }
1384
1385 static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1386 struct genl_info *info)
1387 {
1388 struct devlink *devlink = info->user_ptr[0];
1389 struct devlink_sb *devlink_sb = info->user_ptr[1];
1390 const struct devlink_ops *ops = devlink->ops;
1391
1392 if (ops && ops->sb_occ_max_clear)
1393 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1394 return -EOPNOTSUPP;
1395 }
1396
1397 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
1398 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
1399 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
1400 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
1401 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
1402 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
1403 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
1404 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
1405 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
1406 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
1407 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
1408 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
1409 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
1410 };
1411
1412 static const struct genl_ops devlink_nl_ops[] = {
1413 {
1414 .cmd = DEVLINK_CMD_GET,
1415 .doit = devlink_nl_cmd_get_doit,
1416 .dumpit = devlink_nl_cmd_get_dumpit,
1417 .policy = devlink_nl_policy,
1418 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
1419 /* can be retrieved by unprivileged users */
1420 },
1421 {
1422 .cmd = DEVLINK_CMD_PORT_GET,
1423 .doit = devlink_nl_cmd_port_get_doit,
1424 .dumpit = devlink_nl_cmd_port_get_dumpit,
1425 .policy = devlink_nl_policy,
1426 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
1427 /* can be retrieved by unprivileged users */
1428 },
1429 {
1430 .cmd = DEVLINK_CMD_PORT_SET,
1431 .doit = devlink_nl_cmd_port_set_doit,
1432 .policy = devlink_nl_policy,
1433 .flags = GENL_ADMIN_PERM,
1434 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
1435 },
1436 {
1437 .cmd = DEVLINK_CMD_PORT_SPLIT,
1438 .doit = devlink_nl_cmd_port_split_doit,
1439 .policy = devlink_nl_policy,
1440 .flags = GENL_ADMIN_PERM,
1441 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
1442 },
1443 {
1444 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
1445 .doit = devlink_nl_cmd_port_unsplit_doit,
1446 .policy = devlink_nl_policy,
1447 .flags = GENL_ADMIN_PERM,
1448 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
1449 },
1450 {
1451 .cmd = DEVLINK_CMD_SB_GET,
1452 .doit = devlink_nl_cmd_sb_get_doit,
1453 .dumpit = devlink_nl_cmd_sb_get_dumpit,
1454 .policy = devlink_nl_policy,
1455 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1456 DEVLINK_NL_FLAG_NEED_SB,
1457 /* can be retrieved by unprivileged users */
1458 },
1459 {
1460 .cmd = DEVLINK_CMD_SB_POOL_GET,
1461 .doit = devlink_nl_cmd_sb_pool_get_doit,
1462 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
1463 .policy = devlink_nl_policy,
1464 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1465 DEVLINK_NL_FLAG_NEED_SB,
1466 /* can be retrieved by unprivileged users */
1467 },
1468 {
1469 .cmd = DEVLINK_CMD_SB_POOL_SET,
1470 .doit = devlink_nl_cmd_sb_pool_set_doit,
1471 .policy = devlink_nl_policy,
1472 .flags = GENL_ADMIN_PERM,
1473 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1474 DEVLINK_NL_FLAG_NEED_SB,
1475 },
1476 {
1477 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
1478 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
1479 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
1480 .policy = devlink_nl_policy,
1481 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1482 DEVLINK_NL_FLAG_NEED_SB,
1483 /* can be retrieved by unprivileged users */
1484 },
1485 {
1486 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
1487 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
1488 .policy = devlink_nl_policy,
1489 .flags = GENL_ADMIN_PERM,
1490 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1491 DEVLINK_NL_FLAG_NEED_SB,
1492 },
1493 {
1494 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
1495 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
1496 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
1497 .policy = devlink_nl_policy,
1498 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1499 DEVLINK_NL_FLAG_NEED_SB,
1500 /* can be retrieved by unprivileged users */
1501 },
1502 {
1503 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
1504 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
1505 .policy = devlink_nl_policy,
1506 .flags = GENL_ADMIN_PERM,
1507 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1508 DEVLINK_NL_FLAG_NEED_SB,
1509 },
1510 {
1511 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
1512 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
1513 .policy = devlink_nl_policy,
1514 .flags = GENL_ADMIN_PERM,
1515 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1516 DEVLINK_NL_FLAG_NEED_SB |
1517 DEVLINK_NL_FLAG_LOCK_PORTS,
1518 },
1519 {
1520 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
1521 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
1522 .policy = devlink_nl_policy,
1523 .flags = GENL_ADMIN_PERM,
1524 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1525 DEVLINK_NL_FLAG_NEED_SB |
1526 DEVLINK_NL_FLAG_LOCK_PORTS,
1527 },
1528 };
1529
1530 /**
1531 * devlink_alloc - Allocate new devlink instance resources
1532 *
1533 * @ops: ops
1534 * @priv_size: size of user private data
1535 *
1536 * Allocate new devlink instance resources, including devlink index
1537 * and name.
1538 */
1539 struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
1540 {
1541 struct devlink *devlink;
1542
1543 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
1544 if (!devlink)
1545 return NULL;
1546 devlink->ops = ops;
1547 devlink_net_set(devlink, &init_net);
1548 INIT_LIST_HEAD(&devlink->port_list);
1549 INIT_LIST_HEAD(&devlink->sb_list);
1550 return devlink;
1551 }
1552 EXPORT_SYMBOL_GPL(devlink_alloc);
1553
1554 /**
1555 * devlink_register - Register devlink instance
1556 *
1557 * @devlink: devlink
1558 */
1559 int devlink_register(struct devlink *devlink, struct device *dev)
1560 {
1561 mutex_lock(&devlink_mutex);
1562 devlink->dev = dev;
1563 list_add_tail(&devlink->list, &devlink_list);
1564 devlink_notify(devlink, DEVLINK_CMD_NEW);
1565 mutex_unlock(&devlink_mutex);
1566 return 0;
1567 }
1568 EXPORT_SYMBOL_GPL(devlink_register);
1569
1570 /**
1571 * devlink_unregister - Unregister devlink instance
1572 *
1573 * @devlink: devlink
1574 */
1575 void devlink_unregister(struct devlink *devlink)
1576 {
1577 mutex_lock(&devlink_mutex);
1578 devlink_notify(devlink, DEVLINK_CMD_DEL);
1579 list_del(&devlink->list);
1580 mutex_unlock(&devlink_mutex);
1581 }
1582 EXPORT_SYMBOL_GPL(devlink_unregister);
1583
1584 /**
1585 * devlink_free - Free devlink instance resources
1586 *
1587 * @devlink: devlink
1588 */
1589 void devlink_free(struct devlink *devlink)
1590 {
1591 kfree(devlink);
1592 }
1593 EXPORT_SYMBOL_GPL(devlink_free);
1594
1595 /**
1596 * devlink_port_register - Register devlink port
1597 *
1598 * @devlink: devlink
1599 * @devlink_port: devlink port
1600 * @port_index
1601 *
1602 * Register devlink port with provided port index. User can use
1603 * any indexing, even hw-related one. devlink_port structure
1604 * is convenient to be embedded inside user driver private structure.
1605 * Note that the caller should take care of zeroing the devlink_port
1606 * structure.
1607 */
1608 int devlink_port_register(struct devlink *devlink,
1609 struct devlink_port *devlink_port,
1610 unsigned int port_index)
1611 {
1612 mutex_lock(&devlink_port_mutex);
1613 if (devlink_port_index_exists(devlink, port_index)) {
1614 mutex_unlock(&devlink_port_mutex);
1615 return -EEXIST;
1616 }
1617 devlink_port->devlink = devlink;
1618 devlink_port->index = port_index;
1619 devlink_port->registered = true;
1620 list_add_tail(&devlink_port->list, &devlink->port_list);
1621 mutex_unlock(&devlink_port_mutex);
1622 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1623 return 0;
1624 }
1625 EXPORT_SYMBOL_GPL(devlink_port_register);
1626
1627 /**
1628 * devlink_port_unregister - Unregister devlink port
1629 *
1630 * @devlink_port: devlink port
1631 */
1632 void devlink_port_unregister(struct devlink_port *devlink_port)
1633 {
1634 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
1635 mutex_lock(&devlink_port_mutex);
1636 list_del(&devlink_port->list);
1637 mutex_unlock(&devlink_port_mutex);
1638 }
1639 EXPORT_SYMBOL_GPL(devlink_port_unregister);
1640
1641 static void __devlink_port_type_set(struct devlink_port *devlink_port,
1642 enum devlink_port_type type,
1643 void *type_dev)
1644 {
1645 devlink_port->type = type;
1646 devlink_port->type_dev = type_dev;
1647 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1648 }
1649
1650 /**
1651 * devlink_port_type_eth_set - Set port type to Ethernet
1652 *
1653 * @devlink_port: devlink port
1654 * @netdev: related netdevice
1655 */
1656 void devlink_port_type_eth_set(struct devlink_port *devlink_port,
1657 struct net_device *netdev)
1658 {
1659 return __devlink_port_type_set(devlink_port,
1660 DEVLINK_PORT_TYPE_ETH, netdev);
1661 }
1662 EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
1663
1664 /**
1665 * devlink_port_type_ib_set - Set port type to InfiniBand
1666 *
1667 * @devlink_port: devlink port
1668 * @ibdev: related IB device
1669 */
1670 void devlink_port_type_ib_set(struct devlink_port *devlink_port,
1671 struct ib_device *ibdev)
1672 {
1673 return __devlink_port_type_set(devlink_port,
1674 DEVLINK_PORT_TYPE_IB, ibdev);
1675 }
1676 EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
1677
1678 /**
1679 * devlink_port_type_clear - Clear port type
1680 *
1681 * @devlink_port: devlink port
1682 */
1683 void devlink_port_type_clear(struct devlink_port *devlink_port)
1684 {
1685 return __devlink_port_type_set(devlink_port,
1686 DEVLINK_PORT_TYPE_NOTSET, NULL);
1687 }
1688 EXPORT_SYMBOL_GPL(devlink_port_type_clear);
1689
1690 /**
1691 * devlink_port_split_set - Set port is split
1692 *
1693 * @devlink_port: devlink port
1694 * @split_group: split group - identifies group split port is part of
1695 */
1696 void devlink_port_split_set(struct devlink_port *devlink_port,
1697 u32 split_group)
1698 {
1699 devlink_port->split = true;
1700 devlink_port->split_group = split_group;
1701 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1702 }
1703 EXPORT_SYMBOL_GPL(devlink_port_split_set);
1704
1705 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
1706 u32 size, u16 ingress_pools_count,
1707 u16 egress_pools_count, u16 ingress_tc_count,
1708 u16 egress_tc_count)
1709 {
1710 struct devlink_sb *devlink_sb;
1711 int err = 0;
1712
1713 mutex_lock(&devlink_mutex);
1714 if (devlink_sb_index_exists(devlink, sb_index)) {
1715 err = -EEXIST;
1716 goto unlock;
1717 }
1718
1719 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
1720 if (!devlink_sb) {
1721 err = -ENOMEM;
1722 goto unlock;
1723 }
1724 devlink_sb->index = sb_index;
1725 devlink_sb->size = size;
1726 devlink_sb->ingress_pools_count = ingress_pools_count;
1727 devlink_sb->egress_pools_count = egress_pools_count;
1728 devlink_sb->ingress_tc_count = ingress_tc_count;
1729 devlink_sb->egress_tc_count = egress_tc_count;
1730 list_add_tail(&devlink_sb->list, &devlink->sb_list);
1731 unlock:
1732 mutex_unlock(&devlink_mutex);
1733 return err;
1734 }
1735 EXPORT_SYMBOL_GPL(devlink_sb_register);
1736
1737 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
1738 {
1739 struct devlink_sb *devlink_sb;
1740
1741 mutex_lock(&devlink_mutex);
1742 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
1743 WARN_ON(!devlink_sb);
1744 list_del(&devlink_sb->list);
1745 mutex_unlock(&devlink_mutex);
1746 kfree(devlink_sb);
1747 }
1748 EXPORT_SYMBOL_GPL(devlink_sb_unregister);
1749
1750 static int __init devlink_module_init(void)
1751 {
1752 return genl_register_family_with_ops_groups(&devlink_nl_family,
1753 devlink_nl_ops,
1754 devlink_nl_mcgrps);
1755 }
1756
1757 static void __exit devlink_module_exit(void)
1758 {
1759 genl_unregister_family(&devlink_nl_family);
1760 }
1761
1762 module_init(devlink_module_init);
1763 module_exit(devlink_module_exit);
1764
1765 MODULE_LICENSE("GPL v2");
1766 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
1767 MODULE_DESCRIPTION("Network physical device Netlink interface");
1768 MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);
This page took 0.063774 seconds and 6 git commands to generate.