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