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 static const struct nla_policy ethnl_header_policy
[ETHTOOL_A_HEADER_MAX
+ 1] = {
13 [ETHTOOL_A_HEADER_UNSPEC
] = { .type
= NLA_REJECT
},
14 [ETHTOOL_A_HEADER_DEV_INDEX
] = { .type
= NLA_U32
},
15 [ETHTOOL_A_HEADER_DEV_NAME
] = { .type
= NLA_NUL_STRING
,
16 .len
= ALTIFNAMSIZ
- 1 },
17 [ETHTOOL_A_HEADER_FLAGS
] = { .type
= NLA_U32
},
21 * ethnl_parse_header_dev_get() - parse request header
22 * @req_info: structure to put results into
23 * @header: nest attribute with request header
25 * @extack: netlink extack for error reporting
26 * @require_dev: fail if no device identified in header
28 * Parse request header in nested attribute @nest and puts results into
29 * the structure pointed to by @req_info. Extack from @info is used for error
30 * reporting. If req_info->dev is not null on return, reference to it has
31 * been taken. If error is returned, *req_info is null initialized and no
34 * Return: 0 on success or negative error code
36 int ethnl_parse_header_dev_get(struct ethnl_req_info
*req_info
,
37 const struct nlattr
*header
, struct net
*net
,
38 struct netlink_ext_ack
*extack
, bool require_dev
)
40 struct nlattr
*tb
[ETHTOOL_A_HEADER_MAX
+ 1];
41 const struct nlattr
*devname_attr
;
42 struct net_device
*dev
= NULL
;
47 NL_SET_ERR_MSG(extack
, "request header missing");
50 ret
= nla_parse_nested(tb
, ETHTOOL_A_HEADER_MAX
, header
,
51 ethnl_header_policy
, extack
);
54 if (tb
[ETHTOOL_A_HEADER_FLAGS
]) {
55 flags
= nla_get_u32(tb
[ETHTOOL_A_HEADER_FLAGS
]);
56 if (flags
& ~ETHTOOL_FLAG_ALL
) {
57 NL_SET_ERR_MSG_ATTR(extack
, tb
[ETHTOOL_A_HEADER_FLAGS
],
58 "unrecognized request flags");
59 nl_set_extack_cookie_u32(extack
, ETHTOOL_FLAG_ALL
);
64 devname_attr
= tb
[ETHTOOL_A_HEADER_DEV_NAME
];
65 if (tb
[ETHTOOL_A_HEADER_DEV_INDEX
]) {
66 u32 ifindex
= nla_get_u32(tb
[ETHTOOL_A_HEADER_DEV_INDEX
]);
68 dev
= dev_get_by_index(net
, ifindex
);
70 NL_SET_ERR_MSG_ATTR(extack
,
71 tb
[ETHTOOL_A_HEADER_DEV_INDEX
],
72 "no device matches ifindex");
75 /* if both ifindex and ifname are passed, they must match */
77 strncmp(dev
->name
, nla_data(devname_attr
), IFNAMSIZ
)) {
79 NL_SET_ERR_MSG_ATTR(extack
, header
,
80 "ifindex and name do not match");
83 } else if (devname_attr
) {
84 dev
= dev_get_by_name(net
, nla_data(devname_attr
));
86 NL_SET_ERR_MSG_ATTR(extack
, devname_attr
,
87 "no device matches name");
90 } else if (require_dev
) {
91 NL_SET_ERR_MSG_ATTR(extack
, header
,
92 "neither ifindex nor name specified");
96 if (dev
&& !netif_device_present(dev
)) {
98 NL_SET_ERR_MSG(extack
, "device not present");
103 req_info
->flags
= flags
;
108 * ethnl_fill_reply_header() - Put common header into a reply message
109 * @skb: skb with the message
110 * @dev: network device to describe in header
111 * @attrtype: attribute type to use for the nest
113 * Create a nested attribute with attributes describing given network device.
115 * Return: 0 on success, error value (-EMSGSIZE only) on error
117 int ethnl_fill_reply_header(struct sk_buff
*skb
, struct net_device
*dev
,
124 nest
= nla_nest_start(skb
, attrtype
);
128 if (nla_put_u32(skb
, ETHTOOL_A_HEADER_DEV_INDEX
, (u32
)dev
->ifindex
) ||
129 nla_put_string(skb
, ETHTOOL_A_HEADER_DEV_NAME
, dev
->name
))
130 goto nla_put_failure
;
131 /* If more attributes are put into reply header, ethnl_header_size()
132 * must be updated to account for them.
135 nla_nest_end(skb
, nest
);
139 nla_nest_cancel(skb
, nest
);
144 * ethnl_reply_init() - Create skb for a reply and fill device identification
145 * @payload: payload length (without netlink and genetlink header)
146 * @dev: device the reply is about (may be null)
147 * @cmd: ETHTOOL_MSG_* message type for reply
148 * @hdr_attrtype: attribute type for common header
149 * @info: genetlink info of the received packet we respond to
150 * @ehdrp: place to store payload pointer returned by genlmsg_new()
152 * Return: pointer to allocated skb on success, NULL on error
154 struct sk_buff
*ethnl_reply_init(size_t payload
, struct net_device
*dev
, u8 cmd
,
155 u16 hdr_attrtype
, struct genl_info
*info
,
160 skb
= genlmsg_new(payload
, GFP_KERNEL
);
163 *ehdrp
= genlmsg_put_reply(skb
, info
, ðtool_genl_family
, 0, cmd
);
170 ret
= ethnl_fill_reply_header(skb
, dev
, hdr_attrtype
);
180 GENL_SET_ERR_MSG(info
, "failed to setup reply message");
184 static void *ethnl_bcastmsg_put(struct sk_buff
*skb
, u8 cmd
)
186 return genlmsg_put(skb
, 0, ++ethnl_bcast_seq
, ðtool_genl_family
, 0,
190 static int ethnl_multicast(struct sk_buff
*skb
, struct net_device
*dev
)
192 return genlmsg_multicast_netns(ðtool_genl_family
, dev_net(dev
), skb
,
193 0, ETHNL_MCGRP_MONITOR
, GFP_KERNEL
);
196 /* GET request helpers */
199 * struct ethnl_dump_ctx - context structure for generic dumpit() callback
200 * @ops: request ops of currently processed message type
201 * @req_info: parsed request header of processed request
202 * @reply_data: data needed to compose the reply
203 * @pos_hash: saved iteration position - hashbucket
204 * @pos_idx: saved iteration position - index
206 * These parameters are kept in struct netlink_callback as context preserved
207 * between iterations. They are initialized by ethnl_default_start() and used
208 * in ethnl_default_dumpit() and ethnl_default_done().
210 struct ethnl_dump_ctx
{
211 const struct ethnl_request_ops
*ops
;
212 struct ethnl_req_info
*req_info
;
213 struct ethnl_reply_data
*reply_data
;
218 static const struct ethnl_request_ops
*
219 ethnl_default_requests
[__ETHTOOL_MSG_USER_CNT
] = {
220 [ETHTOOL_MSG_STRSET_GET
] = ðnl_strset_request_ops
,
221 [ETHTOOL_MSG_LINKINFO_GET
] = ðnl_linkinfo_request_ops
,
222 [ETHTOOL_MSG_LINKMODES_GET
] = ðnl_linkmodes_request_ops
,
223 [ETHTOOL_MSG_LINKSTATE_GET
] = ðnl_linkstate_request_ops
,
224 [ETHTOOL_MSG_DEBUG_GET
] = ðnl_debug_request_ops
,
225 [ETHTOOL_MSG_WOL_GET
] = ðnl_wol_request_ops
,
226 [ETHTOOL_MSG_FEATURES_GET
] = ðnl_features_request_ops
,
227 [ETHTOOL_MSG_PRIVFLAGS_GET
] = ðnl_privflags_request_ops
,
228 [ETHTOOL_MSG_RINGS_GET
] = ðnl_rings_request_ops
,
229 [ETHTOOL_MSG_CHANNELS_GET
] = ðnl_channels_request_ops
,
230 [ETHTOOL_MSG_COALESCE_GET
] = ðnl_coalesce_request_ops
,
231 [ETHTOOL_MSG_PAUSE_GET
] = ðnl_pause_request_ops
,
232 [ETHTOOL_MSG_EEE_GET
] = ðnl_eee_request_ops
,
233 [ETHTOOL_MSG_TSINFO_GET
] = ðnl_tsinfo_request_ops
,
236 static struct ethnl_dump_ctx
*ethnl_dump_context(struct netlink_callback
*cb
)
238 return (struct ethnl_dump_ctx
*)cb
->ctx
;
242 * ethnl_default_parse() - Parse request message
243 * @req_info: pointer to structure to put data into
244 * @nlhdr: pointer to request message header
245 * @net: request netns
246 * @request_ops: struct request_ops for request type
247 * @extack: netlink extack for error reporting
248 * @require_dev: fail if no device identified in header
250 * Parse universal request header and call request specific ->parse_request()
251 * callback (if defined) to parse the rest of the message.
253 * Return: 0 on success or negative error code
255 static int ethnl_default_parse(struct ethnl_req_info
*req_info
,
256 const struct nlmsghdr
*nlhdr
, struct net
*net
,
257 const struct ethnl_request_ops
*request_ops
,
258 struct netlink_ext_ack
*extack
, bool require_dev
)
263 tb
= kmalloc_array(request_ops
->max_attr
+ 1, sizeof(tb
[0]),
268 ret
= nlmsg_parse(nlhdr
, GENL_HDRLEN
, tb
, request_ops
->max_attr
,
269 request_ops
->request_policy
, extack
);
272 ret
= ethnl_parse_header_dev_get(req_info
, tb
[request_ops
->hdr_attr
],
273 net
, extack
, require_dev
);
277 if (request_ops
->parse_request
) {
278 ret
= request_ops
->parse_request(req_info
, tb
, extack
);
290 * ethnl_init_reply_data() - Initialize reply data for GET request
291 * @reply_data: pointer to embedded struct ethnl_reply_data
292 * @ops: instance of struct ethnl_request_ops describing the layout
293 * @dev: network device to initialize the reply for
295 * Fills the reply data part with zeros and sets the dev member. Must be called
296 * before calling the ->fill_reply() callback (for each iteration when handling
299 static void ethnl_init_reply_data(struct ethnl_reply_data
*reply_data
,
300 const struct ethnl_request_ops
*ops
,
301 struct net_device
*dev
)
303 memset(reply_data
, 0, ops
->reply_data_size
);
304 reply_data
->dev
= dev
;
307 /* default ->doit() handler for GET type requests */
308 static int ethnl_default_doit(struct sk_buff
*skb
, struct genl_info
*info
)
310 struct ethnl_reply_data
*reply_data
= NULL
;
311 struct ethnl_req_info
*req_info
= NULL
;
312 const u8 cmd
= info
->genlhdr
->cmd
;
313 const struct ethnl_request_ops
*ops
;
314 struct sk_buff
*rskb
;
319 ops
= ethnl_default_requests
[cmd
];
320 if (WARN_ONCE(!ops
, "cmd %u has no ethnl_request_ops\n", cmd
))
322 req_info
= kzalloc(ops
->req_info_size
, GFP_KERNEL
);
325 reply_data
= kmalloc(ops
->reply_data_size
, GFP_KERNEL
);
331 ret
= ethnl_default_parse(req_info
, info
->nlhdr
, genl_info_net(info
), ops
,
332 info
->extack
, !ops
->allow_nodev_do
);
335 ethnl_init_reply_data(reply_data
, ops
, req_info
->dev
);
338 ret
= ops
->prepare_data(req_info
, reply_data
, info
);
342 ret
= ops
->reply_size(req_info
, reply_data
);
347 rskb
= ethnl_reply_init(reply_len
, req_info
->dev
, ops
->reply_cmd
,
348 ops
->hdr_attr
, info
, &reply_payload
);
351 ret
= ops
->fill_reply(rskb
, req_info
, reply_data
);
354 if (ops
->cleanup_data
)
355 ops
->cleanup_data(reply_data
);
357 genlmsg_end(rskb
, reply_payload
);
359 dev_put(req_info
->dev
);
362 return genlmsg_reply(rskb
, info
);
365 WARN_ONCE(ret
== -EMSGSIZE
, "calculated message payload length (%d) not sufficient\n", reply_len
);
368 if (ops
->cleanup_data
)
369 ops
->cleanup_data(reply_data
);
372 dev_put(req_info
->dev
);
378 static int ethnl_default_dump_one(struct sk_buff
*skb
, struct net_device
*dev
,
379 const struct ethnl_dump_ctx
*ctx
)
383 ethnl_init_reply_data(ctx
->reply_data
, ctx
->ops
, dev
);
385 ret
= ctx
->ops
->prepare_data(ctx
->req_info
, ctx
->reply_data
, NULL
);
389 ret
= ethnl_fill_reply_header(skb
, dev
, ctx
->ops
->hdr_attr
);
392 ret
= ctx
->ops
->fill_reply(skb
, ctx
->req_info
, ctx
->reply_data
);
395 if (ctx
->ops
->cleanup_data
)
396 ctx
->ops
->cleanup_data(ctx
->reply_data
);
397 ctx
->reply_data
->dev
= NULL
;
401 /* Default ->dumpit() handler for GET requests. Device iteration copied from
402 * rtnl_dump_ifinfo(); we have to be more careful about device hashtable
403 * persistence as we cannot guarantee to hold RTNL lock through the whole
404 * function as rtnetnlink does.
406 static int ethnl_default_dumpit(struct sk_buff
*skb
,
407 struct netlink_callback
*cb
)
409 struct ethnl_dump_ctx
*ctx
= ethnl_dump_context(cb
);
410 struct net
*net
= sock_net(skb
->sk
);
411 int s_idx
= ctx
->pos_idx
;
417 for (h
= ctx
->pos_hash
; h
< NETDEV_HASHENTRIES
; h
++, s_idx
= 0) {
418 struct hlist_head
*head
;
419 struct net_device
*dev
;
422 head
= &net
->dev_index_head
[h
];
425 seq
= net
->dev_base_seq
;
428 hlist_for_each_entry(dev
, head
, index_hlist
) {
434 ehdr
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
,
436 ðtool_genl_family
, 0,
437 ctx
->ops
->reply_cmd
);
443 ret
= ethnl_default_dump_one(skb
, dev
, ctx
);
446 genlmsg_cancel(skb
, ehdr
);
447 if (ret
== -EOPNOTSUPP
)
449 if (likely(skb
->len
))
453 genlmsg_end(skb
, ehdr
);
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 struct ethnl_dump_ctx
*ctx
= ethnl_dump_context(cb
);
479 struct ethnl_reply_data
*reply_data
;
480 const struct ethnl_request_ops
*ops
;
481 struct ethnl_req_info
*req_info
;
482 struct genlmsghdr
*ghdr
;
485 BUILD_BUG_ON(sizeof(*ctx
) > sizeof(cb
->ctx
));
487 ghdr
= nlmsg_data(cb
->nlh
);
488 ops
= ethnl_default_requests
[ghdr
->cmd
];
489 if (WARN_ONCE(!ops
, "cmd %u has no ethnl_request_ops\n", ghdr
->cmd
))
491 req_info
= kzalloc(ops
->req_info_size
, GFP_KERNEL
);
494 reply_data
= kmalloc(ops
->reply_data_size
, GFP_KERNEL
);
500 ret
= ethnl_default_parse(req_info
, cb
->nlh
, sock_net(cb
->skb
->sk
), ops
,
503 /* We ignore device specification in dump requests but as the
504 * same parser as for non-dump (doit) requests is used, it
505 * would take reference to the device if it finds one
507 dev_put(req_info
->dev
);
508 req_info
->dev
= NULL
;
511 goto free_reply_data
;
514 ctx
->req_info
= req_info
;
515 ctx
->reply_data
= reply_data
;
529 /* default ->done() handler for GET requests */
530 static int ethnl_default_done(struct netlink_callback
*cb
)
532 struct ethnl_dump_ctx
*ctx
= ethnl_dump_context(cb
);
534 kfree(ctx
->reply_data
);
535 kfree(ctx
->req_info
);
540 static const struct ethnl_request_ops
*
541 ethnl_default_notify_ops
[ETHTOOL_MSG_KERNEL_MAX
+ 1] = {
542 [ETHTOOL_MSG_LINKINFO_NTF
] = ðnl_linkinfo_request_ops
,
543 [ETHTOOL_MSG_LINKMODES_NTF
] = ðnl_linkmodes_request_ops
,
544 [ETHTOOL_MSG_DEBUG_NTF
] = ðnl_debug_request_ops
,
545 [ETHTOOL_MSG_WOL_NTF
] = ðnl_wol_request_ops
,
546 [ETHTOOL_MSG_FEATURES_NTF
] = ðnl_features_request_ops
,
547 [ETHTOOL_MSG_PRIVFLAGS_NTF
] = ðnl_privflags_request_ops
,
548 [ETHTOOL_MSG_RINGS_NTF
] = ðnl_rings_request_ops
,
549 [ETHTOOL_MSG_CHANNELS_NTF
] = ðnl_channels_request_ops
,
550 [ETHTOOL_MSG_COALESCE_NTF
] = ðnl_coalesce_request_ops
,
551 [ETHTOOL_MSG_PAUSE_NTF
] = ðnl_pause_request_ops
,
552 [ETHTOOL_MSG_EEE_NTF
] = ðnl_eee_request_ops
,
555 /* default notification handler */
556 static void ethnl_default_notify(struct net_device
*dev
, unsigned int cmd
,
559 struct ethnl_reply_data
*reply_data
;
560 const struct ethnl_request_ops
*ops
;
561 struct ethnl_req_info
*req_info
;
567 if (WARN_ONCE(cmd
> ETHTOOL_MSG_KERNEL_MAX
||
568 !ethnl_default_notify_ops
[cmd
],
569 "unexpected notification type %u\n", cmd
))
571 ops
= ethnl_default_notify_ops
[cmd
];
572 req_info
= kzalloc(ops
->req_info_size
, GFP_KERNEL
);
575 reply_data
= kmalloc(ops
->reply_data_size
, GFP_KERNEL
);
582 req_info
->flags
|= ETHTOOL_FLAG_COMPACT_BITSETS
;
584 ethnl_init_reply_data(reply_data
, ops
, dev
);
585 ret
= ops
->prepare_data(req_info
, reply_data
, NULL
);
588 ret
= ops
->reply_size(req_info
, reply_data
);
593 skb
= genlmsg_new(reply_len
, GFP_KERNEL
);
596 reply_payload
= ethnl_bcastmsg_put(skb
, cmd
);
599 ret
= ethnl_fill_reply_header(skb
, dev
, ops
->hdr_attr
);
602 ret
= ops
->fill_reply(skb
, req_info
, reply_data
);
605 if (ops
->cleanup_data
)
606 ops
->cleanup_data(reply_data
);
608 genlmsg_end(skb
, reply_payload
);
611 ethnl_multicast(skb
, dev
);
615 WARN_ONCE(ret
== -EMSGSIZE
,
616 "calculated message payload length (%d) not sufficient\n",
621 if (ops
->cleanup_data
)
622 ops
->cleanup_data(reply_data
);
630 typedef void (*ethnl_notify_handler_t
)(struct net_device
*dev
, unsigned int cmd
,
633 static const ethnl_notify_handler_t ethnl_notify_handlers
[] = {
634 [ETHTOOL_MSG_LINKINFO_NTF
] = ethnl_default_notify
,
635 [ETHTOOL_MSG_LINKMODES_NTF
] = ethnl_default_notify
,
636 [ETHTOOL_MSG_DEBUG_NTF
] = ethnl_default_notify
,
637 [ETHTOOL_MSG_WOL_NTF
] = ethnl_default_notify
,
638 [ETHTOOL_MSG_FEATURES_NTF
] = ethnl_default_notify
,
639 [ETHTOOL_MSG_PRIVFLAGS_NTF
] = ethnl_default_notify
,
640 [ETHTOOL_MSG_RINGS_NTF
] = ethnl_default_notify
,
641 [ETHTOOL_MSG_CHANNELS_NTF
] = ethnl_default_notify
,
642 [ETHTOOL_MSG_COALESCE_NTF
] = ethnl_default_notify
,
643 [ETHTOOL_MSG_PAUSE_NTF
] = ethnl_default_notify
,
644 [ETHTOOL_MSG_EEE_NTF
] = ethnl_default_notify
,
647 void ethtool_notify(struct net_device
*dev
, unsigned int cmd
, const void *data
)
649 if (unlikely(!ethnl_ok
))
653 if (likely(cmd
< ARRAY_SIZE(ethnl_notify_handlers
) &&
654 ethnl_notify_handlers
[cmd
]))
655 ethnl_notify_handlers
[cmd
](dev
, cmd
, data
);
657 WARN_ONCE(1, "notification %u not implemented (dev=%s)\n",
658 cmd
, netdev_name(dev
));
660 EXPORT_SYMBOL(ethtool_notify
);
662 static void ethnl_notify_features(struct netdev_notifier_info
*info
)
664 struct net_device
*dev
= netdev_notifier_info_to_dev(info
);
666 ethtool_notify(dev
, ETHTOOL_MSG_FEATURES_NTF
, NULL
);
669 static int ethnl_netdev_event(struct notifier_block
*this, unsigned long event
,
673 case NETDEV_FEAT_CHANGE
:
674 ethnl_notify_features(ptr
);
681 static struct notifier_block ethnl_netdev_notifier
= {
682 .notifier_call
= ethnl_netdev_event
,
685 /* genetlink setup */
687 static const struct genl_ops ethtool_genl_ops
[] = {
689 .cmd
= ETHTOOL_MSG_STRSET_GET
,
690 .doit
= ethnl_default_doit
,
691 .start
= ethnl_default_start
,
692 .dumpit
= ethnl_default_dumpit
,
693 .done
= ethnl_default_done
,
696 .cmd
= ETHTOOL_MSG_LINKINFO_GET
,
697 .doit
= ethnl_default_doit
,
698 .start
= ethnl_default_start
,
699 .dumpit
= ethnl_default_dumpit
,
700 .done
= ethnl_default_done
,
703 .cmd
= ETHTOOL_MSG_LINKINFO_SET
,
704 .flags
= GENL_UNS_ADMIN_PERM
,
705 .doit
= ethnl_set_linkinfo
,
708 .cmd
= ETHTOOL_MSG_LINKMODES_GET
,
709 .doit
= ethnl_default_doit
,
710 .start
= ethnl_default_start
,
711 .dumpit
= ethnl_default_dumpit
,
712 .done
= ethnl_default_done
,
715 .cmd
= ETHTOOL_MSG_LINKMODES_SET
,
716 .flags
= GENL_UNS_ADMIN_PERM
,
717 .doit
= ethnl_set_linkmodes
,
720 .cmd
= ETHTOOL_MSG_LINKSTATE_GET
,
721 .doit
= ethnl_default_doit
,
722 .start
= ethnl_default_start
,
723 .dumpit
= ethnl_default_dumpit
,
724 .done
= ethnl_default_done
,
727 .cmd
= ETHTOOL_MSG_DEBUG_GET
,
728 .doit
= ethnl_default_doit
,
729 .start
= ethnl_default_start
,
730 .dumpit
= ethnl_default_dumpit
,
731 .done
= ethnl_default_done
,
734 .cmd
= ETHTOOL_MSG_DEBUG_SET
,
735 .flags
= GENL_UNS_ADMIN_PERM
,
736 .doit
= ethnl_set_debug
,
739 .cmd
= ETHTOOL_MSG_WOL_GET
,
740 .flags
= GENL_UNS_ADMIN_PERM
,
741 .doit
= ethnl_default_doit
,
742 .start
= ethnl_default_start
,
743 .dumpit
= ethnl_default_dumpit
,
744 .done
= ethnl_default_done
,
747 .cmd
= ETHTOOL_MSG_WOL_SET
,
748 .flags
= GENL_UNS_ADMIN_PERM
,
749 .doit
= ethnl_set_wol
,
752 .cmd
= ETHTOOL_MSG_FEATURES_GET
,
753 .doit
= ethnl_default_doit
,
754 .start
= ethnl_default_start
,
755 .dumpit
= ethnl_default_dumpit
,
756 .done
= ethnl_default_done
,
759 .cmd
= ETHTOOL_MSG_FEATURES_SET
,
760 .flags
= GENL_UNS_ADMIN_PERM
,
761 .doit
= ethnl_set_features
,
764 .cmd
= ETHTOOL_MSG_PRIVFLAGS_GET
,
765 .doit
= ethnl_default_doit
,
766 .start
= ethnl_default_start
,
767 .dumpit
= ethnl_default_dumpit
,
768 .done
= ethnl_default_done
,
771 .cmd
= ETHTOOL_MSG_PRIVFLAGS_SET
,
772 .flags
= GENL_UNS_ADMIN_PERM
,
773 .doit
= ethnl_set_privflags
,
776 .cmd
= ETHTOOL_MSG_RINGS_GET
,
777 .doit
= ethnl_default_doit
,
778 .start
= ethnl_default_start
,
779 .dumpit
= ethnl_default_dumpit
,
780 .done
= ethnl_default_done
,
783 .cmd
= ETHTOOL_MSG_RINGS_SET
,
784 .flags
= GENL_UNS_ADMIN_PERM
,
785 .doit
= ethnl_set_rings
,
788 .cmd
= ETHTOOL_MSG_CHANNELS_GET
,
789 .doit
= ethnl_default_doit
,
790 .start
= ethnl_default_start
,
791 .dumpit
= ethnl_default_dumpit
,
792 .done
= ethnl_default_done
,
795 .cmd
= ETHTOOL_MSG_CHANNELS_SET
,
796 .flags
= GENL_UNS_ADMIN_PERM
,
797 .doit
= ethnl_set_channels
,
800 .cmd
= ETHTOOL_MSG_COALESCE_GET
,
801 .doit
= ethnl_default_doit
,
802 .start
= ethnl_default_start
,
803 .dumpit
= ethnl_default_dumpit
,
804 .done
= ethnl_default_done
,
807 .cmd
= ETHTOOL_MSG_COALESCE_SET
,
808 .flags
= GENL_UNS_ADMIN_PERM
,
809 .doit
= ethnl_set_coalesce
,
812 .cmd
= ETHTOOL_MSG_PAUSE_GET
,
813 .doit
= ethnl_default_doit
,
814 .start
= ethnl_default_start
,
815 .dumpit
= ethnl_default_dumpit
,
816 .done
= ethnl_default_done
,
819 .cmd
= ETHTOOL_MSG_PAUSE_SET
,
820 .flags
= GENL_UNS_ADMIN_PERM
,
821 .doit
= ethnl_set_pause
,
824 .cmd
= ETHTOOL_MSG_EEE_GET
,
825 .doit
= ethnl_default_doit
,
826 .start
= ethnl_default_start
,
827 .dumpit
= ethnl_default_dumpit
,
828 .done
= ethnl_default_done
,
831 .cmd
= ETHTOOL_MSG_EEE_SET
,
832 .flags
= GENL_UNS_ADMIN_PERM
,
833 .doit
= ethnl_set_eee
,
836 .cmd
= ETHTOOL_MSG_TSINFO_GET
,
837 .doit
= ethnl_default_doit
,
838 .start
= ethnl_default_start
,
839 .dumpit
= ethnl_default_dumpit
,
840 .done
= ethnl_default_done
,
844 static const struct genl_multicast_group ethtool_nl_mcgrps
[] = {
845 [ETHNL_MCGRP_MONITOR
] = { .name
= ETHTOOL_MCGRP_MONITOR_NAME
},
848 static struct genl_family ethtool_genl_family
= {
849 .name
= ETHTOOL_GENL_NAME
,
850 .version
= ETHTOOL_GENL_VERSION
,
852 .parallel_ops
= true,
853 .ops
= ethtool_genl_ops
,
854 .n_ops
= ARRAY_SIZE(ethtool_genl_ops
),
855 .mcgrps
= ethtool_nl_mcgrps
,
856 .n_mcgrps
= ARRAY_SIZE(ethtool_nl_mcgrps
),
861 static int __init
ethnl_init(void)
865 ret
= genl_register_family(ðtool_genl_family
);
866 if (WARN(ret
< 0, "ethtool: genetlink family registration failed"))
870 ret
= register_netdevice_notifier(ðnl_netdev_notifier
);
871 WARN(ret
< 0, "ethtool: net device notifier registration failed");
875 subsys_initcall(ethnl_init
);