blob: aa0b9e1542e7095a04d22692647d94199fddb000 [file] [log] [blame]
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001/*
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
30static 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 */
38static DEFINE_MUTEX(devlink_mutex);
39
40/* devlink_port_mutex
41 *
42 * Shared lock to guard lists of ports in all devlink devices.
43 */
44static DEFINE_MUTEX(devlink_port_mutex);
45
46static struct net *devlink_net(const struct devlink *devlink)
47{
48 return read_pnet(&devlink->_net);
49}
50
51static void devlink_net_set(struct devlink *devlink, struct net *net)
52{
53 write_pnet(&devlink->_net, net);
54}
55
56static 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
79static 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
84static 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
96static bool devlink_port_index_exists(struct devlink *devlink, int port_index)
97{
98 return devlink_port_get_by_index(devlink, port_index);
99}
100
101static 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
116static 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
Jiri Pirkobf797472016-04-14 18:19:13 +0200122struct 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
132static 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
137static 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
149static 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
155static 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
170static 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
176static 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
192static 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
200static int
201devlink_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
217static int
218devlink_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
224static int
225devlink_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
241static int
242devlink_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
248static int
249devlink_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
270static int
271devlink_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
Jiri Pirko1fc22572016-04-08 19:12:48 +0200280#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
281#define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
Jiri Pirkobf797472016-04-14 18:19:13 +0200282#define DEVLINK_NL_FLAG_NEED_SB BIT(2)
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100283
284static int devlink_nl_pre_doit(const struct genl_ops *ops,
285 struct sk_buff *skb, struct genl_info *info)
286{
287 struct devlink *devlink;
288
289 mutex_lock(&devlink_mutex);
290 devlink = devlink_get_from_info(info);
291 if (IS_ERR(devlink)) {
292 mutex_unlock(&devlink_mutex);
293 return PTR_ERR(devlink);
294 }
Jiri Pirko1fc22572016-04-08 19:12:48 +0200295 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
296 info->user_ptr[0] = devlink;
297 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100298 struct devlink_port *devlink_port;
299
300 mutex_lock(&devlink_port_mutex);
301 devlink_port = devlink_port_get_from_info(devlink, info);
302 if (IS_ERR(devlink_port)) {
303 mutex_unlock(&devlink_port_mutex);
304 mutex_unlock(&devlink_mutex);
305 return PTR_ERR(devlink_port);
306 }
Jiri Pirko1fc22572016-04-08 19:12:48 +0200307 info->user_ptr[0] = devlink_port;
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100308 }
Jiri Pirkobf797472016-04-14 18:19:13 +0200309 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
310 struct devlink_sb *devlink_sb;
311
312 devlink_sb = devlink_sb_get_from_info(devlink, info);
313 if (IS_ERR(devlink_sb)) {
314 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT)
315 mutex_unlock(&devlink_port_mutex);
316 mutex_unlock(&devlink_mutex);
317 return PTR_ERR(devlink_sb);
318 }
319 info->user_ptr[1] = devlink_sb;
320 }
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100321 return 0;
322}
323
324static void devlink_nl_post_doit(const struct genl_ops *ops,
325 struct sk_buff *skb, struct genl_info *info)
326{
327 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT)
328 mutex_unlock(&devlink_port_mutex);
329 mutex_unlock(&devlink_mutex);
330}
331
332static struct genl_family devlink_nl_family = {
333 .id = GENL_ID_GENERATE,
334 .name = DEVLINK_GENL_NAME,
335 .version = DEVLINK_GENL_VERSION,
336 .maxattr = DEVLINK_ATTR_MAX,
337 .netnsok = true,
338 .pre_doit = devlink_nl_pre_doit,
339 .post_doit = devlink_nl_post_doit,
340};
341
342enum devlink_multicast_groups {
343 DEVLINK_MCGRP_CONFIG,
344};
345
346static const struct genl_multicast_group devlink_nl_mcgrps[] = {
347 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
348};
349
350static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
351{
352 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
353 return -EMSGSIZE;
354 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
355 return -EMSGSIZE;
356 return 0;
357}
358
359static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
360 enum devlink_command cmd, u32 portid,
361 u32 seq, int flags)
362{
363 void *hdr;
364
365 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
366 if (!hdr)
367 return -EMSGSIZE;
368
369 if (devlink_nl_put_handle(msg, devlink))
370 goto nla_put_failure;
371
372 genlmsg_end(msg, hdr);
373 return 0;
374
375nla_put_failure:
376 genlmsg_cancel(msg, hdr);
377 return -EMSGSIZE;
378}
379
380static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
381{
382 struct sk_buff *msg;
383 int err;
384
385 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
386
387 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
388 if (!msg)
389 return;
390
391 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
392 if (err) {
393 nlmsg_free(msg);
394 return;
395 }
396
397 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
398 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
399}
400
401static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
402 struct devlink_port *devlink_port,
403 enum devlink_command cmd, u32 portid,
404 u32 seq, int flags)
405{
406 void *hdr;
407
408 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
409 if (!hdr)
410 return -EMSGSIZE;
411
412 if (devlink_nl_put_handle(msg, devlink))
413 goto nla_put_failure;
414 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
415 goto nla_put_failure;
416 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
417 goto nla_put_failure;
418 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
419 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
420 devlink_port->desired_type))
421 goto nla_put_failure;
422 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
423 struct net_device *netdev = devlink_port->type_dev;
424
425 if (netdev &&
426 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
427 netdev->ifindex) ||
428 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
429 netdev->name)))
430 goto nla_put_failure;
431 }
432 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
433 struct ib_device *ibdev = devlink_port->type_dev;
434
435 if (ibdev &&
436 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
437 ibdev->name))
438 goto nla_put_failure;
439 }
440 if (devlink_port->split &&
441 nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
442 devlink_port->split_group))
443 goto nla_put_failure;
444
445 genlmsg_end(msg, hdr);
446 return 0;
447
448nla_put_failure:
449 genlmsg_cancel(msg, hdr);
450 return -EMSGSIZE;
451}
452
453static void devlink_port_notify(struct devlink_port *devlink_port,
454 enum devlink_command cmd)
455{
456 struct devlink *devlink = devlink_port->devlink;
457 struct sk_buff *msg;
458 int err;
459
460 if (!devlink_port->registered)
461 return;
462
463 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
464
465 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
466 if (!msg)
467 return;
468
469 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
470 if (err) {
471 nlmsg_free(msg);
472 return;
473 }
474
475 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
476 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
477}
478
479static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
480{
481 struct devlink *devlink = info->user_ptr[0];
482 struct sk_buff *msg;
483 int err;
484
485 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
486 if (!msg)
487 return -ENOMEM;
488
489 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
490 info->snd_portid, info->snd_seq, 0);
491 if (err) {
492 nlmsg_free(msg);
493 return err;
494 }
495
496 return genlmsg_reply(msg, info);
497}
498
499static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
500 struct netlink_callback *cb)
501{
502 struct devlink *devlink;
503 int start = cb->args[0];
504 int idx = 0;
505 int err;
506
507 mutex_lock(&devlink_mutex);
508 list_for_each_entry(devlink, &devlink_list, list) {
509 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
510 continue;
511 if (idx < start) {
512 idx++;
513 continue;
514 }
515 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
516 NETLINK_CB(cb->skb).portid,
517 cb->nlh->nlmsg_seq, NLM_F_MULTI);
518 if (err)
519 goto out;
520 idx++;
521 }
522out:
523 mutex_unlock(&devlink_mutex);
524
525 cb->args[0] = idx;
526 return msg->len;
527}
528
529static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
530 struct genl_info *info)
531{
Jiri Pirko1fc22572016-04-08 19:12:48 +0200532 struct devlink_port *devlink_port = info->user_ptr[0];
533 struct devlink *devlink = devlink_port->devlink;
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100534 struct sk_buff *msg;
535 int err;
536
537 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
538 if (!msg)
539 return -ENOMEM;
540
541 err = devlink_nl_port_fill(msg, devlink, devlink_port,
542 DEVLINK_CMD_PORT_NEW,
543 info->snd_portid, info->snd_seq, 0);
544 if (err) {
545 nlmsg_free(msg);
546 return err;
547 }
548
549 return genlmsg_reply(msg, info);
550}
551
552static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
553 struct netlink_callback *cb)
554{
555 struct devlink *devlink;
556 struct devlink_port *devlink_port;
557 int start = cb->args[0];
558 int idx = 0;
559 int err;
560
561 mutex_lock(&devlink_mutex);
562 mutex_lock(&devlink_port_mutex);
563 list_for_each_entry(devlink, &devlink_list, list) {
564 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
565 continue;
566 list_for_each_entry(devlink_port, &devlink->port_list, list) {
567 if (idx < start) {
568 idx++;
569 continue;
570 }
571 err = devlink_nl_port_fill(msg, devlink, devlink_port,
572 DEVLINK_CMD_NEW,
573 NETLINK_CB(cb->skb).portid,
574 cb->nlh->nlmsg_seq,
575 NLM_F_MULTI);
576 if (err)
577 goto out;
578 idx++;
579 }
580 }
581out:
582 mutex_unlock(&devlink_port_mutex);
583 mutex_unlock(&devlink_mutex);
584
585 cb->args[0] = idx;
586 return msg->len;
587}
588
589static int devlink_port_type_set(struct devlink *devlink,
590 struct devlink_port *devlink_port,
591 enum devlink_port_type port_type)
592
593{
594 int err;
595
596 if (devlink->ops && devlink->ops->port_type_set) {
597 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
598 return -EINVAL;
599 err = devlink->ops->port_type_set(devlink_port, port_type);
600 if (err)
601 return err;
602 devlink_port->desired_type = port_type;
603 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
604 return 0;
605 }
606 return -EOPNOTSUPP;
607}
608
609static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
610 struct genl_info *info)
611{
Jiri Pirko1fc22572016-04-08 19:12:48 +0200612 struct devlink_port *devlink_port = info->user_ptr[0];
613 struct devlink *devlink = devlink_port->devlink;
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100614 int err;
615
616 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
617 enum devlink_port_type port_type;
618
619 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
620 err = devlink_port_type_set(devlink, devlink_port, port_type);
621 if (err)
622 return err;
623 }
624 return 0;
625}
626
627static int devlink_port_split(struct devlink *devlink,
628 u32 port_index, u32 count)
629
630{
631 if (devlink->ops && devlink->ops->port_split)
632 return devlink->ops->port_split(devlink, port_index, count);
633 return -EOPNOTSUPP;
634}
635
636static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
637 struct genl_info *info)
638{
639 struct devlink *devlink = info->user_ptr[0];
640 u32 port_index;
641 u32 count;
642
643 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
644 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
645 return -EINVAL;
646
647 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
648 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
649 return devlink_port_split(devlink, port_index, count);
650}
651
652static int devlink_port_unsplit(struct devlink *devlink, u32 port_index)
653
654{
655 if (devlink->ops && devlink->ops->port_unsplit)
656 return devlink->ops->port_unsplit(devlink, port_index);
657 return -EOPNOTSUPP;
658}
659
660static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
661 struct genl_info *info)
662{
663 struct devlink *devlink = info->user_ptr[0];
664 u32 port_index;
665
666 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
667 return -EINVAL;
668
669 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
670 return devlink_port_unsplit(devlink, port_index);
671}
672
Jiri Pirkobf797472016-04-14 18:19:13 +0200673static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
674 struct devlink_sb *devlink_sb,
675 enum devlink_command cmd, u32 portid,
676 u32 seq, int flags)
677{
678 void *hdr;
679
680 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
681 if (!hdr)
682 return -EMSGSIZE;
683
684 if (devlink_nl_put_handle(msg, devlink))
685 goto nla_put_failure;
686 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
687 goto nla_put_failure;
688 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
689 goto nla_put_failure;
690 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
691 devlink_sb->ingress_pools_count))
692 goto nla_put_failure;
693 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
694 devlink_sb->egress_pools_count))
695 goto nla_put_failure;
696 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
697 devlink_sb->ingress_tc_count))
698 goto nla_put_failure;
699 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
700 devlink_sb->egress_tc_count))
701 goto nla_put_failure;
702
703 genlmsg_end(msg, hdr);
704 return 0;
705
706nla_put_failure:
707 genlmsg_cancel(msg, hdr);
708 return -EMSGSIZE;
709}
710
711static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
712 struct genl_info *info)
713{
714 struct devlink *devlink = info->user_ptr[0];
715 struct devlink_sb *devlink_sb = info->user_ptr[1];
716 struct sk_buff *msg;
717 int err;
718
719 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
720 if (!msg)
721 return -ENOMEM;
722
723 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
724 DEVLINK_CMD_SB_NEW,
725 info->snd_portid, info->snd_seq, 0);
726 if (err) {
727 nlmsg_free(msg);
728 return err;
729 }
730
731 return genlmsg_reply(msg, info);
732}
733
734static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
735 struct netlink_callback *cb)
736{
737 struct devlink *devlink;
738 struct devlink_sb *devlink_sb;
739 int start = cb->args[0];
740 int idx = 0;
741 int err;
742
743 mutex_lock(&devlink_mutex);
744 list_for_each_entry(devlink, &devlink_list, list) {
745 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
746 continue;
747 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
748 if (idx < start) {
749 idx++;
750 continue;
751 }
752 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
753 DEVLINK_CMD_SB_NEW,
754 NETLINK_CB(cb->skb).portid,
755 cb->nlh->nlmsg_seq,
756 NLM_F_MULTI);
757 if (err)
758 goto out;
759 idx++;
760 }
761 }
762out:
763 mutex_unlock(&devlink_mutex);
764
765 cb->args[0] = idx;
766 return msg->len;
767}
768
769static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
770 struct devlink_sb *devlink_sb,
771 u16 pool_index, enum devlink_command cmd,
772 u32 portid, u32 seq, int flags)
773{
774 struct devlink_sb_pool_info pool_info;
775 void *hdr;
776 int err;
777
778 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
779 pool_index, &pool_info);
780 if (err)
781 return err;
782
783 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
784 if (!hdr)
785 return -EMSGSIZE;
786
787 if (devlink_nl_put_handle(msg, devlink))
788 goto nla_put_failure;
789 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
790 goto nla_put_failure;
791 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
792 goto nla_put_failure;
793 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
794 goto nla_put_failure;
795 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
796 goto nla_put_failure;
797 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
798 pool_info.threshold_type))
799 goto nla_put_failure;
800
801 genlmsg_end(msg, hdr);
802 return 0;
803
804nla_put_failure:
805 genlmsg_cancel(msg, hdr);
806 return -EMSGSIZE;
807}
808
809static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
810 struct genl_info *info)
811{
812 struct devlink *devlink = info->user_ptr[0];
813 struct devlink_sb *devlink_sb = info->user_ptr[1];
814 struct sk_buff *msg;
815 u16 pool_index;
816 int err;
817
818 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
819 &pool_index);
820 if (err)
821 return err;
822
823 if (!devlink->ops || !devlink->ops->sb_pool_get)
824 return -EOPNOTSUPP;
825
826 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
827 if (!msg)
828 return -ENOMEM;
829
830 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
831 DEVLINK_CMD_SB_POOL_NEW,
832 info->snd_portid, info->snd_seq, 0);
833 if (err) {
834 nlmsg_free(msg);
835 return err;
836 }
837
838 return genlmsg_reply(msg, info);
839}
840
841static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
842 struct devlink *devlink,
843 struct devlink_sb *devlink_sb,
844 u32 portid, u32 seq)
845{
846 u16 pool_count = devlink_sb_pool_count(devlink_sb);
847 u16 pool_index;
848 int err;
849
850 for (pool_index = 0; pool_index < pool_count; pool_index++) {
851 if (*p_idx < start) {
852 (*p_idx)++;
853 continue;
854 }
855 err = devlink_nl_sb_pool_fill(msg, devlink,
856 devlink_sb,
857 pool_index,
858 DEVLINK_CMD_SB_POOL_NEW,
859 portid, seq, NLM_F_MULTI);
860 if (err)
861 return err;
862 (*p_idx)++;
863 }
864 return 0;
865}
866
867static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
868 struct netlink_callback *cb)
869{
870 struct devlink *devlink;
871 struct devlink_sb *devlink_sb;
872 int start = cb->args[0];
873 int idx = 0;
874 int err;
875
876 mutex_lock(&devlink_mutex);
877 list_for_each_entry(devlink, &devlink_list, list) {
878 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
879 !devlink->ops || !devlink->ops->sb_pool_get)
880 continue;
881 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
882 err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
883 devlink_sb,
884 NETLINK_CB(cb->skb).portid,
885 cb->nlh->nlmsg_seq);
886 if (err && err != -EOPNOTSUPP)
887 goto out;
888 }
889 }
890out:
891 mutex_unlock(&devlink_mutex);
892
893 cb->args[0] = idx;
894 return msg->len;
895}
896
897static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
898 u16 pool_index, u32 size,
899 enum devlink_sb_threshold_type threshold_type)
900
901{
902 const struct devlink_ops *ops = devlink->ops;
903
904 if (ops && ops->sb_pool_set)
905 return ops->sb_pool_set(devlink, sb_index, pool_index,
906 size, threshold_type);
907 return -EOPNOTSUPP;
908}
909
910static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
911 struct genl_info *info)
912{
913 struct devlink *devlink = info->user_ptr[0];
914 struct devlink_sb *devlink_sb = info->user_ptr[1];
915 enum devlink_sb_threshold_type threshold_type;
916 u16 pool_index;
917 u32 size;
918 int err;
919
920 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
921 &pool_index);
922 if (err)
923 return err;
924
925 err = devlink_sb_th_type_get_from_info(info, &threshold_type);
926 if (err)
927 return err;
928
929 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
930 return -EINVAL;
931
932 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
933 return devlink_sb_pool_set(devlink, devlink_sb->index,
934 pool_index, size, threshold_type);
935}
936
937static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
938 struct devlink *devlink,
939 struct devlink_port *devlink_port,
940 struct devlink_sb *devlink_sb,
941 u16 pool_index,
942 enum devlink_command cmd,
943 u32 portid, u32 seq, int flags)
944{
945 u32 threshold;
946 void *hdr;
947 int err;
948
949 err = devlink->ops->sb_port_pool_get(devlink_port, devlink_sb->index,
950 pool_index, &threshold);
951 if (err)
952 return err;
953
954 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
955 if (!hdr)
956 return -EMSGSIZE;
957
958 if (devlink_nl_put_handle(msg, devlink))
959 goto nla_put_failure;
960 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
961 goto nla_put_failure;
962 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
963 goto nla_put_failure;
964 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
965 goto nla_put_failure;
966 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
967 goto nla_put_failure;
968
969 genlmsg_end(msg, hdr);
970 return 0;
971
972nla_put_failure:
973 genlmsg_cancel(msg, hdr);
974 return -EMSGSIZE;
975}
976
977static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
978 struct genl_info *info)
979{
980 struct devlink_port *devlink_port = info->user_ptr[0];
981 struct devlink *devlink = devlink_port->devlink;
982 struct devlink_sb *devlink_sb = info->user_ptr[1];
983 struct sk_buff *msg;
984 u16 pool_index;
985 int err;
986
987 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
988 &pool_index);
989 if (err)
990 return err;
991
992 if (!devlink->ops || !devlink->ops->sb_port_pool_get)
993 return -EOPNOTSUPP;
994
995 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
996 if (!msg)
997 return -ENOMEM;
998
999 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1000 devlink_sb, pool_index,
1001 DEVLINK_CMD_SB_PORT_POOL_NEW,
1002 info->snd_portid, info->snd_seq, 0);
1003 if (err) {
1004 nlmsg_free(msg);
1005 return err;
1006 }
1007
1008 return genlmsg_reply(msg, info);
1009}
1010
1011static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1012 struct devlink *devlink,
1013 struct devlink_sb *devlink_sb,
1014 u32 portid, u32 seq)
1015{
1016 struct devlink_port *devlink_port;
1017 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1018 u16 pool_index;
1019 int err;
1020
1021 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1022 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1023 if (*p_idx < start) {
1024 (*p_idx)++;
1025 continue;
1026 }
1027 err = devlink_nl_sb_port_pool_fill(msg, devlink,
1028 devlink_port,
1029 devlink_sb,
1030 pool_index,
1031 DEVLINK_CMD_SB_PORT_POOL_NEW,
1032 portid, seq,
1033 NLM_F_MULTI);
1034 if (err)
1035 return err;
1036 (*p_idx)++;
1037 }
1038 }
1039 return 0;
1040}
1041
1042static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1043 struct netlink_callback *cb)
1044{
1045 struct devlink *devlink;
1046 struct devlink_sb *devlink_sb;
1047 int start = cb->args[0];
1048 int idx = 0;
1049 int err;
1050
1051 mutex_lock(&devlink_mutex);
1052 mutex_lock(&devlink_port_mutex);
1053 list_for_each_entry(devlink, &devlink_list, list) {
1054 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1055 !devlink->ops || !devlink->ops->sb_port_pool_get)
1056 continue;
1057 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1058 err = __sb_port_pool_get_dumpit(msg, start, &idx,
1059 devlink, devlink_sb,
1060 NETLINK_CB(cb->skb).portid,
1061 cb->nlh->nlmsg_seq);
1062 if (err && err != -EOPNOTSUPP)
1063 goto out;
1064 }
1065 }
1066out:
1067 mutex_unlock(&devlink_port_mutex);
1068 mutex_unlock(&devlink_mutex);
1069
1070 cb->args[0] = idx;
1071 return msg->len;
1072}
1073
1074static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1075 unsigned int sb_index, u16 pool_index,
1076 u32 threshold)
1077
1078{
1079 const struct devlink_ops *ops = devlink_port->devlink->ops;
1080
1081 if (ops && ops->sb_port_pool_set)
1082 return ops->sb_port_pool_set(devlink_port, sb_index,
1083 pool_index, threshold);
1084 return -EOPNOTSUPP;
1085}
1086
1087static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1088 struct genl_info *info)
1089{
1090 struct devlink_port *devlink_port = info->user_ptr[0];
1091 struct devlink_sb *devlink_sb = info->user_ptr[1];
1092 u16 pool_index;
1093 u32 threshold;
1094 int err;
1095
1096 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1097 &pool_index);
1098 if (err)
1099 return err;
1100
1101 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1102 return -EINVAL;
1103
1104 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1105 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1106 pool_index, threshold);
1107}
1108
1109static int
1110devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1111 struct devlink_port *devlink_port,
1112 struct devlink_sb *devlink_sb, u16 tc_index,
1113 enum devlink_sb_pool_type pool_type,
1114 enum devlink_command cmd,
1115 u32 portid, u32 seq, int flags)
1116{
1117 u16 pool_index;
1118 u32 threshold;
1119 void *hdr;
1120 int err;
1121
1122 err = devlink->ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1123 tc_index, pool_type,
1124 &pool_index, &threshold);
1125 if (err)
1126 return err;
1127
1128 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1129 if (!hdr)
1130 return -EMSGSIZE;
1131
1132 if (devlink_nl_put_handle(msg, devlink))
1133 goto nla_put_failure;
1134 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1135 goto nla_put_failure;
1136 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1137 goto nla_put_failure;
1138 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1139 goto nla_put_failure;
1140 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1141 goto nla_put_failure;
1142 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1143 goto nla_put_failure;
1144 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1145 goto nla_put_failure;
1146
1147 genlmsg_end(msg, hdr);
1148 return 0;
1149
1150nla_put_failure:
1151 genlmsg_cancel(msg, hdr);
1152 return -EMSGSIZE;
1153}
1154
1155static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1156 struct genl_info *info)
1157{
1158 struct devlink_port *devlink_port = info->user_ptr[0];
1159 struct devlink *devlink = devlink_port->devlink;
1160 struct devlink_sb *devlink_sb = info->user_ptr[1];
1161 struct sk_buff *msg;
1162 enum devlink_sb_pool_type pool_type;
1163 u16 tc_index;
1164 int err;
1165
1166 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1167 if (err)
1168 return err;
1169
1170 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1171 pool_type, &tc_index);
1172 if (err)
1173 return err;
1174
1175 if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get)
1176 return -EOPNOTSUPP;
1177
1178 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1179 if (!msg)
1180 return -ENOMEM;
1181
1182 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1183 devlink_sb, tc_index, pool_type,
1184 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1185 info->snd_portid,
1186 info->snd_seq, 0);
1187 if (err) {
1188 nlmsg_free(msg);
1189 return err;
1190 }
1191
1192 return genlmsg_reply(msg, info);
1193}
1194
1195static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1196 int start, int *p_idx,
1197 struct devlink *devlink,
1198 struct devlink_sb *devlink_sb,
1199 u32 portid, u32 seq)
1200{
1201 struct devlink_port *devlink_port;
1202 u16 tc_index;
1203 int err;
1204
1205 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1206 for (tc_index = 0;
1207 tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1208 if (*p_idx < start) {
1209 (*p_idx)++;
1210 continue;
1211 }
1212 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1213 devlink_port,
1214 devlink_sb,
1215 tc_index,
1216 DEVLINK_SB_POOL_TYPE_INGRESS,
1217 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1218 portid, seq,
1219 NLM_F_MULTI);
1220 if (err)
1221 return err;
1222 (*p_idx)++;
1223 }
1224 for (tc_index = 0;
1225 tc_index < devlink_sb->egress_tc_count; tc_index++) {
1226 if (*p_idx < start) {
1227 (*p_idx)++;
1228 continue;
1229 }
1230 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1231 devlink_port,
1232 devlink_sb,
1233 tc_index,
1234 DEVLINK_SB_POOL_TYPE_EGRESS,
1235 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1236 portid, seq,
1237 NLM_F_MULTI);
1238 if (err)
1239 return err;
1240 (*p_idx)++;
1241 }
1242 }
1243 return 0;
1244}
1245
1246static int
1247devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1248 struct netlink_callback *cb)
1249{
1250 struct devlink *devlink;
1251 struct devlink_sb *devlink_sb;
1252 int start = cb->args[0];
1253 int idx = 0;
1254 int err;
1255
1256 mutex_lock(&devlink_mutex);
1257 mutex_lock(&devlink_port_mutex);
1258 list_for_each_entry(devlink, &devlink_list, list) {
1259 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1260 !devlink->ops || !devlink->ops->sb_tc_pool_bind_get)
1261 continue;
1262 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1263 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1264 devlink,
1265 devlink_sb,
1266 NETLINK_CB(cb->skb).portid,
1267 cb->nlh->nlmsg_seq);
1268 if (err && err != -EOPNOTSUPP)
1269 goto out;
1270 }
1271 }
1272out:
1273 mutex_unlock(&devlink_port_mutex);
1274 mutex_unlock(&devlink_mutex);
1275
1276 cb->args[0] = idx;
1277 return msg->len;
1278}
1279
1280static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1281 unsigned int sb_index, u16 tc_index,
1282 enum devlink_sb_pool_type pool_type,
1283 u16 pool_index, u32 threshold)
1284
1285{
1286 const struct devlink_ops *ops = devlink_port->devlink->ops;
1287
1288 if (ops && ops->sb_tc_pool_bind_set)
1289 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1290 tc_index, pool_type,
1291 pool_index, threshold);
1292 return -EOPNOTSUPP;
1293}
1294
1295static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1296 struct genl_info *info)
1297{
1298 struct devlink_port *devlink_port = info->user_ptr[0];
1299 struct devlink_sb *devlink_sb = info->user_ptr[1];
1300 enum devlink_sb_pool_type pool_type;
1301 u16 tc_index;
1302 u16 pool_index;
1303 u32 threshold;
1304 int err;
1305
1306 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1307 if (err)
1308 return err;
1309
1310 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1311 pool_type, &tc_index);
1312 if (err)
1313 return err;
1314
1315 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1316 &pool_index);
1317 if (err)
1318 return err;
1319
1320 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1321 return -EINVAL;
1322
1323 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1324 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1325 tc_index, pool_type,
1326 pool_index, threshold);
1327}
1328
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001329static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
1330 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
1331 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
1332 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
1333 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
1334 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
Jiri Pirkobf797472016-04-14 18:19:13 +02001335 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
1336 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
1337 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
1338 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
1339 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
1340 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
1341 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001342};
1343
1344static const struct genl_ops devlink_nl_ops[] = {
1345 {
1346 .cmd = DEVLINK_CMD_GET,
1347 .doit = devlink_nl_cmd_get_doit,
1348 .dumpit = devlink_nl_cmd_get_dumpit,
1349 .policy = devlink_nl_policy,
Jiri Pirko1fc22572016-04-08 19:12:48 +02001350 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001351 /* can be retrieved by unprivileged users */
1352 },
1353 {
1354 .cmd = DEVLINK_CMD_PORT_GET,
1355 .doit = devlink_nl_cmd_port_get_doit,
1356 .dumpit = devlink_nl_cmd_port_get_dumpit,
1357 .policy = devlink_nl_policy,
1358 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
1359 /* can be retrieved by unprivileged users */
1360 },
1361 {
1362 .cmd = DEVLINK_CMD_PORT_SET,
1363 .doit = devlink_nl_cmd_port_set_doit,
1364 .policy = devlink_nl_policy,
1365 .flags = GENL_ADMIN_PERM,
1366 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
1367 },
1368 {
1369 .cmd = DEVLINK_CMD_PORT_SPLIT,
1370 .doit = devlink_nl_cmd_port_split_doit,
1371 .policy = devlink_nl_policy,
1372 .flags = GENL_ADMIN_PERM,
Jiri Pirko1fc22572016-04-08 19:12:48 +02001373 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001374 },
1375 {
1376 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
1377 .doit = devlink_nl_cmd_port_unsplit_doit,
1378 .policy = devlink_nl_policy,
1379 .flags = GENL_ADMIN_PERM,
Jiri Pirko1fc22572016-04-08 19:12:48 +02001380 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001381 },
Jiri Pirkobf797472016-04-14 18:19:13 +02001382 {
1383 .cmd = DEVLINK_CMD_SB_GET,
1384 .doit = devlink_nl_cmd_sb_get_doit,
1385 .dumpit = devlink_nl_cmd_sb_get_dumpit,
1386 .policy = devlink_nl_policy,
1387 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1388 DEVLINK_NL_FLAG_NEED_SB,
1389 /* can be retrieved by unprivileged users */
1390 },
1391 {
1392 .cmd = DEVLINK_CMD_SB_POOL_GET,
1393 .doit = devlink_nl_cmd_sb_pool_get_doit,
1394 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
1395 .policy = devlink_nl_policy,
1396 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1397 DEVLINK_NL_FLAG_NEED_SB,
1398 /* can be retrieved by unprivileged users */
1399 },
1400 {
1401 .cmd = DEVLINK_CMD_SB_POOL_SET,
1402 .doit = devlink_nl_cmd_sb_pool_set_doit,
1403 .policy = devlink_nl_policy,
1404 .flags = GENL_ADMIN_PERM,
1405 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1406 DEVLINK_NL_FLAG_NEED_SB,
1407 },
1408 {
1409 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
1410 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
1411 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
1412 .policy = devlink_nl_policy,
1413 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1414 DEVLINK_NL_FLAG_NEED_SB,
1415 /* can be retrieved by unprivileged users */
1416 },
1417 {
1418 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
1419 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
1420 .policy = devlink_nl_policy,
1421 .flags = GENL_ADMIN_PERM,
1422 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1423 DEVLINK_NL_FLAG_NEED_SB,
1424 },
1425 {
1426 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
1427 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
1428 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
1429 .policy = devlink_nl_policy,
1430 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1431 DEVLINK_NL_FLAG_NEED_SB,
1432 /* can be retrieved by unprivileged users */
1433 },
1434 {
1435 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
1436 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
1437 .policy = devlink_nl_policy,
1438 .flags = GENL_ADMIN_PERM,
1439 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1440 DEVLINK_NL_FLAG_NEED_SB,
1441 },
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001442};
1443
1444/**
1445 * devlink_alloc - Allocate new devlink instance resources
1446 *
1447 * @ops: ops
1448 * @priv_size: size of user private data
1449 *
1450 * Allocate new devlink instance resources, including devlink index
1451 * and name.
1452 */
1453struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
1454{
1455 struct devlink *devlink;
1456
1457 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
1458 if (!devlink)
1459 return NULL;
1460 devlink->ops = ops;
1461 devlink_net_set(devlink, &init_net);
1462 INIT_LIST_HEAD(&devlink->port_list);
Jiri Pirkobf797472016-04-14 18:19:13 +02001463 INIT_LIST_HEAD(&devlink->sb_list);
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001464 return devlink;
1465}
1466EXPORT_SYMBOL_GPL(devlink_alloc);
1467
1468/**
1469 * devlink_register - Register devlink instance
1470 *
1471 * @devlink: devlink
1472 */
1473int devlink_register(struct devlink *devlink, struct device *dev)
1474{
1475 mutex_lock(&devlink_mutex);
1476 devlink->dev = dev;
1477 list_add_tail(&devlink->list, &devlink_list);
1478 devlink_notify(devlink, DEVLINK_CMD_NEW);
1479 mutex_unlock(&devlink_mutex);
1480 return 0;
1481}
1482EXPORT_SYMBOL_GPL(devlink_register);
1483
1484/**
1485 * devlink_unregister - Unregister devlink instance
1486 *
1487 * @devlink: devlink
1488 */
1489void devlink_unregister(struct devlink *devlink)
1490{
1491 mutex_lock(&devlink_mutex);
1492 devlink_notify(devlink, DEVLINK_CMD_DEL);
1493 list_del(&devlink->list);
1494 mutex_unlock(&devlink_mutex);
1495}
1496EXPORT_SYMBOL_GPL(devlink_unregister);
1497
1498/**
1499 * devlink_free - Free devlink instance resources
1500 *
1501 * @devlink: devlink
1502 */
1503void devlink_free(struct devlink *devlink)
1504{
1505 kfree(devlink);
1506}
1507EXPORT_SYMBOL_GPL(devlink_free);
1508
1509/**
1510 * devlink_port_register - Register devlink port
1511 *
1512 * @devlink: devlink
1513 * @devlink_port: devlink port
1514 * @port_index
1515 *
1516 * Register devlink port with provided port index. User can use
1517 * any indexing, even hw-related one. devlink_port structure
1518 * is convenient to be embedded inside user driver private structure.
1519 * Note that the caller should take care of zeroing the devlink_port
1520 * structure.
1521 */
1522int devlink_port_register(struct devlink *devlink,
1523 struct devlink_port *devlink_port,
1524 unsigned int port_index)
1525{
1526 mutex_lock(&devlink_port_mutex);
1527 if (devlink_port_index_exists(devlink, port_index)) {
1528 mutex_unlock(&devlink_port_mutex);
1529 return -EEXIST;
1530 }
1531 devlink_port->devlink = devlink;
1532 devlink_port->index = port_index;
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001533 devlink_port->registered = true;
1534 list_add_tail(&devlink_port->list, &devlink->port_list);
1535 mutex_unlock(&devlink_port_mutex);
1536 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1537 return 0;
1538}
1539EXPORT_SYMBOL_GPL(devlink_port_register);
1540
1541/**
1542 * devlink_port_unregister - Unregister devlink port
1543 *
1544 * @devlink_port: devlink port
1545 */
1546void devlink_port_unregister(struct devlink_port *devlink_port)
1547{
1548 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
1549 mutex_lock(&devlink_port_mutex);
1550 list_del(&devlink_port->list);
1551 mutex_unlock(&devlink_port_mutex);
1552}
1553EXPORT_SYMBOL_GPL(devlink_port_unregister);
1554
1555static void __devlink_port_type_set(struct devlink_port *devlink_port,
1556 enum devlink_port_type type,
1557 void *type_dev)
1558{
1559 devlink_port->type = type;
1560 devlink_port->type_dev = type_dev;
1561 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1562}
1563
1564/**
1565 * devlink_port_type_eth_set - Set port type to Ethernet
1566 *
1567 * @devlink_port: devlink port
1568 * @netdev: related netdevice
1569 */
1570void devlink_port_type_eth_set(struct devlink_port *devlink_port,
1571 struct net_device *netdev)
1572{
1573 return __devlink_port_type_set(devlink_port,
1574 DEVLINK_PORT_TYPE_ETH, netdev);
1575}
1576EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
1577
1578/**
1579 * devlink_port_type_ib_set - Set port type to InfiniBand
1580 *
1581 * @devlink_port: devlink port
1582 * @ibdev: related IB device
1583 */
1584void devlink_port_type_ib_set(struct devlink_port *devlink_port,
1585 struct ib_device *ibdev)
1586{
1587 return __devlink_port_type_set(devlink_port,
1588 DEVLINK_PORT_TYPE_IB, ibdev);
1589}
1590EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
1591
1592/**
1593 * devlink_port_type_clear - Clear port type
1594 *
1595 * @devlink_port: devlink port
1596 */
1597void devlink_port_type_clear(struct devlink_port *devlink_port)
1598{
1599 return __devlink_port_type_set(devlink_port,
1600 DEVLINK_PORT_TYPE_NOTSET, NULL);
1601}
1602EXPORT_SYMBOL_GPL(devlink_port_type_clear);
1603
1604/**
1605 * devlink_port_split_set - Set port is split
1606 *
1607 * @devlink_port: devlink port
1608 * @split_group: split group - identifies group split port is part of
1609 */
1610void devlink_port_split_set(struct devlink_port *devlink_port,
1611 u32 split_group)
1612{
1613 devlink_port->split = true;
1614 devlink_port->split_group = split_group;
1615 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1616}
1617EXPORT_SYMBOL_GPL(devlink_port_split_set);
1618
Jiri Pirkobf797472016-04-14 18:19:13 +02001619int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
1620 u32 size, u16 ingress_pools_count,
1621 u16 egress_pools_count, u16 ingress_tc_count,
1622 u16 egress_tc_count)
1623{
1624 struct devlink_sb *devlink_sb;
1625 int err = 0;
1626
1627 mutex_lock(&devlink_mutex);
1628 if (devlink_sb_index_exists(devlink, sb_index)) {
1629 err = -EEXIST;
1630 goto unlock;
1631 }
1632
1633 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
1634 if (!devlink_sb) {
1635 err = -ENOMEM;
1636 goto unlock;
1637 }
1638 devlink_sb->index = sb_index;
1639 devlink_sb->size = size;
1640 devlink_sb->ingress_pools_count = ingress_pools_count;
1641 devlink_sb->egress_pools_count = egress_pools_count;
1642 devlink_sb->ingress_tc_count = ingress_tc_count;
1643 devlink_sb->egress_tc_count = egress_tc_count;
1644 list_add_tail(&devlink_sb->list, &devlink->sb_list);
1645unlock:
1646 mutex_unlock(&devlink_mutex);
1647 return err;
1648}
1649EXPORT_SYMBOL_GPL(devlink_sb_register);
1650
1651void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
1652{
1653 struct devlink_sb *devlink_sb;
1654
1655 mutex_lock(&devlink_mutex);
1656 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
1657 WARN_ON(!devlink_sb);
1658 list_del(&devlink_sb->list);
1659 mutex_unlock(&devlink_mutex);
1660 kfree(devlink_sb);
1661}
1662EXPORT_SYMBOL_GPL(devlink_sb_unregister);
1663
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001664static int __init devlink_module_init(void)
1665{
1666 return genl_register_family_with_ops_groups(&devlink_nl_family,
1667 devlink_nl_ops,
1668 devlink_nl_mcgrps);
1669}
1670
1671static void __exit devlink_module_exit(void)
1672{
1673 genl_unregister_family(&devlink_nl_family);
1674}
1675
1676module_init(devlink_module_init);
1677module_exit(devlink_module_exit);
1678
1679MODULE_LICENSE("GPL v2");
1680MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
1681MODULE_DESCRIPTION("Network physical device Netlink interface");
1682MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);