Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
[linux-2.6-microblaze.git] / net / devlink / netlink.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5  */
6
7 #include <net/genetlink.h>
8 #include <net/sock.h>
9
10 #include "devl_internal.h"
11
12 static const struct genl_multicast_group devlink_nl_mcgrps[] = {
13         [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
14 };
15
16 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
17         [DEVLINK_ATTR_UNSPEC] = { .strict_start_type =
18                 DEVLINK_ATTR_TRAP_POLICER_ID },
19         [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
20         [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
21         [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
22         [DEVLINK_ATTR_PORT_TYPE] = NLA_POLICY_RANGE(NLA_U16, DEVLINK_PORT_TYPE_AUTO,
23                                                     DEVLINK_PORT_TYPE_IB),
24         [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
25         [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
26         [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
27         [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
28         [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
29         [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
30         [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
31         [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
32         [DEVLINK_ATTR_ESWITCH_MODE] = NLA_POLICY_RANGE(NLA_U16, DEVLINK_ESWITCH_MODE_LEGACY,
33                                                        DEVLINK_ESWITCH_MODE_SWITCHDEV),
34         [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
35         [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
36         [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
37         [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
38         [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
39         [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
40         [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
41         [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
42         [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
43         [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
44         [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
45         [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 },
46         [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 },
47         [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
48         [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
49         [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
50         [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
51         [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
52         [DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK] =
53                 NLA_POLICY_BITFIELD32(DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS),
54         [DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING },
55         [DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 },
56         [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING },
57         [DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32 },
58         [DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32 },
59         [DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32 },
60         [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP] = { .type = NLA_U8 },
61         [DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32 },
62         [DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 },
63         [DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 },
64         [DEVLINK_ATTR_PORT_FUNCTION] = { .type = NLA_NESTED },
65         [DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
66                                                         DEVLINK_RELOAD_ACTION_MAX),
67         [DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(DEVLINK_RELOAD_LIMITS_VALID_MASK),
68         [DEVLINK_ATTR_PORT_FLAVOUR] = { .type = NLA_U16 },
69         [DEVLINK_ATTR_PORT_PCI_PF_NUMBER] = { .type = NLA_U16 },
70         [DEVLINK_ATTR_PORT_PCI_SF_NUMBER] = { .type = NLA_U32 },
71         [DEVLINK_ATTR_PORT_CONTROLLER_NUMBER] = { .type = NLA_U32 },
72         [DEVLINK_ATTR_RATE_TYPE] = { .type = NLA_U16 },
73         [DEVLINK_ATTR_RATE_TX_SHARE] = { .type = NLA_U64 },
74         [DEVLINK_ATTR_RATE_TX_MAX] = { .type = NLA_U64 },
75         [DEVLINK_ATTR_RATE_NODE_NAME] = { .type = NLA_NUL_STRING },
76         [DEVLINK_ATTR_RATE_PARENT_NODE_NAME] = { .type = NLA_NUL_STRING },
77         [DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32 },
78         [DEVLINK_ATTR_LINECARD_TYPE] = { .type = NLA_NUL_STRING },
79         [DEVLINK_ATTR_SELFTESTS] = { .type = NLA_NESTED },
80         [DEVLINK_ATTR_RATE_TX_PRIORITY] = { .type = NLA_U32 },
81         [DEVLINK_ATTR_RATE_TX_WEIGHT] = { .type = NLA_U32 },
82         [DEVLINK_ATTR_REGION_DIRECT] = { .type = NLA_FLAG },
83 };
84
85 int devlink_nl_msg_reply_and_new(struct sk_buff **msg, struct genl_info *info)
86 {
87         int err;
88
89         if (*msg) {
90                 err = genlmsg_reply(*msg, info);
91                 if (err)
92                         return err;
93         }
94         *msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
95         if (!*msg)
96                 return -ENOMEM;
97         return 0;
98 }
99
100 struct devlink *
101 devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs)
102 {
103         struct devlink *devlink;
104         unsigned long index;
105         char *busname;
106         char *devname;
107
108         if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
109                 return ERR_PTR(-EINVAL);
110
111         busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
112         devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
113
114         devlinks_xa_for_each_registered_get(net, index, devlink) {
115                 devl_lock(devlink);
116                 if (devl_is_registered(devlink) &&
117                     strcmp(devlink->dev->bus->name, busname) == 0 &&
118                     strcmp(dev_name(devlink->dev), devname) == 0)
119                         return devlink;
120                 devl_unlock(devlink);
121                 devlink_put(devlink);
122         }
123
124         return ERR_PTR(-ENODEV);
125 }
126
127 static int __devlink_nl_pre_doit(struct sk_buff *skb, struct genl_info *info,
128                                  u8 flags)
129 {
130         struct devlink_port *devlink_port;
131         struct devlink *devlink;
132         int err;
133
134         devlink = devlink_get_from_attrs_lock(genl_info_net(info), info->attrs);
135         if (IS_ERR(devlink))
136                 return PTR_ERR(devlink);
137
138         info->user_ptr[0] = devlink;
139         if (flags & DEVLINK_NL_FLAG_NEED_PORT) {
140                 devlink_port = devlink_port_get_from_info(devlink, info);
141                 if (IS_ERR(devlink_port)) {
142                         err = PTR_ERR(devlink_port);
143                         goto unlock;
144                 }
145                 info->user_ptr[1] = devlink_port;
146         } else if (flags & DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT) {
147                 devlink_port = devlink_port_get_from_info(devlink, info);
148                 if (!IS_ERR(devlink_port))
149                         info->user_ptr[1] = devlink_port;
150         }
151         return 0;
152
153 unlock:
154         devl_unlock(devlink);
155         devlink_put(devlink);
156         return err;
157 }
158
159 int devlink_nl_pre_doit(const struct genl_split_ops *ops,
160                         struct sk_buff *skb, struct genl_info *info)
161 {
162         return __devlink_nl_pre_doit(skb, info, ops->internal_flags);
163 }
164
165 int devlink_nl_pre_doit_port(const struct genl_split_ops *ops,
166                              struct sk_buff *skb, struct genl_info *info)
167 {
168         return __devlink_nl_pre_doit(skb, info, DEVLINK_NL_FLAG_NEED_PORT);
169 }
170
171 int devlink_nl_pre_doit_port_optional(const struct genl_split_ops *ops,
172                                       struct sk_buff *skb,
173                                       struct genl_info *info)
174 {
175         return __devlink_nl_pre_doit(skb, info, DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT);
176 }
177
178 void devlink_nl_post_doit(const struct genl_split_ops *ops,
179                           struct sk_buff *skb, struct genl_info *info)
180 {
181         struct devlink *devlink;
182
183         devlink = info->user_ptr[0];
184         devl_unlock(devlink);
185         devlink_put(devlink);
186 }
187
188 static int devlink_nl_inst_single_dumpit(struct sk_buff *msg,
189                                          struct netlink_callback *cb, int flags,
190                                          devlink_nl_dump_one_func_t *dump_one,
191                                          struct nlattr **attrs)
192 {
193         struct devlink *devlink;
194         int err;
195
196         devlink = devlink_get_from_attrs_lock(sock_net(msg->sk), attrs);
197         if (IS_ERR(devlink))
198                 return PTR_ERR(devlink);
199         err = dump_one(msg, devlink, cb, flags | NLM_F_DUMP_FILTERED);
200
201         devl_unlock(devlink);
202         devlink_put(devlink);
203
204         if (err != -EMSGSIZE)
205                 return err;
206         return msg->len;
207 }
208
209 static int devlink_nl_inst_iter_dumpit(struct sk_buff *msg,
210                                        struct netlink_callback *cb, int flags,
211                                        devlink_nl_dump_one_func_t *dump_one)
212 {
213         struct devlink_nl_dump_state *state = devlink_dump_state(cb);
214         struct devlink *devlink;
215         int err = 0;
216
217         while ((devlink = devlinks_xa_find_get(sock_net(msg->sk),
218                                                &state->instance))) {
219                 devl_lock(devlink);
220
221                 if (devl_is_registered(devlink))
222                         err = dump_one(msg, devlink, cb, flags);
223                 else
224                         err = 0;
225
226                 devl_unlock(devlink);
227                 devlink_put(devlink);
228
229                 if (err)
230                         break;
231
232                 state->instance++;
233
234                 /* restart sub-object walk for the next instance */
235                 state->idx = 0;
236         }
237
238         if (err != -EMSGSIZE)
239                 return err;
240         return msg->len;
241 }
242
243 int devlink_nl_dumpit(struct sk_buff *msg, struct netlink_callback *cb,
244                       devlink_nl_dump_one_func_t *dump_one)
245 {
246         const struct genl_info *info = genl_info_dump(cb);
247         struct nlattr **attrs = info->attrs;
248         int flags = NLM_F_MULTI;
249
250         if (attrs &&
251             (attrs[DEVLINK_ATTR_BUS_NAME] || attrs[DEVLINK_ATTR_DEV_NAME]))
252                 return devlink_nl_inst_single_dumpit(msg, cb, flags, dump_one,
253                                                      attrs);
254         else
255                 return devlink_nl_inst_iter_dumpit(msg, cb, flags, dump_one);
256 }
257
258 static const struct genl_small_ops devlink_nl_small_ops[40] = {
259         {
260                 .cmd = DEVLINK_CMD_PORT_SET,
261                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
262                 .doit = devlink_nl_cmd_port_set_doit,
263                 .flags = GENL_ADMIN_PERM,
264                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
265         },
266         {
267                 .cmd = DEVLINK_CMD_RATE_SET,
268                 .doit = devlink_nl_cmd_rate_set_doit,
269                 .flags = GENL_ADMIN_PERM,
270         },
271         {
272                 .cmd = DEVLINK_CMD_RATE_NEW,
273                 .doit = devlink_nl_cmd_rate_new_doit,
274                 .flags = GENL_ADMIN_PERM,
275         },
276         {
277                 .cmd = DEVLINK_CMD_RATE_DEL,
278                 .doit = devlink_nl_cmd_rate_del_doit,
279                 .flags = GENL_ADMIN_PERM,
280         },
281         {
282                 .cmd = DEVLINK_CMD_PORT_SPLIT,
283                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
284                 .doit = devlink_nl_cmd_port_split_doit,
285                 .flags = GENL_ADMIN_PERM,
286                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
287         },
288         {
289                 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
290                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
291                 .doit = devlink_nl_cmd_port_unsplit_doit,
292                 .flags = GENL_ADMIN_PERM,
293                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
294         },
295         {
296                 .cmd = DEVLINK_CMD_PORT_NEW,
297                 .doit = devlink_nl_cmd_port_new_doit,
298                 .flags = GENL_ADMIN_PERM,
299         },
300         {
301                 .cmd = DEVLINK_CMD_PORT_DEL,
302                 .doit = devlink_nl_cmd_port_del_doit,
303                 .flags = GENL_ADMIN_PERM,
304                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
305         },
306
307         {
308                 .cmd = DEVLINK_CMD_LINECARD_SET,
309                 .doit = devlink_nl_cmd_linecard_set_doit,
310                 .flags = GENL_ADMIN_PERM,
311         },
312         {
313                 .cmd = DEVLINK_CMD_SB_POOL_SET,
314                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
315                 .doit = devlink_nl_cmd_sb_pool_set_doit,
316                 .flags = GENL_ADMIN_PERM,
317         },
318         {
319                 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
320                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
321                 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
322                 .flags = GENL_ADMIN_PERM,
323                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
324         },
325         {
326                 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
327                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
328                 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
329                 .flags = GENL_ADMIN_PERM,
330                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
331         },
332         {
333                 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
334                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
335                 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
336                 .flags = GENL_ADMIN_PERM,
337         },
338         {
339                 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
340                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
341                 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
342                 .flags = GENL_ADMIN_PERM,
343         },
344         {
345                 .cmd = DEVLINK_CMD_ESWITCH_GET,
346                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
347                 .doit = devlink_nl_cmd_eswitch_get_doit,
348                 .flags = GENL_ADMIN_PERM,
349         },
350         {
351                 .cmd = DEVLINK_CMD_ESWITCH_SET,
352                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
353                 .doit = devlink_nl_cmd_eswitch_set_doit,
354                 .flags = GENL_ADMIN_PERM,
355         },
356         {
357                 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
358                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
359                 .doit = devlink_nl_cmd_dpipe_table_get,
360                 /* can be retrieved by unprivileged users */
361         },
362         {
363                 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
364                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
365                 .doit = devlink_nl_cmd_dpipe_entries_get,
366                 /* can be retrieved by unprivileged users */
367         },
368         {
369                 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
370                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
371                 .doit = devlink_nl_cmd_dpipe_headers_get,
372                 /* can be retrieved by unprivileged users */
373         },
374         {
375                 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
376                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
377                 .doit = devlink_nl_cmd_dpipe_table_counters_set,
378                 .flags = GENL_ADMIN_PERM,
379         },
380         {
381                 .cmd = DEVLINK_CMD_RESOURCE_SET,
382                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
383                 .doit = devlink_nl_cmd_resource_set,
384                 .flags = GENL_ADMIN_PERM,
385         },
386         {
387                 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
388                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
389                 .doit = devlink_nl_cmd_resource_dump,
390                 /* can be retrieved by unprivileged users */
391         },
392         {
393                 .cmd = DEVLINK_CMD_RELOAD,
394                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
395                 .doit = devlink_nl_cmd_reload,
396                 .flags = GENL_ADMIN_PERM,
397         },
398         {
399                 .cmd = DEVLINK_CMD_PARAM_SET,
400                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
401                 .doit = devlink_nl_cmd_param_set_doit,
402                 .flags = GENL_ADMIN_PERM,
403         },
404         {
405                 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
406                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
407                 .doit = devlink_nl_cmd_port_param_get_doit,
408                 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
409                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
410                 /* can be retrieved by unprivileged users */
411         },
412         {
413                 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
414                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
415                 .doit = devlink_nl_cmd_port_param_set_doit,
416                 .flags = GENL_ADMIN_PERM,
417                 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
418         },
419         {
420                 .cmd = DEVLINK_CMD_REGION_NEW,
421                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
422                 .doit = devlink_nl_cmd_region_new,
423                 .flags = GENL_ADMIN_PERM,
424         },
425         {
426                 .cmd = DEVLINK_CMD_REGION_DEL,
427                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
428                 .doit = devlink_nl_cmd_region_del,
429                 .flags = GENL_ADMIN_PERM,
430         },
431         {
432                 .cmd = DEVLINK_CMD_REGION_READ,
433                 .validate = GENL_DONT_VALIDATE_STRICT |
434                             GENL_DONT_VALIDATE_DUMP_STRICT,
435                 .dumpit = devlink_nl_cmd_region_read_dumpit,
436                 .flags = GENL_ADMIN_PERM,
437         },
438         {
439                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
440                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
441                 .doit = devlink_nl_cmd_health_reporter_set_doit,
442                 .flags = GENL_ADMIN_PERM,
443                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
444         },
445         {
446                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
447                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
448                 .doit = devlink_nl_cmd_health_reporter_recover_doit,
449                 .flags = GENL_ADMIN_PERM,
450                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
451         },
452         {
453                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
454                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
455                 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
456                 .flags = GENL_ADMIN_PERM,
457                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
458         },
459         {
460                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
461                 .validate = GENL_DONT_VALIDATE_STRICT |
462                             GENL_DONT_VALIDATE_DUMP_STRICT,
463                 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
464                 .flags = GENL_ADMIN_PERM,
465         },
466         {
467                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
468                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
469                 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
470                 .flags = GENL_ADMIN_PERM,
471                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
472         },
473         {
474                 .cmd = DEVLINK_CMD_HEALTH_REPORTER_TEST,
475                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
476                 .doit = devlink_nl_cmd_health_reporter_test_doit,
477                 .flags = GENL_ADMIN_PERM,
478                 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
479         },
480         {
481                 .cmd = DEVLINK_CMD_FLASH_UPDATE,
482                 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
483                 .doit = devlink_nl_cmd_flash_update,
484                 .flags = GENL_ADMIN_PERM,
485         },
486         {
487                 .cmd = DEVLINK_CMD_TRAP_SET,
488                 .doit = devlink_nl_cmd_trap_set_doit,
489                 .flags = GENL_ADMIN_PERM,
490         },
491         {
492                 .cmd = DEVLINK_CMD_TRAP_GROUP_SET,
493                 .doit = devlink_nl_cmd_trap_group_set_doit,
494                 .flags = GENL_ADMIN_PERM,
495         },
496         {
497                 .cmd = DEVLINK_CMD_TRAP_POLICER_SET,
498                 .doit = devlink_nl_cmd_trap_policer_set_doit,
499                 .flags = GENL_ADMIN_PERM,
500         },
501         {
502                 .cmd = DEVLINK_CMD_SELFTESTS_RUN,
503                 .doit = devlink_nl_cmd_selftests_run,
504                 .flags = GENL_ADMIN_PERM,
505         },
506         /* -- No new ops here! Use split ops going forward! -- */
507 };
508
509 struct genl_family devlink_nl_family __ro_after_init = {
510         .name           = DEVLINK_GENL_NAME,
511         .version        = DEVLINK_GENL_VERSION,
512         .maxattr        = DEVLINK_ATTR_MAX,
513         .policy         = devlink_nl_policy,
514         .netnsok        = true,
515         .parallel_ops   = true,
516         .pre_doit       = devlink_nl_pre_doit,
517         .post_doit      = devlink_nl_post_doit,
518         .module         = THIS_MODULE,
519         .small_ops      = devlink_nl_small_ops,
520         .n_small_ops    = ARRAY_SIZE(devlink_nl_small_ops),
521         .split_ops      = devlink_nl_ops,
522         .n_split_ops    = ARRAY_SIZE(devlink_nl_ops),
523         .resv_start_op  = DEVLINK_CMD_SELFTESTS_RUN + 1,
524         .mcgrps         = devlink_nl_mcgrps,
525         .n_mcgrps       = ARRAY_SIZE(devlink_nl_mcgrps),
526 };