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