1
2
3
4
5
6
7
8
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/slab.h>
14#include <linux/gfp.h>
15#include <linux/device.h>
16#include <linux/list.h>
17#include <linux/netdevice.h>
18#include <linux/spinlock.h>
19#include <linux/refcount.h>
20#include <linux/workqueue.h>
21#include <linux/u64_stats_sync.h>
22#include <linux/timekeeping.h>
23#include <rdma/ib_verbs.h>
24#include <net/netlink.h>
25#include <net/genetlink.h>
26#include <net/rtnetlink.h>
27#include <net/net_namespace.h>
28#include <net/sock.h>
29#include <net/devlink.h>
30#include <net/drop_monitor.h>
31#define CREATE_TRACE_POINTS
32#include <trace/events/devlink.h>
33
34static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
35 {
36 .name = "destination mac",
37 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
38 .bitwidth = 48,
39 },
40};
41
42struct devlink_dpipe_header devlink_dpipe_header_ethernet = {
43 .name = "ethernet",
44 .id = DEVLINK_DPIPE_HEADER_ETHERNET,
45 .fields = devlink_dpipe_fields_ethernet,
46 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet),
47 .global = true,
48};
49EXPORT_SYMBOL(devlink_dpipe_header_ethernet);
50
51static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = {
52 {
53 .name = "destination ip",
54 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
55 .bitwidth = 32,
56 },
57};
58
59struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
60 .name = "ipv4",
61 .id = DEVLINK_DPIPE_HEADER_IPV4,
62 .fields = devlink_dpipe_fields_ipv4,
63 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4),
64 .global = true,
65};
66EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
67
68static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
69 {
70 .name = "destination ip",
71 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
72 .bitwidth = 128,
73 },
74};
75
76struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
77 .name = "ipv6",
78 .id = DEVLINK_DPIPE_HEADER_IPV6,
79 .fields = devlink_dpipe_fields_ipv6,
80 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
81 .global = true,
82};
83EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
84
85EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
86EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr);
87
88static LIST_HEAD(devlink_list);
89
90
91
92
93
94
95
96static DEFINE_MUTEX(devlink_mutex);
97
98struct net *devlink_net(const struct devlink *devlink)
99{
100 return read_pnet(&devlink->_net);
101}
102EXPORT_SYMBOL_GPL(devlink_net);
103
104static void __devlink_net_set(struct devlink *devlink, struct net *net)
105{
106 write_pnet(&devlink->_net, net);
107}
108
109void devlink_net_set(struct devlink *devlink, struct net *net)
110{
111 if (WARN_ON(devlink->registered))
112 return;
113 __devlink_net_set(devlink, net);
114}
115EXPORT_SYMBOL_GPL(devlink_net_set);
116
117static struct devlink *devlink_get_from_attrs(struct net *net,
118 struct nlattr **attrs)
119{
120 struct devlink *devlink;
121 char *busname;
122 char *devname;
123
124 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
125 return ERR_PTR(-EINVAL);
126
127 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
128 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
129
130 lockdep_assert_held(&devlink_mutex);
131
132 list_for_each_entry(devlink, &devlink_list, list) {
133 if (strcmp(devlink->dev->bus->name, busname) == 0 &&
134 strcmp(dev_name(devlink->dev), devname) == 0 &&
135 net_eq(devlink_net(devlink), net))
136 return devlink;
137 }
138
139 return ERR_PTR(-ENODEV);
140}
141
142static struct devlink *devlink_get_from_info(struct genl_info *info)
143{
144 return devlink_get_from_attrs(genl_info_net(info), info->attrs);
145}
146
147static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
148 unsigned int port_index)
149{
150 struct devlink_port *devlink_port;
151
152 list_for_each_entry(devlink_port, &devlink->port_list, list) {
153 if (devlink_port->index == port_index)
154 return devlink_port;
155 }
156 return NULL;
157}
158
159static bool devlink_port_index_exists(struct devlink *devlink,
160 unsigned int port_index)
161{
162 return devlink_port_get_by_index(devlink, port_index);
163}
164
165static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
166 struct nlattr **attrs)
167{
168 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
169 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
170 struct devlink_port *devlink_port;
171
172 devlink_port = devlink_port_get_by_index(devlink, port_index);
173 if (!devlink_port)
174 return ERR_PTR(-ENODEV);
175 return devlink_port;
176 }
177 return ERR_PTR(-EINVAL);
178}
179
180static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
181 struct genl_info *info)
182{
183 return devlink_port_get_from_attrs(devlink, info->attrs);
184}
185
186struct devlink_sb {
187 struct list_head list;
188 unsigned int index;
189 u32 size;
190 u16 ingress_pools_count;
191 u16 egress_pools_count;
192 u16 ingress_tc_count;
193 u16 egress_tc_count;
194};
195
196static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
197{
198 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
199}
200
201static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
202 unsigned int sb_index)
203{
204 struct devlink_sb *devlink_sb;
205
206 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
207 if (devlink_sb->index == sb_index)
208 return devlink_sb;
209 }
210 return NULL;
211}
212
213static bool devlink_sb_index_exists(struct devlink *devlink,
214 unsigned int sb_index)
215{
216 return devlink_sb_get_by_index(devlink, sb_index);
217}
218
219static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
220 struct nlattr **attrs)
221{
222 if (attrs[DEVLINK_ATTR_SB_INDEX]) {
223 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
224 struct devlink_sb *devlink_sb;
225
226 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
227 if (!devlink_sb)
228 return ERR_PTR(-ENODEV);
229 return devlink_sb;
230 }
231 return ERR_PTR(-EINVAL);
232}
233
234static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
235 struct genl_info *info)
236{
237 return devlink_sb_get_from_attrs(devlink, info->attrs);
238}
239
240static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
241 struct nlattr **attrs,
242 u16 *p_pool_index)
243{
244 u16 val;
245
246 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
247 return -EINVAL;
248
249 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
250 if (val >= devlink_sb_pool_count(devlink_sb))
251 return -EINVAL;
252 *p_pool_index = val;
253 return 0;
254}
255
256static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
257 struct genl_info *info,
258 u16 *p_pool_index)
259{
260 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
261 p_pool_index);
262}
263
264static int
265devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
266 enum devlink_sb_pool_type *p_pool_type)
267{
268 u8 val;
269
270 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
271 return -EINVAL;
272
273 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
274 if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
275 val != DEVLINK_SB_POOL_TYPE_EGRESS)
276 return -EINVAL;
277 *p_pool_type = val;
278 return 0;
279}
280
281static int
282devlink_sb_pool_type_get_from_info(struct genl_info *info,
283 enum devlink_sb_pool_type *p_pool_type)
284{
285 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
286}
287
288static int
289devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
290 enum devlink_sb_threshold_type *p_th_type)
291{
292 u8 val;
293
294 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
295 return -EINVAL;
296
297 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
298 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
299 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
300 return -EINVAL;
301 *p_th_type = val;
302 return 0;
303}
304
305static int
306devlink_sb_th_type_get_from_info(struct genl_info *info,
307 enum devlink_sb_threshold_type *p_th_type)
308{
309 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
310}
311
312static int
313devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
314 struct nlattr **attrs,
315 enum devlink_sb_pool_type pool_type,
316 u16 *p_tc_index)
317{
318 u16 val;
319
320 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
321 return -EINVAL;
322
323 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
324 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
325 val >= devlink_sb->ingress_tc_count)
326 return -EINVAL;
327 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
328 val >= devlink_sb->egress_tc_count)
329 return -EINVAL;
330 *p_tc_index = val;
331 return 0;
332}
333
334static int
335devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
336 struct genl_info *info,
337 enum devlink_sb_pool_type pool_type,
338 u16 *p_tc_index)
339{
340 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
341 pool_type, p_tc_index);
342}
343
344struct devlink_region {
345 struct devlink *devlink;
346 struct list_head list;
347 const struct devlink_region_ops *ops;
348 struct list_head snapshot_list;
349 u32 max_snapshots;
350 u32 cur_snapshots;
351 u64 size;
352};
353
354struct devlink_snapshot {
355 struct list_head list;
356 struct devlink_region *region;
357 u8 *data;
358 u32 id;
359};
360
361static struct devlink_region *
362devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
363{
364 struct devlink_region *region;
365
366 list_for_each_entry(region, &devlink->region_list, list)
367 if (!strcmp(region->ops->name, region_name))
368 return region;
369
370 return NULL;
371}
372
373static struct devlink_snapshot *
374devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
375{
376 struct devlink_snapshot *snapshot;
377
378 list_for_each_entry(snapshot, ®ion->snapshot_list, list)
379 if (snapshot->id == id)
380 return snapshot;
381
382 return NULL;
383}
384
385#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
386#define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
387#define DEVLINK_NL_FLAG_NEED_SB BIT(2)
388
389
390
391
392
393#define DEVLINK_NL_FLAG_NO_LOCK BIT(3)
394
395static int devlink_nl_pre_doit(const struct genl_ops *ops,
396 struct sk_buff *skb, struct genl_info *info)
397{
398 struct devlink *devlink;
399 int err;
400
401 mutex_lock(&devlink_mutex);
402 devlink = devlink_get_from_info(info);
403 if (IS_ERR(devlink)) {
404 mutex_unlock(&devlink_mutex);
405 return PTR_ERR(devlink);
406 }
407 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
408 mutex_lock(&devlink->lock);
409 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
410 info->user_ptr[0] = devlink;
411 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
412 struct devlink_port *devlink_port;
413
414 devlink_port = devlink_port_get_from_info(devlink, info);
415 if (IS_ERR(devlink_port)) {
416 err = PTR_ERR(devlink_port);
417 goto unlock;
418 }
419 info->user_ptr[0] = devlink_port;
420 }
421 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
422 struct devlink_sb *devlink_sb;
423
424 devlink_sb = devlink_sb_get_from_info(devlink, info);
425 if (IS_ERR(devlink_sb)) {
426 err = PTR_ERR(devlink_sb);
427 goto unlock;
428 }
429 info->user_ptr[1] = devlink_sb;
430 }
431 return 0;
432
433unlock:
434 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
435 mutex_unlock(&devlink->lock);
436 mutex_unlock(&devlink_mutex);
437 return err;
438}
439
440static void devlink_nl_post_doit(const struct genl_ops *ops,
441 struct sk_buff *skb, struct genl_info *info)
442{
443 struct devlink *devlink;
444
445
446
447
448 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
449 devlink = info->user_ptr[0];
450 } else {
451 devlink = devlink_get_from_info(info);
452 WARN_ON(IS_ERR(devlink));
453 }
454 if (!IS_ERR(devlink) && ~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
455 mutex_unlock(&devlink->lock);
456 mutex_unlock(&devlink_mutex);
457}
458
459static struct genl_family devlink_nl_family;
460
461enum devlink_multicast_groups {
462 DEVLINK_MCGRP_CONFIG,
463};
464
465static const struct genl_multicast_group devlink_nl_mcgrps[] = {
466 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
467};
468
469static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
470{
471 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
472 return -EMSGSIZE;
473 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
474 return -EMSGSIZE;
475 return 0;
476}
477
478static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
479 enum devlink_command cmd, u32 portid,
480 u32 seq, int flags)
481{
482 void *hdr;
483
484 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
485 if (!hdr)
486 return -EMSGSIZE;
487
488 if (devlink_nl_put_handle(msg, devlink))
489 goto nla_put_failure;
490 if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed))
491 goto nla_put_failure;
492
493 genlmsg_end(msg, hdr);
494 return 0;
495
496nla_put_failure:
497 genlmsg_cancel(msg, hdr);
498 return -EMSGSIZE;
499}
500
501static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
502{
503 struct sk_buff *msg;
504 int err;
505
506 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
507
508 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
509 if (!msg)
510 return;
511
512 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
513 if (err) {
514 nlmsg_free(msg);
515 return;
516 }
517
518 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
519 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
520}
521
522static int devlink_nl_port_attrs_put(struct sk_buff *msg,
523 struct devlink_port *devlink_port)
524{
525 struct devlink_port_attrs *attrs = &devlink_port->attrs;
526
527 if (!attrs->set)
528 return 0;
529 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
530 return -EMSGSIZE;
531 switch (devlink_port->attrs.flavour) {
532 case DEVLINK_PORT_FLAVOUR_PCI_PF:
533 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
534 attrs->pci_pf.pf))
535 return -EMSGSIZE;
536 break;
537 case DEVLINK_PORT_FLAVOUR_PCI_VF:
538 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
539 attrs->pci_vf.pf) ||
540 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER,
541 attrs->pci_vf.vf))
542 return -EMSGSIZE;
543 break;
544 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
545 case DEVLINK_PORT_FLAVOUR_CPU:
546 case DEVLINK_PORT_FLAVOUR_DSA:
547 case DEVLINK_PORT_FLAVOUR_VIRTUAL:
548 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER,
549 attrs->phys.port_number))
550 return -EMSGSIZE;
551 if (!attrs->split)
552 return 0;
553 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
554 attrs->phys.port_number))
555 return -EMSGSIZE;
556 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
557 attrs->phys.split_subport_number))
558 return -EMSGSIZE;
559 break;
560 default:
561 break;
562 }
563 return 0;
564}
565
566static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
567 struct devlink_port *devlink_port,
568 enum devlink_command cmd, u32 portid,
569 u32 seq, int flags)
570{
571 void *hdr;
572
573 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
574 if (!hdr)
575 return -EMSGSIZE;
576
577 if (devlink_nl_put_handle(msg, devlink))
578 goto nla_put_failure;
579 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
580 goto nla_put_failure;
581
582 spin_lock_bh(&devlink_port->type_lock);
583 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
584 goto nla_put_failure_type_locked;
585 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
586 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
587 devlink_port->desired_type))
588 goto nla_put_failure_type_locked;
589 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
590 struct net_device *netdev = devlink_port->type_dev;
591
592 if (netdev &&
593 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
594 netdev->ifindex) ||
595 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
596 netdev->name)))
597 goto nla_put_failure_type_locked;
598 }
599 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
600 struct ib_device *ibdev = devlink_port->type_dev;
601
602 if (ibdev &&
603 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
604 ibdev->name))
605 goto nla_put_failure_type_locked;
606 }
607 spin_unlock_bh(&devlink_port->type_lock);
608 if (devlink_nl_port_attrs_put(msg, devlink_port))
609 goto nla_put_failure;
610
611 genlmsg_end(msg, hdr);
612 return 0;
613
614nla_put_failure_type_locked:
615 spin_unlock_bh(&devlink_port->type_lock);
616nla_put_failure:
617 genlmsg_cancel(msg, hdr);
618 return -EMSGSIZE;
619}
620
621static void devlink_port_notify(struct devlink_port *devlink_port,
622 enum devlink_command cmd)
623{
624 struct devlink *devlink = devlink_port->devlink;
625 struct sk_buff *msg;
626 int err;
627
628 if (!devlink_port->registered)
629 return;
630
631 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
632
633 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
634 if (!msg)
635 return;
636
637 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
638 if (err) {
639 nlmsg_free(msg);
640 return;
641 }
642
643 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
644 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
645}
646
647static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
648{
649 struct devlink *devlink = info->user_ptr[0];
650 struct sk_buff *msg;
651 int err;
652
653 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
654 if (!msg)
655 return -ENOMEM;
656
657 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
658 info->snd_portid, info->snd_seq, 0);
659 if (err) {
660 nlmsg_free(msg);
661 return err;
662 }
663
664 return genlmsg_reply(msg, info);
665}
666
667static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
668 struct netlink_callback *cb)
669{
670 struct devlink *devlink;
671 int start = cb->args[0];
672 int idx = 0;
673 int err;
674
675 mutex_lock(&devlink_mutex);
676 list_for_each_entry(devlink, &devlink_list, list) {
677 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
678 continue;
679 if (idx < start) {
680 idx++;
681 continue;
682 }
683 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
684 NETLINK_CB(cb->skb).portid,
685 cb->nlh->nlmsg_seq, NLM_F_MULTI);
686 if (err)
687 goto out;
688 idx++;
689 }
690out:
691 mutex_unlock(&devlink_mutex);
692
693 cb->args[0] = idx;
694 return msg->len;
695}
696
697static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
698 struct genl_info *info)
699{
700 struct devlink_port *devlink_port = info->user_ptr[0];
701 struct devlink *devlink = devlink_port->devlink;
702 struct sk_buff *msg;
703 int err;
704
705 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
706 if (!msg)
707 return -ENOMEM;
708
709 err = devlink_nl_port_fill(msg, devlink, devlink_port,
710 DEVLINK_CMD_PORT_NEW,
711 info->snd_portid, info->snd_seq, 0);
712 if (err) {
713 nlmsg_free(msg);
714 return err;
715 }
716
717 return genlmsg_reply(msg, info);
718}
719
720static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
721 struct netlink_callback *cb)
722{
723 struct devlink *devlink;
724 struct devlink_port *devlink_port;
725 int start = cb->args[0];
726 int idx = 0;
727 int err;
728
729 mutex_lock(&devlink_mutex);
730 list_for_each_entry(devlink, &devlink_list, list) {
731 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
732 continue;
733 mutex_lock(&devlink->lock);
734 list_for_each_entry(devlink_port, &devlink->port_list, list) {
735 if (idx < start) {
736 idx++;
737 continue;
738 }
739 err = devlink_nl_port_fill(msg, devlink, devlink_port,
740 DEVLINK_CMD_NEW,
741 NETLINK_CB(cb->skb).portid,
742 cb->nlh->nlmsg_seq,
743 NLM_F_MULTI);
744 if (err) {
745 mutex_unlock(&devlink->lock);
746 goto out;
747 }
748 idx++;
749 }
750 mutex_unlock(&devlink->lock);
751 }
752out:
753 mutex_unlock(&devlink_mutex);
754
755 cb->args[0] = idx;
756 return msg->len;
757}
758
759static int devlink_port_type_set(struct devlink *devlink,
760 struct devlink_port *devlink_port,
761 enum devlink_port_type port_type)
762
763{
764 int err;
765
766 if (devlink->ops->port_type_set) {
767 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
768 return -EINVAL;
769 if (port_type == devlink_port->type)
770 return 0;
771 err = devlink->ops->port_type_set(devlink_port, port_type);
772 if (err)
773 return err;
774 devlink_port->desired_type = port_type;
775 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
776 return 0;
777 }
778 return -EOPNOTSUPP;
779}
780
781static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
782 struct genl_info *info)
783{
784 struct devlink_port *devlink_port = info->user_ptr[0];
785 struct devlink *devlink = devlink_port->devlink;
786 int err;
787
788 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
789 enum devlink_port_type port_type;
790
791 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
792 err = devlink_port_type_set(devlink, devlink_port, port_type);
793 if (err)
794 return err;
795 }
796 return 0;
797}
798
799static int devlink_port_split(struct devlink *devlink, u32 port_index,
800 u32 count, struct netlink_ext_ack *extack)
801
802{
803 if (devlink->ops->port_split)
804 return devlink->ops->port_split(devlink, port_index, count,
805 extack);
806 return -EOPNOTSUPP;
807}
808
809static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
810 struct genl_info *info)
811{
812 struct devlink *devlink = info->user_ptr[0];
813 u32 port_index;
814 u32 count;
815
816 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
817 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
818 return -EINVAL;
819
820 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
821 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
822 return devlink_port_split(devlink, port_index, count, info->extack);
823}
824
825static int devlink_port_unsplit(struct devlink *devlink, u32 port_index,
826 struct netlink_ext_ack *extack)
827
828{
829 if (devlink->ops->port_unsplit)
830 return devlink->ops->port_unsplit(devlink, port_index, extack);
831 return -EOPNOTSUPP;
832}
833
834static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
835 struct genl_info *info)
836{
837 struct devlink *devlink = info->user_ptr[0];
838 u32 port_index;
839
840 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
841 return -EINVAL;
842
843 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
844 return devlink_port_unsplit(devlink, port_index, info->extack);
845}
846
847static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
848 struct devlink_sb *devlink_sb,
849 enum devlink_command cmd, u32 portid,
850 u32 seq, int flags)
851{
852 void *hdr;
853
854 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
855 if (!hdr)
856 return -EMSGSIZE;
857
858 if (devlink_nl_put_handle(msg, devlink))
859 goto nla_put_failure;
860 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
861 goto nla_put_failure;
862 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
863 goto nla_put_failure;
864 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
865 devlink_sb->ingress_pools_count))
866 goto nla_put_failure;
867 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
868 devlink_sb->egress_pools_count))
869 goto nla_put_failure;
870 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
871 devlink_sb->ingress_tc_count))
872 goto nla_put_failure;
873 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
874 devlink_sb->egress_tc_count))
875 goto nla_put_failure;
876
877 genlmsg_end(msg, hdr);
878 return 0;
879
880nla_put_failure:
881 genlmsg_cancel(msg, hdr);
882 return -EMSGSIZE;
883}
884
885static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
886 struct genl_info *info)
887{
888 struct devlink *devlink = info->user_ptr[0];
889 struct devlink_sb *devlink_sb = info->user_ptr[1];
890 struct sk_buff *msg;
891 int err;
892
893 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
894 if (!msg)
895 return -ENOMEM;
896
897 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
898 DEVLINK_CMD_SB_NEW,
899 info->snd_portid, info->snd_seq, 0);
900 if (err) {
901 nlmsg_free(msg);
902 return err;
903 }
904
905 return genlmsg_reply(msg, info);
906}
907
908static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
909 struct netlink_callback *cb)
910{
911 struct devlink *devlink;
912 struct devlink_sb *devlink_sb;
913 int start = cb->args[0];
914 int idx = 0;
915 int err;
916
917 mutex_lock(&devlink_mutex);
918 list_for_each_entry(devlink, &devlink_list, list) {
919 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
920 continue;
921 mutex_lock(&devlink->lock);
922 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
923 if (idx < start) {
924 idx++;
925 continue;
926 }
927 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
928 DEVLINK_CMD_SB_NEW,
929 NETLINK_CB(cb->skb).portid,
930 cb->nlh->nlmsg_seq,
931 NLM_F_MULTI);
932 if (err) {
933 mutex_unlock(&devlink->lock);
934 goto out;
935 }
936 idx++;
937 }
938 mutex_unlock(&devlink->lock);
939 }
940out:
941 mutex_unlock(&devlink_mutex);
942
943 cb->args[0] = idx;
944 return msg->len;
945}
946
947static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
948 struct devlink_sb *devlink_sb,
949 u16 pool_index, enum devlink_command cmd,
950 u32 portid, u32 seq, int flags)
951{
952 struct devlink_sb_pool_info pool_info;
953 void *hdr;
954 int err;
955
956 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
957 pool_index, &pool_info);
958 if (err)
959 return err;
960
961 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
962 if (!hdr)
963 return -EMSGSIZE;
964
965 if (devlink_nl_put_handle(msg, devlink))
966 goto nla_put_failure;
967 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
968 goto nla_put_failure;
969 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
970 goto nla_put_failure;
971 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
972 goto nla_put_failure;
973 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
974 goto nla_put_failure;
975 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
976 pool_info.threshold_type))
977 goto nla_put_failure;
978 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
979 pool_info.cell_size))
980 goto nla_put_failure;
981
982 genlmsg_end(msg, hdr);
983 return 0;
984
985nla_put_failure:
986 genlmsg_cancel(msg, hdr);
987 return -EMSGSIZE;
988}
989
990static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
991 struct genl_info *info)
992{
993 struct devlink *devlink = info->user_ptr[0];
994 struct devlink_sb *devlink_sb = info->user_ptr[1];
995 struct sk_buff *msg;
996 u16 pool_index;
997 int err;
998
999 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1000 &pool_index);
1001 if (err)
1002 return err;
1003
1004 if (!devlink->ops->sb_pool_get)
1005 return -EOPNOTSUPP;
1006
1007 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1008 if (!msg)
1009 return -ENOMEM;
1010
1011 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
1012 DEVLINK_CMD_SB_POOL_NEW,
1013 info->snd_portid, info->snd_seq, 0);
1014 if (err) {
1015 nlmsg_free(msg);
1016 return err;
1017 }
1018
1019 return genlmsg_reply(msg, info);
1020}
1021
1022static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1023 struct devlink *devlink,
1024 struct devlink_sb *devlink_sb,
1025 u32 portid, u32 seq)
1026{
1027 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1028 u16 pool_index;
1029 int err;
1030
1031 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1032 if (*p_idx < start) {
1033 (*p_idx)++;
1034 continue;
1035 }
1036 err = devlink_nl_sb_pool_fill(msg, devlink,
1037 devlink_sb,
1038 pool_index,
1039 DEVLINK_CMD_SB_POOL_NEW,
1040 portid, seq, NLM_F_MULTI);
1041 if (err)
1042 return err;
1043 (*p_idx)++;
1044 }
1045 return 0;
1046}
1047
1048static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
1049 struct netlink_callback *cb)
1050{
1051 struct devlink *devlink;
1052 struct devlink_sb *devlink_sb;
1053 int start = cb->args[0];
1054 int idx = 0;
1055 int err = 0;
1056
1057 mutex_lock(&devlink_mutex);
1058 list_for_each_entry(devlink, &devlink_list, list) {
1059 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1060 !devlink->ops->sb_pool_get)
1061 continue;
1062 mutex_lock(&devlink->lock);
1063 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1064 err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
1065 devlink_sb,
1066 NETLINK_CB(cb->skb).portid,
1067 cb->nlh->nlmsg_seq);
1068 if (err == -EOPNOTSUPP) {
1069 err = 0;
1070 } else if (err) {
1071 mutex_unlock(&devlink->lock);
1072 goto out;
1073 }
1074 }
1075 mutex_unlock(&devlink->lock);
1076 }
1077out:
1078 mutex_unlock(&devlink_mutex);
1079
1080 if (err != -EMSGSIZE)
1081 return err;
1082
1083 cb->args[0] = idx;
1084 return msg->len;
1085}
1086
1087static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
1088 u16 pool_index, u32 size,
1089 enum devlink_sb_threshold_type threshold_type,
1090 struct netlink_ext_ack *extack)
1091
1092{
1093 const struct devlink_ops *ops = devlink->ops;
1094
1095 if (ops->sb_pool_set)
1096 return ops->sb_pool_set(devlink, sb_index, pool_index,
1097 size, threshold_type, extack);
1098 return -EOPNOTSUPP;
1099}
1100
1101static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
1102 struct genl_info *info)
1103{
1104 struct devlink *devlink = info->user_ptr[0];
1105 struct devlink_sb *devlink_sb = info->user_ptr[1];
1106 enum devlink_sb_threshold_type threshold_type;
1107 u16 pool_index;
1108 u32 size;
1109 int err;
1110
1111 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1112 &pool_index);
1113 if (err)
1114 return err;
1115
1116 err = devlink_sb_th_type_get_from_info(info, &threshold_type);
1117 if (err)
1118 return err;
1119
1120 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
1121 return -EINVAL;
1122
1123 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
1124 return devlink_sb_pool_set(devlink, devlink_sb->index,
1125 pool_index, size, threshold_type,
1126 info->extack);
1127}
1128
1129static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
1130 struct devlink *devlink,
1131 struct devlink_port *devlink_port,
1132 struct devlink_sb *devlink_sb,
1133 u16 pool_index,
1134 enum devlink_command cmd,
1135 u32 portid, u32 seq, int flags)
1136{
1137 const struct devlink_ops *ops = devlink->ops;
1138 u32 threshold;
1139 void *hdr;
1140 int err;
1141
1142 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
1143 pool_index, &threshold);
1144 if (err)
1145 return err;
1146
1147 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1148 if (!hdr)
1149 return -EMSGSIZE;
1150
1151 if (devlink_nl_put_handle(msg, devlink))
1152 goto nla_put_failure;
1153 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1154 goto nla_put_failure;
1155 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1156 goto nla_put_failure;
1157 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1158 goto nla_put_failure;
1159 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1160 goto nla_put_failure;
1161
1162 if (ops->sb_occ_port_pool_get) {
1163 u32 cur;
1164 u32 max;
1165
1166 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
1167 pool_index, &cur, &max);
1168 if (err && err != -EOPNOTSUPP)
1169 return err;
1170 if (!err) {
1171 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1172 goto nla_put_failure;
1173 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1174 goto nla_put_failure;
1175 }
1176 }
1177
1178 genlmsg_end(msg, hdr);
1179 return 0;
1180
1181nla_put_failure:
1182 genlmsg_cancel(msg, hdr);
1183 return -EMSGSIZE;
1184}
1185
1186static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1187 struct genl_info *info)
1188{
1189 struct devlink_port *devlink_port = info->user_ptr[0];
1190 struct devlink *devlink = devlink_port->devlink;
1191 struct devlink_sb *devlink_sb = info->user_ptr[1];
1192 struct sk_buff *msg;
1193 u16 pool_index;
1194 int err;
1195
1196 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1197 &pool_index);
1198 if (err)
1199 return err;
1200
1201 if (!devlink->ops->sb_port_pool_get)
1202 return -EOPNOTSUPP;
1203
1204 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1205 if (!msg)
1206 return -ENOMEM;
1207
1208 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1209 devlink_sb, pool_index,
1210 DEVLINK_CMD_SB_PORT_POOL_NEW,
1211 info->snd_portid, info->snd_seq, 0);
1212 if (err) {
1213 nlmsg_free(msg);
1214 return err;
1215 }
1216
1217 return genlmsg_reply(msg, info);
1218}
1219
1220static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1221 struct devlink *devlink,
1222 struct devlink_sb *devlink_sb,
1223 u32 portid, u32 seq)
1224{
1225 struct devlink_port *devlink_port;
1226 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1227 u16 pool_index;
1228 int err;
1229
1230 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1231 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1232 if (*p_idx < start) {
1233 (*p_idx)++;
1234 continue;
1235 }
1236 err = devlink_nl_sb_port_pool_fill(msg, devlink,
1237 devlink_port,
1238 devlink_sb,
1239 pool_index,
1240 DEVLINK_CMD_SB_PORT_POOL_NEW,
1241 portid, seq,
1242 NLM_F_MULTI);
1243 if (err)
1244 return err;
1245 (*p_idx)++;
1246 }
1247 }
1248 return 0;
1249}
1250
1251static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1252 struct netlink_callback *cb)
1253{
1254 struct devlink *devlink;
1255 struct devlink_sb *devlink_sb;
1256 int start = cb->args[0];
1257 int idx = 0;
1258 int err = 0;
1259
1260 mutex_lock(&devlink_mutex);
1261 list_for_each_entry(devlink, &devlink_list, list) {
1262 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1263 !devlink->ops->sb_port_pool_get)
1264 continue;
1265 mutex_lock(&devlink->lock);
1266 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1267 err = __sb_port_pool_get_dumpit(msg, start, &idx,
1268 devlink, devlink_sb,
1269 NETLINK_CB(cb->skb).portid,
1270 cb->nlh->nlmsg_seq);
1271 if (err == -EOPNOTSUPP) {
1272 err = 0;
1273 } else if (err) {
1274 mutex_unlock(&devlink->lock);
1275 goto out;
1276 }
1277 }
1278 mutex_unlock(&devlink->lock);
1279 }
1280out:
1281 mutex_unlock(&devlink_mutex);
1282
1283 if (err != -EMSGSIZE)
1284 return err;
1285
1286 cb->args[0] = idx;
1287 return msg->len;
1288}
1289
1290static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1291 unsigned int sb_index, u16 pool_index,
1292 u32 threshold,
1293 struct netlink_ext_ack *extack)
1294
1295{
1296 const struct devlink_ops *ops = devlink_port->devlink->ops;
1297
1298 if (ops->sb_port_pool_set)
1299 return ops->sb_port_pool_set(devlink_port, sb_index,
1300 pool_index, threshold, extack);
1301 return -EOPNOTSUPP;
1302}
1303
1304static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1305 struct genl_info *info)
1306{
1307 struct devlink_port *devlink_port = info->user_ptr[0];
1308 struct devlink_sb *devlink_sb = info->user_ptr[1];
1309 u16 pool_index;
1310 u32 threshold;
1311 int err;
1312
1313 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1314 &pool_index);
1315 if (err)
1316 return err;
1317
1318 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1319 return -EINVAL;
1320
1321 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1322 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1323 pool_index, threshold, info->extack);
1324}
1325
1326static int
1327devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1328 struct devlink_port *devlink_port,
1329 struct devlink_sb *devlink_sb, u16 tc_index,
1330 enum devlink_sb_pool_type pool_type,
1331 enum devlink_command cmd,
1332 u32 portid, u32 seq, int flags)
1333{
1334 const struct devlink_ops *ops = devlink->ops;
1335 u16 pool_index;
1336 u32 threshold;
1337 void *hdr;
1338 int err;
1339
1340 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1341 tc_index, pool_type,
1342 &pool_index, &threshold);
1343 if (err)
1344 return err;
1345
1346 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1347 if (!hdr)
1348 return -EMSGSIZE;
1349
1350 if (devlink_nl_put_handle(msg, devlink))
1351 goto nla_put_failure;
1352 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1353 goto nla_put_failure;
1354 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1355 goto nla_put_failure;
1356 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1357 goto nla_put_failure;
1358 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1359 goto nla_put_failure;
1360 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1361 goto nla_put_failure;
1362 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1363 goto nla_put_failure;
1364
1365 if (ops->sb_occ_tc_port_bind_get) {
1366 u32 cur;
1367 u32 max;
1368
1369 err = ops->sb_occ_tc_port_bind_get(devlink_port,
1370 devlink_sb->index,
1371 tc_index, pool_type,
1372 &cur, &max);
1373 if (err && err != -EOPNOTSUPP)
1374 return err;
1375 if (!err) {
1376 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1377 goto nla_put_failure;
1378 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1379 goto nla_put_failure;
1380 }
1381 }
1382
1383 genlmsg_end(msg, hdr);
1384 return 0;
1385
1386nla_put_failure:
1387 genlmsg_cancel(msg, hdr);
1388 return -EMSGSIZE;
1389}
1390
1391static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1392 struct genl_info *info)
1393{
1394 struct devlink_port *devlink_port = info->user_ptr[0];
1395 struct devlink *devlink = devlink_port->devlink;
1396 struct devlink_sb *devlink_sb = info->user_ptr[1];
1397 struct sk_buff *msg;
1398 enum devlink_sb_pool_type pool_type;
1399 u16 tc_index;
1400 int err;
1401
1402 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1403 if (err)
1404 return err;
1405
1406 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1407 pool_type, &tc_index);
1408 if (err)
1409 return err;
1410
1411 if (!devlink->ops->sb_tc_pool_bind_get)
1412 return -EOPNOTSUPP;
1413
1414 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1415 if (!msg)
1416 return -ENOMEM;
1417
1418 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1419 devlink_sb, tc_index, pool_type,
1420 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1421 info->snd_portid,
1422 info->snd_seq, 0);
1423 if (err) {
1424 nlmsg_free(msg);
1425 return err;
1426 }
1427
1428 return genlmsg_reply(msg, info);
1429}
1430
1431static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1432 int start, int *p_idx,
1433 struct devlink *devlink,
1434 struct devlink_sb *devlink_sb,
1435 u32 portid, u32 seq)
1436{
1437 struct devlink_port *devlink_port;
1438 u16 tc_index;
1439 int err;
1440
1441 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1442 for (tc_index = 0;
1443 tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1444 if (*p_idx < start) {
1445 (*p_idx)++;
1446 continue;
1447 }
1448 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1449 devlink_port,
1450 devlink_sb,
1451 tc_index,
1452 DEVLINK_SB_POOL_TYPE_INGRESS,
1453 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1454 portid, seq,
1455 NLM_F_MULTI);
1456 if (err)
1457 return err;
1458 (*p_idx)++;
1459 }
1460 for (tc_index = 0;
1461 tc_index < devlink_sb->egress_tc_count; tc_index++) {
1462 if (*p_idx < start) {
1463 (*p_idx)++;
1464 continue;
1465 }
1466 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1467 devlink_port,
1468 devlink_sb,
1469 tc_index,
1470 DEVLINK_SB_POOL_TYPE_EGRESS,
1471 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1472 portid, seq,
1473 NLM_F_MULTI);
1474 if (err)
1475 return err;
1476 (*p_idx)++;
1477 }
1478 }
1479 return 0;
1480}
1481
1482static int
1483devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1484 struct netlink_callback *cb)
1485{
1486 struct devlink *devlink;
1487 struct devlink_sb *devlink_sb;
1488 int start = cb->args[0];
1489 int idx = 0;
1490 int err = 0;
1491
1492 mutex_lock(&devlink_mutex);
1493 list_for_each_entry(devlink, &devlink_list, list) {
1494 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1495 !devlink->ops->sb_tc_pool_bind_get)
1496 continue;
1497
1498 mutex_lock(&devlink->lock);
1499 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1500 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1501 devlink,
1502 devlink_sb,
1503 NETLINK_CB(cb->skb).portid,
1504 cb->nlh->nlmsg_seq);
1505 if (err == -EOPNOTSUPP) {
1506 err = 0;
1507 } else if (err) {
1508 mutex_unlock(&devlink->lock);
1509 goto out;
1510 }
1511 }
1512 mutex_unlock(&devlink->lock);
1513 }
1514out:
1515 mutex_unlock(&devlink_mutex);
1516
1517 if (err != -EMSGSIZE)
1518 return err;
1519
1520 cb->args[0] = idx;
1521 return msg->len;
1522}
1523
1524static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1525 unsigned int sb_index, u16 tc_index,
1526 enum devlink_sb_pool_type pool_type,
1527 u16 pool_index, u32 threshold,
1528 struct netlink_ext_ack *extack)
1529
1530{
1531 const struct devlink_ops *ops = devlink_port->devlink->ops;
1532
1533 if (ops->sb_tc_pool_bind_set)
1534 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1535 tc_index, pool_type,
1536 pool_index, threshold, extack);
1537 return -EOPNOTSUPP;
1538}
1539
1540static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1541 struct genl_info *info)
1542{
1543 struct devlink_port *devlink_port = info->user_ptr[0];
1544 struct devlink_sb *devlink_sb = info->user_ptr[1];
1545 enum devlink_sb_pool_type pool_type;
1546 u16 tc_index;
1547 u16 pool_index;
1548 u32 threshold;
1549 int err;
1550
1551 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1552 if (err)
1553 return err;
1554
1555 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1556 pool_type, &tc_index);
1557 if (err)
1558 return err;
1559
1560 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1561 &pool_index);
1562 if (err)
1563 return err;
1564
1565 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1566 return -EINVAL;
1567
1568 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1569 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1570 tc_index, pool_type,
1571 pool_index, threshold, info->extack);
1572}
1573
1574static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1575 struct genl_info *info)
1576{
1577 struct devlink *devlink = info->user_ptr[0];
1578 struct devlink_sb *devlink_sb = info->user_ptr[1];
1579 const struct devlink_ops *ops = devlink->ops;
1580
1581 if (ops->sb_occ_snapshot)
1582 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1583 return -EOPNOTSUPP;
1584}
1585
1586static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1587 struct genl_info *info)
1588{
1589 struct devlink *devlink = info->user_ptr[0];
1590 struct devlink_sb *devlink_sb = info->user_ptr[1];
1591 const struct devlink_ops *ops = devlink->ops;
1592
1593 if (ops->sb_occ_max_clear)
1594 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1595 return -EOPNOTSUPP;
1596}
1597
1598static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
1599 enum devlink_command cmd, u32 portid,
1600 u32 seq, int flags)
1601{
1602 const struct devlink_ops *ops = devlink->ops;
1603 enum devlink_eswitch_encap_mode encap_mode;
1604 u8 inline_mode;
1605 void *hdr;
1606 int err = 0;
1607 u16 mode;
1608
1609 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1610 if (!hdr)
1611 return -EMSGSIZE;
1612
1613 err = devlink_nl_put_handle(msg, devlink);
1614 if (err)
1615 goto nla_put_failure;
1616
1617 if (ops->eswitch_mode_get) {
1618 err = ops->eswitch_mode_get(devlink, &mode);
1619 if (err)
1620 goto nla_put_failure;
1621 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
1622 if (err)
1623 goto nla_put_failure;
1624 }
1625
1626 if (ops->eswitch_inline_mode_get) {
1627 err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
1628 if (err)
1629 goto nla_put_failure;
1630 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
1631 inline_mode);
1632 if (err)
1633 goto nla_put_failure;
1634 }
1635
1636 if (ops->eswitch_encap_mode_get) {
1637 err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
1638 if (err)
1639 goto nla_put_failure;
1640 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
1641 if (err)
1642 goto nla_put_failure;
1643 }
1644
1645 genlmsg_end(msg, hdr);
1646 return 0;
1647
1648nla_put_failure:
1649 genlmsg_cancel(msg, hdr);
1650 return err;
1651}
1652
1653static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb,
1654 struct genl_info *info)
1655{
1656 struct devlink *devlink = info->user_ptr[0];
1657 struct sk_buff *msg;
1658 int err;
1659
1660 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1661 if (!msg)
1662 return -ENOMEM;
1663
1664 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
1665 info->snd_portid, info->snd_seq, 0);
1666
1667 if (err) {
1668 nlmsg_free(msg);
1669 return err;
1670 }
1671
1672 return genlmsg_reply(msg, info);
1673}
1674
1675static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
1676 struct genl_info *info)
1677{
1678 struct devlink *devlink = info->user_ptr[0];
1679 const struct devlink_ops *ops = devlink->ops;
1680 enum devlink_eswitch_encap_mode encap_mode;
1681 u8 inline_mode;
1682 int err = 0;
1683 u16 mode;
1684
1685 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
1686 if (!ops->eswitch_mode_set)
1687 return -EOPNOTSUPP;
1688 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
1689 err = ops->eswitch_mode_set(devlink, mode, info->extack);
1690 if (err)
1691 return err;
1692 }
1693
1694 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
1695 if (!ops->eswitch_inline_mode_set)
1696 return -EOPNOTSUPP;
1697 inline_mode = nla_get_u8(
1698 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
1699 err = ops->eswitch_inline_mode_set(devlink, inline_mode,
1700 info->extack);
1701 if (err)
1702 return err;
1703 }
1704
1705 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
1706 if (!ops->eswitch_encap_mode_set)
1707 return -EOPNOTSUPP;
1708 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
1709 err = ops->eswitch_encap_mode_set(devlink, encap_mode,
1710 info->extack);
1711 if (err)
1712 return err;
1713 }
1714
1715 return 0;
1716}
1717
1718int devlink_dpipe_match_put(struct sk_buff *skb,
1719 struct devlink_dpipe_match *match)
1720{
1721 struct devlink_dpipe_header *header = match->header;
1722 struct devlink_dpipe_field *field = &header->fields[match->field_id];
1723 struct nlattr *match_attr;
1724
1725 match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH);
1726 if (!match_attr)
1727 return -EMSGSIZE;
1728
1729 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) ||
1730 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) ||
1731 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1732 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1733 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1734 goto nla_put_failure;
1735
1736 nla_nest_end(skb, match_attr);
1737 return 0;
1738
1739nla_put_failure:
1740 nla_nest_cancel(skb, match_attr);
1741 return -EMSGSIZE;
1742}
1743EXPORT_SYMBOL_GPL(devlink_dpipe_match_put);
1744
1745static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table,
1746 struct sk_buff *skb)
1747{
1748 struct nlattr *matches_attr;
1749
1750 matches_attr = nla_nest_start_noflag(skb,
1751 DEVLINK_ATTR_DPIPE_TABLE_MATCHES);
1752 if (!matches_attr)
1753 return -EMSGSIZE;
1754
1755 if (table->table_ops->matches_dump(table->priv, skb))
1756 goto nla_put_failure;
1757
1758 nla_nest_end(skb, matches_attr);
1759 return 0;
1760
1761nla_put_failure:
1762 nla_nest_cancel(skb, matches_attr);
1763 return -EMSGSIZE;
1764}
1765
1766int devlink_dpipe_action_put(struct sk_buff *skb,
1767 struct devlink_dpipe_action *action)
1768{
1769 struct devlink_dpipe_header *header = action->header;
1770 struct devlink_dpipe_field *field = &header->fields[action->field_id];
1771 struct nlattr *action_attr;
1772
1773 action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION);
1774 if (!action_attr)
1775 return -EMSGSIZE;
1776
1777 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) ||
1778 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) ||
1779 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1780 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1781 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1782 goto nla_put_failure;
1783
1784 nla_nest_end(skb, action_attr);
1785 return 0;
1786
1787nla_put_failure:
1788 nla_nest_cancel(skb, action_attr);
1789 return -EMSGSIZE;
1790}
1791EXPORT_SYMBOL_GPL(devlink_dpipe_action_put);
1792
1793static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table,
1794 struct sk_buff *skb)
1795{
1796 struct nlattr *actions_attr;
1797
1798 actions_attr = nla_nest_start_noflag(skb,
1799 DEVLINK_ATTR_DPIPE_TABLE_ACTIONS);
1800 if (!actions_attr)
1801 return -EMSGSIZE;
1802
1803 if (table->table_ops->actions_dump(table->priv, skb))
1804 goto nla_put_failure;
1805
1806 nla_nest_end(skb, actions_attr);
1807 return 0;
1808
1809nla_put_failure:
1810 nla_nest_cancel(skb, actions_attr);
1811 return -EMSGSIZE;
1812}
1813
1814static int devlink_dpipe_table_put(struct sk_buff *skb,
1815 struct devlink_dpipe_table *table)
1816{
1817 struct nlattr *table_attr;
1818 u64 table_size;
1819
1820 table_size = table->table_ops->size_get(table->priv);
1821 table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE);
1822 if (!table_attr)
1823 return -EMSGSIZE;
1824
1825 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
1826 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
1827 DEVLINK_ATTR_PAD))
1828 goto nla_put_failure;
1829 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
1830 table->counters_enabled))
1831 goto nla_put_failure;
1832
1833 if (table->resource_valid) {
1834 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
1835 table->resource_id, DEVLINK_ATTR_PAD) ||
1836 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
1837 table->resource_units, DEVLINK_ATTR_PAD))
1838 goto nla_put_failure;
1839 }
1840 if (devlink_dpipe_matches_put(table, skb))
1841 goto nla_put_failure;
1842
1843 if (devlink_dpipe_actions_put(table, skb))
1844 goto nla_put_failure;
1845
1846 nla_nest_end(skb, table_attr);
1847 return 0;
1848
1849nla_put_failure:
1850 nla_nest_cancel(skb, table_attr);
1851 return -EMSGSIZE;
1852}
1853
1854static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb,
1855 struct genl_info *info)
1856{
1857 int err;
1858
1859 if (*pskb) {
1860 err = genlmsg_reply(*pskb, info);
1861 if (err)
1862 return err;
1863 }
1864 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1865 if (!*pskb)
1866 return -ENOMEM;
1867 return 0;
1868}
1869
1870static int devlink_dpipe_tables_fill(struct genl_info *info,
1871 enum devlink_command cmd, int flags,
1872 struct list_head *dpipe_tables,
1873 const char *table_name)
1874{
1875 struct devlink *devlink = info->user_ptr[0];
1876 struct devlink_dpipe_table *table;
1877 struct nlattr *tables_attr;
1878 struct sk_buff *skb = NULL;
1879 struct nlmsghdr *nlh;
1880 bool incomplete;
1881 void *hdr;
1882 int i;
1883 int err;
1884
1885 table = list_first_entry(dpipe_tables,
1886 struct devlink_dpipe_table, list);
1887start_again:
1888 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1889 if (err)
1890 return err;
1891
1892 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
1893 &devlink_nl_family, NLM_F_MULTI, cmd);
1894 if (!hdr) {
1895 nlmsg_free(skb);
1896 return -EMSGSIZE;
1897 }
1898
1899 if (devlink_nl_put_handle(skb, devlink))
1900 goto nla_put_failure;
1901 tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES);
1902 if (!tables_attr)
1903 goto nla_put_failure;
1904
1905 i = 0;
1906 incomplete = false;
1907 list_for_each_entry_from(table, dpipe_tables, list) {
1908 if (!table_name) {
1909 err = devlink_dpipe_table_put(skb, table);
1910 if (err) {
1911 if (!i)
1912 goto err_table_put;
1913 incomplete = true;
1914 break;
1915 }
1916 } else {
1917 if (!strcmp(table->name, table_name)) {
1918 err = devlink_dpipe_table_put(skb, table);
1919 if (err)
1920 break;
1921 }
1922 }
1923 i++;
1924 }
1925
1926 nla_nest_end(skb, tables_attr);
1927 genlmsg_end(skb, hdr);
1928 if (incomplete)
1929 goto start_again;
1930
1931send_done:
1932 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
1933 NLMSG_DONE, 0, flags | NLM_F_MULTI);
1934 if (!nlh) {
1935 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1936 if (err)
1937 return err;
1938 goto send_done;
1939 }
1940
1941 return genlmsg_reply(skb, info);
1942
1943nla_put_failure:
1944 err = -EMSGSIZE;
1945err_table_put:
1946 nlmsg_free(skb);
1947 return err;
1948}
1949
1950static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb,
1951 struct genl_info *info)
1952{
1953 struct devlink *devlink = info->user_ptr[0];
1954 const char *table_name = NULL;
1955
1956 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
1957 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
1958
1959 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0,
1960 &devlink->dpipe_table_list,
1961 table_name);
1962}
1963
1964static int devlink_dpipe_value_put(struct sk_buff *skb,
1965 struct devlink_dpipe_value *value)
1966{
1967 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE,
1968 value->value_size, value->value))
1969 return -EMSGSIZE;
1970 if (value->mask)
1971 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK,
1972 value->value_size, value->mask))
1973 return -EMSGSIZE;
1974 if (value->mapping_valid)
1975 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING,
1976 value->mapping_value))
1977 return -EMSGSIZE;
1978 return 0;
1979}
1980
1981static int devlink_dpipe_action_value_put(struct sk_buff *skb,
1982 struct devlink_dpipe_value *value)
1983{
1984 if (!value->action)
1985 return -EINVAL;
1986 if (devlink_dpipe_action_put(skb, value->action))
1987 return -EMSGSIZE;
1988 if (devlink_dpipe_value_put(skb, value))
1989 return -EMSGSIZE;
1990 return 0;
1991}
1992
1993static int devlink_dpipe_action_values_put(struct sk_buff *skb,
1994 struct devlink_dpipe_value *values,
1995 unsigned int values_count)
1996{
1997 struct nlattr *action_attr;
1998 int i;
1999 int err;
2000
2001 for (i = 0; i < values_count; i++) {
2002 action_attr = nla_nest_start_noflag(skb,
2003 DEVLINK_ATTR_DPIPE_ACTION_VALUE);
2004 if (!action_attr)
2005 return -EMSGSIZE;
2006 err = devlink_dpipe_action_value_put(skb, &values[i]);
2007 if (err)
2008 goto err_action_value_put;
2009 nla_nest_end(skb, action_attr);
2010 }
2011 return 0;
2012
2013err_action_value_put:
2014 nla_nest_cancel(skb, action_attr);
2015 return err;
2016}
2017
2018static int devlink_dpipe_match_value_put(struct sk_buff *skb,
2019 struct devlink_dpipe_value *value)
2020{
2021 if (!value->match)
2022 return -EINVAL;
2023 if (devlink_dpipe_match_put(skb, value->match))
2024 return -EMSGSIZE;
2025 if (devlink_dpipe_value_put(skb, value))
2026 return -EMSGSIZE;
2027 return 0;
2028}
2029
2030static int devlink_dpipe_match_values_put(struct sk_buff *skb,
2031 struct devlink_dpipe_value *values,
2032 unsigned int values_count)
2033{
2034 struct nlattr *match_attr;
2035 int i;
2036 int err;
2037
2038 for (i = 0; i < values_count; i++) {
2039 match_attr = nla_nest_start_noflag(skb,
2040 DEVLINK_ATTR_DPIPE_MATCH_VALUE);
2041 if (!match_attr)
2042 return -EMSGSIZE;
2043 err = devlink_dpipe_match_value_put(skb, &values[i]);
2044 if (err)
2045 goto err_match_value_put;
2046 nla_nest_end(skb, match_attr);
2047 }
2048 return 0;
2049
2050err_match_value_put:
2051 nla_nest_cancel(skb, match_attr);
2052 return err;
2053}
2054
2055static int devlink_dpipe_entry_put(struct sk_buff *skb,
2056 struct devlink_dpipe_entry *entry)
2057{
2058 struct nlattr *entry_attr, *matches_attr, *actions_attr;
2059 int err;
2060
2061 entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY);
2062 if (!entry_attr)
2063 return -EMSGSIZE;
2064
2065 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index,
2066 DEVLINK_ATTR_PAD))
2067 goto nla_put_failure;
2068 if (entry->counter_valid)
2069 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER,
2070 entry->counter, DEVLINK_ATTR_PAD))
2071 goto nla_put_failure;
2072
2073 matches_attr = nla_nest_start_noflag(skb,
2074 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES);
2075 if (!matches_attr)
2076 goto nla_put_failure;
2077
2078 err = devlink_dpipe_match_values_put(skb, entry->match_values,
2079 entry->match_values_count);
2080 if (err) {
2081 nla_nest_cancel(skb, matches_attr);
2082 goto err_match_values_put;
2083 }
2084 nla_nest_end(skb, matches_attr);
2085
2086 actions_attr = nla_nest_start_noflag(skb,
2087 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES);
2088 if (!actions_attr)
2089 goto nla_put_failure;
2090
2091 err = devlink_dpipe_action_values_put(skb, entry->action_values,
2092 entry->action_values_count);
2093 if (err) {
2094 nla_nest_cancel(skb, actions_attr);
2095 goto err_action_values_put;
2096 }
2097 nla_nest_end(skb, actions_attr);
2098
2099 nla_nest_end(skb, entry_attr);
2100 return 0;
2101
2102nla_put_failure:
2103 err = -EMSGSIZE;
2104err_match_values_put:
2105err_action_values_put:
2106 nla_nest_cancel(skb, entry_attr);
2107 return err;
2108}
2109
2110static struct devlink_dpipe_table *
2111devlink_dpipe_table_find(struct list_head *dpipe_tables,
2112 const char *table_name, struct devlink *devlink)
2113{
2114 struct devlink_dpipe_table *table;
2115 list_for_each_entry_rcu(table, dpipe_tables, list,
2116 lockdep_is_held(&devlink->lock)) {
2117 if (!strcmp(table->name, table_name))
2118 return table;
2119 }
2120 return NULL;
2121}
2122
2123int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
2124{
2125 struct devlink *devlink;
2126 int err;
2127
2128 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb,
2129 dump_ctx->info);
2130 if (err)
2131 return err;
2132
2133 dump_ctx->hdr = genlmsg_put(dump_ctx->skb,
2134 dump_ctx->info->snd_portid,
2135 dump_ctx->info->snd_seq,
2136 &devlink_nl_family, NLM_F_MULTI,
2137 dump_ctx->cmd);
2138 if (!dump_ctx->hdr)
2139 goto nla_put_failure;
2140
2141 devlink = dump_ctx->info->user_ptr[0];
2142 if (devlink_nl_put_handle(dump_ctx->skb, devlink))
2143 goto nla_put_failure;
2144 dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb,
2145 DEVLINK_ATTR_DPIPE_ENTRIES);
2146 if (!dump_ctx->nest)
2147 goto nla_put_failure;
2148 return 0;
2149
2150nla_put_failure:
2151 nlmsg_free(dump_ctx->skb);
2152 return -EMSGSIZE;
2153}
2154EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare);
2155
2156int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
2157 struct devlink_dpipe_entry *entry)
2158{
2159 return devlink_dpipe_entry_put(dump_ctx->skb, entry);
2160}
2161EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append);
2162
2163int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
2164{
2165 nla_nest_end(dump_ctx->skb, dump_ctx->nest);
2166 genlmsg_end(dump_ctx->skb, dump_ctx->hdr);
2167 return 0;
2168}
2169EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
2170
2171void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
2172
2173{
2174 unsigned int value_count, value_index;
2175 struct devlink_dpipe_value *value;
2176
2177 value = entry->action_values;
2178 value_count = entry->action_values_count;
2179 for (value_index = 0; value_index < value_count; value_index++) {
2180 kfree(value[value_index].value);
2181 kfree(value[value_index].mask);
2182 }
2183
2184 value = entry->match_values;
2185 value_count = entry->match_values_count;
2186 for (value_index = 0; value_index < value_count; value_index++) {
2187 kfree(value[value_index].value);
2188 kfree(value[value_index].mask);
2189 }
2190}
2191EXPORT_SYMBOL(devlink_dpipe_entry_clear);
2192
2193static int devlink_dpipe_entries_fill(struct genl_info *info,
2194 enum devlink_command cmd, int flags,
2195 struct devlink_dpipe_table *table)
2196{
2197 struct devlink_dpipe_dump_ctx dump_ctx;
2198 struct nlmsghdr *nlh;
2199 int err;
2200
2201 dump_ctx.skb = NULL;
2202 dump_ctx.cmd = cmd;
2203 dump_ctx.info = info;
2204
2205 err = table->table_ops->entries_dump(table->priv,
2206 table->counters_enabled,
2207 &dump_ctx);
2208 if (err)
2209 return err;
2210
2211send_done:
2212 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq,
2213 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2214 if (!nlh) {
2215 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info);
2216 if (err)
2217 return err;
2218 goto send_done;
2219 }
2220 return genlmsg_reply(dump_ctx.skb, info);
2221}
2222
2223static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
2224 struct genl_info *info)
2225{
2226 struct devlink *devlink = info->user_ptr[0];
2227 struct devlink_dpipe_table *table;
2228 const char *table_name;
2229
2230 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
2231 return -EINVAL;
2232
2233 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2234 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2235 table_name, devlink);
2236 if (!table)
2237 return -EINVAL;
2238
2239 if (!table->table_ops->entries_dump)
2240 return -EINVAL;
2241
2242 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET,
2243 0, table);
2244}
2245
2246static int devlink_dpipe_fields_put(struct sk_buff *skb,
2247 const struct devlink_dpipe_header *header)
2248{
2249 struct devlink_dpipe_field *field;
2250 struct nlattr *field_attr;
2251 int i;
2252
2253 for (i = 0; i < header->fields_count; i++) {
2254 field = &header->fields[i];
2255 field_attr = nla_nest_start_noflag(skb,
2256 DEVLINK_ATTR_DPIPE_FIELD);
2257 if (!field_attr)
2258 return -EMSGSIZE;
2259 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) ||
2260 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
2261 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) ||
2262 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type))
2263 goto nla_put_failure;
2264 nla_nest_end(skb, field_attr);
2265 }
2266 return 0;
2267
2268nla_put_failure:
2269 nla_nest_cancel(skb, field_attr);
2270 return -EMSGSIZE;
2271}
2272
2273static int devlink_dpipe_header_put(struct sk_buff *skb,
2274 struct devlink_dpipe_header *header)
2275{
2276 struct nlattr *fields_attr, *header_attr;
2277 int err;
2278
2279 header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER);
2280 if (!header_attr)
2281 return -EMSGSIZE;
2282
2283 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) ||
2284 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
2285 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
2286 goto nla_put_failure;
2287
2288 fields_attr = nla_nest_start_noflag(skb,
2289 DEVLINK_ATTR_DPIPE_HEADER_FIELDS);
2290 if (!fields_attr)
2291 goto nla_put_failure;
2292
2293 err = devlink_dpipe_fields_put(skb, header);
2294 if (err) {
2295 nla_nest_cancel(skb, fields_attr);
2296 goto nla_put_failure;
2297 }
2298 nla_nest_end(skb, fields_attr);
2299 nla_nest_end(skb, header_attr);
2300 return 0;
2301
2302nla_put_failure:
2303 err = -EMSGSIZE;
2304 nla_nest_cancel(skb, header_attr);
2305 return err;
2306}
2307
2308static int devlink_dpipe_headers_fill(struct genl_info *info,
2309 enum devlink_command cmd, int flags,
2310 struct devlink_dpipe_headers *
2311 dpipe_headers)
2312{
2313 struct devlink *devlink = info->user_ptr[0];
2314 struct nlattr *headers_attr;
2315 struct sk_buff *skb = NULL;
2316 struct nlmsghdr *nlh;
2317 void *hdr;
2318 int i, j;
2319 int err;
2320
2321 i = 0;
2322start_again:
2323 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2324 if (err)
2325 return err;
2326
2327 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2328 &devlink_nl_family, NLM_F_MULTI, cmd);
2329 if (!hdr) {
2330 nlmsg_free(skb);
2331 return -EMSGSIZE;
2332 }
2333
2334 if (devlink_nl_put_handle(skb, devlink))
2335 goto nla_put_failure;
2336 headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS);
2337 if (!headers_attr)
2338 goto nla_put_failure;
2339
2340 j = 0;
2341 for (; i < dpipe_headers->headers_count; i++) {
2342 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]);
2343 if (err) {
2344 if (!j)
2345 goto err_table_put;
2346 break;
2347 }
2348 j++;
2349 }
2350 nla_nest_end(skb, headers_attr);
2351 genlmsg_end(skb, hdr);
2352 if (i != dpipe_headers->headers_count)
2353 goto start_again;
2354
2355send_done:
2356 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2357 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2358 if (!nlh) {
2359 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2360 if (err)
2361 return err;
2362 goto send_done;
2363 }
2364 return genlmsg_reply(skb, info);
2365
2366nla_put_failure:
2367 err = -EMSGSIZE;
2368err_table_put:
2369 nlmsg_free(skb);
2370 return err;
2371}
2372
2373static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
2374 struct genl_info *info)
2375{
2376 struct devlink *devlink = info->user_ptr[0];
2377
2378 if (!devlink->dpipe_headers)
2379 return -EOPNOTSUPP;
2380 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET,
2381 0, devlink->dpipe_headers);
2382}
2383
2384static int devlink_dpipe_table_counters_set(struct devlink *devlink,
2385 const char *table_name,
2386 bool enable)
2387{
2388 struct devlink_dpipe_table *table;
2389
2390 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2391 table_name, devlink);
2392 if (!table)
2393 return -EINVAL;
2394
2395 if (table->counter_control_extern)
2396 return -EOPNOTSUPP;
2397
2398 if (!(table->counters_enabled ^ enable))
2399 return 0;
2400
2401 table->counters_enabled = enable;
2402 if (table->table_ops->counters_set_update)
2403 table->table_ops->counters_set_update(table->priv, enable);
2404 return 0;
2405}
2406
2407static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
2408 struct genl_info *info)
2409{
2410 struct devlink *devlink = info->user_ptr[0];
2411 const char *table_name;
2412 bool counters_enable;
2413
2414 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] ||
2415 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED])
2416 return -EINVAL;
2417
2418 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2419 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
2420
2421 return devlink_dpipe_table_counters_set(devlink, table_name,
2422 counters_enable);
2423}
2424
2425static struct devlink_resource *
2426devlink_resource_find(struct devlink *devlink,
2427 struct devlink_resource *resource, u64 resource_id)
2428{
2429 struct list_head *resource_list;
2430
2431 if (resource)
2432 resource_list = &resource->resource_list;
2433 else
2434 resource_list = &devlink->resource_list;
2435
2436 list_for_each_entry(resource, resource_list, list) {
2437 struct devlink_resource *child_resource;
2438
2439 if (resource->id == resource_id)
2440 return resource;
2441
2442 child_resource = devlink_resource_find(devlink, resource,
2443 resource_id);
2444 if (child_resource)
2445 return child_resource;
2446 }
2447 return NULL;
2448}
2449
2450static void
2451devlink_resource_validate_children(struct devlink_resource *resource)
2452{
2453 struct devlink_resource *child_resource;
2454 bool size_valid = true;
2455 u64 parts_size = 0;
2456
2457 if (list_empty(&resource->resource_list))
2458 goto out;
2459
2460 list_for_each_entry(child_resource, &resource->resource_list, list)
2461 parts_size += child_resource->size_new;
2462
2463 if (parts_size > resource->size_new)
2464 size_valid = false;
2465out:
2466 resource->size_valid = size_valid;
2467}
2468
2469static int
2470devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
2471 struct netlink_ext_ack *extack)
2472{
2473 u64 reminder;
2474 int err = 0;
2475
2476 if (size > resource->size_params.size_max) {
2477 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
2478 err = -EINVAL;
2479 }
2480
2481 if (size < resource->size_params.size_min) {
2482 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
2483 err = -EINVAL;
2484 }
2485
2486 div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
2487 if (reminder) {
2488 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
2489 err = -EINVAL;
2490 }
2491
2492 return err;
2493}
2494
2495static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2496 struct genl_info *info)
2497{
2498 struct devlink *devlink = info->user_ptr[0];
2499 struct devlink_resource *resource;
2500 u64 resource_id;
2501 u64 size;
2502 int err;
2503
2504 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] ||
2505 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE])
2506 return -EINVAL;
2507 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
2508
2509 resource = devlink_resource_find(devlink, NULL, resource_id);
2510 if (!resource)
2511 return -EINVAL;
2512
2513 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
2514 err = devlink_resource_validate_size(resource, size, info->extack);
2515 if (err)
2516 return err;
2517
2518 resource->size_new = size;
2519 devlink_resource_validate_children(resource);
2520 if (resource->parent)
2521 devlink_resource_validate_children(resource->parent);
2522 return 0;
2523}
2524
2525static int
2526devlink_resource_size_params_put(struct devlink_resource *resource,
2527 struct sk_buff *skb)
2528{
2529 struct devlink_resource_size_params *size_params;
2530
2531 size_params = &resource->size_params;
2532 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
2533 size_params->size_granularity, DEVLINK_ATTR_PAD) ||
2534 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
2535 size_params->size_max, DEVLINK_ATTR_PAD) ||
2536 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
2537 size_params->size_min, DEVLINK_ATTR_PAD) ||
2538 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
2539 return -EMSGSIZE;
2540 return 0;
2541}
2542
2543static int devlink_resource_occ_put(struct devlink_resource *resource,
2544 struct sk_buff *skb)
2545{
2546 if (!resource->occ_get)
2547 return 0;
2548 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
2549 resource->occ_get(resource->occ_get_priv),
2550 DEVLINK_ATTR_PAD);
2551}
2552
2553static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
2554 struct devlink_resource *resource)
2555{
2556 struct devlink_resource *child_resource;
2557 struct nlattr *child_resource_attr;
2558 struct nlattr *resource_attr;
2559
2560 resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE);
2561 if (!resource_attr)
2562 return -EMSGSIZE;
2563
2564 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
2565 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size,
2566 DEVLINK_ATTR_PAD) ||
2567 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id,
2568 DEVLINK_ATTR_PAD))
2569 goto nla_put_failure;
2570 if (resource->size != resource->size_new)
2571 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
2572 resource->size_new, DEVLINK_ATTR_PAD);
2573 if (devlink_resource_occ_put(resource, skb))
2574 goto nla_put_failure;
2575 if (devlink_resource_size_params_put(resource, skb))
2576 goto nla_put_failure;
2577 if (list_empty(&resource->resource_list))
2578 goto out;
2579
2580 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
2581 resource->size_valid))
2582 goto nla_put_failure;
2583
2584 child_resource_attr = nla_nest_start_noflag(skb,
2585 DEVLINK_ATTR_RESOURCE_LIST);
2586 if (!child_resource_attr)
2587 goto nla_put_failure;
2588
2589 list_for_each_entry(child_resource, &resource->resource_list, list) {
2590 if (devlink_resource_put(devlink, skb, child_resource))
2591 goto resource_put_failure;
2592 }
2593
2594 nla_nest_end(skb, child_resource_attr);
2595out:
2596 nla_nest_end(skb, resource_attr);
2597 return 0;
2598
2599resource_put_failure:
2600 nla_nest_cancel(skb, child_resource_attr);
2601nla_put_failure:
2602 nla_nest_cancel(skb, resource_attr);
2603 return -EMSGSIZE;
2604}
2605
2606static int devlink_resource_fill(struct genl_info *info,
2607 enum devlink_command cmd, int flags)
2608{
2609 struct devlink *devlink = info->user_ptr[0];
2610 struct devlink_resource *resource;
2611 struct nlattr *resources_attr;
2612 struct sk_buff *skb = NULL;
2613 struct nlmsghdr *nlh;
2614 bool incomplete;
2615 void *hdr;
2616 int i;
2617 int err;
2618
2619 resource = list_first_entry(&devlink->resource_list,
2620 struct devlink_resource, list);
2621start_again:
2622 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2623 if (err)
2624 return err;
2625
2626 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2627 &devlink_nl_family, NLM_F_MULTI, cmd);
2628 if (!hdr) {
2629 nlmsg_free(skb);
2630 return -EMSGSIZE;
2631 }
2632
2633 if (devlink_nl_put_handle(skb, devlink))
2634 goto nla_put_failure;
2635
2636 resources_attr = nla_nest_start_noflag(skb,
2637 DEVLINK_ATTR_RESOURCE_LIST);
2638 if (!resources_attr)
2639 goto nla_put_failure;
2640
2641 incomplete = false;
2642 i = 0;
2643 list_for_each_entry_from(resource, &devlink->resource_list, list) {
2644 err = devlink_resource_put(devlink, skb, resource);
2645 if (err) {
2646 if (!i)
2647 goto err_resource_put;
2648 incomplete = true;
2649 break;
2650 }
2651 i++;
2652 }
2653 nla_nest_end(skb, resources_attr);
2654 genlmsg_end(skb, hdr);
2655 if (incomplete)
2656 goto start_again;
2657send_done:
2658 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2659 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2660 if (!nlh) {
2661 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2662 if (err)
2663 return err;
2664 goto send_done;
2665 }
2666 return genlmsg_reply(skb, info);
2667
2668nla_put_failure:
2669 err = -EMSGSIZE;
2670err_resource_put:
2671 nlmsg_free(skb);
2672 return err;
2673}
2674
2675static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
2676 struct genl_info *info)
2677{
2678 struct devlink *devlink = info->user_ptr[0];
2679
2680 if (list_empty(&devlink->resource_list))
2681 return -EOPNOTSUPP;
2682
2683 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
2684}
2685
2686static int
2687devlink_resources_validate(struct devlink *devlink,
2688 struct devlink_resource *resource,
2689 struct genl_info *info)
2690{
2691 struct list_head *resource_list;
2692 int err = 0;
2693
2694 if (resource)
2695 resource_list = &resource->resource_list;
2696 else
2697 resource_list = &devlink->resource_list;
2698
2699 list_for_each_entry(resource, resource_list, list) {
2700 if (!resource->size_valid)
2701 return -EINVAL;
2702 err = devlink_resources_validate(devlink, resource, info);
2703 if (err)
2704 return err;
2705 }
2706 return err;
2707}
2708
2709static struct net *devlink_netns_get(struct sk_buff *skb,
2710 struct genl_info *info)
2711{
2712 struct nlattr *netns_pid_attr = info->attrs[DEVLINK_ATTR_NETNS_PID];
2713 struct nlattr *netns_fd_attr = info->attrs[DEVLINK_ATTR_NETNS_FD];
2714 struct nlattr *netns_id_attr = info->attrs[DEVLINK_ATTR_NETNS_ID];
2715 struct net *net;
2716
2717 if (!!netns_pid_attr + !!netns_fd_attr + !!netns_id_attr > 1) {
2718 NL_SET_ERR_MSG_MOD(info->extack, "multiple netns identifying attributes specified");
2719 return ERR_PTR(-EINVAL);
2720 }
2721
2722 if (netns_pid_attr) {
2723 net = get_net_ns_by_pid(nla_get_u32(netns_pid_attr));
2724 } else if (netns_fd_attr) {
2725 net = get_net_ns_by_fd(nla_get_u32(netns_fd_attr));
2726 } else if (netns_id_attr) {
2727 net = get_net_ns_by_id(sock_net(skb->sk),
2728 nla_get_u32(netns_id_attr));
2729 if (!net)
2730 net = ERR_PTR(-EINVAL);
2731 } else {
2732 WARN_ON(1);
2733 net = ERR_PTR(-EINVAL);
2734 }
2735 if (IS_ERR(net)) {
2736 NL_SET_ERR_MSG_MOD(info->extack, "Unknown network namespace");
2737 return ERR_PTR(-EINVAL);
2738 }
2739 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
2740 put_net(net);
2741 return ERR_PTR(-EPERM);
2742 }
2743 return net;
2744}
2745
2746static void devlink_param_notify(struct devlink *devlink,
2747 unsigned int port_index,
2748 struct devlink_param_item *param_item,
2749 enum devlink_command cmd);
2750
2751static void devlink_reload_netns_change(struct devlink *devlink,
2752 struct net *dest_net)
2753{
2754 struct devlink_param_item *param_item;
2755
2756
2757
2758
2759
2760
2761
2762 list_for_each_entry(param_item, &devlink->param_list, list)
2763 devlink_param_notify(devlink, 0, param_item,
2764 DEVLINK_CMD_PARAM_DEL);
2765 devlink_notify(devlink, DEVLINK_CMD_DEL);
2766
2767 __devlink_net_set(devlink, dest_net);
2768
2769 devlink_notify(devlink, DEVLINK_CMD_NEW);
2770 list_for_each_entry(param_item, &devlink->param_list, list)
2771 devlink_param_notify(devlink, 0, param_item,
2772 DEVLINK_CMD_PARAM_NEW);
2773}
2774
2775static bool devlink_reload_supported(struct devlink *devlink)
2776{
2777 return devlink->ops->reload_down && devlink->ops->reload_up;
2778}
2779
2780static void devlink_reload_failed_set(struct devlink *devlink,
2781 bool reload_failed)
2782{
2783 if (devlink->reload_failed == reload_failed)
2784 return;
2785 devlink->reload_failed = reload_failed;
2786 devlink_notify(devlink, DEVLINK_CMD_NEW);
2787}
2788
2789bool devlink_is_reload_failed(const struct devlink *devlink)
2790{
2791 return devlink->reload_failed;
2792}
2793EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
2794
2795static int devlink_reload(struct devlink *devlink, struct net *dest_net,
2796 struct netlink_ext_ack *extack)
2797{
2798 int err;
2799
2800 if (!devlink->reload_enabled)
2801 return -EOPNOTSUPP;
2802
2803 err = devlink->ops->reload_down(devlink, !!dest_net, extack);
2804 if (err)
2805 return err;
2806
2807 if (dest_net && !net_eq(dest_net, devlink_net(devlink)))
2808 devlink_reload_netns_change(devlink, dest_net);
2809
2810 err = devlink->ops->reload_up(devlink, extack);
2811 devlink_reload_failed_set(devlink, !!err);
2812 return err;
2813}
2814
2815static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
2816{
2817 struct devlink *devlink = info->user_ptr[0];
2818 struct net *dest_net = NULL;
2819 int err;
2820
2821 if (!devlink_reload_supported(devlink) || !devlink->reload_enabled)
2822 return -EOPNOTSUPP;
2823
2824 err = devlink_resources_validate(devlink, NULL, info);
2825 if (err) {
2826 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
2827 return err;
2828 }
2829
2830 if (info->attrs[DEVLINK_ATTR_NETNS_PID] ||
2831 info->attrs[DEVLINK_ATTR_NETNS_FD] ||
2832 info->attrs[DEVLINK_ATTR_NETNS_ID]) {
2833 dest_net = devlink_netns_get(skb, info);
2834 if (IS_ERR(dest_net))
2835 return PTR_ERR(dest_net);
2836 }
2837
2838 err = devlink_reload(devlink, dest_net, info->extack);
2839
2840 if (dest_net)
2841 put_net(dest_net);
2842
2843 return err;
2844}
2845
2846static int devlink_nl_flash_update_fill(struct sk_buff *msg,
2847 struct devlink *devlink,
2848 enum devlink_command cmd,
2849 const char *status_msg,
2850 const char *component,
2851 unsigned long done, unsigned long total)
2852{
2853 void *hdr;
2854
2855 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
2856 if (!hdr)
2857 return -EMSGSIZE;
2858
2859 if (devlink_nl_put_handle(msg, devlink))
2860 goto nla_put_failure;
2861
2862 if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
2863 goto out;
2864
2865 if (status_msg &&
2866 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
2867 status_msg))
2868 goto nla_put_failure;
2869 if (component &&
2870 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
2871 component))
2872 goto nla_put_failure;
2873 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
2874 done, DEVLINK_ATTR_PAD))
2875 goto nla_put_failure;
2876 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
2877 total, DEVLINK_ATTR_PAD))
2878 goto nla_put_failure;
2879
2880out:
2881 genlmsg_end(msg, hdr);
2882 return 0;
2883
2884nla_put_failure:
2885 genlmsg_cancel(msg, hdr);
2886 return -EMSGSIZE;
2887}
2888
2889static void __devlink_flash_update_notify(struct devlink *devlink,
2890 enum devlink_command cmd,
2891 const char *status_msg,
2892 const char *component,
2893 unsigned long done,
2894 unsigned long total)
2895{
2896 struct sk_buff *msg;
2897 int err;
2898
2899 WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
2900 cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
2901 cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
2902
2903 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2904 if (!msg)
2905 return;
2906
2907 err = devlink_nl_flash_update_fill(msg, devlink, cmd, status_msg,
2908 component, done, total);
2909 if (err)
2910 goto out_free_msg;
2911
2912 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
2913 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
2914 return;
2915
2916out_free_msg:
2917 nlmsg_free(msg);
2918}
2919
2920void devlink_flash_update_begin_notify(struct devlink *devlink)
2921{
2922 __devlink_flash_update_notify(devlink,
2923 DEVLINK_CMD_FLASH_UPDATE,
2924 NULL, NULL, 0, 0);
2925}
2926EXPORT_SYMBOL_GPL(devlink_flash_update_begin_notify);
2927
2928void devlink_flash_update_end_notify(struct devlink *devlink)
2929{
2930 __devlink_flash_update_notify(devlink,
2931 DEVLINK_CMD_FLASH_UPDATE_END,
2932 NULL, NULL, 0, 0);
2933}
2934EXPORT_SYMBOL_GPL(devlink_flash_update_end_notify);
2935
2936void devlink_flash_update_status_notify(struct devlink *devlink,
2937 const char *status_msg,
2938 const char *component,
2939 unsigned long done,
2940 unsigned long total)
2941{
2942 __devlink_flash_update_notify(devlink,
2943 DEVLINK_CMD_FLASH_UPDATE_STATUS,
2944 status_msg, component, done, total);
2945}
2946EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);
2947
2948static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
2949 struct genl_info *info)
2950{
2951 struct devlink *devlink = info->user_ptr[0];
2952 const char *file_name, *component;
2953 struct nlattr *nla_component;
2954
2955 if (!devlink->ops->flash_update)
2956 return -EOPNOTSUPP;
2957
2958 if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME])
2959 return -EINVAL;
2960 file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]);
2961
2962 nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT];
2963 component = nla_component ? nla_data(nla_component) : NULL;
2964
2965 return devlink->ops->flash_update(devlink, file_name, component,
2966 info->extack);
2967}
2968
2969static const struct devlink_param devlink_param_generic[] = {
2970 {
2971 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
2972 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
2973 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
2974 },
2975 {
2976 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
2977 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
2978 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
2979 },
2980 {
2981 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
2982 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
2983 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
2984 },
2985 {
2986 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
2987 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
2988 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
2989 },
2990 {
2991 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
2992 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
2993 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
2994 },
2995 {
2996 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
2997 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
2998 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
2999 },
3000 {
3001 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
3002 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
3003 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
3004 },
3005 {
3006 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
3007 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
3008 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
3009 },
3010 {
3011 .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE,
3012 .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
3013 .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
3014 },
3015 {
3016 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
3017 .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME,
3018 .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE,
3019 },
3020};
3021
3022static int devlink_param_generic_verify(const struct devlink_param *param)
3023{
3024
3025 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
3026 return -EINVAL;
3027 if (strcmp(param->name, devlink_param_generic[param->id].name))
3028 return -ENOENT;
3029
3030 WARN_ON(param->type != devlink_param_generic[param->id].type);
3031
3032 return 0;
3033}
3034
3035static int devlink_param_driver_verify(const struct devlink_param *param)
3036{
3037 int i;
3038
3039 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
3040 return -EINVAL;
3041
3042 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
3043 if (!strcmp(param->name, devlink_param_generic[i].name))
3044 return -EEXIST;
3045
3046 return 0;
3047}
3048
3049static struct devlink_param_item *
3050devlink_param_find_by_name(struct list_head *param_list,
3051 const char *param_name)
3052{
3053 struct devlink_param_item *param_item;
3054
3055 list_for_each_entry(param_item, param_list, list)
3056 if (!strcmp(param_item->param->name, param_name))
3057 return param_item;
3058 return NULL;
3059}
3060
3061static struct devlink_param_item *
3062devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
3063{
3064 struct devlink_param_item *param_item;
3065
3066 list_for_each_entry(param_item, param_list, list)
3067 if (param_item->param->id == param_id)
3068 return param_item;
3069 return NULL;
3070}
3071
3072static bool
3073devlink_param_cmode_is_supported(const struct devlink_param *param,
3074 enum devlink_param_cmode cmode)
3075{
3076 return test_bit(cmode, ¶m->supported_cmodes);
3077}
3078
3079static int devlink_param_get(struct devlink *devlink,
3080 const struct devlink_param *param,
3081 struct devlink_param_gset_ctx *ctx)
3082{
3083 if (!param->get)
3084 return -EOPNOTSUPP;
3085 return param->get(devlink, param->id, ctx);
3086}
3087
3088static int devlink_param_set(struct devlink *devlink,
3089 const struct devlink_param *param,
3090 struct devlink_param_gset_ctx *ctx)
3091{
3092 if (!param->set)
3093 return -EOPNOTSUPP;
3094 return param->set(devlink, param->id, ctx);
3095}
3096
3097static int
3098devlink_param_type_to_nla_type(enum devlink_param_type param_type)
3099{
3100 switch (param_type) {
3101 case DEVLINK_PARAM_TYPE_U8:
3102 return NLA_U8;
3103 case DEVLINK_PARAM_TYPE_U16:
3104 return NLA_U16;
3105 case DEVLINK_PARAM_TYPE_U32:
3106 return NLA_U32;
3107 case DEVLINK_PARAM_TYPE_STRING:
3108 return NLA_STRING;
3109 case DEVLINK_PARAM_TYPE_BOOL:
3110 return NLA_FLAG;
3111 default:
3112 return -EINVAL;
3113 }
3114}
3115
3116static int
3117devlink_nl_param_value_fill_one(struct sk_buff *msg,
3118 enum devlink_param_type type,
3119 enum devlink_param_cmode cmode,
3120 union devlink_param_value val)
3121{
3122 struct nlattr *param_value_attr;
3123
3124 param_value_attr = nla_nest_start_noflag(msg,
3125 DEVLINK_ATTR_PARAM_VALUE);
3126 if (!param_value_attr)
3127 goto nla_put_failure;
3128
3129 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
3130 goto value_nest_cancel;
3131
3132 switch (type) {
3133 case DEVLINK_PARAM_TYPE_U8:
3134 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
3135 goto value_nest_cancel;
3136 break;
3137 case DEVLINK_PARAM_TYPE_U16:
3138 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
3139 goto value_nest_cancel;
3140 break;
3141 case DEVLINK_PARAM_TYPE_U32:
3142 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
3143 goto value_nest_cancel;
3144 break;
3145 case DEVLINK_PARAM_TYPE_STRING:
3146 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
3147 val.vstr))
3148 goto value_nest_cancel;
3149 break;
3150 case DEVLINK_PARAM_TYPE_BOOL:
3151 if (val.vbool &&
3152 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
3153 goto value_nest_cancel;
3154 break;
3155 }
3156
3157 nla_nest_end(msg, param_value_attr);
3158 return 0;
3159
3160value_nest_cancel:
3161 nla_nest_cancel(msg, param_value_attr);
3162nla_put_failure:
3163 return -EMSGSIZE;
3164}
3165
3166static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
3167 unsigned int port_index,
3168 struct devlink_param_item *param_item,
3169 enum devlink_command cmd,
3170 u32 portid, u32 seq, int flags)
3171{
3172 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
3173 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
3174 const struct devlink_param *param = param_item->param;
3175 struct devlink_param_gset_ctx ctx;
3176 struct nlattr *param_values_list;
3177 struct nlattr *param_attr;
3178 int nla_type;
3179 void *hdr;
3180 int err;
3181 int i;
3182
3183
3184 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3185 if (!devlink_param_cmode_is_supported(param, i))
3186 continue;
3187 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3188 if (!param_item->driverinit_value_valid)
3189 return -EOPNOTSUPP;
3190 param_value[i] = param_item->driverinit_value;
3191 } else {
3192 if (!param_item->published)
3193 continue;
3194 ctx.cmode = i;
3195 err = devlink_param_get(devlink, param, &ctx);
3196 if (err)
3197 return err;
3198 param_value[i] = ctx.val;
3199 }
3200 param_value_set[i] = true;
3201 }
3202
3203 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3204 if (!hdr)
3205 return -EMSGSIZE;
3206
3207 if (devlink_nl_put_handle(msg, devlink))
3208 goto genlmsg_cancel;
3209
3210 if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
3211 cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
3212 cmd == DEVLINK_CMD_PORT_PARAM_DEL)
3213 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
3214 goto genlmsg_cancel;
3215
3216 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
3217 if (!param_attr)
3218 goto genlmsg_cancel;
3219 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
3220 goto param_nest_cancel;
3221 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
3222 goto param_nest_cancel;
3223
3224 nla_type = devlink_param_type_to_nla_type(param->type);
3225 if (nla_type < 0)
3226 goto param_nest_cancel;
3227 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
3228 goto param_nest_cancel;
3229
3230 param_values_list = nla_nest_start_noflag(msg,
3231 DEVLINK_ATTR_PARAM_VALUES_LIST);
3232 if (!param_values_list)
3233 goto param_nest_cancel;
3234
3235 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3236 if (!param_value_set[i])
3237 continue;
3238 err = devlink_nl_param_value_fill_one(msg, param->type,
3239 i, param_value[i]);
3240 if (err)
3241 goto values_list_nest_cancel;
3242 }
3243
3244 nla_nest_end(msg, param_values_list);
3245 nla_nest_end(msg, param_attr);
3246 genlmsg_end(msg, hdr);
3247 return 0;
3248
3249values_list_nest_cancel:
3250 nla_nest_end(msg, param_values_list);
3251param_nest_cancel:
3252 nla_nest_cancel(msg, param_attr);
3253genlmsg_cancel:
3254 genlmsg_cancel(msg, hdr);
3255 return -EMSGSIZE;
3256}
3257
3258static void devlink_param_notify(struct devlink *devlink,
3259 unsigned int port_index,
3260 struct devlink_param_item *param_item,
3261 enum devlink_command cmd)
3262{
3263 struct sk_buff *msg;
3264 int err;
3265
3266 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
3267 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
3268 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
3269
3270 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3271 if (!msg)
3272 return;
3273 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
3274 0, 0, 0);
3275 if (err) {
3276 nlmsg_free(msg);
3277 return;
3278 }
3279
3280 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3281 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3282}
3283
3284static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
3285 struct netlink_callback *cb)
3286{
3287 struct devlink_param_item *param_item;
3288 struct devlink *devlink;
3289 int start = cb->args[0];
3290 int idx = 0;
3291 int err = 0;
3292
3293 mutex_lock(&devlink_mutex);
3294 list_for_each_entry(devlink, &devlink_list, list) {
3295 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3296 continue;
3297 mutex_lock(&devlink->lock);
3298 list_for_each_entry(param_item, &devlink->param_list, list) {
3299 if (idx < start) {
3300 idx++;
3301 continue;
3302 }
3303 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3304 DEVLINK_CMD_PARAM_GET,
3305 NETLINK_CB(cb->skb).portid,
3306 cb->nlh->nlmsg_seq,
3307 NLM_F_MULTI);
3308 if (err == -EOPNOTSUPP) {
3309 err = 0;
3310 } else if (err) {
3311 mutex_unlock(&devlink->lock);
3312 goto out;
3313 }
3314 idx++;
3315 }
3316 mutex_unlock(&devlink->lock);
3317 }
3318out:
3319 mutex_unlock(&devlink_mutex);
3320
3321 if (err != -EMSGSIZE)
3322 return err;
3323
3324 cb->args[0] = idx;
3325 return msg->len;
3326}
3327
3328static int
3329devlink_param_type_get_from_info(struct genl_info *info,
3330 enum devlink_param_type *param_type)
3331{
3332 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
3333 return -EINVAL;
3334
3335 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
3336 case NLA_U8:
3337 *param_type = DEVLINK_PARAM_TYPE_U8;
3338 break;
3339 case NLA_U16:
3340 *param_type = DEVLINK_PARAM_TYPE_U16;
3341 break;
3342 case NLA_U32:
3343 *param_type = DEVLINK_PARAM_TYPE_U32;
3344 break;
3345 case NLA_STRING:
3346 *param_type = DEVLINK_PARAM_TYPE_STRING;
3347 break;
3348 case NLA_FLAG:
3349 *param_type = DEVLINK_PARAM_TYPE_BOOL;
3350 break;
3351 default:
3352 return -EINVAL;
3353 }
3354
3355 return 0;
3356}
3357
3358static int
3359devlink_param_value_get_from_info(const struct devlink_param *param,
3360 struct genl_info *info,
3361 union devlink_param_value *value)
3362{
3363 struct nlattr *param_data;
3364 int len;
3365
3366 param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
3367
3368 if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
3369 return -EINVAL;
3370
3371 switch (param->type) {
3372 case DEVLINK_PARAM_TYPE_U8:
3373 if (nla_len(param_data) != sizeof(u8))
3374 return -EINVAL;
3375 value->vu8 = nla_get_u8(param_data);
3376 break;
3377 case DEVLINK_PARAM_TYPE_U16:
3378 if (nla_len(param_data) != sizeof(u16))
3379 return -EINVAL;
3380 value->vu16 = nla_get_u16(param_data);
3381 break;
3382 case DEVLINK_PARAM_TYPE_U32:
3383 if (nla_len(param_data) != sizeof(u32))
3384 return -EINVAL;
3385 value->vu32 = nla_get_u32(param_data);
3386 break;
3387 case DEVLINK_PARAM_TYPE_STRING:
3388 len = strnlen(nla_data(param_data), nla_len(param_data));
3389 if (len == nla_len(param_data) ||
3390 len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
3391 return -EINVAL;
3392 strcpy(value->vstr, nla_data(param_data));
3393 break;
3394 case DEVLINK_PARAM_TYPE_BOOL:
3395 if (param_data && nla_len(param_data))
3396 return -EINVAL;
3397 value->vbool = nla_get_flag(param_data);
3398 break;
3399 }
3400 return 0;
3401}
3402
3403static struct devlink_param_item *
3404devlink_param_get_from_info(struct list_head *param_list,
3405 struct genl_info *info)
3406{
3407 char *param_name;
3408
3409 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
3410 return NULL;
3411
3412 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
3413 return devlink_param_find_by_name(param_list, param_name);
3414}
3415
3416static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
3417 struct genl_info *info)
3418{
3419 struct devlink *devlink = info->user_ptr[0];
3420 struct devlink_param_item *param_item;
3421 struct sk_buff *msg;
3422 int err;
3423
3424 param_item = devlink_param_get_from_info(&devlink->param_list, info);
3425 if (!param_item)
3426 return -EINVAL;
3427
3428 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3429 if (!msg)
3430 return -ENOMEM;
3431
3432 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3433 DEVLINK_CMD_PARAM_GET,
3434 info->snd_portid, info->snd_seq, 0);
3435 if (err) {
3436 nlmsg_free(msg);
3437 return err;
3438 }
3439
3440 return genlmsg_reply(msg, info);
3441}
3442
3443static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
3444 unsigned int port_index,
3445 struct list_head *param_list,
3446 struct genl_info *info,
3447 enum devlink_command cmd)
3448{
3449 enum devlink_param_type param_type;
3450 struct devlink_param_gset_ctx ctx;
3451 enum devlink_param_cmode cmode;
3452 struct devlink_param_item *param_item;
3453 const struct devlink_param *param;
3454 union devlink_param_value value;
3455 int err = 0;
3456
3457 param_item = devlink_param_get_from_info(param_list, info);
3458 if (!param_item)
3459 return -EINVAL;
3460 param = param_item->param;
3461 err = devlink_param_type_get_from_info(info, ¶m_type);
3462 if (err)
3463 return err;
3464 if (param_type != param->type)
3465 return -EINVAL;
3466 err = devlink_param_value_get_from_info(param, info, &value);
3467 if (err)
3468 return err;
3469 if (param->validate) {
3470 err = param->validate(devlink, param->id, value, info->extack);
3471 if (err)
3472 return err;
3473 }
3474
3475 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
3476 return -EINVAL;
3477 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
3478 if (!devlink_param_cmode_is_supported(param, cmode))
3479 return -EOPNOTSUPP;
3480
3481 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3482 if (param->type == DEVLINK_PARAM_TYPE_STRING)
3483 strcpy(param_item->driverinit_value.vstr, value.vstr);
3484 else
3485 param_item->driverinit_value = value;
3486 param_item->driverinit_value_valid = true;
3487 } else {
3488 if (!param->set)
3489 return -EOPNOTSUPP;
3490 ctx.val = value;
3491 ctx.cmode = cmode;
3492 err = devlink_param_set(devlink, param, &ctx);
3493 if (err)
3494 return err;
3495 }
3496
3497 devlink_param_notify(devlink, port_index, param_item, cmd);
3498 return 0;
3499}
3500
3501static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
3502 struct genl_info *info)
3503{
3504 struct devlink *devlink = info->user_ptr[0];
3505
3506 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
3507 info, DEVLINK_CMD_PARAM_NEW);
3508}
3509
3510static int devlink_param_register_one(struct devlink *devlink,
3511 unsigned int port_index,
3512 struct list_head *param_list,
3513 const struct devlink_param *param,
3514 enum devlink_command cmd)
3515{
3516 struct devlink_param_item *param_item;
3517
3518 if (devlink_param_find_by_name(param_list, param->name))
3519 return -EEXIST;
3520
3521 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
3522 WARN_ON(param->get || param->set);
3523 else
3524 WARN_ON(!param->get || !param->set);
3525
3526 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
3527 if (!param_item)
3528 return -ENOMEM;
3529 param_item->param = param;
3530
3531 list_add_tail(¶m_item->list, param_list);
3532 devlink_param_notify(devlink, port_index, param_item, cmd);
3533 return 0;
3534}
3535
3536static void devlink_param_unregister_one(struct devlink *devlink,
3537 unsigned int port_index,
3538 struct list_head *param_list,
3539 const struct devlink_param *param,
3540 enum devlink_command cmd)
3541{
3542 struct devlink_param_item *param_item;
3543
3544 param_item = devlink_param_find_by_name(param_list, param->name);
3545 WARN_ON(!param_item);
3546 devlink_param_notify(devlink, port_index, param_item, cmd);
3547 list_del(¶m_item->list);
3548 kfree(param_item);
3549}
3550
3551static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
3552 struct netlink_callback *cb)
3553{
3554 struct devlink_param_item *param_item;
3555 struct devlink_port *devlink_port;
3556 struct devlink *devlink;
3557 int start = cb->args[0];
3558 int idx = 0;
3559 int err = 0;
3560
3561 mutex_lock(&devlink_mutex);
3562 list_for_each_entry(devlink, &devlink_list, list) {
3563 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3564 continue;
3565 mutex_lock(&devlink->lock);
3566 list_for_each_entry(devlink_port, &devlink->port_list, list) {
3567 list_for_each_entry(param_item,
3568 &devlink_port->param_list, list) {
3569 if (idx < start) {
3570 idx++;
3571 continue;
3572 }
3573 err = devlink_nl_param_fill(msg,
3574 devlink_port->devlink,
3575 devlink_port->index, param_item,
3576 DEVLINK_CMD_PORT_PARAM_GET,
3577 NETLINK_CB(cb->skb).portid,
3578 cb->nlh->nlmsg_seq,
3579 NLM_F_MULTI);
3580 if (err == -EOPNOTSUPP) {
3581 err = 0;
3582 } else if (err) {
3583 mutex_unlock(&devlink->lock);
3584 goto out;
3585 }
3586 idx++;
3587 }
3588 }
3589 mutex_unlock(&devlink->lock);
3590 }
3591out:
3592 mutex_unlock(&devlink_mutex);
3593
3594 if (err != -EMSGSIZE)
3595 return err;
3596
3597 cb->args[0] = idx;
3598 return msg->len;
3599}
3600
3601static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
3602 struct genl_info *info)
3603{
3604 struct devlink_port *devlink_port = info->user_ptr[0];
3605 struct devlink_param_item *param_item;
3606 struct sk_buff *msg;
3607 int err;
3608
3609 param_item = devlink_param_get_from_info(&devlink_port->param_list,
3610 info);
3611 if (!param_item)
3612 return -EINVAL;
3613
3614 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3615 if (!msg)
3616 return -ENOMEM;
3617
3618 err = devlink_nl_param_fill(msg, devlink_port->devlink,
3619 devlink_port->index, param_item,
3620 DEVLINK_CMD_PORT_PARAM_GET,
3621 info->snd_portid, info->snd_seq, 0);
3622 if (err) {
3623 nlmsg_free(msg);
3624 return err;
3625 }
3626
3627 return genlmsg_reply(msg, info);
3628}
3629
3630static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
3631 struct genl_info *info)
3632{
3633 struct devlink_port *devlink_port = info->user_ptr[0];
3634
3635 return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
3636 devlink_port->index,
3637 &devlink_port->param_list, info,
3638 DEVLINK_CMD_PORT_PARAM_NEW);
3639}
3640
3641static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
3642 struct devlink *devlink,
3643 struct devlink_snapshot *snapshot)
3644{
3645 struct nlattr *snap_attr;
3646 int err;
3647
3648 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
3649 if (!snap_attr)
3650 return -EINVAL;
3651
3652 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
3653 if (err)
3654 goto nla_put_failure;
3655
3656 nla_nest_end(msg, snap_attr);
3657 return 0;
3658
3659nla_put_failure:
3660 nla_nest_cancel(msg, snap_attr);
3661 return err;
3662}
3663
3664static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
3665 struct devlink *devlink,
3666 struct devlink_region *region)
3667{
3668 struct devlink_snapshot *snapshot;
3669 struct nlattr *snapshots_attr;
3670 int err;
3671
3672 snapshots_attr = nla_nest_start_noflag(msg,
3673 DEVLINK_ATTR_REGION_SNAPSHOTS);
3674 if (!snapshots_attr)
3675 return -EINVAL;
3676
3677 list_for_each_entry(snapshot, ®ion->snapshot_list, list) {
3678 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
3679 if (err)
3680 goto nla_put_failure;
3681 }
3682
3683 nla_nest_end(msg, snapshots_attr);
3684 return 0;
3685
3686nla_put_failure:
3687 nla_nest_cancel(msg, snapshots_attr);
3688 return err;
3689}
3690
3691static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
3692 enum devlink_command cmd, u32 portid,
3693 u32 seq, int flags,
3694 struct devlink_region *region)
3695{
3696 void *hdr;
3697 int err;
3698
3699 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3700 if (!hdr)
3701 return -EMSGSIZE;
3702
3703 err = devlink_nl_put_handle(msg, devlink);
3704 if (err)
3705 goto nla_put_failure;
3706
3707 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
3708 if (err)
3709 goto nla_put_failure;
3710
3711 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3712 region->size,
3713 DEVLINK_ATTR_PAD);
3714 if (err)
3715 goto nla_put_failure;
3716
3717 err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
3718 if (err)
3719 goto nla_put_failure;
3720
3721 genlmsg_end(msg, hdr);
3722 return 0;
3723
3724nla_put_failure:
3725 genlmsg_cancel(msg, hdr);
3726 return err;
3727}
3728
3729static struct sk_buff *
3730devlink_nl_region_notify_build(struct devlink_region *region,
3731 struct devlink_snapshot *snapshot,
3732 enum devlink_command cmd, u32 portid, u32 seq)
3733{
3734 struct devlink *devlink = region->devlink;
3735 struct sk_buff *msg;
3736 void *hdr;
3737 int err;
3738
3739
3740 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3741 if (!msg)
3742 return ERR_PTR(-ENOMEM);
3743
3744 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
3745 if (!hdr) {
3746 err = -EMSGSIZE;
3747 goto out_free_msg;
3748 }
3749
3750 err = devlink_nl_put_handle(msg, devlink);
3751 if (err)
3752 goto out_cancel_msg;
3753
3754 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
3755 region->ops->name);
3756 if (err)
3757 goto out_cancel_msg;
3758
3759 if (snapshot) {
3760 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
3761 snapshot->id);
3762 if (err)
3763 goto out_cancel_msg;
3764 } else {
3765 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3766 region->size, DEVLINK_ATTR_PAD);
3767 if (err)
3768 goto out_cancel_msg;
3769 }
3770 genlmsg_end(msg, hdr);
3771
3772 return msg;
3773
3774out_cancel_msg:
3775 genlmsg_cancel(msg, hdr);
3776out_free_msg:
3777 nlmsg_free(msg);
3778 return ERR_PTR(err);
3779}
3780
3781static void devlink_nl_region_notify(struct devlink_region *region,
3782 struct devlink_snapshot *snapshot,
3783 enum devlink_command cmd)
3784{
3785 struct devlink *devlink = region->devlink;
3786 struct sk_buff *msg;
3787
3788 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
3789
3790 msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
3791 if (IS_ERR(msg))
3792 return;
3793
3794 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3795 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3796}
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
3814{
3815 unsigned long count;
3816 void *p;
3817
3818 lockdep_assert_held(&devlink->lock);
3819
3820 p = xa_load(&devlink->snapshot_ids, id);
3821 if (WARN_ON(!p))
3822 return -EINVAL;
3823
3824 if (WARN_ON(!xa_is_value(p)))
3825 return -EINVAL;
3826
3827 count = xa_to_value(p);
3828 count++;
3829
3830 return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
3831 GFP_KERNEL));
3832}
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
3850{
3851 unsigned long count;
3852 void *p;
3853
3854 lockdep_assert_held(&devlink->lock);
3855
3856 p = xa_load(&devlink->snapshot_ids, id);
3857 if (WARN_ON(!p))
3858 return;
3859
3860 if (WARN_ON(!xa_is_value(p)))
3861 return;
3862
3863 count = xa_to_value(p);
3864
3865 if (count > 1) {
3866 count--;
3867 xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
3868 GFP_KERNEL);
3869 } else {
3870
3871 xa_erase(&devlink->snapshot_ids, id);
3872 }
3873}
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
3892{
3893 lockdep_assert_held(&devlink->lock);
3894
3895 if (WARN_ON(xa_load(&devlink->snapshot_ids, id)))
3896 return -EEXIST;
3897
3898 return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
3899 GFP_KERNEL));
3900}
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
3919{
3920 lockdep_assert_held(&devlink->lock);
3921
3922 return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
3923 xa_limit_32b, GFP_KERNEL);
3924}
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940static int
3941__devlink_region_snapshot_create(struct devlink_region *region,
3942 u8 *data, u32 snapshot_id)
3943{
3944 struct devlink *devlink = region->devlink;
3945 struct devlink_snapshot *snapshot;
3946 int err;
3947
3948 lockdep_assert_held(&devlink->lock);
3949
3950
3951 if (region->cur_snapshots == region->max_snapshots)
3952 return -ENOSPC;
3953
3954 if (devlink_region_snapshot_get_by_id(region, snapshot_id))
3955 return -EEXIST;
3956
3957 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
3958 if (!snapshot)
3959 return -ENOMEM;
3960
3961 err = __devlink_snapshot_id_increment(devlink, snapshot_id);
3962 if (err)
3963 goto err_snapshot_id_increment;
3964
3965 snapshot->id = snapshot_id;
3966 snapshot->region = region;
3967 snapshot->data = data;
3968
3969 list_add_tail(&snapshot->list, ®ion->snapshot_list);
3970
3971 region->cur_snapshots++;
3972
3973 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
3974 return 0;
3975
3976err_snapshot_id_increment:
3977 kfree(snapshot);
3978 return err;
3979}
3980
3981static void devlink_region_snapshot_del(struct devlink_region *region,
3982 struct devlink_snapshot *snapshot)
3983{
3984 struct devlink *devlink = region->devlink;
3985
3986 lockdep_assert_held(&devlink->lock);
3987
3988 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
3989 region->cur_snapshots--;
3990 list_del(&snapshot->list);
3991 region->ops->destructor(snapshot->data);
3992 __devlink_snapshot_id_decrement(devlink, snapshot->id);
3993 kfree(snapshot);
3994}
3995
3996static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
3997 struct genl_info *info)
3998{
3999 struct devlink *devlink = info->user_ptr[0];
4000 struct devlink_region *region;
4001 const char *region_name;
4002 struct sk_buff *msg;
4003 int err;
4004
4005 if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
4006 return -EINVAL;
4007
4008 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
4009 region = devlink_region_get_by_name(devlink, region_name);
4010 if (!region)
4011 return -EINVAL;
4012
4013 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4014 if (!msg)
4015 return -ENOMEM;
4016
4017 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
4018 info->snd_portid, info->snd_seq, 0,
4019 region);
4020 if (err) {
4021 nlmsg_free(msg);
4022 return err;
4023 }
4024
4025 return genlmsg_reply(msg, info);
4026}
4027
4028static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
4029 struct netlink_callback *cb)
4030{
4031 struct devlink_region *region;
4032 struct devlink *devlink;
4033 int start = cb->args[0];
4034 int idx = 0;
4035 int err;
4036
4037 mutex_lock(&devlink_mutex);
4038 list_for_each_entry(devlink, &devlink_list, list) {
4039 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4040 continue;
4041
4042 mutex_lock(&devlink->lock);
4043 list_for_each_entry(region, &devlink->region_list, list) {
4044 if (idx < start) {
4045 idx++;
4046 continue;
4047 }
4048 err = devlink_nl_region_fill(msg, devlink,
4049 DEVLINK_CMD_REGION_GET,
4050 NETLINK_CB(cb->skb).portid,
4051 cb->nlh->nlmsg_seq,
4052 NLM_F_MULTI, region);
4053 if (err) {
4054 mutex_unlock(&devlink->lock);
4055 goto out;
4056 }
4057 idx++;
4058 }
4059 mutex_unlock(&devlink->lock);
4060 }
4061out:
4062 mutex_unlock(&devlink_mutex);
4063 cb->args[0] = idx;
4064 return msg->len;
4065}
4066
4067static int devlink_nl_cmd_region_del(struct sk_buff *skb,
4068 struct genl_info *info)
4069{
4070 struct devlink *devlink = info->user_ptr[0];
4071 struct devlink_snapshot *snapshot;
4072 struct devlink_region *region;
4073 const char *region_name;
4074 u32 snapshot_id;
4075
4076 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
4077 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
4078 return -EINVAL;
4079
4080 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
4081 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
4082
4083 region = devlink_region_get_by_name(devlink, region_name);
4084 if (!region)
4085 return -EINVAL;
4086
4087 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
4088 if (!snapshot)
4089 return -EINVAL;
4090
4091 devlink_region_snapshot_del(region, snapshot);
4092 return 0;
4093}
4094
4095static int
4096devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
4097{
4098 struct devlink *devlink = info->user_ptr[0];
4099 struct devlink_snapshot *snapshot;
4100 struct nlattr *snapshot_id_attr;
4101 struct devlink_region *region;
4102 const char *region_name;
4103 u32 snapshot_id;
4104 u8 *data;
4105 int err;
4106
4107 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) {
4108 NL_SET_ERR_MSG_MOD(info->extack, "No region name provided");
4109 return -EINVAL;
4110 }
4111
4112 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
4113 region = devlink_region_get_by_name(devlink, region_name);
4114 if (!region) {
4115 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not exist");
4116 return -EINVAL;
4117 }
4118
4119 if (!region->ops->snapshot) {
4120 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not support taking an immediate snapshot");
4121 return -EOPNOTSUPP;
4122 }
4123
4124 if (region->cur_snapshots == region->max_snapshots) {
4125 NL_SET_ERR_MSG_MOD(info->extack, "The region has reached the maximum number of stored snapshots");
4126 return -ENOSPC;
4127 }
4128
4129 snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
4130 if (snapshot_id_attr) {
4131 snapshot_id = nla_get_u32(snapshot_id_attr);
4132
4133 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
4134 NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use");
4135 return -EEXIST;
4136 }
4137
4138 err = __devlink_snapshot_id_insert(devlink, snapshot_id);
4139 if (err)
4140 return err;
4141 } else {
4142 err = __devlink_region_snapshot_id_get(devlink, &snapshot_id);
4143 if (err) {
4144 NL_SET_ERR_MSG_MOD(info->extack, "Failed to allocate a new snapshot id");
4145 return err;
4146 }
4147 }
4148
4149 err = region->ops->snapshot(devlink, info->extack, &data);
4150 if (err)
4151 goto err_snapshot_capture;
4152
4153 err = __devlink_region_snapshot_create(region, data, snapshot_id);
4154 if (err)
4155 goto err_snapshot_create;
4156
4157 if (!snapshot_id_attr) {
4158 struct sk_buff *msg;
4159
4160 snapshot = devlink_region_snapshot_get_by_id(region,
4161 snapshot_id);
4162 if (WARN_ON(!snapshot))
4163 return -EINVAL;
4164
4165 msg = devlink_nl_region_notify_build(region, snapshot,
4166 DEVLINK_CMD_REGION_NEW,
4167 info->snd_portid,
4168 info->snd_seq);
4169 err = PTR_ERR_OR_ZERO(msg);
4170 if (err)
4171 goto err_notify;
4172
4173 err = genlmsg_reply(msg, info);
4174 if (err)
4175 goto err_notify;
4176 }
4177
4178 return 0;
4179
4180err_snapshot_create:
4181 region->ops->destructor(data);
4182err_snapshot_capture:
4183 __devlink_snapshot_id_decrement(devlink, snapshot_id);
4184 return err;
4185
4186err_notify:
4187 devlink_region_snapshot_del(region, snapshot);
4188 return err;
4189}
4190
4191static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
4192 struct devlink *devlink,
4193 u8 *chunk, u32 chunk_size,
4194 u64 addr)
4195{
4196 struct nlattr *chunk_attr;
4197 int err;
4198
4199 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
4200 if (!chunk_attr)
4201 return -EINVAL;
4202
4203 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
4204 if (err)
4205 goto nla_put_failure;
4206
4207 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
4208 DEVLINK_ATTR_PAD);
4209 if (err)
4210 goto nla_put_failure;
4211
4212 nla_nest_end(msg, chunk_attr);
4213 return 0;
4214
4215nla_put_failure:
4216 nla_nest_cancel(msg, chunk_attr);
4217 return err;
4218}
4219
4220#define DEVLINK_REGION_READ_CHUNK_SIZE 256
4221
4222static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
4223 struct devlink *devlink,
4224 struct devlink_region *region,
4225 struct nlattr **attrs,
4226 u64 start_offset,
4227 u64 end_offset,
4228 u64 *new_offset)
4229{
4230 struct devlink_snapshot *snapshot;
4231 u64 curr_offset = start_offset;
4232 u32 snapshot_id;
4233 int err = 0;
4234
4235 *new_offset = start_offset;
4236
4237 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
4238 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
4239 if (!snapshot)
4240 return -EINVAL;
4241
4242 while (curr_offset < end_offset) {
4243 u32 data_size;
4244 u8 *data;
4245
4246 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
4247 data_size = end_offset - curr_offset;
4248 else
4249 data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
4250
4251 data = &snapshot->data[curr_offset];
4252 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
4253 data, data_size,
4254 curr_offset);
4255 if (err)
4256 break;
4257
4258 curr_offset += data_size;
4259 }
4260 *new_offset = curr_offset;
4261
4262 return err;
4263}
4264
4265static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
4266 struct netlink_callback *cb)
4267{
4268 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
4269 u64 ret_offset, start_offset, end_offset = U64_MAX;
4270 struct nlattr **attrs = info->attrs;
4271 struct devlink_region *region;
4272 struct nlattr *chunks_attr;
4273 const char *region_name;
4274 struct devlink *devlink;
4275 void *hdr;
4276 int err;
4277
4278 start_offset = *((u64 *)&cb->args[0]);
4279
4280 mutex_lock(&devlink_mutex);
4281 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
4282 if (IS_ERR(devlink)) {
4283 err = PTR_ERR(devlink);
4284 goto out_dev;
4285 }
4286
4287 mutex_lock(&devlink->lock);
4288
4289 if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
4290 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) {
4291 err = -EINVAL;
4292 goto out_unlock;
4293 }
4294
4295 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
4296 region = devlink_region_get_by_name(devlink, region_name);
4297 if (!region) {
4298 err = -EINVAL;
4299 goto out_unlock;
4300 }
4301
4302 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
4303 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
4304 if (!start_offset)
4305 start_offset =
4306 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
4307
4308 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
4309 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
4310 }
4311
4312 if (end_offset > region->size)
4313 end_offset = region->size;
4314
4315
4316 if (start_offset == end_offset) {
4317 err = 0;
4318 goto out_unlock;
4319 }
4320
4321 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
4322 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
4323 DEVLINK_CMD_REGION_READ);
4324 if (!hdr) {
4325 err = -EMSGSIZE;
4326 goto out_unlock;
4327 }
4328
4329 err = devlink_nl_put_handle(skb, devlink);
4330 if (err)
4331 goto nla_put_failure;
4332
4333 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
4334 if (err)
4335 goto nla_put_failure;
4336
4337 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
4338 if (!chunks_attr) {
4339 err = -EMSGSIZE;
4340 goto nla_put_failure;
4341 }
4342
4343 err = devlink_nl_region_read_snapshot_fill(skb, devlink,
4344 region, attrs,
4345 start_offset,
4346 end_offset, &ret_offset);
4347
4348 if (err && err != -EMSGSIZE)
4349 goto nla_put_failure;
4350
4351
4352 if (ret_offset == start_offset) {
4353 err = -EINVAL;
4354 goto nla_put_failure;
4355 }
4356
4357 *((u64 *)&cb->args[0]) = ret_offset;
4358
4359 nla_nest_end(skb, chunks_attr);
4360 genlmsg_end(skb, hdr);
4361 mutex_unlock(&devlink->lock);
4362 mutex_unlock(&devlink_mutex);
4363
4364 return skb->len;
4365
4366nla_put_failure:
4367 genlmsg_cancel(skb, hdr);
4368out_unlock:
4369 mutex_unlock(&devlink->lock);
4370out_dev:
4371 mutex_unlock(&devlink_mutex);
4372 return err;
4373}
4374
4375struct devlink_info_req {
4376 struct sk_buff *msg;
4377};
4378
4379int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
4380{
4381 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
4382}
4383EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
4384
4385int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
4386{
4387 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
4388}
4389EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
4390
4391static int devlink_info_version_put(struct devlink_info_req *req, int attr,
4392 const char *version_name,
4393 const char *version_value)
4394{
4395 struct nlattr *nest;
4396 int err;
4397
4398 nest = nla_nest_start_noflag(req->msg, attr);
4399 if (!nest)
4400 return -EMSGSIZE;
4401
4402 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
4403 version_name);
4404 if (err)
4405 goto nla_put_failure;
4406
4407 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
4408 version_value);
4409 if (err)
4410 goto nla_put_failure;
4411
4412 nla_nest_end(req->msg, nest);
4413
4414 return 0;
4415
4416nla_put_failure:
4417 nla_nest_cancel(req->msg, nest);
4418 return err;
4419}
4420
4421int devlink_info_version_fixed_put(struct devlink_info_req *req,
4422 const char *version_name,
4423 const char *version_value)
4424{
4425 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
4426 version_name, version_value);
4427}
4428EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
4429
4430int devlink_info_version_stored_put(struct devlink_info_req *req,
4431 const char *version_name,
4432 const char *version_value)
4433{
4434 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
4435 version_name, version_value);
4436}
4437EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
4438
4439int devlink_info_version_running_put(struct devlink_info_req *req,
4440 const char *version_name,
4441 const char *version_value)
4442{
4443 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
4444 version_name, version_value);
4445}
4446EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
4447
4448static int
4449devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
4450 enum devlink_command cmd, u32 portid,
4451 u32 seq, int flags, struct netlink_ext_ack *extack)
4452{
4453 struct devlink_info_req req;
4454 void *hdr;
4455 int err;
4456
4457 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4458 if (!hdr)
4459 return -EMSGSIZE;
4460
4461 err = -EMSGSIZE;
4462 if (devlink_nl_put_handle(msg, devlink))
4463 goto err_cancel_msg;
4464
4465 req.msg = msg;
4466 err = devlink->ops->info_get(devlink, &req, extack);
4467 if (err)
4468 goto err_cancel_msg;
4469
4470 genlmsg_end(msg, hdr);
4471 return 0;
4472
4473err_cancel_msg:
4474 genlmsg_cancel(msg, hdr);
4475 return err;
4476}
4477
4478static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
4479 struct genl_info *info)
4480{
4481 struct devlink *devlink = info->user_ptr[0];
4482 struct sk_buff *msg;
4483 int err;
4484
4485 if (!devlink->ops->info_get)
4486 return -EOPNOTSUPP;
4487
4488 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4489 if (!msg)
4490 return -ENOMEM;
4491
4492 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4493 info->snd_portid, info->snd_seq, 0,
4494 info->extack);
4495 if (err) {
4496 nlmsg_free(msg);
4497 return err;
4498 }
4499
4500 return genlmsg_reply(msg, info);
4501}
4502
4503static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
4504 struct netlink_callback *cb)
4505{
4506 struct devlink *devlink;
4507 int start = cb->args[0];
4508 int idx = 0;
4509 int err = 0;
4510
4511 mutex_lock(&devlink_mutex);
4512 list_for_each_entry(devlink, &devlink_list, list) {
4513 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4514 continue;
4515 if (idx < start) {
4516 idx++;
4517 continue;
4518 }
4519
4520 if (!devlink->ops->info_get) {
4521 idx++;
4522 continue;
4523 }
4524
4525 mutex_lock(&devlink->lock);
4526 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4527 NETLINK_CB(cb->skb).portid,
4528 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4529 cb->extack);
4530 mutex_unlock(&devlink->lock);
4531 if (err == -EOPNOTSUPP)
4532 err = 0;
4533 else if (err)
4534 break;
4535 idx++;
4536 }
4537 mutex_unlock(&devlink_mutex);
4538
4539 if (err != -EMSGSIZE)
4540 return err;
4541
4542 cb->args[0] = idx;
4543 return msg->len;
4544}
4545
4546struct devlink_fmsg_item {
4547 struct list_head list;
4548 int attrtype;
4549 u8 nla_type;
4550 u16 len;
4551 int value[];
4552};
4553
4554struct devlink_fmsg {
4555 struct list_head item_list;
4556 bool putting_binary;
4557
4558
4559
4560
4561
4562};
4563
4564static struct devlink_fmsg *devlink_fmsg_alloc(void)
4565{
4566 struct devlink_fmsg *fmsg;
4567
4568 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
4569 if (!fmsg)
4570 return NULL;
4571
4572 INIT_LIST_HEAD(&fmsg->item_list);
4573
4574 return fmsg;
4575}
4576
4577static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
4578{
4579 struct devlink_fmsg_item *item, *tmp;
4580
4581 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
4582 list_del(&item->list);
4583 kfree(item);
4584 }
4585 kfree(fmsg);
4586}
4587
4588static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
4589 int attrtype)
4590{
4591 struct devlink_fmsg_item *item;
4592
4593 item = kzalloc(sizeof(*item), GFP_KERNEL);
4594 if (!item)
4595 return -ENOMEM;
4596
4597 item->attrtype = attrtype;
4598 list_add_tail(&item->list, &fmsg->item_list);
4599
4600 return 0;
4601}
4602
4603int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
4604{
4605 if (fmsg->putting_binary)
4606 return -EINVAL;
4607
4608 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
4609}
4610EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
4611
4612static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
4613{
4614 if (fmsg->putting_binary)
4615 return -EINVAL;
4616
4617 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
4618}
4619
4620int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
4621{
4622 if (fmsg->putting_binary)
4623 return -EINVAL;
4624
4625 return devlink_fmsg_nest_end(fmsg);
4626}
4627EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
4628
4629#define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
4630
4631static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
4632{
4633 struct devlink_fmsg_item *item;
4634
4635 if (fmsg->putting_binary)
4636 return -EINVAL;
4637
4638 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
4639 return -EMSGSIZE;
4640
4641 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
4642 if (!item)
4643 return -ENOMEM;
4644
4645 item->nla_type = NLA_NUL_STRING;
4646 item->len = strlen(name) + 1;
4647 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
4648 memcpy(&item->value, name, item->len);
4649 list_add_tail(&item->list, &fmsg->item_list);
4650
4651 return 0;
4652}
4653
4654int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
4655{
4656 int err;
4657
4658 if (fmsg->putting_binary)
4659 return -EINVAL;
4660
4661 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
4662 if (err)
4663 return err;
4664
4665 err = devlink_fmsg_put_name(fmsg, name);
4666 if (err)
4667 return err;
4668
4669 return 0;
4670}
4671EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
4672
4673int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
4674{
4675 if (fmsg->putting_binary)
4676 return -EINVAL;
4677
4678 return devlink_fmsg_nest_end(fmsg);
4679}
4680EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
4681
4682int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
4683 const char *name)
4684{
4685 int err;
4686
4687 if (fmsg->putting_binary)
4688 return -EINVAL;
4689
4690 err = devlink_fmsg_pair_nest_start(fmsg, name);
4691 if (err)
4692 return err;
4693
4694 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
4695 if (err)
4696 return err;
4697
4698 return 0;
4699}
4700EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
4701
4702int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
4703{
4704 int err;
4705
4706 if (fmsg->putting_binary)
4707 return -EINVAL;
4708
4709 err = devlink_fmsg_nest_end(fmsg);
4710 if (err)
4711 return err;
4712
4713 err = devlink_fmsg_nest_end(fmsg);
4714 if (err)
4715 return err;
4716
4717 return 0;
4718}
4719EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
4720
4721int devlink_fmsg_binary_pair_nest_start(struct devlink_fmsg *fmsg,
4722 const char *name)
4723{
4724 int err;
4725
4726 err = devlink_fmsg_arr_pair_nest_start(fmsg, name);
4727 if (err)
4728 return err;
4729
4730 fmsg->putting_binary = true;
4731 return err;
4732}
4733EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_start);
4734
4735int devlink_fmsg_binary_pair_nest_end(struct devlink_fmsg *fmsg)
4736{
4737 if (!fmsg->putting_binary)
4738 return -EINVAL;
4739
4740 fmsg->putting_binary = false;
4741 return devlink_fmsg_arr_pair_nest_end(fmsg);
4742}
4743EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_end);
4744
4745static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
4746 const void *value, u16 value_len,
4747 u8 value_nla_type)
4748{
4749 struct devlink_fmsg_item *item;
4750
4751 if (value_len > DEVLINK_FMSG_MAX_SIZE)
4752 return -EMSGSIZE;
4753
4754 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
4755 if (!item)
4756 return -ENOMEM;
4757
4758 item->nla_type = value_nla_type;
4759 item->len = value_len;
4760 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4761 memcpy(&item->value, value, item->len);
4762 list_add_tail(&item->list, &fmsg->item_list);
4763
4764 return 0;
4765}
4766
4767int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
4768{
4769 if (fmsg->putting_binary)
4770 return -EINVAL;
4771
4772 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG);
4773}
4774EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put);
4775
4776int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
4777{
4778 if (fmsg->putting_binary)
4779 return -EINVAL;
4780
4781 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
4782}
4783EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put);
4784
4785int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
4786{
4787 if (fmsg->putting_binary)
4788 return -EINVAL;
4789
4790 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
4791}
4792EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
4793
4794int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
4795{
4796 if (fmsg->putting_binary)
4797 return -EINVAL;
4798
4799 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
4800}
4801EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put);
4802
4803int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
4804{
4805 if (fmsg->putting_binary)
4806 return -EINVAL;
4807
4808 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
4809 NLA_NUL_STRING);
4810}
4811EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
4812
4813int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
4814 u16 value_len)
4815{
4816 if (!fmsg->putting_binary)
4817 return -EINVAL;
4818
4819 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
4820}
4821EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
4822
4823int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
4824 bool value)
4825{
4826 int err;
4827
4828 err = devlink_fmsg_pair_nest_start(fmsg, name);
4829 if (err)
4830 return err;
4831
4832 err = devlink_fmsg_bool_put(fmsg, value);
4833 if (err)
4834 return err;
4835
4836 err = devlink_fmsg_pair_nest_end(fmsg);
4837 if (err)
4838 return err;
4839
4840 return 0;
4841}
4842EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
4843
4844int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
4845 u8 value)
4846{
4847 int err;
4848
4849 err = devlink_fmsg_pair_nest_start(fmsg, name);
4850 if (err)
4851 return err;
4852
4853 err = devlink_fmsg_u8_put(fmsg, value);
4854 if (err)
4855 return err;
4856
4857 err = devlink_fmsg_pair_nest_end(fmsg);
4858 if (err)
4859 return err;
4860
4861 return 0;
4862}
4863EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
4864
4865int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
4866 u32 value)
4867{
4868 int err;
4869
4870 err = devlink_fmsg_pair_nest_start(fmsg, name);
4871 if (err)
4872 return err;
4873
4874 err = devlink_fmsg_u32_put(fmsg, value);
4875 if (err)
4876 return err;
4877
4878 err = devlink_fmsg_pair_nest_end(fmsg);
4879 if (err)
4880 return err;
4881
4882 return 0;
4883}
4884EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
4885
4886int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
4887 u64 value)
4888{
4889 int err;
4890
4891 err = devlink_fmsg_pair_nest_start(fmsg, name);
4892 if (err)
4893 return err;
4894
4895 err = devlink_fmsg_u64_put(fmsg, value);
4896 if (err)
4897 return err;
4898
4899 err = devlink_fmsg_pair_nest_end(fmsg);
4900 if (err)
4901 return err;
4902
4903 return 0;
4904}
4905EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
4906
4907int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
4908 const char *value)
4909{
4910 int err;
4911
4912 err = devlink_fmsg_pair_nest_start(fmsg, name);
4913 if (err)
4914 return err;
4915
4916 err = devlink_fmsg_string_put(fmsg, value);
4917 if (err)
4918 return err;
4919
4920 err = devlink_fmsg_pair_nest_end(fmsg);
4921 if (err)
4922 return err;
4923
4924 return 0;
4925}
4926EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
4927
4928int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
4929 const void *value, u32 value_len)
4930{
4931 u32 data_size;
4932 int end_err;
4933 u32 offset;
4934 int err;
4935
4936 err = devlink_fmsg_binary_pair_nest_start(fmsg, name);
4937 if (err)
4938 return err;
4939
4940 for (offset = 0; offset < value_len; offset += data_size) {
4941 data_size = value_len - offset;
4942 if (data_size > DEVLINK_FMSG_MAX_SIZE)
4943 data_size = DEVLINK_FMSG_MAX_SIZE;
4944 err = devlink_fmsg_binary_put(fmsg, value + offset, data_size);
4945 if (err)
4946 break;
4947
4948
4949
4950
4951 }
4952
4953 end_err = devlink_fmsg_binary_pair_nest_end(fmsg);
4954 if (end_err)
4955 err = end_err;
4956
4957 return err;
4958}
4959EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
4960
4961static int
4962devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4963{
4964 switch (msg->nla_type) {
4965 case NLA_FLAG:
4966 case NLA_U8:
4967 case NLA_U32:
4968 case NLA_U64:
4969 case NLA_NUL_STRING:
4970 case NLA_BINARY:
4971 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
4972 msg->nla_type);
4973 default:
4974 return -EINVAL;
4975 }
4976}
4977
4978static int
4979devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4980{
4981 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4982 u8 tmp;
4983
4984 switch (msg->nla_type) {
4985 case NLA_FLAG:
4986
4987 tmp = *(bool *) msg->value;
4988
4989 return nla_put_u8(skb, attrtype, tmp);
4990 case NLA_U8:
4991 return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
4992 case NLA_U32:
4993 return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
4994 case NLA_U64:
4995 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
4996 DEVLINK_ATTR_PAD);
4997 case NLA_NUL_STRING:
4998 return nla_put_string(skb, attrtype, (char *) &msg->value);
4999 case NLA_BINARY:
5000 return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
5001 default:
5002 return -EINVAL;
5003 }
5004}
5005
5006static int
5007devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
5008 int *start)
5009{
5010 struct devlink_fmsg_item *item;
5011 struct nlattr *fmsg_nlattr;
5012 int i = 0;
5013 int err;
5014
5015 fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
5016 if (!fmsg_nlattr)
5017 return -EMSGSIZE;
5018
5019 list_for_each_entry(item, &fmsg->item_list, list) {
5020 if (i < *start) {
5021 i++;
5022 continue;
5023 }
5024
5025 switch (item->attrtype) {
5026 case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
5027 case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
5028 case DEVLINK_ATTR_FMSG_ARR_NEST_START:
5029 case DEVLINK_ATTR_FMSG_NEST_END:
5030 err = nla_put_flag(skb, item->attrtype);
5031 break;
5032 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
5033 err = devlink_fmsg_item_fill_type(item, skb);
5034 if (err)
5035 break;
5036 err = devlink_fmsg_item_fill_data(item, skb);
5037 break;
5038 case DEVLINK_ATTR_FMSG_OBJ_NAME:
5039 err = nla_put_string(skb, item->attrtype,
5040 (char *) &item->value);
5041 break;
5042 default:
5043 err = -EINVAL;
5044 break;
5045 }
5046 if (!err)
5047 *start = ++i;
5048 else
5049 break;
5050 }
5051
5052 nla_nest_end(skb, fmsg_nlattr);
5053 return err;
5054}
5055
5056static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
5057 struct genl_info *info,
5058 enum devlink_command cmd, int flags)
5059{
5060 struct nlmsghdr *nlh;
5061 struct sk_buff *skb;
5062 bool last = false;
5063 int index = 0;
5064 void *hdr;
5065 int err;
5066
5067 while (!last) {
5068 int tmp_index = index;
5069
5070 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
5071 if (!skb)
5072 return -ENOMEM;
5073
5074 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
5075 &devlink_nl_family, flags | NLM_F_MULTI, cmd);
5076 if (!hdr) {
5077 err = -EMSGSIZE;
5078 goto nla_put_failure;
5079 }
5080
5081 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
5082 if (!err)
5083 last = true;
5084 else if (err != -EMSGSIZE || tmp_index == index)
5085 goto nla_put_failure;
5086
5087 genlmsg_end(skb, hdr);
5088 err = genlmsg_reply(skb, info);
5089 if (err)
5090 return err;
5091 }
5092
5093 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
5094 if (!skb)
5095 return -ENOMEM;
5096 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
5097 NLMSG_DONE, 0, flags | NLM_F_MULTI);
5098 if (!nlh) {
5099 err = -EMSGSIZE;
5100 goto nla_put_failure;
5101 }
5102
5103 return genlmsg_reply(skb, info);
5104
5105nla_put_failure:
5106 nlmsg_free(skb);
5107 return err;
5108}
5109
5110static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
5111 struct netlink_callback *cb,
5112 enum devlink_command cmd)
5113{
5114 int index = cb->args[0];
5115 int tmp_index = index;
5116 void *hdr;
5117 int err;
5118
5119 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
5120 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd);
5121 if (!hdr) {
5122 err = -EMSGSIZE;
5123 goto nla_put_failure;
5124 }
5125
5126 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
5127 if ((err && err != -EMSGSIZE) || tmp_index == index)
5128 goto nla_put_failure;
5129
5130 cb->args[0] = index;
5131 genlmsg_end(skb, hdr);
5132 return skb->len;
5133
5134nla_put_failure:
5135 genlmsg_cancel(skb, hdr);
5136 return err;
5137}
5138
5139struct devlink_health_reporter {
5140 struct list_head list;
5141 void *priv;
5142 const struct devlink_health_reporter_ops *ops;
5143 struct devlink *devlink;
5144 struct devlink_fmsg *dump_fmsg;
5145 struct mutex dump_lock;
5146 u64 graceful_period;
5147 bool auto_recover;
5148 bool auto_dump;
5149 u8 health_state;
5150 u64 dump_ts;
5151 u64 dump_real_ts;
5152 u64 error_count;
5153 u64 recovery_count;
5154 u64 last_recovery_ts;
5155 refcount_t refcount;
5156};
5157
5158void *
5159devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
5160{
5161 return reporter->priv;
5162}
5163EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
5164
5165static struct devlink_health_reporter *
5166devlink_health_reporter_find_by_name(struct devlink *devlink,
5167 const char *reporter_name)
5168{
5169 struct devlink_health_reporter *reporter;
5170
5171 lockdep_assert_held(&devlink->reporters_lock);
5172 list_for_each_entry(reporter, &devlink->reporter_list, list)
5173 if (!strcmp(reporter->ops->name, reporter_name))
5174 return reporter;
5175 return NULL;
5176}
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186struct devlink_health_reporter *
5187devlink_health_reporter_create(struct devlink *devlink,
5188 const struct devlink_health_reporter_ops *ops,
5189 u64 graceful_period, void *priv)
5190{
5191 struct devlink_health_reporter *reporter;
5192
5193 mutex_lock(&devlink->reporters_lock);
5194 if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
5195 reporter = ERR_PTR(-EEXIST);
5196 goto unlock;
5197 }
5198
5199 if (WARN_ON(graceful_period && !ops->recover)) {
5200 reporter = ERR_PTR(-EINVAL);
5201 goto unlock;
5202 }
5203
5204 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
5205 if (!reporter) {
5206 reporter = ERR_PTR(-ENOMEM);
5207 goto unlock;
5208 }
5209
5210 reporter->priv = priv;
5211 reporter->ops = ops;
5212 reporter->devlink = devlink;
5213 reporter->graceful_period = graceful_period;
5214 reporter->auto_recover = !!ops->recover;
5215 reporter->auto_dump = !!ops->dump;
5216 mutex_init(&reporter->dump_lock);
5217 refcount_set(&reporter->refcount, 1);
5218 list_add_tail(&reporter->list, &devlink->reporter_list);
5219unlock:
5220 mutex_unlock(&devlink->reporters_lock);
5221 return reporter;
5222}
5223EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
5224
5225
5226
5227
5228
5229
5230void
5231devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
5232{
5233 mutex_lock(&reporter->devlink->reporters_lock);
5234 list_del(&reporter->list);
5235 mutex_unlock(&reporter->devlink->reporters_lock);
5236 while (refcount_read(&reporter->refcount) > 1)
5237 msleep(100);
5238 mutex_destroy(&reporter->dump_lock);
5239 if (reporter->dump_fmsg)
5240 devlink_fmsg_free(reporter->dump_fmsg);
5241 kfree(reporter);
5242}
5243EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
5244
5245static int
5246devlink_nl_health_reporter_fill(struct sk_buff *msg,
5247 struct devlink *devlink,
5248 struct devlink_health_reporter *reporter,
5249 enum devlink_command cmd, u32 portid,
5250 u32 seq, int flags)
5251{
5252 struct nlattr *reporter_attr;
5253 void *hdr;
5254
5255 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5256 if (!hdr)
5257 return -EMSGSIZE;
5258
5259 if (devlink_nl_put_handle(msg, devlink))
5260 goto genlmsg_cancel;
5261
5262 reporter_attr = nla_nest_start_noflag(msg,
5263 DEVLINK_ATTR_HEALTH_REPORTER);
5264 if (!reporter_attr)
5265 goto genlmsg_cancel;
5266 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
5267 reporter->ops->name))
5268 goto reporter_nest_cancel;
5269 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
5270 reporter->health_state))
5271 goto reporter_nest_cancel;
5272 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
5273 reporter->error_count, DEVLINK_ATTR_PAD))
5274 goto reporter_nest_cancel;
5275 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
5276 reporter->recovery_count, DEVLINK_ATTR_PAD))
5277 goto reporter_nest_cancel;
5278 if (reporter->ops->recover &&
5279 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
5280 reporter->graceful_period,
5281 DEVLINK_ATTR_PAD))
5282 goto reporter_nest_cancel;
5283 if (reporter->ops->recover &&
5284 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
5285 reporter->auto_recover))
5286 goto reporter_nest_cancel;
5287 if (reporter->dump_fmsg &&
5288 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
5289 jiffies_to_msecs(reporter->dump_ts),
5290 DEVLINK_ATTR_PAD))
5291 goto reporter_nest_cancel;
5292 if (reporter->dump_fmsg &&
5293 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
5294 reporter->dump_real_ts, DEVLINK_ATTR_PAD))
5295 goto reporter_nest_cancel;
5296 if (reporter->ops->dump &&
5297 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP,
5298 reporter->auto_dump))
5299 goto reporter_nest_cancel;
5300
5301 nla_nest_end(msg, reporter_attr);
5302 genlmsg_end(msg, hdr);
5303 return 0;
5304
5305reporter_nest_cancel:
5306 nla_nest_end(msg, reporter_attr);
5307genlmsg_cancel:
5308 genlmsg_cancel(msg, hdr);
5309 return -EMSGSIZE;
5310}
5311
5312static void devlink_recover_notify(struct devlink_health_reporter *reporter,
5313 enum devlink_command cmd)
5314{
5315 struct sk_buff *msg;
5316 int err;
5317
5318 WARN_ON(cmd != DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
5319
5320 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5321 if (!msg)
5322 return;
5323
5324 err = devlink_nl_health_reporter_fill(msg, reporter->devlink,
5325 reporter, cmd, 0, 0, 0);
5326 if (err) {
5327 nlmsg_free(msg);
5328 return;
5329 }
5330
5331 genlmsg_multicast_netns(&devlink_nl_family,
5332 devlink_net(reporter->devlink),
5333 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
5334}
5335
5336void
5337devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter)
5338{
5339 reporter->recovery_count++;
5340 reporter->last_recovery_ts = jiffies;
5341}
5342EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done);
5343
5344static int
5345devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
5346 void *priv_ctx, struct netlink_ext_ack *extack)
5347{
5348 int err;
5349
5350 if (reporter->health_state == DEVLINK_HEALTH_REPORTER_STATE_HEALTHY)
5351 return 0;
5352
5353 if (!reporter->ops->recover)
5354 return -EOPNOTSUPP;
5355
5356 err = reporter->ops->recover(reporter, priv_ctx, extack);
5357 if (err)
5358 return err;
5359
5360 devlink_health_reporter_recovery_done(reporter);
5361 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
5362 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
5363
5364 return 0;
5365}
5366
5367static void
5368devlink_health_dump_clear(struct devlink_health_reporter *reporter)
5369{
5370 if (!reporter->dump_fmsg)
5371 return;
5372 devlink_fmsg_free(reporter->dump_fmsg);
5373 reporter->dump_fmsg = NULL;
5374}
5375
5376static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
5377 void *priv_ctx,
5378 struct netlink_ext_ack *extack)
5379{
5380 int err;
5381
5382 if (!reporter->ops->dump)
5383 return 0;
5384
5385 if (reporter->dump_fmsg)
5386 return 0;
5387
5388 reporter->dump_fmsg = devlink_fmsg_alloc();
5389 if (!reporter->dump_fmsg) {
5390 err = -ENOMEM;
5391 return err;
5392 }
5393
5394 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
5395 if (err)
5396 goto dump_err;
5397
5398 err = reporter->ops->dump(reporter, reporter->dump_fmsg,
5399 priv_ctx, extack);
5400 if (err)
5401 goto dump_err;
5402
5403 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
5404 if (err)
5405 goto dump_err;
5406
5407 reporter->dump_ts = jiffies;
5408 reporter->dump_real_ts = ktime_get_real_ns();
5409
5410 return 0;
5411
5412dump_err:
5413 devlink_health_dump_clear(reporter);
5414 return err;
5415}
5416
5417int devlink_health_report(struct devlink_health_reporter *reporter,
5418 const char *msg, void *priv_ctx)
5419{
5420 enum devlink_health_reporter_state prev_health_state;
5421 struct devlink *devlink = reporter->devlink;
5422 unsigned long recover_ts_threshold;
5423
5424
5425 WARN_ON(!msg);
5426 trace_devlink_health_report(devlink, reporter->ops->name, msg);
5427 reporter->error_count++;
5428 prev_health_state = reporter->health_state;
5429 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
5430 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
5431
5432
5433 recover_ts_threshold = reporter->last_recovery_ts +
5434 msecs_to_jiffies(reporter->graceful_period);
5435 if (reporter->auto_recover &&
5436 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
5437 (reporter->last_recovery_ts && reporter->recovery_count &&
5438 time_is_after_jiffies(recover_ts_threshold)))) {
5439 trace_devlink_health_recover_aborted(devlink,
5440 reporter->ops->name,
5441 reporter->health_state,
5442 jiffies -
5443 reporter->last_recovery_ts);
5444 return -ECANCELED;
5445 }
5446
5447 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
5448
5449 if (reporter->auto_dump) {
5450 mutex_lock(&reporter->dump_lock);
5451
5452 devlink_health_do_dump(reporter, priv_ctx, NULL);
5453 mutex_unlock(&reporter->dump_lock);
5454 }
5455
5456 if (reporter->auto_recover)
5457 return devlink_health_reporter_recover(reporter,
5458 priv_ctx, NULL);
5459
5460 return 0;
5461}
5462EXPORT_SYMBOL_GPL(devlink_health_report);
5463
5464static struct devlink_health_reporter *
5465devlink_health_reporter_get_from_attrs(struct devlink *devlink,
5466 struct nlattr **attrs)
5467{
5468 struct devlink_health_reporter *reporter;
5469 char *reporter_name;
5470
5471 if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
5472 return NULL;
5473
5474 reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
5475 mutex_lock(&devlink->reporters_lock);
5476 reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
5477 if (reporter)
5478 refcount_inc(&reporter->refcount);
5479 mutex_unlock(&devlink->reporters_lock);
5480 return reporter;
5481}
5482
5483static struct devlink_health_reporter *
5484devlink_health_reporter_get_from_info(struct devlink *devlink,
5485 struct genl_info *info)
5486{
5487 return devlink_health_reporter_get_from_attrs(devlink, info->attrs);
5488}
5489
5490static struct devlink_health_reporter *
5491devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
5492{
5493 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
5494 struct devlink_health_reporter *reporter;
5495 struct nlattr **attrs = info->attrs;
5496 struct devlink *devlink;
5497
5498 mutex_lock(&devlink_mutex);
5499 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
5500 if (IS_ERR(devlink))
5501 goto unlock;
5502
5503 reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
5504 mutex_unlock(&devlink_mutex);
5505 return reporter;
5506unlock:
5507 mutex_unlock(&devlink_mutex);
5508 return NULL;
5509}
5510
5511static void
5512devlink_health_reporter_put(struct devlink_health_reporter *reporter)
5513{
5514 refcount_dec(&reporter->refcount);
5515}
5516
5517void
5518devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
5519 enum devlink_health_reporter_state state)
5520{
5521 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
5522 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
5523 return;
5524
5525 if (reporter->health_state == state)
5526 return;
5527
5528 reporter->health_state = state;
5529 trace_devlink_health_reporter_state_update(reporter->devlink,
5530 reporter->ops->name, state);
5531 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
5532}
5533EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
5534
5535static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
5536 struct genl_info *info)
5537{
5538 struct devlink *devlink = info->user_ptr[0];
5539 struct devlink_health_reporter *reporter;
5540 struct sk_buff *msg;
5541 int err;
5542
5543 reporter = devlink_health_reporter_get_from_info(devlink, info);
5544 if (!reporter)
5545 return -EINVAL;
5546
5547 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5548 if (!msg) {
5549 err = -ENOMEM;
5550 goto out;
5551 }
5552
5553 err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
5554 DEVLINK_CMD_HEALTH_REPORTER_GET,
5555 info->snd_portid, info->snd_seq,
5556 0);
5557 if (err) {
5558 nlmsg_free(msg);
5559 goto out;
5560 }
5561
5562 err = genlmsg_reply(msg, info);
5563out:
5564 devlink_health_reporter_put(reporter);
5565 return err;
5566}
5567
5568static int
5569devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
5570 struct netlink_callback *cb)
5571{
5572 struct devlink_health_reporter *reporter;
5573 struct devlink *devlink;
5574 int start = cb->args[0];
5575 int idx = 0;
5576 int err;
5577
5578 mutex_lock(&devlink_mutex);
5579 list_for_each_entry(devlink, &devlink_list, list) {
5580 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5581 continue;
5582 mutex_lock(&devlink->reporters_lock);
5583 list_for_each_entry(reporter, &devlink->reporter_list,
5584 list) {
5585 if (idx < start) {
5586 idx++;
5587 continue;
5588 }
5589 err = devlink_nl_health_reporter_fill(msg, devlink,
5590 reporter,
5591 DEVLINK_CMD_HEALTH_REPORTER_GET,
5592 NETLINK_CB(cb->skb).portid,
5593 cb->nlh->nlmsg_seq,
5594 NLM_F_MULTI);
5595 if (err) {
5596 mutex_unlock(&devlink->reporters_lock);
5597 goto out;
5598 }
5599 idx++;
5600 }
5601 mutex_unlock(&devlink->reporters_lock);
5602 }
5603out:
5604 mutex_unlock(&devlink_mutex);
5605
5606 cb->args[0] = idx;
5607 return msg->len;
5608}
5609
5610static int
5611devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
5612 struct genl_info *info)
5613{
5614 struct devlink *devlink = info->user_ptr[0];
5615 struct devlink_health_reporter *reporter;
5616 int err;
5617
5618 reporter = devlink_health_reporter_get_from_info(devlink, info);
5619 if (!reporter)
5620 return -EINVAL;
5621
5622 if (!reporter->ops->recover &&
5623 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
5624 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
5625 err = -EOPNOTSUPP;
5626 goto out;
5627 }
5628 if (!reporter->ops->dump &&
5629 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]) {
5630 err = -EOPNOTSUPP;
5631 goto out;
5632 }
5633
5634 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
5635 reporter->graceful_period =
5636 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
5637
5638 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
5639 reporter->auto_recover =
5640 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
5641
5642 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP])
5643 reporter->auto_dump =
5644 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]);
5645
5646 devlink_health_reporter_put(reporter);
5647 return 0;
5648out:
5649 devlink_health_reporter_put(reporter);
5650 return err;
5651}
5652
5653static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
5654 struct genl_info *info)
5655{
5656 struct devlink *devlink = info->user_ptr[0];
5657 struct devlink_health_reporter *reporter;
5658 int err;
5659
5660 reporter = devlink_health_reporter_get_from_info(devlink, info);
5661 if (!reporter)
5662 return -EINVAL;
5663
5664 err = devlink_health_reporter_recover(reporter, NULL, info->extack);
5665
5666 devlink_health_reporter_put(reporter);
5667 return err;
5668}
5669
5670static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
5671 struct genl_info *info)
5672{
5673 struct devlink *devlink = info->user_ptr[0];
5674 struct devlink_health_reporter *reporter;
5675 struct devlink_fmsg *fmsg;
5676 int err;
5677
5678 reporter = devlink_health_reporter_get_from_info(devlink, info);
5679 if (!reporter)
5680 return -EINVAL;
5681
5682 if (!reporter->ops->diagnose) {
5683 devlink_health_reporter_put(reporter);
5684 return -EOPNOTSUPP;
5685 }
5686
5687 fmsg = devlink_fmsg_alloc();
5688 if (!fmsg) {
5689 devlink_health_reporter_put(reporter);
5690 return -ENOMEM;
5691 }
5692
5693 err = devlink_fmsg_obj_nest_start(fmsg);
5694 if (err)
5695 goto out;
5696
5697 err = reporter->ops->diagnose(reporter, fmsg, info->extack);
5698 if (err)
5699 goto out;
5700
5701 err = devlink_fmsg_obj_nest_end(fmsg);
5702 if (err)
5703 goto out;
5704
5705 err = devlink_fmsg_snd(fmsg, info,
5706 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
5707
5708out:
5709 devlink_fmsg_free(fmsg);
5710 devlink_health_reporter_put(reporter);
5711 return err;
5712}
5713
5714static int
5715devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
5716 struct netlink_callback *cb)
5717{
5718 struct devlink_health_reporter *reporter;
5719 u64 start = cb->args[0];
5720 int err;
5721
5722 reporter = devlink_health_reporter_get_from_cb(cb);
5723 if (!reporter)
5724 return -EINVAL;
5725
5726 if (!reporter->ops->dump) {
5727 err = -EOPNOTSUPP;
5728 goto out;
5729 }
5730 mutex_lock(&reporter->dump_lock);
5731 if (!start) {
5732 err = devlink_health_do_dump(reporter, NULL, cb->extack);
5733 if (err)
5734 goto unlock;
5735 cb->args[1] = reporter->dump_ts;
5736 }
5737 if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) {
5738 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry");
5739 err = -EAGAIN;
5740 goto unlock;
5741 }
5742
5743 err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb,
5744 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
5745unlock:
5746 mutex_unlock(&reporter->dump_lock);
5747out:
5748 devlink_health_reporter_put(reporter);
5749 return err;
5750}
5751
5752static int
5753devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
5754 struct genl_info *info)
5755{
5756 struct devlink *devlink = info->user_ptr[0];
5757 struct devlink_health_reporter *reporter;
5758
5759 reporter = devlink_health_reporter_get_from_info(devlink, info);
5760 if (!reporter)
5761 return -EINVAL;
5762
5763 if (!reporter->ops->dump) {
5764 devlink_health_reporter_put(reporter);
5765 return -EOPNOTSUPP;
5766 }
5767
5768 mutex_lock(&reporter->dump_lock);
5769 devlink_health_dump_clear(reporter);
5770 mutex_unlock(&reporter->dump_lock);
5771 devlink_health_reporter_put(reporter);
5772 return 0;
5773}
5774
5775struct devlink_stats {
5776 u64 rx_bytes;
5777 u64 rx_packets;
5778 struct u64_stats_sync syncp;
5779};
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791struct devlink_trap_policer_item {
5792 const struct devlink_trap_policer *policer;
5793 u64 rate;
5794 u64 burst;
5795 struct list_head list;
5796};
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808struct devlink_trap_group_item {
5809 const struct devlink_trap_group *group;
5810 struct devlink_trap_policer_item *policer_item;
5811 struct list_head list;
5812 struct devlink_stats __percpu *stats;
5813};
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827struct devlink_trap_item {
5828 const struct devlink_trap *trap;
5829 struct devlink_trap_group_item *group_item;
5830 struct list_head list;
5831 enum devlink_trap_action action;
5832 struct devlink_stats __percpu *stats;
5833 void *priv;
5834};
5835
5836static struct devlink_trap_policer_item *
5837devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id)
5838{
5839 struct devlink_trap_policer_item *policer_item;
5840
5841 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
5842 if (policer_item->policer->id == id)
5843 return policer_item;
5844 }
5845
5846 return NULL;
5847}
5848
5849static struct devlink_trap_item *
5850devlink_trap_item_lookup(struct devlink *devlink, const char *name)
5851{
5852 struct devlink_trap_item *trap_item;
5853
5854 list_for_each_entry(trap_item, &devlink->trap_list, list) {
5855 if (!strcmp(trap_item->trap->name, name))
5856 return trap_item;
5857 }
5858
5859 return NULL;
5860}
5861
5862static struct devlink_trap_item *
5863devlink_trap_item_get_from_info(struct devlink *devlink,
5864 struct genl_info *info)
5865{
5866 struct nlattr *attr;
5867
5868 if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
5869 return NULL;
5870 attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
5871
5872 return devlink_trap_item_lookup(devlink, nla_data(attr));
5873}
5874
5875static int
5876devlink_trap_action_get_from_info(struct genl_info *info,
5877 enum devlink_trap_action *p_trap_action)
5878{
5879 u8 val;
5880
5881 val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
5882 switch (val) {
5883 case DEVLINK_TRAP_ACTION_DROP:
5884 case DEVLINK_TRAP_ACTION_TRAP:
5885 case DEVLINK_TRAP_ACTION_MIRROR:
5886 *p_trap_action = val;
5887 break;
5888 default:
5889 return -EINVAL;
5890 }
5891
5892 return 0;
5893}
5894
5895static int devlink_trap_metadata_put(struct sk_buff *msg,
5896 const struct devlink_trap *trap)
5897{
5898 struct nlattr *attr;
5899
5900 attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
5901 if (!attr)
5902 return -EMSGSIZE;
5903
5904 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
5905 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
5906 goto nla_put_failure;
5907 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) &&
5908 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE))
5909 goto nla_put_failure;
5910
5911 nla_nest_end(msg, attr);
5912
5913 return 0;
5914
5915nla_put_failure:
5916 nla_nest_cancel(msg, attr);
5917 return -EMSGSIZE;
5918}
5919
5920static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
5921 struct devlink_stats *stats)
5922{
5923 int i;
5924
5925 memset(stats, 0, sizeof(*stats));
5926 for_each_possible_cpu(i) {
5927 struct devlink_stats *cpu_stats;
5928 u64 rx_packets, rx_bytes;
5929 unsigned int start;
5930
5931 cpu_stats = per_cpu_ptr(trap_stats, i);
5932 do {
5933 start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
5934 rx_packets = cpu_stats->rx_packets;
5935 rx_bytes = cpu_stats->rx_bytes;
5936 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
5937
5938 stats->rx_packets += rx_packets;
5939 stats->rx_bytes += rx_bytes;
5940 }
5941}
5942
5943static int devlink_trap_stats_put(struct sk_buff *msg,
5944 struct devlink_stats __percpu *trap_stats)
5945{
5946 struct devlink_stats stats;
5947 struct nlattr *attr;
5948
5949 devlink_trap_stats_read(trap_stats, &stats);
5950
5951 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
5952 if (!attr)
5953 return -EMSGSIZE;
5954
5955 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
5956 stats.rx_packets, DEVLINK_ATTR_PAD))
5957 goto nla_put_failure;
5958
5959 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
5960 stats.rx_bytes, DEVLINK_ATTR_PAD))
5961 goto nla_put_failure;
5962
5963 nla_nest_end(msg, attr);
5964
5965 return 0;
5966
5967nla_put_failure:
5968 nla_nest_cancel(msg, attr);
5969 return -EMSGSIZE;
5970}
5971
5972static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
5973 const struct devlink_trap_item *trap_item,
5974 enum devlink_command cmd, u32 portid, u32 seq,
5975 int flags)
5976{
5977 struct devlink_trap_group_item *group_item = trap_item->group_item;
5978 void *hdr;
5979 int err;
5980
5981 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5982 if (!hdr)
5983 return -EMSGSIZE;
5984
5985 if (devlink_nl_put_handle(msg, devlink))
5986 goto nla_put_failure;
5987
5988 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
5989 group_item->group->name))
5990 goto nla_put_failure;
5991
5992 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
5993 goto nla_put_failure;
5994
5995 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
5996 goto nla_put_failure;
5997
5998 if (trap_item->trap->generic &&
5999 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
6000 goto nla_put_failure;
6001
6002 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
6003 goto nla_put_failure;
6004
6005 err = devlink_trap_metadata_put(msg, trap_item->trap);
6006 if (err)
6007 goto nla_put_failure;
6008
6009 err = devlink_trap_stats_put(msg, trap_item->stats);
6010 if (err)
6011 goto nla_put_failure;
6012
6013 genlmsg_end(msg, hdr);
6014
6015 return 0;
6016
6017nla_put_failure:
6018 genlmsg_cancel(msg, hdr);
6019 return -EMSGSIZE;
6020}
6021
6022static int devlink_nl_cmd_trap_get_doit(struct sk_buff *skb,
6023 struct genl_info *info)
6024{
6025 struct netlink_ext_ack *extack = info->extack;
6026 struct devlink *devlink = info->user_ptr[0];
6027 struct devlink_trap_item *trap_item;
6028 struct sk_buff *msg;
6029 int err;
6030
6031 if (list_empty(&devlink->trap_list))
6032 return -EOPNOTSUPP;
6033
6034 trap_item = devlink_trap_item_get_from_info(devlink, info);
6035 if (!trap_item) {
6036 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
6037 return -ENOENT;
6038 }
6039
6040 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6041 if (!msg)
6042 return -ENOMEM;
6043
6044 err = devlink_nl_trap_fill(msg, devlink, trap_item,
6045 DEVLINK_CMD_TRAP_NEW, info->snd_portid,
6046 info->snd_seq, 0);
6047 if (err)
6048 goto err_trap_fill;
6049
6050 return genlmsg_reply(msg, info);
6051
6052err_trap_fill:
6053 nlmsg_free(msg);
6054 return err;
6055}
6056
6057static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg,
6058 struct netlink_callback *cb)
6059{
6060 struct devlink_trap_item *trap_item;
6061 struct devlink *devlink;
6062 int start = cb->args[0];
6063 int idx = 0;
6064 int err;
6065
6066 mutex_lock(&devlink_mutex);
6067 list_for_each_entry(devlink, &devlink_list, list) {
6068 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
6069 continue;
6070 mutex_lock(&devlink->lock);
6071 list_for_each_entry(trap_item, &devlink->trap_list, list) {
6072 if (idx < start) {
6073 idx++;
6074 continue;
6075 }
6076 err = devlink_nl_trap_fill(msg, devlink, trap_item,
6077 DEVLINK_CMD_TRAP_NEW,
6078 NETLINK_CB(cb->skb).portid,
6079 cb->nlh->nlmsg_seq,
6080 NLM_F_MULTI);
6081 if (err) {
6082 mutex_unlock(&devlink->lock);
6083 goto out;
6084 }
6085 idx++;
6086 }
6087 mutex_unlock(&devlink->lock);
6088 }
6089out:
6090 mutex_unlock(&devlink_mutex);
6091
6092 cb->args[0] = idx;
6093 return msg->len;
6094}
6095
6096static int __devlink_trap_action_set(struct devlink *devlink,
6097 struct devlink_trap_item *trap_item,
6098 enum devlink_trap_action trap_action,
6099 struct netlink_ext_ack *extack)
6100{
6101 int err;
6102
6103 if (trap_item->action != trap_action &&
6104 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
6105 NL_SET_ERR_MSG_MOD(extack, "Cannot change action of non-drop traps. Skipping");
6106 return 0;
6107 }
6108
6109 err = devlink->ops->trap_action_set(devlink, trap_item->trap,
6110 trap_action);
6111 if (err)
6112 return err;
6113
6114 trap_item->action = trap_action;
6115
6116 return 0;
6117}
6118
6119static int devlink_trap_action_set(struct devlink *devlink,
6120 struct devlink_trap_item *trap_item,
6121 struct genl_info *info)
6122{
6123 enum devlink_trap_action trap_action;
6124 int err;
6125
6126 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
6127 return 0;
6128
6129 err = devlink_trap_action_get_from_info(info, &trap_action);
6130 if (err) {
6131 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
6132 return -EINVAL;
6133 }
6134
6135 return __devlink_trap_action_set(devlink, trap_item, trap_action,
6136 info->extack);
6137}
6138
6139static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb,
6140 struct genl_info *info)
6141{
6142 struct netlink_ext_ack *extack = info->extack;
6143 struct devlink *devlink = info->user_ptr[0];
6144 struct devlink_trap_item *trap_item;
6145 int err;
6146
6147 if (list_empty(&devlink->trap_list))
6148 return -EOPNOTSUPP;
6149
6150 trap_item = devlink_trap_item_get_from_info(devlink, info);
6151 if (!trap_item) {
6152 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
6153 return -ENOENT;
6154 }
6155
6156 err = devlink_trap_action_set(devlink, trap_item, info);
6157 if (err)
6158 return err;
6159
6160 return 0;
6161}
6162
6163static struct devlink_trap_group_item *
6164devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
6165{
6166 struct devlink_trap_group_item *group_item;
6167
6168 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
6169 if (!strcmp(group_item->group->name, name))
6170 return group_item;
6171 }
6172
6173 return NULL;
6174}
6175
6176static struct devlink_trap_group_item *
6177devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id)
6178{
6179 struct devlink_trap_group_item *group_item;
6180
6181 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
6182 if (group_item->group->id == id)
6183 return group_item;
6184 }
6185
6186 return NULL;
6187}
6188
6189static struct devlink_trap_group_item *
6190devlink_trap_group_item_get_from_info(struct devlink *devlink,
6191 struct genl_info *info)
6192{
6193 char *name;
6194
6195 if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
6196 return NULL;
6197 name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
6198
6199 return devlink_trap_group_item_lookup(devlink, name);
6200}
6201
6202static int
6203devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
6204 const struct devlink_trap_group_item *group_item,
6205 enum devlink_command cmd, u32 portid, u32 seq,
6206 int flags)
6207{
6208 void *hdr;
6209 int err;
6210
6211 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
6212 if (!hdr)
6213 return -EMSGSIZE;
6214
6215 if (devlink_nl_put_handle(msg, devlink))
6216 goto nla_put_failure;
6217
6218 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
6219 group_item->group->name))
6220 goto nla_put_failure;
6221
6222 if (group_item->group->generic &&
6223 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
6224 goto nla_put_failure;
6225
6226 if (group_item->policer_item &&
6227 nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
6228 group_item->policer_item->policer->id))
6229 goto nla_put_failure;
6230
6231 err = devlink_trap_stats_put(msg, group_item->stats);
6232 if (err)
6233 goto nla_put_failure;
6234
6235 genlmsg_end(msg, hdr);
6236
6237 return 0;
6238
6239nla_put_failure:
6240 genlmsg_cancel(msg, hdr);
6241 return -EMSGSIZE;
6242}
6243
6244static int devlink_nl_cmd_trap_group_get_doit(struct sk_buff *skb,
6245 struct genl_info *info)
6246{
6247 struct netlink_ext_ack *extack = info->extack;
6248 struct devlink *devlink = info->user_ptr[0];
6249 struct devlink_trap_group_item *group_item;
6250 struct sk_buff *msg;
6251 int err;
6252
6253 if (list_empty(&devlink->trap_group_list))
6254 return -EOPNOTSUPP;
6255
6256 group_item = devlink_trap_group_item_get_from_info(devlink, info);
6257 if (!group_item) {
6258 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
6259 return -ENOENT;
6260 }
6261
6262 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6263 if (!msg)
6264 return -ENOMEM;
6265
6266 err = devlink_nl_trap_group_fill(msg, devlink, group_item,
6267 DEVLINK_CMD_TRAP_GROUP_NEW,
6268 info->snd_portid, info->snd_seq, 0);
6269 if (err)
6270 goto err_trap_group_fill;
6271
6272 return genlmsg_reply(msg, info);
6273
6274err_trap_group_fill:
6275 nlmsg_free(msg);
6276 return err;
6277}
6278
6279static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg,
6280 struct netlink_callback *cb)
6281{
6282 enum devlink_command cmd = DEVLINK_CMD_TRAP_GROUP_NEW;
6283 struct devlink_trap_group_item *group_item;
6284 u32 portid = NETLINK_CB(cb->skb).portid;
6285 struct devlink *devlink;
6286 int start = cb->args[0];
6287 int idx = 0;
6288 int err;
6289
6290 mutex_lock(&devlink_mutex);
6291 list_for_each_entry(devlink, &devlink_list, list) {
6292 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
6293 continue;
6294 mutex_lock(&devlink->lock);
6295 list_for_each_entry(group_item, &devlink->trap_group_list,
6296 list) {
6297 if (idx < start) {
6298 idx++;
6299 continue;
6300 }
6301 err = devlink_nl_trap_group_fill(msg, devlink,
6302 group_item, cmd,
6303 portid,
6304 cb->nlh->nlmsg_seq,
6305 NLM_F_MULTI);
6306 if (err) {
6307 mutex_unlock(&devlink->lock);
6308 goto out;
6309 }
6310 idx++;
6311 }
6312 mutex_unlock(&devlink->lock);
6313 }
6314out:
6315 mutex_unlock(&devlink_mutex);
6316
6317 cb->args[0] = idx;
6318 return msg->len;
6319}
6320
6321static int
6322__devlink_trap_group_action_set(struct devlink *devlink,
6323 struct devlink_trap_group_item *group_item,
6324 enum devlink_trap_action trap_action,
6325 struct netlink_ext_ack *extack)
6326{
6327 const char *group_name = group_item->group->name;
6328 struct devlink_trap_item *trap_item;
6329 int err;
6330
6331 list_for_each_entry(trap_item, &devlink->trap_list, list) {
6332 if (strcmp(trap_item->group_item->group->name, group_name))
6333 continue;
6334 err = __devlink_trap_action_set(devlink, trap_item,
6335 trap_action, extack);
6336 if (err)
6337 return err;
6338 }
6339
6340 return 0;
6341}
6342
6343static int
6344devlink_trap_group_action_set(struct devlink *devlink,
6345 struct devlink_trap_group_item *group_item,
6346 struct genl_info *info, bool *p_modified)
6347{
6348 enum devlink_trap_action trap_action;
6349 int err;
6350
6351 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
6352 return 0;
6353
6354 err = devlink_trap_action_get_from_info(info, &trap_action);
6355 if (err) {
6356 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
6357 return -EINVAL;
6358 }
6359
6360 err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
6361 info->extack);
6362 if (err)
6363 return err;
6364
6365 *p_modified = true;
6366
6367 return 0;
6368}
6369
6370static int devlink_trap_group_set(struct devlink *devlink,
6371 struct devlink_trap_group_item *group_item,
6372 struct genl_info *info)
6373{
6374 struct devlink_trap_policer_item *policer_item;
6375 struct netlink_ext_ack *extack = info->extack;
6376 const struct devlink_trap_policer *policer;
6377 struct nlattr **attrs = info->attrs;
6378 int err;
6379
6380 if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
6381 return 0;
6382
6383 if (!devlink->ops->trap_group_set)
6384 return -EOPNOTSUPP;
6385
6386 policer_item = group_item->policer_item;
6387 if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) {
6388 u32 policer_id;
6389
6390 policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
6391 policer_item = devlink_trap_policer_item_lookup(devlink,
6392 policer_id);
6393 if (policer_id && !policer_item) {
6394 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
6395 return -ENOENT;
6396 }
6397 }
6398 policer = policer_item ? policer_item->policer : NULL;
6399
6400 err = devlink->ops->trap_group_set(devlink, group_item->group, policer);
6401 if (err)
6402 return err;
6403
6404 group_item->policer_item = policer_item;
6405
6406 return 0;
6407}
6408
6409static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
6410 struct genl_info *info)
6411{
6412 struct netlink_ext_ack *extack = info->extack;
6413 struct devlink *devlink = info->user_ptr[0];
6414 struct devlink_trap_group_item *group_item;
6415 bool modified = false;
6416 int err;
6417
6418 if (list_empty(&devlink->trap_group_list))
6419 return -EOPNOTSUPP;
6420
6421 group_item = devlink_trap_group_item_get_from_info(devlink, info);
6422 if (!group_item) {
6423 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
6424 return -ENOENT;
6425 }
6426
6427 err = devlink_trap_group_action_set(devlink, group_item, info,
6428 &modified);
6429 if (err)
6430 return err;
6431
6432 err = devlink_trap_group_set(devlink, group_item, info);
6433 if (err)
6434 goto err_trap_group_set;
6435
6436 return 0;
6437
6438err_trap_group_set:
6439 if (modified)
6440 NL_SET_ERR_MSG_MOD(extack, "Trap group set failed, but some changes were committed already");
6441 return err;
6442}
6443
6444static struct devlink_trap_policer_item *
6445devlink_trap_policer_item_get_from_info(struct devlink *devlink,
6446 struct genl_info *info)
6447{
6448 u32 id;
6449
6450 if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
6451 return NULL;
6452 id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
6453
6454 return devlink_trap_policer_item_lookup(devlink, id);
6455}
6456
6457static int
6458devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink,
6459 const struct devlink_trap_policer *policer)
6460{
6461 struct nlattr *attr;
6462 u64 drops;
6463 int err;
6464
6465 if (!devlink->ops->trap_policer_counter_get)
6466 return 0;
6467
6468 err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops);
6469 if (err)
6470 return err;
6471
6472 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
6473 if (!attr)
6474 return -EMSGSIZE;
6475
6476 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
6477 DEVLINK_ATTR_PAD))
6478 goto nla_put_failure;
6479
6480 nla_nest_end(msg, attr);
6481
6482 return 0;
6483
6484nla_put_failure:
6485 nla_nest_cancel(msg, attr);
6486 return -EMSGSIZE;
6487}
6488
6489static int
6490devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink,
6491 const struct devlink_trap_policer_item *policer_item,
6492 enum devlink_command cmd, u32 portid, u32 seq,
6493 int flags)
6494{
6495 void *hdr;
6496 int err;
6497
6498 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
6499 if (!hdr)
6500 return -EMSGSIZE;
6501
6502 if (devlink_nl_put_handle(msg, devlink))
6503 goto nla_put_failure;
6504
6505 if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
6506 policer_item->policer->id))
6507 goto nla_put_failure;
6508
6509 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE,
6510 policer_item->rate, DEVLINK_ATTR_PAD))
6511 goto nla_put_failure;
6512
6513 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST,
6514 policer_item->burst, DEVLINK_ATTR_PAD))
6515 goto nla_put_failure;
6516
6517 err = devlink_trap_policer_stats_put(msg, devlink,
6518 policer_item->policer);
6519 if (err)
6520 goto nla_put_failure;
6521
6522 genlmsg_end(msg, hdr);
6523
6524 return 0;
6525
6526nla_put_failure:
6527 genlmsg_cancel(msg, hdr);
6528 return -EMSGSIZE;
6529}
6530
6531static int devlink_nl_cmd_trap_policer_get_doit(struct sk_buff *skb,
6532 struct genl_info *info)
6533{
6534 struct devlink_trap_policer_item *policer_item;
6535 struct netlink_ext_ack *extack = info->extack;
6536 struct devlink *devlink = info->user_ptr[0];
6537 struct sk_buff *msg;
6538 int err;
6539
6540 if (list_empty(&devlink->trap_policer_list))
6541 return -EOPNOTSUPP;
6542
6543 policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
6544 if (!policer_item) {
6545 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
6546 return -ENOENT;
6547 }
6548
6549 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6550 if (!msg)
6551 return -ENOMEM;
6552
6553 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
6554 DEVLINK_CMD_TRAP_POLICER_NEW,
6555 info->snd_portid, info->snd_seq, 0);
6556 if (err)
6557 goto err_trap_policer_fill;
6558
6559 return genlmsg_reply(msg, info);
6560
6561err_trap_policer_fill:
6562 nlmsg_free(msg);
6563 return err;
6564}
6565
6566static int devlink_nl_cmd_trap_policer_get_dumpit(struct sk_buff *msg,
6567 struct netlink_callback *cb)
6568{
6569 enum devlink_command cmd = DEVLINK_CMD_TRAP_POLICER_NEW;
6570 struct devlink_trap_policer_item *policer_item;
6571 u32 portid = NETLINK_CB(cb->skb).portid;
6572 struct devlink *devlink;
6573 int start = cb->args[0];
6574 int idx = 0;
6575 int err;
6576
6577 mutex_lock(&devlink_mutex);
6578 list_for_each_entry(devlink, &devlink_list, list) {
6579 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
6580 continue;
6581 mutex_lock(&devlink->lock);
6582 list_for_each_entry(policer_item, &devlink->trap_policer_list,
6583 list) {
6584 if (idx < start) {
6585 idx++;
6586 continue;
6587 }
6588 err = devlink_nl_trap_policer_fill(msg, devlink,
6589 policer_item, cmd,
6590 portid,
6591 cb->nlh->nlmsg_seq,
6592 NLM_F_MULTI);
6593 if (err) {
6594 mutex_unlock(&devlink->lock);
6595 goto out;
6596 }
6597 idx++;
6598 }
6599 mutex_unlock(&devlink->lock);
6600 }
6601out:
6602 mutex_unlock(&devlink_mutex);
6603
6604 cb->args[0] = idx;
6605 return msg->len;
6606}
6607
6608static int
6609devlink_trap_policer_set(struct devlink *devlink,
6610 struct devlink_trap_policer_item *policer_item,
6611 struct genl_info *info)
6612{
6613 struct netlink_ext_ack *extack = info->extack;
6614 struct nlattr **attrs = info->attrs;
6615 u64 rate, burst;
6616 int err;
6617
6618 rate = policer_item->rate;
6619 burst = policer_item->burst;
6620
6621 if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE])
6622 rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]);
6623
6624 if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST])
6625 burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]);
6626
6627 if (rate < policer_item->policer->min_rate) {
6628 NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
6629 return -EINVAL;
6630 }
6631
6632 if (rate > policer_item->policer->max_rate) {
6633 NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
6634 return -EINVAL;
6635 }
6636
6637 if (burst < policer_item->policer->min_burst) {
6638 NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
6639 return -EINVAL;
6640 }
6641
6642 if (burst > policer_item->policer->max_burst) {
6643 NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
6644 return -EINVAL;
6645 }
6646
6647 err = devlink->ops->trap_policer_set(devlink, policer_item->policer,
6648 rate, burst, info->extack);
6649 if (err)
6650 return err;
6651
6652 policer_item->rate = rate;
6653 policer_item->burst = burst;
6654
6655 return 0;
6656}
6657
6658static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
6659 struct genl_info *info)
6660{
6661 struct devlink_trap_policer_item *policer_item;
6662 struct netlink_ext_ack *extack = info->extack;
6663 struct devlink *devlink = info->user_ptr[0];
6664
6665 if (list_empty(&devlink->trap_policer_list))
6666 return -EOPNOTSUPP;
6667
6668 if (!devlink->ops->trap_policer_set)
6669 return -EOPNOTSUPP;
6670
6671 policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
6672 if (!policer_item) {
6673 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
6674 return -ENOENT;
6675 }
6676
6677 return devlink_trap_policer_set(devlink, policer_item, info);
6678}
6679
6680static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
6681 [DEVLINK_ATTR_UNSPEC] = { .strict_start_type =
6682 DEVLINK_ATTR_TRAP_POLICER_ID },
6683 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
6684 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
6685 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
6686 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
6687 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
6688 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
6689 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
6690 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
6691 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
6692 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
6693 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
6694 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
6695 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
6696 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
6697 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
6698 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
6699 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
6700 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
6701 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
6702 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
6703 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
6704 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
6705 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
6706 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
6707 [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 },
6708 [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 },
6709 [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
6710 [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
6711 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
6712 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
6713 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
6714 [DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING },
6715 [DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 },
6716 [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING },
6717 [DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32 },
6718 [DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32 },
6719 [DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32 },
6720 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP] = { .type = NLA_U8 },
6721 [DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32 },
6722 [DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 },
6723 [DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 },
6724};
6725
6726static const struct genl_ops devlink_nl_ops[] = {
6727 {
6728 .cmd = DEVLINK_CMD_GET,
6729 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6730 .doit = devlink_nl_cmd_get_doit,
6731 .dumpit = devlink_nl_cmd_get_dumpit,
6732 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6733
6734 },
6735 {
6736 .cmd = DEVLINK_CMD_PORT_GET,
6737 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6738 .doit = devlink_nl_cmd_port_get_doit,
6739 .dumpit = devlink_nl_cmd_port_get_dumpit,
6740 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6741
6742 },
6743 {
6744 .cmd = DEVLINK_CMD_PORT_SET,
6745 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6746 .doit = devlink_nl_cmd_port_set_doit,
6747 .flags = GENL_ADMIN_PERM,
6748 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6749 },
6750 {
6751 .cmd = DEVLINK_CMD_PORT_SPLIT,
6752 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6753 .doit = devlink_nl_cmd_port_split_doit,
6754 .flags = GENL_ADMIN_PERM,
6755 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6756 DEVLINK_NL_FLAG_NO_LOCK,
6757 },
6758 {
6759 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
6760 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6761 .doit = devlink_nl_cmd_port_unsplit_doit,
6762 .flags = GENL_ADMIN_PERM,
6763 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6764 DEVLINK_NL_FLAG_NO_LOCK,
6765 },
6766 {
6767 .cmd = DEVLINK_CMD_SB_GET,
6768 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6769 .doit = devlink_nl_cmd_sb_get_doit,
6770 .dumpit = devlink_nl_cmd_sb_get_dumpit,
6771 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6772 DEVLINK_NL_FLAG_NEED_SB,
6773
6774 },
6775 {
6776 .cmd = DEVLINK_CMD_SB_POOL_GET,
6777 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6778 .doit = devlink_nl_cmd_sb_pool_get_doit,
6779 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
6780 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6781 DEVLINK_NL_FLAG_NEED_SB,
6782
6783 },
6784 {
6785 .cmd = DEVLINK_CMD_SB_POOL_SET,
6786 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6787 .doit = devlink_nl_cmd_sb_pool_set_doit,
6788 .flags = GENL_ADMIN_PERM,
6789 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6790 DEVLINK_NL_FLAG_NEED_SB,
6791 },
6792 {
6793 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
6794 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6795 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
6796 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
6797 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
6798 DEVLINK_NL_FLAG_NEED_SB,
6799
6800 },
6801 {
6802 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
6803 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6804 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
6805 .flags = GENL_ADMIN_PERM,
6806 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
6807 DEVLINK_NL_FLAG_NEED_SB,
6808 },
6809 {
6810 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
6811 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6812 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
6813 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
6814 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
6815 DEVLINK_NL_FLAG_NEED_SB,
6816
6817 },
6818 {
6819 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
6820 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6821 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
6822 .flags = GENL_ADMIN_PERM,
6823 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
6824 DEVLINK_NL_FLAG_NEED_SB,
6825 },
6826 {
6827 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
6828 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6829 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
6830 .flags = GENL_ADMIN_PERM,
6831 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6832 DEVLINK_NL_FLAG_NEED_SB,
6833 },
6834 {
6835 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
6836 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6837 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
6838 .flags = GENL_ADMIN_PERM,
6839 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6840 DEVLINK_NL_FLAG_NEED_SB,
6841 },
6842 {
6843 .cmd = DEVLINK_CMD_ESWITCH_GET,
6844 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6845 .doit = devlink_nl_cmd_eswitch_get_doit,
6846 .flags = GENL_ADMIN_PERM,
6847 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6848 DEVLINK_NL_FLAG_NO_LOCK,
6849 },
6850 {
6851 .cmd = DEVLINK_CMD_ESWITCH_SET,
6852 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6853 .doit = devlink_nl_cmd_eswitch_set_doit,
6854 .flags = GENL_ADMIN_PERM,
6855 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6856 DEVLINK_NL_FLAG_NO_LOCK,
6857 },
6858 {
6859 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
6860 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6861 .doit = devlink_nl_cmd_dpipe_table_get,
6862 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6863
6864 },
6865 {
6866 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
6867 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6868 .doit = devlink_nl_cmd_dpipe_entries_get,
6869 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6870
6871 },
6872 {
6873 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
6874 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6875 .doit = devlink_nl_cmd_dpipe_headers_get,
6876 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6877
6878 },
6879 {
6880 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
6881 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6882 .doit = devlink_nl_cmd_dpipe_table_counters_set,
6883 .flags = GENL_ADMIN_PERM,
6884 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6885 },
6886 {
6887 .cmd = DEVLINK_CMD_RESOURCE_SET,
6888 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6889 .doit = devlink_nl_cmd_resource_set,
6890 .flags = GENL_ADMIN_PERM,
6891 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6892 },
6893 {
6894 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
6895 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6896 .doit = devlink_nl_cmd_resource_dump,
6897 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6898
6899 },
6900 {
6901 .cmd = DEVLINK_CMD_RELOAD,
6902 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6903 .doit = devlink_nl_cmd_reload,
6904 .flags = GENL_ADMIN_PERM,
6905 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6906 DEVLINK_NL_FLAG_NO_LOCK,
6907 },
6908 {
6909 .cmd = DEVLINK_CMD_PARAM_GET,
6910 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6911 .doit = devlink_nl_cmd_param_get_doit,
6912 .dumpit = devlink_nl_cmd_param_get_dumpit,
6913 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6914
6915 },
6916 {
6917 .cmd = DEVLINK_CMD_PARAM_SET,
6918 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6919 .doit = devlink_nl_cmd_param_set_doit,
6920 .flags = GENL_ADMIN_PERM,
6921 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6922 },
6923 {
6924 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
6925 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6926 .doit = devlink_nl_cmd_port_param_get_doit,
6927 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
6928 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6929
6930 },
6931 {
6932 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
6933 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6934 .doit = devlink_nl_cmd_port_param_set_doit,
6935 .flags = GENL_ADMIN_PERM,
6936 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6937 },
6938 {
6939 .cmd = DEVLINK_CMD_REGION_GET,
6940 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6941 .doit = devlink_nl_cmd_region_get_doit,
6942 .dumpit = devlink_nl_cmd_region_get_dumpit,
6943 .flags = GENL_ADMIN_PERM,
6944 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6945 },
6946 {
6947 .cmd = DEVLINK_CMD_REGION_NEW,
6948 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6949 .doit = devlink_nl_cmd_region_new,
6950 .flags = GENL_ADMIN_PERM,
6951 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6952 },
6953 {
6954 .cmd = DEVLINK_CMD_REGION_DEL,
6955 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6956 .doit = devlink_nl_cmd_region_del,
6957 .flags = GENL_ADMIN_PERM,
6958 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6959 },
6960 {
6961 .cmd = DEVLINK_CMD_REGION_READ,
6962 .validate = GENL_DONT_VALIDATE_STRICT |
6963 GENL_DONT_VALIDATE_DUMP_STRICT,
6964 .dumpit = devlink_nl_cmd_region_read_dumpit,
6965 .flags = GENL_ADMIN_PERM,
6966 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6967 },
6968 {
6969 .cmd = DEVLINK_CMD_INFO_GET,
6970 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6971 .doit = devlink_nl_cmd_info_get_doit,
6972 .dumpit = devlink_nl_cmd_info_get_dumpit,
6973 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6974
6975 },
6976 {
6977 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
6978 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6979 .doit = devlink_nl_cmd_health_reporter_get_doit,
6980 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
6981 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6982 DEVLINK_NL_FLAG_NO_LOCK,
6983
6984 },
6985 {
6986 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
6987 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6988 .doit = devlink_nl_cmd_health_reporter_set_doit,
6989 .flags = GENL_ADMIN_PERM,
6990 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6991 DEVLINK_NL_FLAG_NO_LOCK,
6992 },
6993 {
6994 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
6995 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6996 .doit = devlink_nl_cmd_health_reporter_recover_doit,
6997 .flags = GENL_ADMIN_PERM,
6998 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6999 DEVLINK_NL_FLAG_NO_LOCK,
7000 },
7001 {
7002 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
7003 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7004 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
7005 .flags = GENL_ADMIN_PERM,
7006 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
7007 DEVLINK_NL_FLAG_NO_LOCK,
7008 },
7009 {
7010 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
7011 .validate = GENL_DONT_VALIDATE_STRICT |
7012 GENL_DONT_VALIDATE_DUMP_STRICT,
7013 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
7014 .flags = GENL_ADMIN_PERM,
7015 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
7016 DEVLINK_NL_FLAG_NO_LOCK,
7017 },
7018 {
7019 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
7020 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7021 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
7022 .flags = GENL_ADMIN_PERM,
7023 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
7024 DEVLINK_NL_FLAG_NO_LOCK,
7025 },
7026 {
7027 .cmd = DEVLINK_CMD_FLASH_UPDATE,
7028 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7029 .doit = devlink_nl_cmd_flash_update,
7030 .flags = GENL_ADMIN_PERM,
7031 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
7032 },
7033 {
7034 .cmd = DEVLINK_CMD_TRAP_GET,
7035 .doit = devlink_nl_cmd_trap_get_doit,
7036 .dumpit = devlink_nl_cmd_trap_get_dumpit,
7037 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
7038
7039 },
7040 {
7041 .cmd = DEVLINK_CMD_TRAP_SET,
7042 .doit = devlink_nl_cmd_trap_set_doit,
7043 .flags = GENL_ADMIN_PERM,
7044 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
7045 },
7046 {
7047 .cmd = DEVLINK_CMD_TRAP_GROUP_GET,
7048 .doit = devlink_nl_cmd_trap_group_get_doit,
7049 .dumpit = devlink_nl_cmd_trap_group_get_dumpit,
7050 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
7051
7052 },
7053 {
7054 .cmd = DEVLINK_CMD_TRAP_GROUP_SET,
7055 .doit = devlink_nl_cmd_trap_group_set_doit,
7056 .flags = GENL_ADMIN_PERM,
7057 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
7058 },
7059 {
7060 .cmd = DEVLINK_CMD_TRAP_POLICER_GET,
7061 .doit = devlink_nl_cmd_trap_policer_get_doit,
7062 .dumpit = devlink_nl_cmd_trap_policer_get_dumpit,
7063 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
7064
7065 },
7066 {
7067 .cmd = DEVLINK_CMD_TRAP_POLICER_SET,
7068 .doit = devlink_nl_cmd_trap_policer_set_doit,
7069 .flags = GENL_ADMIN_PERM,
7070 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
7071 },
7072};
7073
7074static struct genl_family devlink_nl_family __ro_after_init = {
7075 .name = DEVLINK_GENL_NAME,
7076 .version = DEVLINK_GENL_VERSION,
7077 .maxattr = DEVLINK_ATTR_MAX,
7078 .policy = devlink_nl_policy,
7079 .netnsok = true,
7080 .pre_doit = devlink_nl_pre_doit,
7081 .post_doit = devlink_nl_post_doit,
7082 .module = THIS_MODULE,
7083 .ops = devlink_nl_ops,
7084 .n_ops = ARRAY_SIZE(devlink_nl_ops),
7085 .mcgrps = devlink_nl_mcgrps,
7086 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps),
7087};
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
7099{
7100 struct devlink *devlink;
7101
7102 if (WARN_ON(!ops))
7103 return NULL;
7104
7105 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
7106 if (!devlink)
7107 return NULL;
7108 devlink->ops = ops;
7109 xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC);
7110 __devlink_net_set(devlink, &init_net);
7111 INIT_LIST_HEAD(&devlink->port_list);
7112 INIT_LIST_HEAD(&devlink->sb_list);
7113 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
7114 INIT_LIST_HEAD(&devlink->resource_list);
7115 INIT_LIST_HEAD(&devlink->param_list);
7116 INIT_LIST_HEAD(&devlink->region_list);
7117 INIT_LIST_HEAD(&devlink->reporter_list);
7118 INIT_LIST_HEAD(&devlink->trap_list);
7119 INIT_LIST_HEAD(&devlink->trap_group_list);
7120 INIT_LIST_HEAD(&devlink->trap_policer_list);
7121 mutex_init(&devlink->lock);
7122 mutex_init(&devlink->reporters_lock);
7123 return devlink;
7124}
7125EXPORT_SYMBOL_GPL(devlink_alloc);
7126
7127
7128
7129
7130
7131
7132
7133int devlink_register(struct devlink *devlink, struct device *dev)
7134{
7135 mutex_lock(&devlink_mutex);
7136 devlink->dev = dev;
7137 devlink->registered = true;
7138 list_add_tail(&devlink->list, &devlink_list);
7139 devlink_notify(devlink, DEVLINK_CMD_NEW);
7140 mutex_unlock(&devlink_mutex);
7141 return 0;
7142}
7143EXPORT_SYMBOL_GPL(devlink_register);
7144
7145
7146
7147
7148
7149
7150void devlink_unregister(struct devlink *devlink)
7151{
7152 mutex_lock(&devlink_mutex);
7153 WARN_ON(devlink_reload_supported(devlink) &&
7154 devlink->reload_enabled);
7155 devlink_notify(devlink, DEVLINK_CMD_DEL);
7156 list_del(&devlink->list);
7157 mutex_unlock(&devlink_mutex);
7158}
7159EXPORT_SYMBOL_GPL(devlink_unregister);
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169void devlink_reload_enable(struct devlink *devlink)
7170{
7171 mutex_lock(&devlink_mutex);
7172 devlink->reload_enabled = true;
7173 mutex_unlock(&devlink_mutex);
7174}
7175EXPORT_SYMBOL_GPL(devlink_reload_enable);
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185void devlink_reload_disable(struct devlink *devlink)
7186{
7187 mutex_lock(&devlink_mutex);
7188
7189
7190
7191 devlink->reload_enabled = false;
7192 mutex_unlock(&devlink_mutex);
7193}
7194EXPORT_SYMBOL_GPL(devlink_reload_disable);
7195
7196
7197
7198
7199
7200
7201void devlink_free(struct devlink *devlink)
7202{
7203 mutex_destroy(&devlink->reporters_lock);
7204 mutex_destroy(&devlink->lock);
7205 WARN_ON(!list_empty(&devlink->trap_policer_list));
7206 WARN_ON(!list_empty(&devlink->trap_group_list));
7207 WARN_ON(!list_empty(&devlink->trap_list));
7208 WARN_ON(!list_empty(&devlink->reporter_list));
7209 WARN_ON(!list_empty(&devlink->region_list));
7210 WARN_ON(!list_empty(&devlink->param_list));
7211 WARN_ON(!list_empty(&devlink->resource_list));
7212 WARN_ON(!list_empty(&devlink->dpipe_table_list));
7213 WARN_ON(!list_empty(&devlink->sb_list));
7214 WARN_ON(!list_empty(&devlink->port_list));
7215
7216 xa_destroy(&devlink->snapshot_ids);
7217
7218 kfree(devlink);
7219}
7220EXPORT_SYMBOL_GPL(devlink_free);
7221
7222static void devlink_port_type_warn(struct work_struct *work)
7223{
7224 WARN(true, "Type was not set for devlink port.");
7225}
7226
7227static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
7228{
7229
7230 return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
7231 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA;
7232}
7233
7234#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600)
7235
7236static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
7237{
7238 if (!devlink_port_type_should_warn(devlink_port))
7239 return;
7240
7241
7242
7243 schedule_delayed_work(&devlink_port->type_warn_dw,
7244 DEVLINK_PORT_TYPE_WARN_TIMEOUT);
7245}
7246
7247static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
7248{
7249 if (!devlink_port_type_should_warn(devlink_port))
7250 return;
7251 cancel_delayed_work_sync(&devlink_port->type_warn_dw);
7252}
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267int devlink_port_register(struct devlink *devlink,
7268 struct devlink_port *devlink_port,
7269 unsigned int port_index)
7270{
7271 mutex_lock(&devlink->lock);
7272 if (devlink_port_index_exists(devlink, port_index)) {
7273 mutex_unlock(&devlink->lock);
7274 return -EEXIST;
7275 }
7276 devlink_port->devlink = devlink;
7277 devlink_port->index = port_index;
7278 devlink_port->registered = true;
7279 spin_lock_init(&devlink_port->type_lock);
7280 list_add_tail(&devlink_port->list, &devlink->port_list);
7281 INIT_LIST_HEAD(&devlink_port->param_list);
7282 mutex_unlock(&devlink->lock);
7283 INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
7284 devlink_port_type_warn_schedule(devlink_port);
7285 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
7286 return 0;
7287}
7288EXPORT_SYMBOL_GPL(devlink_port_register);
7289
7290
7291
7292
7293
7294
7295void devlink_port_unregister(struct devlink_port *devlink_port)
7296{
7297 struct devlink *devlink = devlink_port->devlink;
7298
7299 devlink_port_type_warn_cancel(devlink_port);
7300 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
7301 mutex_lock(&devlink->lock);
7302 list_del(&devlink_port->list);
7303 mutex_unlock(&devlink->lock);
7304}
7305EXPORT_SYMBOL_GPL(devlink_port_unregister);
7306
7307static void __devlink_port_type_set(struct devlink_port *devlink_port,
7308 enum devlink_port_type type,
7309 void *type_dev)
7310{
7311 if (WARN_ON(!devlink_port->registered))
7312 return;
7313 devlink_port_type_warn_cancel(devlink_port);
7314 spin_lock_bh(&devlink_port->type_lock);
7315 devlink_port->type = type;
7316 devlink_port->type_dev = type_dev;
7317 spin_unlock_bh(&devlink_port->type_lock);
7318 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
7319}
7320
7321
7322
7323
7324
7325
7326
7327void devlink_port_type_eth_set(struct devlink_port *devlink_port,
7328 struct net_device *netdev)
7329{
7330 const struct net_device_ops *ops = netdev->netdev_ops;
7331
7332
7333
7334
7335
7336 if (ops->ndo_get_phys_port_name) {
7337
7338
7339
7340
7341
7342
7343 char name[IFNAMSIZ];
7344 int err;
7345
7346 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
7347 WARN_ON(err != -EOPNOTSUPP);
7348 }
7349 if (ops->ndo_get_port_parent_id) {
7350
7351
7352
7353
7354
7355
7356 struct netdev_phys_item_id ppid;
7357 int err;
7358
7359 err = ops->ndo_get_port_parent_id(netdev, &ppid);
7360 WARN_ON(err != -EOPNOTSUPP);
7361 }
7362 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
7363}
7364EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
7365
7366
7367
7368
7369
7370
7371
7372void devlink_port_type_ib_set(struct devlink_port *devlink_port,
7373 struct ib_device *ibdev)
7374{
7375 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
7376}
7377EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
7378
7379
7380
7381
7382
7383
7384void devlink_port_type_clear(struct devlink_port *devlink_port)
7385{
7386 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
7387 devlink_port_type_warn_schedule(devlink_port);
7388}
7389EXPORT_SYMBOL_GPL(devlink_port_type_clear);
7390
7391static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
7392 enum devlink_port_flavour flavour,
7393 const unsigned char *switch_id,
7394 unsigned char switch_id_len)
7395{
7396 struct devlink_port_attrs *attrs = &devlink_port->attrs;
7397
7398 if (WARN_ON(devlink_port->registered))
7399 return -EEXIST;
7400 attrs->set = true;
7401 attrs->flavour = flavour;
7402 if (switch_id) {
7403 attrs->switch_port = true;
7404 if (WARN_ON(switch_id_len > MAX_PHYS_ITEM_ID_LEN))
7405 switch_id_len = MAX_PHYS_ITEM_ID_LEN;
7406 memcpy(attrs->switch_id.id, switch_id, switch_id_len);
7407 attrs->switch_id.id_len = switch_id_len;
7408 } else {
7409 attrs->switch_port = false;
7410 }
7411 return 0;
7412}
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428void devlink_port_attrs_set(struct devlink_port *devlink_port,
7429 enum devlink_port_flavour flavour,
7430 u32 port_number, bool split,
7431 u32 split_subport_number,
7432 const unsigned char *switch_id,
7433 unsigned char switch_id_len)
7434{
7435 struct devlink_port_attrs *attrs = &devlink_port->attrs;
7436 int ret;
7437
7438 ret = __devlink_port_attrs_set(devlink_port, flavour,
7439 switch_id, switch_id_len);
7440 if (ret)
7441 return;
7442 attrs->split = split;
7443 attrs->phys.port_number = port_number;
7444 attrs->phys.split_subport_number = split_subport_number;
7445}
7446EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port,
7458 const unsigned char *switch_id,
7459 unsigned char switch_id_len, u16 pf)
7460{
7461 struct devlink_port_attrs *attrs = &devlink_port->attrs;
7462 int ret;
7463
7464 ret = __devlink_port_attrs_set(devlink_port,
7465 DEVLINK_PORT_FLAVOUR_PCI_PF,
7466 switch_id, switch_id_len);
7467 if (ret)
7468 return;
7469
7470 attrs->pci_pf.pf = pf;
7471}
7472EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port,
7485 const unsigned char *switch_id,
7486 unsigned char switch_id_len,
7487 u16 pf, u16 vf)
7488{
7489 struct devlink_port_attrs *attrs = &devlink_port->attrs;
7490 int ret;
7491
7492 ret = __devlink_port_attrs_set(devlink_port,
7493 DEVLINK_PORT_FLAVOUR_PCI_VF,
7494 switch_id, switch_id_len);
7495 if (ret)
7496 return;
7497 attrs->pci_vf.pf = pf;
7498 attrs->pci_vf.vf = vf;
7499}
7500EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
7501
7502static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
7503 char *name, size_t len)
7504{
7505 struct devlink_port_attrs *attrs = &devlink_port->attrs;
7506 int n = 0;
7507
7508 if (!attrs->set)
7509 return -EOPNOTSUPP;
7510
7511 switch (attrs->flavour) {
7512 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
7513 case DEVLINK_PORT_FLAVOUR_VIRTUAL:
7514 if (!attrs->split)
7515 n = snprintf(name, len, "p%u", attrs->phys.port_number);
7516 else
7517 n = snprintf(name, len, "p%us%u",
7518 attrs->phys.port_number,
7519 attrs->phys.split_subport_number);
7520 break;
7521 case DEVLINK_PORT_FLAVOUR_CPU:
7522 case DEVLINK_PORT_FLAVOUR_DSA:
7523
7524
7525
7526 WARN_ON(1);
7527 return -EINVAL;
7528 case DEVLINK_PORT_FLAVOUR_PCI_PF:
7529 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
7530 break;
7531 case DEVLINK_PORT_FLAVOUR_PCI_VF:
7532 n = snprintf(name, len, "pf%uvf%u",
7533 attrs->pci_vf.pf, attrs->pci_vf.vf);
7534 break;
7535 }
7536
7537 if (n >= len)
7538 return -EINVAL;
7539
7540 return 0;
7541}
7542
7543int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
7544 u32 size, u16 ingress_pools_count,
7545 u16 egress_pools_count, u16 ingress_tc_count,
7546 u16 egress_tc_count)
7547{
7548 struct devlink_sb *devlink_sb;
7549 int err = 0;
7550
7551 mutex_lock(&devlink->lock);
7552 if (devlink_sb_index_exists(devlink, sb_index)) {
7553 err = -EEXIST;
7554 goto unlock;
7555 }
7556
7557 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
7558 if (!devlink_sb) {
7559 err = -ENOMEM;
7560 goto unlock;
7561 }
7562 devlink_sb->index = sb_index;
7563 devlink_sb->size = size;
7564 devlink_sb->ingress_pools_count = ingress_pools_count;
7565 devlink_sb->egress_pools_count = egress_pools_count;
7566 devlink_sb->ingress_tc_count = ingress_tc_count;
7567 devlink_sb->egress_tc_count = egress_tc_count;
7568 list_add_tail(&devlink_sb->list, &devlink->sb_list);
7569unlock:
7570 mutex_unlock(&devlink->lock);
7571 return err;
7572}
7573EXPORT_SYMBOL_GPL(devlink_sb_register);
7574
7575void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
7576{
7577 struct devlink_sb *devlink_sb;
7578
7579 mutex_lock(&devlink->lock);
7580 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
7581 WARN_ON(!devlink_sb);
7582 list_del(&devlink_sb->list);
7583 mutex_unlock(&devlink->lock);
7584 kfree(devlink_sb);
7585}
7586EXPORT_SYMBOL_GPL(devlink_sb_unregister);
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596int devlink_dpipe_headers_register(struct devlink *devlink,
7597 struct devlink_dpipe_headers *dpipe_headers)
7598{
7599 mutex_lock(&devlink->lock);
7600 devlink->dpipe_headers = dpipe_headers;
7601 mutex_unlock(&devlink->lock);
7602 return 0;
7603}
7604EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register);
7605
7606
7607
7608
7609
7610
7611
7612
7613void devlink_dpipe_headers_unregister(struct devlink *devlink)
7614{
7615 mutex_lock(&devlink->lock);
7616 devlink->dpipe_headers = NULL;
7617 mutex_unlock(&devlink->lock);
7618}
7619EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister);
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
7636 const char *table_name)
7637{
7638 struct devlink_dpipe_table *table;
7639 bool enabled;
7640
7641 rcu_read_lock();
7642 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
7643 table_name, devlink);
7644 enabled = false;
7645 if (table)
7646 enabled = table->counters_enabled;
7647 rcu_read_unlock();
7648 return enabled;
7649}
7650EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661int devlink_dpipe_table_register(struct devlink *devlink,
7662 const char *table_name,
7663 struct devlink_dpipe_table_ops *table_ops,
7664 void *priv, bool counter_control_extern)
7665{
7666 struct devlink_dpipe_table *table;
7667 int err = 0;
7668
7669 if (WARN_ON(!table_ops->size_get))
7670 return -EINVAL;
7671
7672 mutex_lock(&devlink->lock);
7673
7674 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name,
7675 devlink)) {
7676 err = -EEXIST;
7677 goto unlock;
7678 }
7679
7680 table = kzalloc(sizeof(*table), GFP_KERNEL);
7681 if (!table) {
7682 err = -ENOMEM;
7683 goto unlock;
7684 }
7685
7686 table->name = table_name;
7687 table->table_ops = table_ops;
7688 table->priv = priv;
7689 table->counter_control_extern = counter_control_extern;
7690
7691 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
7692unlock:
7693 mutex_unlock(&devlink->lock);
7694 return err;
7695}
7696EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
7697
7698
7699
7700
7701
7702
7703
7704void devlink_dpipe_table_unregister(struct devlink *devlink,
7705 const char *table_name)
7706{
7707 struct devlink_dpipe_table *table;
7708
7709 mutex_lock(&devlink->lock);
7710 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
7711 table_name, devlink);
7712 if (!table)
7713 goto unlock;
7714 list_del_rcu(&table->list);
7715 mutex_unlock(&devlink->lock);
7716 kfree_rcu(table, rcu);
7717 return;
7718unlock:
7719 mutex_unlock(&devlink->lock);
7720}
7721EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister);
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733int devlink_resource_register(struct devlink *devlink,
7734 const char *resource_name,
7735 u64 resource_size,
7736 u64 resource_id,
7737 u64 parent_resource_id,
7738 const struct devlink_resource_size_params *size_params)
7739{
7740 struct devlink_resource *resource;
7741 struct list_head *resource_list;
7742 bool top_hierarchy;
7743 int err = 0;
7744
7745 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
7746
7747 mutex_lock(&devlink->lock);
7748 resource = devlink_resource_find(devlink, NULL, resource_id);
7749 if (resource) {
7750 err = -EINVAL;
7751 goto out;
7752 }
7753
7754 resource = kzalloc(sizeof(*resource), GFP_KERNEL);
7755 if (!resource) {
7756 err = -ENOMEM;
7757 goto out;
7758 }
7759
7760 if (top_hierarchy) {
7761 resource_list = &devlink->resource_list;
7762 } else {
7763 struct devlink_resource *parent_resource;
7764
7765 parent_resource = devlink_resource_find(devlink, NULL,
7766 parent_resource_id);
7767 if (parent_resource) {
7768 resource_list = &parent_resource->resource_list;
7769 resource->parent = parent_resource;
7770 } else {
7771 kfree(resource);
7772 err = -EINVAL;
7773 goto out;
7774 }
7775 }
7776
7777 resource->name = resource_name;
7778 resource->size = resource_size;
7779 resource->size_new = resource_size;
7780 resource->id = resource_id;
7781 resource->size_valid = true;
7782 memcpy(&resource->size_params, size_params,
7783 sizeof(resource->size_params));
7784 INIT_LIST_HEAD(&resource->resource_list);
7785 list_add_tail(&resource->list, resource_list);
7786out:
7787 mutex_unlock(&devlink->lock);
7788 return err;
7789}
7790EXPORT_SYMBOL_GPL(devlink_resource_register);
7791
7792
7793
7794
7795
7796
7797
7798void devlink_resources_unregister(struct devlink *devlink,
7799 struct devlink_resource *resource)
7800{
7801 struct devlink_resource *tmp, *child_resource;
7802 struct list_head *resource_list;
7803
7804 if (resource)
7805 resource_list = &resource->resource_list;
7806 else
7807 resource_list = &devlink->resource_list;
7808
7809 if (!resource)
7810 mutex_lock(&devlink->lock);
7811
7812 list_for_each_entry_safe(child_resource, tmp, resource_list, list) {
7813 devlink_resources_unregister(devlink, child_resource);
7814 list_del(&child_resource->list);
7815 kfree(child_resource);
7816 }
7817
7818 if (!resource)
7819 mutex_unlock(&devlink->lock);
7820}
7821EXPORT_SYMBOL_GPL(devlink_resources_unregister);
7822
7823
7824
7825
7826
7827
7828
7829
7830int devlink_resource_size_get(struct devlink *devlink,
7831 u64 resource_id,
7832 u64 *p_resource_size)
7833{
7834 struct devlink_resource *resource;
7835 int err = 0;
7836
7837 mutex_lock(&devlink->lock);
7838 resource = devlink_resource_find(devlink, NULL, resource_id);
7839 if (!resource) {
7840 err = -EINVAL;
7841 goto out;
7842 }
7843 *p_resource_size = resource->size_new;
7844 resource->size = resource->size_new;
7845out:
7846 mutex_unlock(&devlink->lock);
7847 return err;
7848}
7849EXPORT_SYMBOL_GPL(devlink_resource_size_get);
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859int devlink_dpipe_table_resource_set(struct devlink *devlink,
7860 const char *table_name, u64 resource_id,
7861 u64 resource_units)
7862{
7863 struct devlink_dpipe_table *table;
7864 int err = 0;
7865
7866 mutex_lock(&devlink->lock);
7867 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
7868 table_name, devlink);
7869 if (!table) {
7870 err = -EINVAL;
7871 goto out;
7872 }
7873 table->resource_id = resource_id;
7874 table->resource_units = resource_units;
7875 table->resource_valid = true;
7876out:
7877 mutex_unlock(&devlink->lock);
7878 return err;
7879}
7880EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890void devlink_resource_occ_get_register(struct devlink *devlink,
7891 u64 resource_id,
7892 devlink_resource_occ_get_t *occ_get,
7893 void *occ_get_priv)
7894{
7895 struct devlink_resource *resource;
7896
7897 mutex_lock(&devlink->lock);
7898 resource = devlink_resource_find(devlink, NULL, resource_id);
7899 if (WARN_ON(!resource))
7900 goto out;
7901 WARN_ON(resource->occ_get);
7902
7903 resource->occ_get = occ_get;
7904 resource->occ_get_priv = occ_get_priv;
7905out:
7906 mutex_unlock(&devlink->lock);
7907}
7908EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
7909
7910
7911
7912
7913
7914
7915
7916void devlink_resource_occ_get_unregister(struct devlink *devlink,
7917 u64 resource_id)
7918{
7919 struct devlink_resource *resource;
7920
7921 mutex_lock(&devlink->lock);
7922 resource = devlink_resource_find(devlink, NULL, resource_id);
7923 if (WARN_ON(!resource))
7924 goto out;
7925 WARN_ON(!resource->occ_get);
7926
7927 resource->occ_get = NULL;
7928 resource->occ_get_priv = NULL;
7929out:
7930 mutex_unlock(&devlink->lock);
7931}
7932EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
7933
7934static int devlink_param_verify(const struct devlink_param *param)
7935{
7936 if (!param || !param->name || !param->supported_cmodes)
7937 return -EINVAL;
7938 if (param->generic)
7939 return devlink_param_generic_verify(param);
7940 else
7941 return devlink_param_driver_verify(param);
7942}
7943
7944static int __devlink_params_register(struct devlink *devlink,
7945 unsigned int port_index,
7946 struct list_head *param_list,
7947 const struct devlink_param *params,
7948 size_t params_count,
7949 enum devlink_command reg_cmd,
7950 enum devlink_command unreg_cmd)
7951{
7952 const struct devlink_param *param = params;
7953 int i;
7954 int err;
7955
7956 mutex_lock(&devlink->lock);
7957 for (i = 0; i < params_count; i++, param++) {
7958 err = devlink_param_verify(param);
7959 if (err)
7960 goto rollback;
7961
7962 err = devlink_param_register_one(devlink, port_index,
7963 param_list, param, reg_cmd);
7964 if (err)
7965 goto rollback;
7966 }
7967
7968 mutex_unlock(&devlink->lock);
7969 return 0;
7970
7971rollback:
7972 if (!i)
7973 goto unlock;
7974 for (param--; i > 0; i--, param--)
7975 devlink_param_unregister_one(devlink, port_index, param_list,
7976 param, unreg_cmd);
7977unlock:
7978 mutex_unlock(&devlink->lock);
7979 return err;
7980}
7981
7982static void __devlink_params_unregister(struct devlink *devlink,
7983 unsigned int port_index,
7984 struct list_head *param_list,
7985 const struct devlink_param *params,
7986 size_t params_count,
7987 enum devlink_command cmd)
7988{
7989 const struct devlink_param *param = params;
7990 int i;
7991
7992 mutex_lock(&devlink->lock);
7993 for (i = 0; i < params_count; i++, param++)
7994 devlink_param_unregister_one(devlink, 0, param_list, param,
7995 cmd);
7996 mutex_unlock(&devlink->lock);
7997}
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008int devlink_params_register(struct devlink *devlink,
8009 const struct devlink_param *params,
8010 size_t params_count)
8011{
8012 return __devlink_params_register(devlink, 0, &devlink->param_list,
8013 params, params_count,
8014 DEVLINK_CMD_PARAM_NEW,
8015 DEVLINK_CMD_PARAM_DEL);
8016}
8017EXPORT_SYMBOL_GPL(devlink_params_register);
8018
8019
8020
8021
8022
8023
8024
8025void devlink_params_unregister(struct devlink *devlink,
8026 const struct devlink_param *params,
8027 size_t params_count)
8028{
8029 return __devlink_params_unregister(devlink, 0, &devlink->param_list,
8030 params, params_count,
8031 DEVLINK_CMD_PARAM_DEL);
8032}
8033EXPORT_SYMBOL_GPL(devlink_params_unregister);
8034
8035
8036
8037
8038
8039
8040
8041
8042void devlink_params_publish(struct devlink *devlink)
8043{
8044 struct devlink_param_item *param_item;
8045
8046 list_for_each_entry(param_item, &devlink->param_list, list) {
8047 if (param_item->published)
8048 continue;
8049 param_item->published = true;
8050 devlink_param_notify(devlink, 0, param_item,
8051 DEVLINK_CMD_PARAM_NEW);
8052 }
8053}
8054EXPORT_SYMBOL_GPL(devlink_params_publish);
8055
8056
8057
8058
8059
8060
8061
8062
8063void devlink_params_unpublish(struct devlink *devlink)
8064{
8065 struct devlink_param_item *param_item;
8066
8067 list_for_each_entry(param_item, &devlink->param_list, list) {
8068 if (!param_item->published)
8069 continue;
8070 param_item->published = false;
8071 devlink_param_notify(devlink, 0, param_item,
8072 DEVLINK_CMD_PARAM_DEL);
8073 }
8074}
8075EXPORT_SYMBOL_GPL(devlink_params_unpublish);
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086int devlink_port_params_register(struct devlink_port *devlink_port,
8087 const struct devlink_param *params,
8088 size_t params_count)
8089{
8090 return __devlink_params_register(devlink_port->devlink,
8091 devlink_port->index,
8092 &devlink_port->param_list, params,
8093 params_count,
8094 DEVLINK_CMD_PORT_PARAM_NEW,
8095 DEVLINK_CMD_PORT_PARAM_DEL);
8096}
8097EXPORT_SYMBOL_GPL(devlink_port_params_register);
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107void devlink_port_params_unregister(struct devlink_port *devlink_port,
8108 const struct devlink_param *params,
8109 size_t params_count)
8110{
8111 return __devlink_params_unregister(devlink_port->devlink,
8112 devlink_port->index,
8113 &devlink_port->param_list,
8114 params, params_count,
8115 DEVLINK_CMD_PORT_PARAM_DEL);
8116}
8117EXPORT_SYMBOL_GPL(devlink_port_params_unregister);
8118
8119static int
8120__devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id,
8121 union devlink_param_value *init_val)
8122{
8123 struct devlink_param_item *param_item;
8124
8125 param_item = devlink_param_find_by_id(param_list, param_id);
8126 if (!param_item)
8127 return -EINVAL;
8128
8129 if (!param_item->driverinit_value_valid ||
8130 !devlink_param_cmode_is_supported(param_item->param,
8131 DEVLINK_PARAM_CMODE_DRIVERINIT))
8132 return -EOPNOTSUPP;
8133
8134 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
8135 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
8136 else
8137 *init_val = param_item->driverinit_value;
8138
8139 return 0;
8140}
8141
8142static int
8143__devlink_param_driverinit_value_set(struct devlink *devlink,
8144 unsigned int port_index,
8145 struct list_head *param_list, u32 param_id,
8146 union devlink_param_value init_val,
8147 enum devlink_command cmd)
8148{
8149 struct devlink_param_item *param_item;
8150
8151 param_item = devlink_param_find_by_id(param_list, param_id);
8152 if (!param_item)
8153 return -EINVAL;
8154
8155 if (!devlink_param_cmode_is_supported(param_item->param,
8156 DEVLINK_PARAM_CMODE_DRIVERINIT))
8157 return -EOPNOTSUPP;
8158
8159 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
8160 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
8161 else
8162 param_item->driverinit_value = init_val;
8163 param_item->driverinit_value_valid = true;
8164
8165 devlink_param_notify(devlink, port_index, param_item, cmd);
8166 return 0;
8167}
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
8181 union devlink_param_value *init_val)
8182{
8183 if (!devlink_reload_supported(devlink))
8184 return -EOPNOTSUPP;
8185
8186 return __devlink_param_driverinit_value_get(&devlink->param_list,
8187 param_id, init_val);
8188}
8189EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
8204 union devlink_param_value init_val)
8205{
8206 return __devlink_param_driverinit_value_set(devlink, 0,
8207 &devlink->param_list,
8208 param_id, init_val,
8209 DEVLINK_CMD_PARAM_NEW);
8210}
8211EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port,
8225 u32 param_id,
8226 union devlink_param_value *init_val)
8227{
8228 struct devlink *devlink = devlink_port->devlink;
8229
8230 if (!devlink_reload_supported(devlink))
8231 return -EOPNOTSUPP;
8232
8233 return __devlink_param_driverinit_value_get(&devlink_port->param_list,
8234 param_id, init_val);
8235}
8236EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get);
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port,
8251 u32 param_id,
8252 union devlink_param_value init_val)
8253{
8254 return __devlink_param_driverinit_value_set(devlink_port->devlink,
8255 devlink_port->index,
8256 &devlink_port->param_list,
8257 param_id, init_val,
8258 DEVLINK_CMD_PORT_PARAM_NEW);
8259}
8260EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set);
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
8275{
8276 struct devlink_param_item *param_item;
8277
8278 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
8279 WARN_ON(!param_item);
8280
8281 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
8282}
8283EXPORT_SYMBOL_GPL(devlink_param_value_changed);
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298void devlink_port_param_value_changed(struct devlink_port *devlink_port,
8299 u32 param_id)
8300{
8301 struct devlink_param_item *param_item;
8302
8303 param_item = devlink_param_find_by_id(&devlink_port->param_list,
8304 param_id);
8305 WARN_ON(!param_item);
8306
8307 devlink_param_notify(devlink_port->devlink, devlink_port->index,
8308 param_item, DEVLINK_CMD_PORT_PARAM_NEW);
8309}
8310EXPORT_SYMBOL_GPL(devlink_port_param_value_changed);
8311
8312
8313
8314
8315
8316
8317
8318
8319void devlink_param_value_str_fill(union devlink_param_value *dst_val,
8320 const char *src)
8321{
8322 size_t len;
8323
8324 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
8325 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
8326}
8327EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337struct devlink_region *
8338devlink_region_create(struct devlink *devlink,
8339 const struct devlink_region_ops *ops,
8340 u32 region_max_snapshots, u64 region_size)
8341{
8342 struct devlink_region *region;
8343 int err = 0;
8344
8345 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
8346 return ERR_PTR(-EINVAL);
8347
8348 mutex_lock(&devlink->lock);
8349
8350 if (devlink_region_get_by_name(devlink, ops->name)) {
8351 err = -EEXIST;
8352 goto unlock;
8353 }
8354
8355 region = kzalloc(sizeof(*region), GFP_KERNEL);
8356 if (!region) {
8357 err = -ENOMEM;
8358 goto unlock;
8359 }
8360
8361 region->devlink = devlink;
8362 region->max_snapshots = region_max_snapshots;
8363 region->ops = ops;
8364 region->size = region_size;
8365 INIT_LIST_HEAD(®ion->snapshot_list);
8366 list_add_tail(®ion->list, &devlink->region_list);
8367 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
8368
8369 mutex_unlock(&devlink->lock);
8370 return region;
8371
8372unlock:
8373 mutex_unlock(&devlink->lock);
8374 return ERR_PTR(err);
8375}
8376EXPORT_SYMBOL_GPL(devlink_region_create);
8377
8378
8379
8380
8381
8382
8383void devlink_region_destroy(struct devlink_region *region)
8384{
8385 struct devlink *devlink = region->devlink;
8386 struct devlink_snapshot *snapshot, *ts;
8387
8388 mutex_lock(&devlink->lock);
8389
8390
8391 list_for_each_entry_safe(snapshot, ts, ®ion->snapshot_list, list)
8392 devlink_region_snapshot_del(region, snapshot);
8393
8394 list_del(®ion->list);
8395
8396 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
8397 mutex_unlock(&devlink->lock);
8398 kfree(region);
8399}
8400EXPORT_SYMBOL_GPL(devlink_region_destroy);
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
8418{
8419 int err;
8420
8421 mutex_lock(&devlink->lock);
8422 err = __devlink_region_snapshot_id_get(devlink, id);
8423 mutex_unlock(&devlink->lock);
8424
8425 return err;
8426}
8427EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
8440{
8441 mutex_lock(&devlink->lock);
8442 __devlink_snapshot_id_decrement(devlink, id);
8443 mutex_unlock(&devlink->lock);
8444}
8445EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459int devlink_region_snapshot_create(struct devlink_region *region,
8460 u8 *data, u32 snapshot_id)
8461{
8462 struct devlink *devlink = region->devlink;
8463 int err;
8464
8465 mutex_lock(&devlink->lock);
8466 err = __devlink_region_snapshot_create(region, data, snapshot_id);
8467 mutex_unlock(&devlink->lock);
8468
8469 return err;
8470}
8471EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
8472
8473#define DEVLINK_TRAP(_id, _type) \
8474 { \
8475 .type = DEVLINK_TRAP_TYPE_##_type, \
8476 .id = DEVLINK_TRAP_GENERIC_ID_##_id, \
8477 .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \
8478 }
8479
8480static const struct devlink_trap devlink_trap_generic[] = {
8481 DEVLINK_TRAP(SMAC_MC, DROP),
8482 DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
8483 DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
8484 DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
8485 DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
8486 DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
8487 DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
8488 DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
8489 DEVLINK_TRAP(TAIL_DROP, DROP),
8490 DEVLINK_TRAP(NON_IP_PACKET, DROP),
8491 DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP),
8492 DEVLINK_TRAP(DIP_LB, DROP),
8493 DEVLINK_TRAP(SIP_MC, DROP),
8494 DEVLINK_TRAP(SIP_LB, DROP),
8495 DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP),
8496 DEVLINK_TRAP(IPV4_SIP_BC, DROP),
8497 DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP),
8498 DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP),
8499 DEVLINK_TRAP(MTU_ERROR, EXCEPTION),
8500 DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION),
8501 DEVLINK_TRAP(RPF, EXCEPTION),
8502 DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
8503 DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
8504 DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
8505 DEVLINK_TRAP(NON_ROUTABLE, DROP),
8506 DEVLINK_TRAP(DECAP_ERROR, EXCEPTION),
8507 DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP),
8508 DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP),
8509 DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP),
8510 DEVLINK_TRAP(STP, CONTROL),
8511 DEVLINK_TRAP(LACP, CONTROL),
8512 DEVLINK_TRAP(LLDP, CONTROL),
8513 DEVLINK_TRAP(IGMP_QUERY, CONTROL),
8514 DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL),
8515 DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL),
8516 DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL),
8517 DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL),
8518 DEVLINK_TRAP(MLD_QUERY, CONTROL),
8519 DEVLINK_TRAP(MLD_V1_REPORT, CONTROL),
8520 DEVLINK_TRAP(MLD_V2_REPORT, CONTROL),
8521 DEVLINK_TRAP(MLD_V1_DONE, CONTROL),
8522 DEVLINK_TRAP(IPV4_DHCP, CONTROL),
8523 DEVLINK_TRAP(IPV6_DHCP, CONTROL),
8524 DEVLINK_TRAP(ARP_REQUEST, CONTROL),
8525 DEVLINK_TRAP(ARP_RESPONSE, CONTROL),
8526 DEVLINK_TRAP(ARP_OVERLAY, CONTROL),
8527 DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL),
8528 DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL),
8529 DEVLINK_TRAP(IPV4_BFD, CONTROL),
8530 DEVLINK_TRAP(IPV6_BFD, CONTROL),
8531 DEVLINK_TRAP(IPV4_OSPF, CONTROL),
8532 DEVLINK_TRAP(IPV6_OSPF, CONTROL),
8533 DEVLINK_TRAP(IPV4_BGP, CONTROL),
8534 DEVLINK_TRAP(IPV6_BGP, CONTROL),
8535 DEVLINK_TRAP(IPV4_VRRP, CONTROL),
8536 DEVLINK_TRAP(IPV6_VRRP, CONTROL),
8537 DEVLINK_TRAP(IPV4_PIM, CONTROL),
8538 DEVLINK_TRAP(IPV6_PIM, CONTROL),
8539 DEVLINK_TRAP(UC_LB, CONTROL),
8540 DEVLINK_TRAP(LOCAL_ROUTE, CONTROL),
8541 DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL),
8542 DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL),
8543 DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL),
8544 DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL),
8545 DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL),
8546 DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL),
8547 DEVLINK_TRAP(IPV6_REDIRECT, CONTROL),
8548 DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL),
8549 DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL),
8550 DEVLINK_TRAP(PTP_EVENT, CONTROL),
8551 DEVLINK_TRAP(PTP_GENERAL, CONTROL),
8552 DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL),
8553 DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL),
8554};
8555
8556#define DEVLINK_TRAP_GROUP(_id) \
8557 { \
8558 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \
8559 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \
8560 }
8561
8562static const struct devlink_trap_group devlink_trap_group_generic[] = {
8563 DEVLINK_TRAP_GROUP(L2_DROPS),
8564 DEVLINK_TRAP_GROUP(L3_DROPS),
8565 DEVLINK_TRAP_GROUP(L3_EXCEPTIONS),
8566 DEVLINK_TRAP_GROUP(BUFFER_DROPS),
8567 DEVLINK_TRAP_GROUP(TUNNEL_DROPS),
8568 DEVLINK_TRAP_GROUP(ACL_DROPS),
8569 DEVLINK_TRAP_GROUP(STP),
8570 DEVLINK_TRAP_GROUP(LACP),
8571 DEVLINK_TRAP_GROUP(LLDP),
8572 DEVLINK_TRAP_GROUP(MC_SNOOPING),
8573 DEVLINK_TRAP_GROUP(DHCP),
8574 DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY),
8575 DEVLINK_TRAP_GROUP(BFD),
8576 DEVLINK_TRAP_GROUP(OSPF),
8577 DEVLINK_TRAP_GROUP(BGP),
8578 DEVLINK_TRAP_GROUP(VRRP),
8579 DEVLINK_TRAP_GROUP(PIM),
8580 DEVLINK_TRAP_GROUP(UC_LB),
8581 DEVLINK_TRAP_GROUP(LOCAL_DELIVERY),
8582 DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY),
8583 DEVLINK_TRAP_GROUP(IPV6),
8584 DEVLINK_TRAP_GROUP(PTP_EVENT),
8585 DEVLINK_TRAP_GROUP(PTP_GENERAL),
8586 DEVLINK_TRAP_GROUP(ACL_SAMPLE),
8587 DEVLINK_TRAP_GROUP(ACL_TRAP),
8588};
8589
8590static int devlink_trap_generic_verify(const struct devlink_trap *trap)
8591{
8592 if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
8593 return -EINVAL;
8594
8595 if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
8596 return -EINVAL;
8597
8598 if (trap->type != devlink_trap_generic[trap->id].type)
8599 return -EINVAL;
8600
8601 return 0;
8602}
8603
8604static int devlink_trap_driver_verify(const struct devlink_trap *trap)
8605{
8606 int i;
8607
8608 if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
8609 return -EINVAL;
8610
8611 for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
8612 if (!strcmp(trap->name, devlink_trap_generic[i].name))
8613 return -EEXIST;
8614 }
8615
8616 return 0;
8617}
8618
8619static int devlink_trap_verify(const struct devlink_trap *trap)
8620{
8621 if (!trap || !trap->name)
8622 return -EINVAL;
8623
8624 if (trap->generic)
8625 return devlink_trap_generic_verify(trap);
8626 else
8627 return devlink_trap_driver_verify(trap);
8628}
8629
8630static int
8631devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
8632{
8633 if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
8634 return -EINVAL;
8635
8636 if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
8637 return -EINVAL;
8638
8639 return 0;
8640}
8641
8642static int
8643devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
8644{
8645 int i;
8646
8647 if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
8648 return -EINVAL;
8649
8650 for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
8651 if (!strcmp(group->name, devlink_trap_group_generic[i].name))
8652 return -EEXIST;
8653 }
8654
8655 return 0;
8656}
8657
8658static int devlink_trap_group_verify(const struct devlink_trap_group *group)
8659{
8660 if (group->generic)
8661 return devlink_trap_group_generic_verify(group);
8662 else
8663 return devlink_trap_group_driver_verify(group);
8664}
8665
8666static void
8667devlink_trap_group_notify(struct devlink *devlink,
8668 const struct devlink_trap_group_item *group_item,
8669 enum devlink_command cmd)
8670{
8671 struct sk_buff *msg;
8672 int err;
8673
8674 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
8675 cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
8676
8677 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8678 if (!msg)
8679 return;
8680
8681 err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
8682 0);
8683 if (err) {
8684 nlmsg_free(msg);
8685 return;
8686 }
8687
8688 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
8689 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
8690}
8691
8692static int
8693devlink_trap_item_group_link(struct devlink *devlink,
8694 struct devlink_trap_item *trap_item)
8695{
8696 u16 group_id = trap_item->trap->init_group_id;
8697 struct devlink_trap_group_item *group_item;
8698
8699 group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id);
8700 if (WARN_ON_ONCE(!group_item))
8701 return -EINVAL;
8702
8703 trap_item->group_item = group_item;
8704
8705 return 0;
8706}
8707
8708static void devlink_trap_notify(struct devlink *devlink,
8709 const struct devlink_trap_item *trap_item,
8710 enum devlink_command cmd)
8711{
8712 struct sk_buff *msg;
8713 int err;
8714
8715 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
8716 cmd != DEVLINK_CMD_TRAP_DEL);
8717
8718 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8719 if (!msg)
8720 return;
8721
8722 err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
8723 if (err) {
8724 nlmsg_free(msg);
8725 return;
8726 }
8727
8728 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
8729 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
8730}
8731
8732static int
8733devlink_trap_register(struct devlink *devlink,
8734 const struct devlink_trap *trap, void *priv)
8735{
8736 struct devlink_trap_item *trap_item;
8737 int err;
8738
8739 if (devlink_trap_item_lookup(devlink, trap->name))
8740 return -EEXIST;
8741
8742 trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
8743 if (!trap_item)
8744 return -ENOMEM;
8745
8746 trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
8747 if (!trap_item->stats) {
8748 err = -ENOMEM;
8749 goto err_stats_alloc;
8750 }
8751
8752 trap_item->trap = trap;
8753 trap_item->action = trap->init_action;
8754 trap_item->priv = priv;
8755
8756 err = devlink_trap_item_group_link(devlink, trap_item);
8757 if (err)
8758 goto err_group_link;
8759
8760 err = devlink->ops->trap_init(devlink, trap, trap_item);
8761 if (err)
8762 goto err_trap_init;
8763
8764 list_add_tail(&trap_item->list, &devlink->trap_list);
8765 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
8766
8767 return 0;
8768
8769err_trap_init:
8770err_group_link:
8771 free_percpu(trap_item->stats);
8772err_stats_alloc:
8773 kfree(trap_item);
8774 return err;
8775}
8776
8777static void devlink_trap_unregister(struct devlink *devlink,
8778 const struct devlink_trap *trap)
8779{
8780 struct devlink_trap_item *trap_item;
8781
8782 trap_item = devlink_trap_item_lookup(devlink, trap->name);
8783 if (WARN_ON_ONCE(!trap_item))
8784 return;
8785
8786 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
8787 list_del(&trap_item->list);
8788 if (devlink->ops->trap_fini)
8789 devlink->ops->trap_fini(devlink, trap, trap_item);
8790 free_percpu(trap_item->stats);
8791 kfree(trap_item);
8792}
8793
8794static void devlink_trap_disable(struct devlink *devlink,
8795 const struct devlink_trap *trap)
8796{
8797 struct devlink_trap_item *trap_item;
8798
8799 trap_item = devlink_trap_item_lookup(devlink, trap->name);
8800 if (WARN_ON_ONCE(!trap_item))
8801 return;
8802
8803 devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP);
8804 trap_item->action = DEVLINK_TRAP_ACTION_DROP;
8805}
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816int devlink_traps_register(struct devlink *devlink,
8817 const struct devlink_trap *traps,
8818 size_t traps_count, void *priv)
8819{
8820 int i, err;
8821
8822 if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
8823 return -EINVAL;
8824
8825 mutex_lock(&devlink->lock);
8826 for (i = 0; i < traps_count; i++) {
8827 const struct devlink_trap *trap = &traps[i];
8828
8829 err = devlink_trap_verify(trap);
8830 if (err)
8831 goto err_trap_verify;
8832
8833 err = devlink_trap_register(devlink, trap, priv);
8834 if (err)
8835 goto err_trap_register;
8836 }
8837 mutex_unlock(&devlink->lock);
8838
8839 return 0;
8840
8841err_trap_register:
8842err_trap_verify:
8843 for (i--; i >= 0; i--)
8844 devlink_trap_unregister(devlink, &traps[i]);
8845 mutex_unlock(&devlink->lock);
8846 return err;
8847}
8848EXPORT_SYMBOL_GPL(devlink_traps_register);
8849
8850
8851
8852
8853
8854
8855
8856void devlink_traps_unregister(struct devlink *devlink,
8857 const struct devlink_trap *traps,
8858 size_t traps_count)
8859{
8860 int i;
8861
8862 mutex_lock(&devlink->lock);
8863
8864
8865
8866 for (i = traps_count - 1; i >= 0; i--)
8867 devlink_trap_disable(devlink, &traps[i]);
8868 synchronize_rcu();
8869 for (i = traps_count - 1; i >= 0; i--)
8870 devlink_trap_unregister(devlink, &traps[i]);
8871 mutex_unlock(&devlink->lock);
8872}
8873EXPORT_SYMBOL_GPL(devlink_traps_unregister);
8874
8875static void
8876devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
8877 size_t skb_len)
8878{
8879 struct devlink_stats *stats;
8880
8881 stats = this_cpu_ptr(trap_stats);
8882 u64_stats_update_begin(&stats->syncp);
8883 stats->rx_bytes += skb_len;
8884 stats->rx_packets++;
8885 u64_stats_update_end(&stats->syncp);
8886}
8887
8888static void
8889devlink_trap_report_metadata_fill(struct net_dm_hw_metadata *hw_metadata,
8890 const struct devlink_trap_item *trap_item,
8891 struct devlink_port *in_devlink_port,
8892 const struct flow_action_cookie *fa_cookie)
8893{
8894 struct devlink_trap_group_item *group_item = trap_item->group_item;
8895
8896 hw_metadata->trap_group_name = group_item->group->name;
8897 hw_metadata->trap_name = trap_item->trap->name;
8898 hw_metadata->fa_cookie = fa_cookie;
8899
8900 spin_lock(&in_devlink_port->type_lock);
8901 if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
8902 hw_metadata->input_dev = in_devlink_port->type_dev;
8903 spin_unlock(&in_devlink_port->type_lock);
8904}
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
8915 void *trap_ctx, struct devlink_port *in_devlink_port,
8916 const struct flow_action_cookie *fa_cookie)
8917
8918{
8919 struct devlink_trap_item *trap_item = trap_ctx;
8920 struct net_dm_hw_metadata hw_metadata = {};
8921
8922 devlink_trap_stats_update(trap_item->stats, skb->len);
8923 devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
8924
8925
8926
8927
8928
8929 if (trap_item->trap->type == DEVLINK_TRAP_TYPE_CONTROL)
8930 return;
8931
8932 devlink_trap_report_metadata_fill(&hw_metadata, trap_item,
8933 in_devlink_port, fa_cookie);
8934 net_dm_hw_report(skb, &hw_metadata);
8935}
8936EXPORT_SYMBOL_GPL(devlink_trap_report);
8937
8938
8939
8940
8941
8942
8943
8944void *devlink_trap_ctx_priv(void *trap_ctx)
8945{
8946 struct devlink_trap_item *trap_item = trap_ctx;
8947
8948 return trap_item->priv;
8949}
8950EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
8951
8952static int
8953devlink_trap_group_item_policer_link(struct devlink *devlink,
8954 struct devlink_trap_group_item *group_item)
8955{
8956 u32 policer_id = group_item->group->init_policer_id;
8957 struct devlink_trap_policer_item *policer_item;
8958
8959 if (policer_id == 0)
8960 return 0;
8961
8962 policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
8963 if (WARN_ON_ONCE(!policer_item))
8964 return -EINVAL;
8965
8966 group_item->policer_item = policer_item;
8967
8968 return 0;
8969}
8970
8971static int
8972devlink_trap_group_register(struct devlink *devlink,
8973 const struct devlink_trap_group *group)
8974{
8975 struct devlink_trap_group_item *group_item;
8976 int err;
8977
8978 if (devlink_trap_group_item_lookup(devlink, group->name))
8979 return -EEXIST;
8980
8981 group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
8982 if (!group_item)
8983 return -ENOMEM;
8984
8985 group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
8986 if (!group_item->stats) {
8987 err = -ENOMEM;
8988 goto err_stats_alloc;
8989 }
8990
8991 group_item->group = group;
8992
8993 err = devlink_trap_group_item_policer_link(devlink, group_item);
8994 if (err)
8995 goto err_policer_link;
8996
8997 if (devlink->ops->trap_group_init) {
8998 err = devlink->ops->trap_group_init(devlink, group);
8999 if (err)
9000 goto err_group_init;
9001 }
9002
9003 list_add_tail(&group_item->list, &devlink->trap_group_list);
9004 devlink_trap_group_notify(devlink, group_item,
9005 DEVLINK_CMD_TRAP_GROUP_NEW);
9006
9007 return 0;
9008
9009err_group_init:
9010err_policer_link:
9011 free_percpu(group_item->stats);
9012err_stats_alloc:
9013 kfree(group_item);
9014 return err;
9015}
9016
9017static void
9018devlink_trap_group_unregister(struct devlink *devlink,
9019 const struct devlink_trap_group *group)
9020{
9021 struct devlink_trap_group_item *group_item;
9022
9023 group_item = devlink_trap_group_item_lookup(devlink, group->name);
9024 if (WARN_ON_ONCE(!group_item))
9025 return;
9026
9027 devlink_trap_group_notify(devlink, group_item,
9028 DEVLINK_CMD_TRAP_GROUP_DEL);
9029 list_del(&group_item->list);
9030 free_percpu(group_item->stats);
9031 kfree(group_item);
9032}
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042int devlink_trap_groups_register(struct devlink *devlink,
9043 const struct devlink_trap_group *groups,
9044 size_t groups_count)
9045{
9046 int i, err;
9047
9048 mutex_lock(&devlink->lock);
9049 for (i = 0; i < groups_count; i++) {
9050 const struct devlink_trap_group *group = &groups[i];
9051
9052 err = devlink_trap_group_verify(group);
9053 if (err)
9054 goto err_trap_group_verify;
9055
9056 err = devlink_trap_group_register(devlink, group);
9057 if (err)
9058 goto err_trap_group_register;
9059 }
9060 mutex_unlock(&devlink->lock);
9061
9062 return 0;
9063
9064err_trap_group_register:
9065err_trap_group_verify:
9066 for (i--; i >= 0; i--)
9067 devlink_trap_group_unregister(devlink, &groups[i]);
9068 mutex_unlock(&devlink->lock);
9069 return err;
9070}
9071EXPORT_SYMBOL_GPL(devlink_trap_groups_register);
9072
9073
9074
9075
9076
9077
9078
9079void devlink_trap_groups_unregister(struct devlink *devlink,
9080 const struct devlink_trap_group *groups,
9081 size_t groups_count)
9082{
9083 int i;
9084
9085 mutex_lock(&devlink->lock);
9086 for (i = groups_count - 1; i >= 0; i--)
9087 devlink_trap_group_unregister(devlink, &groups[i]);
9088 mutex_unlock(&devlink->lock);
9089}
9090EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister);
9091
9092static void
9093devlink_trap_policer_notify(struct devlink *devlink,
9094 const struct devlink_trap_policer_item *policer_item,
9095 enum devlink_command cmd)
9096{
9097 struct sk_buff *msg;
9098 int err;
9099
9100 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW &&
9101 cmd != DEVLINK_CMD_TRAP_POLICER_DEL);
9102
9103 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
9104 if (!msg)
9105 return;
9106
9107 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0,
9108 0, 0);
9109 if (err) {
9110 nlmsg_free(msg);
9111 return;
9112 }
9113
9114 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
9115 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
9116}
9117
9118static int
9119devlink_trap_policer_register(struct devlink *devlink,
9120 const struct devlink_trap_policer *policer)
9121{
9122 struct devlink_trap_policer_item *policer_item;
9123 int err;
9124
9125 if (devlink_trap_policer_item_lookup(devlink, policer->id))
9126 return -EEXIST;
9127
9128 policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
9129 if (!policer_item)
9130 return -ENOMEM;
9131
9132 policer_item->policer = policer;
9133 policer_item->rate = policer->init_rate;
9134 policer_item->burst = policer->init_burst;
9135
9136 if (devlink->ops->trap_policer_init) {
9137 err = devlink->ops->trap_policer_init(devlink, policer);
9138 if (err)
9139 goto err_policer_init;
9140 }
9141
9142 list_add_tail(&policer_item->list, &devlink->trap_policer_list);
9143 devlink_trap_policer_notify(devlink, policer_item,
9144 DEVLINK_CMD_TRAP_POLICER_NEW);
9145
9146 return 0;
9147
9148err_policer_init:
9149 kfree(policer_item);
9150 return err;
9151}
9152
9153static void
9154devlink_trap_policer_unregister(struct devlink *devlink,
9155 const struct devlink_trap_policer *policer)
9156{
9157 struct devlink_trap_policer_item *policer_item;
9158
9159 policer_item = devlink_trap_policer_item_lookup(devlink, policer->id);
9160 if (WARN_ON_ONCE(!policer_item))
9161 return;
9162
9163 devlink_trap_policer_notify(devlink, policer_item,
9164 DEVLINK_CMD_TRAP_POLICER_DEL);
9165 list_del(&policer_item->list);
9166 if (devlink->ops->trap_policer_fini)
9167 devlink->ops->trap_policer_fini(devlink, policer);
9168 kfree(policer_item);
9169}
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179int
9180devlink_trap_policers_register(struct devlink *devlink,
9181 const struct devlink_trap_policer *policers,
9182 size_t policers_count)
9183{
9184 int i, err;
9185
9186 mutex_lock(&devlink->lock);
9187 for (i = 0; i < policers_count; i++) {
9188 const struct devlink_trap_policer *policer = &policers[i];
9189
9190 if (WARN_ON(policer->id == 0 ||
9191 policer->max_rate < policer->min_rate ||
9192 policer->max_burst < policer->min_burst)) {
9193 err = -EINVAL;
9194 goto err_trap_policer_verify;
9195 }
9196
9197 err = devlink_trap_policer_register(devlink, policer);
9198 if (err)
9199 goto err_trap_policer_register;
9200 }
9201 mutex_unlock(&devlink->lock);
9202
9203 return 0;
9204
9205err_trap_policer_register:
9206err_trap_policer_verify:
9207 for (i--; i >= 0; i--)
9208 devlink_trap_policer_unregister(devlink, &policers[i]);
9209 mutex_unlock(&devlink->lock);
9210 return err;
9211}
9212EXPORT_SYMBOL_GPL(devlink_trap_policers_register);
9213
9214
9215
9216
9217
9218
9219
9220void
9221devlink_trap_policers_unregister(struct devlink *devlink,
9222 const struct devlink_trap_policer *policers,
9223 size_t policers_count)
9224{
9225 int i;
9226
9227 mutex_lock(&devlink->lock);
9228 for (i = policers_count - 1; i >= 0; i--)
9229 devlink_trap_policer_unregister(devlink, &policers[i]);
9230 mutex_unlock(&devlink->lock);
9231}
9232EXPORT_SYMBOL_GPL(devlink_trap_policers_unregister);
9233
9234static void __devlink_compat_running_version(struct devlink *devlink,
9235 char *buf, size_t len)
9236{
9237 const struct nlattr *nlattr;
9238 struct devlink_info_req req;
9239 struct sk_buff *msg;
9240 int rem, err;
9241
9242 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
9243 if (!msg)
9244 return;
9245
9246 req.msg = msg;
9247 err = devlink->ops->info_get(devlink, &req, NULL);
9248 if (err)
9249 goto free_msg;
9250
9251 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
9252 const struct nlattr *kv;
9253 int rem_kv;
9254
9255 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
9256 continue;
9257
9258 nla_for_each_nested(kv, nlattr, rem_kv) {
9259 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
9260 continue;
9261
9262 strlcat(buf, nla_data(kv), len);
9263 strlcat(buf, " ", len);
9264 }
9265 }
9266free_msg:
9267 nlmsg_free(msg);
9268}
9269
9270void devlink_compat_running_version(struct net_device *dev,
9271 char *buf, size_t len)
9272{
9273 struct devlink *devlink;
9274
9275 dev_hold(dev);
9276 rtnl_unlock();
9277
9278 devlink = netdev_to_devlink(dev);
9279 if (!devlink || !devlink->ops->info_get)
9280 goto out;
9281
9282 mutex_lock(&devlink->lock);
9283 __devlink_compat_running_version(devlink, buf, len);
9284 mutex_unlock(&devlink->lock);
9285
9286out:
9287 rtnl_lock();
9288 dev_put(dev);
9289}
9290
9291int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
9292{
9293 struct devlink *devlink;
9294 int ret;
9295
9296 dev_hold(dev);
9297 rtnl_unlock();
9298
9299 devlink = netdev_to_devlink(dev);
9300 if (!devlink || !devlink->ops->flash_update) {
9301 ret = -EOPNOTSUPP;
9302 goto out;
9303 }
9304
9305 mutex_lock(&devlink->lock);
9306 ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL);
9307 mutex_unlock(&devlink->lock);
9308
9309out:
9310 rtnl_lock();
9311 dev_put(dev);
9312
9313 return ret;
9314}
9315
9316int devlink_compat_phys_port_name_get(struct net_device *dev,
9317 char *name, size_t len)
9318{
9319 struct devlink_port *devlink_port;
9320
9321
9322
9323
9324
9325 ASSERT_RTNL();
9326
9327 devlink_port = netdev_to_devlink_port(dev);
9328 if (!devlink_port)
9329 return -EOPNOTSUPP;
9330
9331 return __devlink_port_phys_port_name_get(devlink_port, name, len);
9332}
9333
9334int devlink_compat_switch_id_get(struct net_device *dev,
9335 struct netdev_phys_item_id *ppid)
9336{
9337 struct devlink_port *devlink_port;
9338
9339
9340
9341
9342
9343 devlink_port = netdev_to_devlink_port(dev);
9344 if (!devlink_port || !devlink_port->attrs.switch_port)
9345 return -EOPNOTSUPP;
9346
9347 memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
9348
9349 return 0;
9350}
9351
9352static void __net_exit devlink_pernet_pre_exit(struct net *net)
9353{
9354 struct devlink *devlink;
9355 int err;
9356
9357
9358
9359
9360 mutex_lock(&devlink_mutex);
9361 list_for_each_entry(devlink, &devlink_list, list) {
9362 if (net_eq(devlink_net(devlink), net)) {
9363 if (WARN_ON(!devlink_reload_supported(devlink)))
9364 continue;
9365 err = devlink_reload(devlink, &init_net, NULL);
9366 if (err && err != -EOPNOTSUPP)
9367 pr_warn("Failed to reload devlink instance into init_net\n");
9368 }
9369 }
9370 mutex_unlock(&devlink_mutex);
9371}
9372
9373static struct pernet_operations devlink_pernet_ops __net_initdata = {
9374 .pre_exit = devlink_pernet_pre_exit,
9375};
9376
9377static int __init devlink_init(void)
9378{
9379 int err;
9380
9381 err = genl_register_family(&devlink_nl_family);
9382 if (err)
9383 goto out;
9384 err = register_pernet_subsys(&devlink_pernet_ops);
9385
9386out:
9387 WARN_ON(err);
9388 return err;
9389}
9390
9391subsys_initcall(devlink_init);
9392