1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <linux/ethtool_netlink.h>
7 static struct genl_family ethtool_genl_family
;
9 static bool ethnl_ok __read_mostly
;
10 static u32 ethnl_bcast_seq
;
12 #define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \
13 ETHTOOL_FLAG_OMIT_REPLY)
14 #define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS)
16 const struct nla_policy ethnl_header_policy
[] = {
17 [ETHTOOL_A_HEADER_DEV_INDEX
] = { .type
= NLA_U32
},
18 [ETHTOOL_A_HEADER_DEV_NAME
] = { .type
= NLA_NUL_STRING
,
19 .len
= ALTIFNAMSIZ
- 1 },
20 [ETHTOOL_A_HEADER_FLAGS
] = NLA_POLICY_MASK(NLA_U32
,
24 const struct nla_policy ethnl_header_policy_stats
[] = {
25 [ETHTOOL_A_HEADER_DEV_INDEX
] = { .type
= NLA_U32
},
26 [ETHTOOL_A_HEADER_DEV_NAME
] = { .type
= NLA_NUL_STRING
,
27 .len
= ALTIFNAMSIZ
- 1 },
28 [ETHTOOL_A_HEADER_FLAGS
] = NLA_POLICY_MASK(NLA_U32
,
33 * ethnl_parse_header_dev_get() - parse request header
34 * @req_info: structure to put results into
35 * @header: nest attribute with request header
37 * @extack: netlink extack for error reporting
38 * @require_dev: fail if no device identified in header
40 * Parse request header in nested attribute @nest and puts results into
41 * the structure pointed to by @req_info. Extack from @info is used for error
42 * reporting. If req_info->dev is not null on return, reference to it has
43 * been taken. If error is returned, *req_info is null initialized and no
46 * Return: 0 on success or negative error code
48 int ethnl_parse_header_dev_get(struct ethnl_req_info
*req_info
,
49 const struct nlattr
*header
, struct net
*net
,
50 struct netlink_ext_ack
*extack
, bool require_dev
)
52 struct nlattr
*tb
[ARRAY_SIZE(ethnl_header_policy
)];
53 const struct nlattr
*devname_attr
;
54 struct net_device
*dev
= NULL
;
59 NL_SET_ERR_MSG(extack
, "request header missing");
62 /* No validation here, command policy should have a nested policy set
63 * for the header, therefore validation should have already been done.
65 ret
= nla_parse_nested(tb
, ARRAY_SIZE(ethnl_header_policy
) - 1, header
,
69 if (tb
[ETHTOOL_A_HEADER_FLAGS
])
70 flags
= nla_get_u32(tb
[ETHTOOL_A_HEADER_FLAGS
]);
72 devname_attr
= tb
[ETHTOOL_A_HEADER_DEV_NAME
];
73 if (tb
[ETHTOOL_A_HEADER_DEV_INDEX
]) {
74 u32 ifindex
= nla_get_u32(tb
[ETHTOOL_A_HEADER_DEV_INDEX
]);
76 dev
= dev_get_by_index(net
, ifindex
);
78 NL_SET_ERR_MSG_ATTR(extack
,
79 tb
[ETHTOOL_A_HEADER_DEV_INDEX
],
80 "no device matches ifindex");
83 /* if both ifindex and ifname are passed, they must match */
85 strncmp(dev
->name
, nla_data(devname_attr
), IFNAMSIZ
)) {
87 NL_SET_ERR_MSG_ATTR(extack
, header
,
88 "ifindex and name do not match");
91 } else if (devname_attr
) {
92 dev
= dev_get_by_name(net
, nla_data(devname_attr
));
94 NL_SET_ERR_MSG_ATTR(extack
, devname_attr
,
95 "no device matches name");
98 } else if (require_dev
) {
99 NL_SET_ERR_MSG_ATTR(extack
, header
,
100 "neither ifindex nor name specified");
104 if (dev
&& !netif_device_present(dev
)) {
106 NL_SET_ERR_MSG(extack
, "device not present");
111 req_info
->flags
= flags
;
116 * ethnl_fill_reply_header() - Put common header into a reply message
117 * @skb: skb with the message
118 * @dev: network device to describe in header
119 * @attrtype: attribute type to use for the nest
121 * Create a nested attribute with attributes describing given network device.
123 * Return: 0 on success, error value (-EMSGSIZE only) on error
125 int ethnl_fill_reply_header(struct sk_buff
*skb
, struct net_device
*dev
,
132 nest
= nla_nest_start(skb
, attrtype
);
136 if (nla_put_u32(skb
, ETHTOOL_A_HEADER_DEV_INDEX
, (u32
)dev
->ifindex
) ||
137 nla_put_string(skb
, ETHTOOL_A_HEADER_DEV_NAME
, dev
->name
))
138 goto nla_put_failure
;
139 /* If more attributes are put into reply header, ethnl_header_size()
140 * must be updated to account for them.
143 nla_nest_end(skb
, nest
);
147 nla_nest_cancel(skb
, nest
);
152 * ethnl_reply_init() - Create skb for a reply and fill device identification
153 * @payload: payload length (without netlink and genetlink header)
154 * @dev: device the reply is about (may be null)
155 * @cmd: ETHTOOL_MSG_* message type for reply
156 * @hdr_attrtype: attribute type for common header
157 * @info: genetlink info of the received packet we respond to
158 * @ehdrp: place to store payload pointer returned by genlmsg_new()
160 * Return: pointer to allocated skb on success, NULL on error
162 struct sk_buff
*ethnl_reply_init(size_t payload
, struct net_device
*dev
, u8 cmd
,
163 u16 hdr_attrtype
, struct genl_info
*info
,
168 skb
= genlmsg_new(payload
, GFP_KERNEL
);
171 *ehdrp
= genlmsg_put_reply(skb
, info
, ðtool_genl_family
, 0, cmd
);
178 ret
= ethnl_fill_reply_header(skb
, dev
, hdr_attrtype
);
188 GENL_SET_ERR_MSG(info
, "failed to setup reply message");
192 void *ethnl_dump_put(struct sk_buff
*skb
, struct netlink_callback
*cb
, u8 cmd
)
194 return genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
, cb
->nlh
->nlmsg_seq
,
195 ðtool_genl_family
, 0, cmd
);
198 void *ethnl_bcastmsg_put(struct sk_buff
*skb
, u8 cmd
)
200 return genlmsg_put(skb
, 0, ++ethnl_bcast_seq
, ðtool_genl_family
, 0,
204 int ethnl_multicast(struct sk_buff
*skb
, struct net_device
*dev
)
206 return genlmsg_multicast_netns(ðtool_genl_family
, dev_net(dev
), skb
,
207 0, ETHNL_MCGRP_MONITOR
, GFP_KERNEL
);
210 /* GET request helpers */
213 * struct ethnl_dump_ctx - context structure for generic dumpit() callback
214 * @ops: request ops of currently processed message type
215 * @req_info: parsed request header of processed request
216 * @reply_data: data needed to compose the reply
217 * @pos_hash: saved iteration position - hashbucket
218 * @pos_idx: saved iteration position - index
220 * These parameters are kept in struct netlink_callback as context preserved
221 * between iterations. They are initialized by ethnl_default_start() and used
222 * in ethnl_default_dumpit() and ethnl_default_done().
224 struct ethnl_dump_ctx
{
225 const struct ethnl_request_ops
*ops
;
226 struct ethnl_req_info
*req_info
;
227 struct ethnl_reply_data
*reply_data
;
232 static const struct ethnl_request_ops
*
233 ethnl_default_requests
[__ETHTOOL_MSG_USER_CNT
] = {
234 [ETHTOOL_MSG_STRSET_GET
] = ðnl_strset_request_ops
,
235 [ETHTOOL_MSG_LINKINFO_GET
] = ðnl_linkinfo_request_ops
,
236 [ETHTOOL_MSG_LINKMODES_GET
] = ðnl_linkmodes_request_ops
,
237 [ETHTOOL_MSG_LINKSTATE_GET
] = ðnl_linkstate_request_ops
,
238 [ETHTOOL_MSG_DEBUG_GET
] = ðnl_debug_request_ops
,
239 [ETHTOOL_MSG_WOL_GET
] = ðnl_wol_request_ops
,
240 [ETHTOOL_MSG_FEATURES_GET
] = ðnl_features_request_ops
,
241 [ETHTOOL_MSG_PRIVFLAGS_GET
] = ðnl_privflags_request_ops
,
242 [ETHTOOL_MSG_RINGS_GET
] = ðnl_rings_request_ops
,
243 [ETHTOOL_MSG_CHANNELS_GET
] = ðnl_channels_request_ops
,
244 [ETHTOOL_MSG_COALESCE_GET
] = ðnl_coalesce_request_ops
,
245 [ETHTOOL_MSG_PAUSE_GET
] = ðnl_pause_request_ops
,
246 [ETHTOOL_MSG_EEE_GET
] = ðnl_eee_request_ops
,
247 [ETHTOOL_MSG_TSINFO_GET
] = ðnl_tsinfo_request_ops
,
250 static struct ethnl_dump_ctx
*ethnl_dump_context(struct netlink_callback
*cb
)
252 return (struct ethnl_dump_ctx
*)cb
->ctx
;
256 * ethnl_default_parse() - Parse request message
257 * @req_info: pointer to structure to put data into
258 * @tb: parsed attributes
259 * @net: request netns
260 * @request_ops: struct request_ops for request type
261 * @extack: netlink extack for error reporting
262 * @require_dev: fail if no device identified in header
264 * Parse universal request header and call request specific ->parse_request()
265 * callback (if defined) to parse the rest of the message.
267 * Return: 0 on success or negative error code
269 static int ethnl_default_parse(struct ethnl_req_info
*req_info
,
270 struct nlattr
**tb
, struct net
*net
,
271 const struct ethnl_request_ops
*request_ops
,
272 struct netlink_ext_ack
*extack
, bool require_dev
)
276 ret
= ethnl_parse_header_dev_get(req_info
, tb
[request_ops
->hdr_attr
],
277 net
, extack
, require_dev
);
281 if (request_ops
->parse_request
) {
282 ret
= request_ops
->parse_request(req_info
, tb
, extack
);
291 * ethnl_init_reply_data() - Initialize reply data for GET request
292 * @reply_data: pointer to embedded struct ethnl_reply_data
293 * @ops: instance of struct ethnl_request_ops describing the layout
294 * @dev: network device to initialize the reply for
296 * Fills the reply data part with zeros and sets the dev member. Must be called
297 * before calling the ->fill_reply() callback (for each iteration when handling
300 static void ethnl_init_reply_data(struct ethnl_reply_data
*reply_data
,
301 const struct ethnl_request_ops
*ops
,
302 struct net_device
*dev
)
304 memset(reply_data
, 0, ops
->reply_data_size
);
305 reply_data
->dev
= dev
;
308 /* default ->doit() handler for GET type requests */
309 static int ethnl_default_doit(struct sk_buff
*skb
, struct genl_info
*info
)
311 struct ethnl_reply_data
*reply_data
= NULL
;
312 struct ethnl_req_info
*req_info
= NULL
;
313 const u8 cmd
= info
->genlhdr
->cmd
;
314 const struct ethnl_request_ops
*ops
;
315 struct sk_buff
*rskb
;
320 ops
= ethnl_default_requests
[cmd
];
321 if (WARN_ONCE(!ops
, "cmd %u has no ethnl_request_ops\n", cmd
))
323 req_info
= kzalloc(ops
->req_info_size
, GFP_KERNEL
);
326 reply_data
= kmalloc(ops
->reply_data_size
, GFP_KERNEL
);
332 ret
= ethnl_default_parse(req_info
, info
->attrs
, genl_info_net(info
),
333 ops
, info
->extack
, !ops
->allow_nodev_do
);
336 ethnl_init_reply_data(reply_data
, ops
, req_info
->dev
);
339 ret
= ops
->prepare_data(req_info
, reply_data
, info
);
343 ret
= ops
->reply_size(req_info
, reply_data
);
346 reply_len
= ret
+ ethnl_reply_header_size();
348 rskb
= ethnl_reply_init(reply_len
, req_info
->dev
, ops
->reply_cmd
,
349 ops
->hdr_attr
, info
, &reply_payload
);
352 ret
= ops
->fill_reply(rskb
, req_info
, reply_data
);
355 if (ops
->cleanup_data
)
356 ops
->cleanup_data(reply_data
);
358 genlmsg_end(rskb
, reply_payload
);
360 dev_put(req_info
->dev
);
363 return genlmsg_reply(rskb
, info
);
366 WARN_ONCE(ret
== -EMSGSIZE
, "calculated message payload length (%d) not sufficient\n", reply_len
);
369 if (ops
->cleanup_data
)
370 ops
->cleanup_data(reply_data
);
373 dev_put(req_info
->dev
);
379 static int ethnl_default_dump_one(struct sk_buff
*skb
, struct net_device
*dev
,
380 const struct ethnl_dump_ctx
*ctx
,
381 struct netlink_callback
*cb
)
386 ehdr
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
, cb
->nlh
->nlmsg_seq
,
387 ðtool_genl_family
, 0, ctx
->ops
->reply_cmd
);
391 ethnl_init_reply_data(ctx
->reply_data
, ctx
->ops
, dev
);
393 ret
= ctx
->ops
->prepare_data(ctx
->req_info
, ctx
->reply_data
, NULL
);
397 ret
= ethnl_fill_reply_header(skb
, dev
, ctx
->ops
->hdr_attr
);
400 ret
= ctx
->ops
->fill_reply(skb
, ctx
->req_info
, ctx
->reply_data
);
403 if (ctx
->ops
->cleanup_data
)
404 ctx
->ops
->cleanup_data(ctx
->reply_data
);
405 ctx
->reply_data
->dev
= NULL
;
407 genlmsg_cancel(skb
, ehdr
);
409 genlmsg_end(skb
, ehdr
);
413 /* Default ->dumpit() handler for GET requests. Device iteration copied from
414 * rtnl_dump_ifinfo(); we have to be more careful about device hashtable
415 * persistence as we cannot guarantee to hold RTNL lock through the whole
416 * function as rtnetnlink does.
418 static int ethnl_default_dumpit(struct sk_buff
*skb
,
419 struct netlink_callback
*cb
)
421 struct ethnl_dump_ctx
*ctx
= ethnl_dump_context(cb
);
422 struct net
*net
= sock_net(skb
->sk
);
423 int s_idx
= ctx
->pos_idx
;
428 for (h
= ctx
->pos_hash
; h
< NETDEV_HASHENTRIES
; h
++, s_idx
= 0) {
429 struct hlist_head
*head
;
430 struct net_device
*dev
;
433 head
= &net
->dev_index_head
[h
];
436 seq
= net
->dev_base_seq
;
439 hlist_for_each_entry(dev
, head
, index_hlist
) {
445 ret
= ethnl_default_dump_one(skb
, dev
, ctx
, cb
);
448 if (ret
== -EOPNOTSUPP
)
450 if (likely(skb
->len
))
456 if (net
->dev_base_seq
!= seq
) {
470 nl_dump_check_consistent(cb
, nlmsg_hdr(skb
));
475 /* generic ->start() handler for GET requests */
476 static int ethnl_default_start(struct netlink_callback
*cb
)
478 const struct genl_dumpit_info
*info
= genl_dumpit_info(cb
);
479 struct ethnl_dump_ctx
*ctx
= ethnl_dump_context(cb
);
480 struct ethnl_reply_data
*reply_data
;
481 const struct ethnl_request_ops
*ops
;
482 struct ethnl_req_info
*req_info
;
483 struct genlmsghdr
*ghdr
;
486 BUILD_BUG_ON(sizeof(*ctx
) > sizeof(cb
->ctx
));
488 ghdr
= nlmsg_data(cb
->nlh
);
489 ops
= ethnl_default_requests
[ghdr
->cmd
];
490 if (WARN_ONCE(!ops
, "cmd %u has no ethnl_request_ops\n", ghdr
->cmd
))
492 req_info
= kzalloc(ops
->req_info_size
, GFP_KERNEL
);
495 reply_data
= kmalloc(ops
->reply_data_size
, GFP_KERNEL
);
501 ret
= ethnl_default_parse(req_info
, info
->attrs
, sock_net(cb
->skb
->sk
),
502 ops
, cb
->extack
, false);
504 /* We ignore device specification in dump requests but as the
505 * same parser as for non-dump (doit) requests is used, it
506 * would take reference to the device if it finds one
508 dev_put(req_info
->dev
);
509 req_info
->dev
= NULL
;
512 goto free_reply_data
;
515 ctx
->req_info
= req_info
;
516 ctx
->reply_data
= reply_data
;
530 /* default ->done() handler for GET requests */
531 static int ethnl_default_done(struct netlink_callback
*cb
)
533 struct ethnl_dump_ctx
*ctx
= ethnl_dump_context(cb
);
535 kfree(ctx
->reply_data
);
536 kfree(ctx
->req_info
);
541 static const struct ethnl_request_ops
*
542 ethnl_default_notify_ops
[ETHTOOL_MSG_KERNEL_MAX
+ 1] = {
543 [ETHTOOL_MSG_LINKINFO_NTF
] = ðnl_linkinfo_request_ops
,
544 [ETHTOOL_MSG_LINKMODES_NTF
] = ðnl_linkmodes_request_ops
,
545 [ETHTOOL_MSG_DEBUG_NTF
] = ðnl_debug_request_ops
,
546 [ETHTOOL_MSG_WOL_NTF
] = ðnl_wol_request_ops
,
547 [ETHTOOL_MSG_FEATURES_NTF
] = ðnl_features_request_ops
,
548 [ETHTOOL_MSG_PRIVFLAGS_NTF
] = ðnl_privflags_request_ops
,
549 [ETHTOOL_MSG_RINGS_NTF
] = ðnl_rings_request_ops
,
550 [ETHTOOL_MSG_CHANNELS_NTF
] = ðnl_channels_request_ops
,
551 [ETHTOOL_MSG_COALESCE_NTF
] = ðnl_coalesce_request_ops
,
552 [ETHTOOL_MSG_PAUSE_NTF
] = ðnl_pause_request_ops
,
553 [ETHTOOL_MSG_EEE_NTF
] = ðnl_eee_request_ops
,
556 /* default notification handler */
557 static void ethnl_default_notify(struct net_device
*dev
, unsigned int cmd
,
560 struct ethnl_reply_data
*reply_data
;
561 const struct ethnl_request_ops
*ops
;
562 struct ethnl_req_info
*req_info
;
568 if (WARN_ONCE(cmd
> ETHTOOL_MSG_KERNEL_MAX
||
569 !ethnl_default_notify_ops
[cmd
],
570 "unexpected notification type %u\n", cmd
))
572 ops
= ethnl_default_notify_ops
[cmd
];
573 req_info
= kzalloc(ops
->req_info_size
, GFP_KERNEL
);
576 reply_data
= kmalloc(ops
->reply_data_size
, GFP_KERNEL
);
583 req_info
->flags
|= ETHTOOL_FLAG_COMPACT_BITSETS
;
585 ethnl_init_reply_data(reply_data
, ops
, dev
);
586 ret
= ops
->prepare_data(req_info
, reply_data
, NULL
);
589 ret
= ops
->reply_size(req_info
, reply_data
);
592 reply_len
= ret
+ ethnl_reply_header_size();
594 skb
= genlmsg_new(reply_len
, GFP_KERNEL
);
597 reply_payload
= ethnl_bcastmsg_put(skb
, cmd
);
600 ret
= ethnl_fill_reply_header(skb
, dev
, ops
->hdr_attr
);
603 ret
= ops
->fill_reply(skb
, req_info
, reply_data
);
606 if (ops
->cleanup_data
)
607 ops
->cleanup_data(reply_data
);
609 genlmsg_end(skb
, reply_payload
);
612 ethnl_multicast(skb
, dev
);
616 WARN_ONCE(ret
== -EMSGSIZE
,
617 "calculated message payload length (%d) not sufficient\n",
622 if (ops
->cleanup_data
)
623 ops
->cleanup_data(reply_data
);
631 typedef void (*ethnl_notify_handler_t
)(struct net_device
*dev
, unsigned int cmd
,
634 static const ethnl_notify_handler_t ethnl_notify_handlers
[] = {
635 [ETHTOOL_MSG_LINKINFO_NTF
] = ethnl_default_notify
,
636 [ETHTOOL_MSG_LINKMODES_NTF
] = ethnl_default_notify
,
637 [ETHTOOL_MSG_DEBUG_NTF
] = ethnl_default_notify
,
638 [ETHTOOL_MSG_WOL_NTF
] = ethnl_default_notify
,
639 [ETHTOOL_MSG_FEATURES_NTF
] = ethnl_default_notify
,
640 [ETHTOOL_MSG_PRIVFLAGS_NTF
] = ethnl_default_notify
,
641 [ETHTOOL_MSG_RINGS_NTF
] = ethnl_default_notify
,
642 [ETHTOOL_MSG_CHANNELS_NTF
] = ethnl_default_notify
,
643 [ETHTOOL_MSG_COALESCE_NTF
] = ethnl_default_notify
,
644 [ETHTOOL_MSG_PAUSE_NTF
] = ethnl_default_notify
,
645 [ETHTOOL_MSG_EEE_NTF
] = ethnl_default_notify
,
648 void ethtool_notify(struct net_device
*dev
, unsigned int cmd
, const void *data
)
650 if (unlikely(!ethnl_ok
))
654 if (likely(cmd
< ARRAY_SIZE(ethnl_notify_handlers
) &&
655 ethnl_notify_handlers
[cmd
]))
656 ethnl_notify_handlers
[cmd
](dev
, cmd
, data
);
658 WARN_ONCE(1, "notification %u not implemented (dev=%s)\n",
659 cmd
, netdev_name(dev
));
661 EXPORT_SYMBOL(ethtool_notify
);
663 static void ethnl_notify_features(struct netdev_notifier_info
*info
)
665 struct net_device
*dev
= netdev_notifier_info_to_dev(info
);
667 ethtool_notify(dev
, ETHTOOL_MSG_FEATURES_NTF
, NULL
);
670 static int ethnl_netdev_event(struct notifier_block
*this, unsigned long event
,
674 case NETDEV_FEAT_CHANGE
:
675 ethnl_notify_features(ptr
);
682 static struct notifier_block ethnl_netdev_notifier
= {
683 .notifier_call
= ethnl_netdev_event
,
686 /* genetlink setup */
688 static const struct genl_ops ethtool_genl_ops
[] = {
690 .cmd
= ETHTOOL_MSG_STRSET_GET
,
691 .doit
= ethnl_default_doit
,
692 .start
= ethnl_default_start
,
693 .dumpit
= ethnl_default_dumpit
,
694 .done
= ethnl_default_done
,
695 .policy
= ethnl_strset_get_policy
,
696 .maxattr
= ARRAY_SIZE(ethnl_strset_get_policy
) - 1,
699 .cmd
= ETHTOOL_MSG_LINKINFO_GET
,
700 .doit
= ethnl_default_doit
,
701 .start
= ethnl_default_start
,
702 .dumpit
= ethnl_default_dumpit
,
703 .done
= ethnl_default_done
,
704 .policy
= ethnl_linkinfo_get_policy
,
705 .maxattr
= ARRAY_SIZE(ethnl_linkinfo_get_policy
) - 1,
708 .cmd
= ETHTOOL_MSG_LINKINFO_SET
,
709 .flags
= GENL_UNS_ADMIN_PERM
,
710 .doit
= ethnl_set_linkinfo
,
711 .policy
= ethnl_linkinfo_set_policy
,
712 .maxattr
= ARRAY_SIZE(ethnl_linkinfo_set_policy
) - 1,
715 .cmd
= ETHTOOL_MSG_LINKMODES_GET
,
716 .doit
= ethnl_default_doit
,
717 .start
= ethnl_default_start
,
718 .dumpit
= ethnl_default_dumpit
,
719 .done
= ethnl_default_done
,
720 .policy
= ethnl_linkmodes_get_policy
,
721 .maxattr
= ARRAY_SIZE(ethnl_linkmodes_get_policy
) - 1,
724 .cmd
= ETHTOOL_MSG_LINKMODES_SET
,
725 .flags
= GENL_UNS_ADMIN_PERM
,
726 .doit
= ethnl_set_linkmodes
,
727 .policy
= ethnl_linkmodes_set_policy
,
728 .maxattr
= ARRAY_SIZE(ethnl_linkmodes_set_policy
) - 1,
731 .cmd
= ETHTOOL_MSG_LINKSTATE_GET
,
732 .doit
= ethnl_default_doit
,
733 .start
= ethnl_default_start
,
734 .dumpit
= ethnl_default_dumpit
,
735 .done
= ethnl_default_done
,
736 .policy
= ethnl_linkstate_get_policy
,
737 .maxattr
= ARRAY_SIZE(ethnl_linkstate_get_policy
) - 1,
740 .cmd
= ETHTOOL_MSG_DEBUG_GET
,
741 .doit
= ethnl_default_doit
,
742 .start
= ethnl_default_start
,
743 .dumpit
= ethnl_default_dumpit
,
744 .done
= ethnl_default_done
,
745 .policy
= ethnl_debug_get_policy
,
746 .maxattr
= ARRAY_SIZE(ethnl_debug_get_policy
) - 1,
749 .cmd
= ETHTOOL_MSG_DEBUG_SET
,
750 .flags
= GENL_UNS_ADMIN_PERM
,
751 .doit
= ethnl_set_debug
,
752 .policy
= ethnl_debug_set_policy
,
753 .maxattr
= ARRAY_SIZE(ethnl_debug_set_policy
) - 1,
756 .cmd
= ETHTOOL_MSG_WOL_GET
,
757 .flags
= GENL_UNS_ADMIN_PERM
,
758 .doit
= ethnl_default_doit
,
759 .start
= ethnl_default_start
,
760 .dumpit
= ethnl_default_dumpit
,
761 .done
= ethnl_default_done
,
762 .policy
= ethnl_wol_get_policy
,
763 .maxattr
= ARRAY_SIZE(ethnl_wol_get_policy
) - 1,
766 .cmd
= ETHTOOL_MSG_WOL_SET
,
767 .flags
= GENL_UNS_ADMIN_PERM
,
768 .doit
= ethnl_set_wol
,
769 .policy
= ethnl_wol_set_policy
,
770 .maxattr
= ARRAY_SIZE(ethnl_wol_set_policy
) - 1,
773 .cmd
= ETHTOOL_MSG_FEATURES_GET
,
774 .doit
= ethnl_default_doit
,
775 .start
= ethnl_default_start
,
776 .dumpit
= ethnl_default_dumpit
,
777 .done
= ethnl_default_done
,
778 .policy
= ethnl_features_get_policy
,
779 .maxattr
= ARRAY_SIZE(ethnl_features_get_policy
) - 1,
782 .cmd
= ETHTOOL_MSG_FEATURES_SET
,
783 .flags
= GENL_UNS_ADMIN_PERM
,
784 .doit
= ethnl_set_features
,
785 .policy
= ethnl_features_set_policy
,
786 .maxattr
= ARRAY_SIZE(ethnl_features_set_policy
) - 1,
789 .cmd
= ETHTOOL_MSG_PRIVFLAGS_GET
,
790 .doit
= ethnl_default_doit
,
791 .start
= ethnl_default_start
,
792 .dumpit
= ethnl_default_dumpit
,
793 .done
= ethnl_default_done
,
794 .policy
= ethnl_privflags_get_policy
,
795 .maxattr
= ARRAY_SIZE(ethnl_privflags_get_policy
) - 1,
798 .cmd
= ETHTOOL_MSG_PRIVFLAGS_SET
,
799 .flags
= GENL_UNS_ADMIN_PERM
,
800 .doit
= ethnl_set_privflags
,
801 .policy
= ethnl_privflags_set_policy
,
802 .maxattr
= ARRAY_SIZE(ethnl_privflags_set_policy
) - 1,
805 .cmd
= ETHTOOL_MSG_RINGS_GET
,
806 .doit
= ethnl_default_doit
,
807 .start
= ethnl_default_start
,
808 .dumpit
= ethnl_default_dumpit
,
809 .done
= ethnl_default_done
,
810 .policy
= ethnl_rings_get_policy
,
811 .maxattr
= ARRAY_SIZE(ethnl_rings_get_policy
) - 1,
814 .cmd
= ETHTOOL_MSG_RINGS_SET
,
815 .flags
= GENL_UNS_ADMIN_PERM
,
816 .doit
= ethnl_set_rings
,
817 .policy
= ethnl_rings_set_policy
,
818 .maxattr
= ARRAY_SIZE(ethnl_rings_set_policy
) - 1,
821 .cmd
= ETHTOOL_MSG_CHANNELS_GET
,
822 .doit
= ethnl_default_doit
,
823 .start
= ethnl_default_start
,
824 .dumpit
= ethnl_default_dumpit
,
825 .done
= ethnl_default_done
,
826 .policy
= ethnl_channels_get_policy
,
827 .maxattr
= ARRAY_SIZE(ethnl_channels_get_policy
) - 1,
830 .cmd
= ETHTOOL_MSG_CHANNELS_SET
,
831 .flags
= GENL_UNS_ADMIN_PERM
,
832 .doit
= ethnl_set_channels
,
833 .policy
= ethnl_channels_set_policy
,
834 .maxattr
= ARRAY_SIZE(ethnl_channels_set_policy
) - 1,
837 .cmd
= ETHTOOL_MSG_COALESCE_GET
,
838 .doit
= ethnl_default_doit
,
839 .start
= ethnl_default_start
,
840 .dumpit
= ethnl_default_dumpit
,
841 .done
= ethnl_default_done
,
842 .policy
= ethnl_coalesce_get_policy
,
843 .maxattr
= ARRAY_SIZE(ethnl_coalesce_get_policy
) - 1,
846 .cmd
= ETHTOOL_MSG_COALESCE_SET
,
847 .flags
= GENL_UNS_ADMIN_PERM
,
848 .doit
= ethnl_set_coalesce
,
849 .policy
= ethnl_coalesce_set_policy
,
850 .maxattr
= ARRAY_SIZE(ethnl_coalesce_set_policy
) - 1,
853 .cmd
= ETHTOOL_MSG_PAUSE_GET
,
854 .doit
= ethnl_default_doit
,
855 .start
= ethnl_default_start
,
856 .dumpit
= ethnl_default_dumpit
,
857 .done
= ethnl_default_done
,
858 .policy
= ethnl_pause_get_policy
,
859 .maxattr
= ARRAY_SIZE(ethnl_pause_get_policy
) - 1,
862 .cmd
= ETHTOOL_MSG_PAUSE_SET
,
863 .flags
= GENL_UNS_ADMIN_PERM
,
864 .doit
= ethnl_set_pause
,
865 .policy
= ethnl_pause_set_policy
,
866 .maxattr
= ARRAY_SIZE(ethnl_pause_set_policy
) - 1,
869 .cmd
= ETHTOOL_MSG_EEE_GET
,
870 .doit
= ethnl_default_doit
,
871 .start
= ethnl_default_start
,
872 .dumpit
= ethnl_default_dumpit
,
873 .done
= ethnl_default_done
,
874 .policy
= ethnl_eee_get_policy
,
875 .maxattr
= ARRAY_SIZE(ethnl_eee_get_policy
) - 1,
878 .cmd
= ETHTOOL_MSG_EEE_SET
,
879 .flags
= GENL_UNS_ADMIN_PERM
,
880 .doit
= ethnl_set_eee
,
881 .policy
= ethnl_eee_set_policy
,
882 .maxattr
= ARRAY_SIZE(ethnl_eee_set_policy
) - 1,
885 .cmd
= ETHTOOL_MSG_TSINFO_GET
,
886 .doit
= ethnl_default_doit
,
887 .start
= ethnl_default_start
,
888 .dumpit
= ethnl_default_dumpit
,
889 .done
= ethnl_default_done
,
890 .policy
= ethnl_tsinfo_get_policy
,
891 .maxattr
= ARRAY_SIZE(ethnl_tsinfo_get_policy
) - 1,
894 .cmd
= ETHTOOL_MSG_CABLE_TEST_ACT
,
895 .flags
= GENL_UNS_ADMIN_PERM
,
896 .doit
= ethnl_act_cable_test
,
897 .policy
= ethnl_cable_test_act_policy
,
898 .maxattr
= ARRAY_SIZE(ethnl_cable_test_act_policy
) - 1,
901 .cmd
= ETHTOOL_MSG_CABLE_TEST_TDR_ACT
,
902 .flags
= GENL_UNS_ADMIN_PERM
,
903 .doit
= ethnl_act_cable_test_tdr
,
904 .policy
= ethnl_cable_test_tdr_act_policy
,
905 .maxattr
= ARRAY_SIZE(ethnl_cable_test_tdr_act_policy
) - 1,
908 .cmd
= ETHTOOL_MSG_TUNNEL_INFO_GET
,
909 .doit
= ethnl_tunnel_info_doit
,
910 .start
= ethnl_tunnel_info_start
,
911 .dumpit
= ethnl_tunnel_info_dumpit
,
912 .policy
= ethnl_tunnel_info_get_policy
,
913 .maxattr
= ARRAY_SIZE(ethnl_tunnel_info_get_policy
) - 1,
917 static const struct genl_multicast_group ethtool_nl_mcgrps
[] = {
918 [ETHNL_MCGRP_MONITOR
] = { .name
= ETHTOOL_MCGRP_MONITOR_NAME
},
921 static struct genl_family ethtool_genl_family __ro_after_init
= {
922 .name
= ETHTOOL_GENL_NAME
,
923 .version
= ETHTOOL_GENL_VERSION
,
925 .parallel_ops
= true,
926 .ops
= ethtool_genl_ops
,
927 .n_ops
= ARRAY_SIZE(ethtool_genl_ops
),
928 .mcgrps
= ethtool_nl_mcgrps
,
929 .n_mcgrps
= ARRAY_SIZE(ethtool_nl_mcgrps
),
934 static int __init
ethnl_init(void)
938 ret
= genl_register_family(ðtool_genl_family
);
939 if (WARN(ret
< 0, "ethtool: genetlink family registration failed"))
943 ret
= register_netdevice_notifier(ðnl_netdev_notifier
);
944 WARN(ret
< 0, "ethtool: net device notifier registration failed");
948 subsys_initcall(ethnl_init
);