1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <net/netdev_lock.h> 4 #include <net/netdev_queues.h> 5 #include <net/sock.h> 6 #include <linux/ethtool_netlink.h> 7 #include <linux/phy_link_topology.h> 8 #include <linux/pm_runtime.h> 9 10 #include "module_fw.h" 11 #include "netlink.h" 12 13 static struct genl_family ethtool_genl_family; 14 15 static bool ethnl_ok __read_mostly; 16 static u32 ethnl_bcast_seq; 17 18 #define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \ 19 ETHTOOL_FLAG_OMIT_REPLY) 20 #define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS) 21 22 const struct nla_policy ethnl_header_policy[] = { 23 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, 24 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, 25 .len = ALTIFNAMSIZ - 1 }, 26 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, 27 ETHTOOL_FLAGS_BASIC), 28 }; 29 30 const struct nla_policy ethnl_header_policy_stats[] = { 31 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, 32 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, 33 .len = ALTIFNAMSIZ - 1 }, 34 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, 35 ETHTOOL_FLAGS_STATS), 36 }; 37 38 const struct nla_policy ethnl_header_policy_phy[] = { 39 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, 40 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, 41 .len = ALTIFNAMSIZ - 1 }, 42 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, 43 ETHTOOL_FLAGS_BASIC), 44 [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1), 45 }; 46 47 const struct nla_policy ethnl_header_policy_phy_stats[] = { 48 [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 }, 49 [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING, 50 .len = ALTIFNAMSIZ - 1 }, 51 [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32, 52 ETHTOOL_FLAGS_STATS), 53 [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1), 54 }; 55 56 int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid, 57 enum ethnl_sock_type type) 58 { 59 struct ethnl_sock_priv *sk_priv; 60 61 sk_priv = genl_sk_priv_get(ðtool_genl_family, NETLINK_CB(skb).sk); 62 if (IS_ERR(sk_priv)) 63 return PTR_ERR(sk_priv); 64 65 sk_priv->dev = dev; 66 sk_priv->portid = portid; 67 sk_priv->type = type; 68 69 return 0; 70 } 71 72 static void ethnl_sock_priv_destroy(void *priv) 73 { 74 struct ethnl_sock_priv *sk_priv = priv; 75 76 switch (sk_priv->type) { 77 case ETHTOOL_SOCK_TYPE_MODULE_FW_FLASH: 78 ethnl_module_fw_flash_sock_destroy(sk_priv); 79 break; 80 default: 81 break; 82 } 83 } 84 85 u32 ethnl_bcast_seq_next(void) 86 { 87 ASSERT_RTNL(); 88 return ++ethnl_bcast_seq; 89 } 90 91 int ethnl_ops_begin(struct net_device *dev) 92 { 93 int ret; 94 95 if (!dev) 96 return -ENODEV; 97 98 if (dev->dev.parent) 99 pm_runtime_get_sync(dev->dev.parent); 100 101 netdev_ops_assert_locked(dev); 102 103 if (!netif_device_present(dev) || 104 dev->reg_state >= NETREG_UNREGISTERING) { 105 ret = -ENODEV; 106 goto err; 107 } 108 109 if (dev->ethtool_ops->begin) { 110 ret = dev->ethtool_ops->begin(dev); 111 if (ret) 112 goto err; 113 } 114 115 return 0; 116 err: 117 if (dev->dev.parent) 118 pm_runtime_put(dev->dev.parent); 119 120 return ret; 121 } 122 123 void ethnl_ops_complete(struct net_device *dev) 124 { 125 if (dev->ethtool_ops->complete) 126 dev->ethtool_ops->complete(dev); 127 128 if (dev->dev.parent) 129 pm_runtime_put(dev->dev.parent); 130 } 131 132 /** 133 * ethnl_parse_header_dev_get() - parse request header 134 * @req_info: structure to put results into 135 * @header: nest attribute with request header 136 * @net: request netns 137 * @extack: netlink extack for error reporting 138 * @require_dev: fail if no device identified in header 139 * 140 * Parse request header in nested attribute @nest and puts results into 141 * the structure pointed to by @req_info. Extack from @info is used for error 142 * reporting. If req_info->dev is not null on return, reference to it has 143 * been taken. If error is returned, *req_info is null initialized and no 144 * reference is held. 145 * 146 * Return: 0 on success or negative error code 147 */ 148 int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info, 149 const struct nlattr *header, struct net *net, 150 struct netlink_ext_ack *extack, bool require_dev) 151 { 152 struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy_phy)]; 153 const struct nlattr *devname_attr; 154 struct net_device *dev = NULL; 155 u32 flags = 0; 156 int ret; 157 158 if (!header) { 159 if (!require_dev) 160 return 0; 161 NL_SET_ERR_MSG(extack, "request header missing"); 162 return -EINVAL; 163 } 164 /* No validation here, command policy should have a nested policy set 165 * for the header, therefore validation should have already been done. 166 */ 167 ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy_phy) - 1, header, 168 NULL, extack); 169 if (ret < 0) 170 return ret; 171 if (tb[ETHTOOL_A_HEADER_FLAGS]) 172 flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]); 173 174 devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME]; 175 if (tb[ETHTOOL_A_HEADER_DEV_INDEX]) { 176 u32 ifindex = nla_get_u32(tb[ETHTOOL_A_HEADER_DEV_INDEX]); 177 178 dev = netdev_get_by_index(net, ifindex, &req_info->dev_tracker, 179 GFP_KERNEL); 180 if (!dev) { 181 NL_SET_ERR_MSG_ATTR(extack, 182 tb[ETHTOOL_A_HEADER_DEV_INDEX], 183 "no device matches ifindex"); 184 return -ENODEV; 185 } 186 /* if both ifindex and ifname are passed, they must match */ 187 if (devname_attr && 188 strncmp(dev->name, nla_data(devname_attr), IFNAMSIZ)) { 189 netdev_put(dev, &req_info->dev_tracker); 190 NL_SET_ERR_MSG_ATTR(extack, header, 191 "ifindex and name do not match"); 192 return -ENODEV; 193 } 194 } else if (devname_attr) { 195 dev = netdev_get_by_name(net, nla_data(devname_attr), 196 &req_info->dev_tracker, GFP_KERNEL); 197 if (!dev) { 198 NL_SET_ERR_MSG_ATTR(extack, devname_attr, 199 "no device matches name"); 200 return -ENODEV; 201 } 202 } else if (require_dev) { 203 NL_SET_ERR_MSG_ATTR(extack, header, 204 "neither ifindex nor name specified"); 205 return -EINVAL; 206 } 207 208 if (tb[ETHTOOL_A_HEADER_PHY_INDEX]) { 209 if (dev) { 210 req_info->phy_index = nla_get_u32(tb[ETHTOOL_A_HEADER_PHY_INDEX]); 211 } else { 212 NL_SET_ERR_MSG_ATTR(extack, header, 213 "phy_index set without a netdev"); 214 return -EINVAL; 215 } 216 } 217 218 req_info->dev = dev; 219 req_info->flags = flags; 220 return 0; 221 } 222 223 struct phy_device *ethnl_req_get_phydev(const struct ethnl_req_info *req_info, 224 struct nlattr **tb, unsigned int header, 225 struct netlink_ext_ack *extack) 226 { 227 struct phy_device *phydev; 228 229 ASSERT_RTNL(); 230 231 if (!req_info->dev) 232 return NULL; 233 234 if (!req_info->phy_index) 235 return req_info->dev->phydev; 236 237 phydev = phy_link_topo_get_phy(req_info->dev, req_info->phy_index); 238 if (!phydev && tb) { 239 NL_SET_ERR_MSG_ATTR(extack, tb[header], 240 "no phy matching phyindex"); 241 return ERR_PTR(-ENODEV); 242 } 243 244 return phydev; 245 } 246 247 /** 248 * ethnl_fill_reply_header() - Put common header into a reply message 249 * @skb: skb with the message 250 * @dev: network device to describe in header 251 * @attrtype: attribute type to use for the nest 252 * 253 * Create a nested attribute with attributes describing given network device. 254 * 255 * Return: 0 on success, error value (-EMSGSIZE only) on error 256 */ 257 int ethnl_fill_reply_header(struct sk_buff *skb, struct net_device *dev, 258 u16 attrtype) 259 { 260 struct nlattr *nest; 261 262 if (!dev) 263 return 0; 264 nest = nla_nest_start(skb, attrtype); 265 if (!nest) 266 return -EMSGSIZE; 267 268 if (nla_put_u32(skb, ETHTOOL_A_HEADER_DEV_INDEX, (u32)dev->ifindex) || 269 nla_put_string(skb, ETHTOOL_A_HEADER_DEV_NAME, dev->name)) 270 goto nla_put_failure; 271 /* If more attributes are put into reply header, ethnl_header_size() 272 * must be updated to account for them. 273 */ 274 275 nla_nest_end(skb, nest); 276 return 0; 277 278 nla_put_failure: 279 nla_nest_cancel(skb, nest); 280 return -EMSGSIZE; 281 } 282 283 /** 284 * ethnl_reply_init() - Create skb for a reply and fill device identification 285 * @payload: payload length (without netlink and genetlink header) 286 * @dev: device the reply is about (may be null) 287 * @cmd: ETHTOOL_MSG_* message type for reply 288 * @hdr_attrtype: attribute type for common header 289 * @info: genetlink info of the received packet we respond to 290 * @ehdrp: place to store payload pointer returned by genlmsg_new() 291 * 292 * Return: pointer to allocated skb on success, NULL on error 293 */ 294 struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd, 295 u16 hdr_attrtype, struct genl_info *info, 296 void **ehdrp) 297 { 298 struct sk_buff *skb; 299 300 skb = genlmsg_new(payload, GFP_KERNEL); 301 if (!skb) 302 goto err; 303 *ehdrp = genlmsg_put_reply(skb, info, ðtool_genl_family, 0, cmd); 304 if (!*ehdrp) 305 goto err_free; 306 307 if (dev) { 308 int ret; 309 310 ret = ethnl_fill_reply_header(skb, dev, hdr_attrtype); 311 if (ret < 0) 312 goto err_free; 313 } 314 return skb; 315 316 err_free: 317 nlmsg_free(skb); 318 err: 319 if (info) 320 GENL_SET_ERR_MSG(info, "failed to setup reply message"); 321 return NULL; 322 } 323 324 void *ethnl_dump_put(struct sk_buff *skb, struct netlink_callback *cb, u8 cmd) 325 { 326 return genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 327 ðtool_genl_family, 0, cmd); 328 } 329 330 void *ethnl_bcastmsg_put(struct sk_buff *skb, u8 cmd) 331 { 332 return genlmsg_put(skb, 0, ++ethnl_bcast_seq, ðtool_genl_family, 0, 333 cmd); 334 } 335 336 void *ethnl_unicast_put(struct sk_buff *skb, u32 portid, u32 seq, u8 cmd) 337 { 338 return genlmsg_put(skb, portid, seq, ðtool_genl_family, 0, cmd); 339 } 340 341 int ethnl_multicast(struct sk_buff *skb, struct net_device *dev) 342 { 343 return genlmsg_multicast_netns(ðtool_genl_family, dev_net(dev), skb, 344 0, ETHNL_MCGRP_MONITOR, GFP_KERNEL); 345 } 346 347 /* GET request helpers */ 348 349 /** 350 * struct ethnl_dump_ctx - context structure for generic dumpit() callback 351 * @ops: request ops of currently processed message type 352 * @req_info: parsed request header of processed request 353 * @reply_data: data needed to compose the reply 354 * @pos_ifindex: saved iteration position - ifindex 355 * 356 * These parameters are kept in struct netlink_callback as context preserved 357 * between iterations. They are initialized by ethnl_default_start() and used 358 * in ethnl_default_dumpit() and ethnl_default_done(). 359 */ 360 struct ethnl_dump_ctx { 361 const struct ethnl_request_ops *ops; 362 struct ethnl_req_info *req_info; 363 struct ethnl_reply_data *reply_data; 364 unsigned long pos_ifindex; 365 }; 366 367 /** 368 * struct ethnl_perphy_dump_ctx - context for dumpit() PHY-aware callbacks 369 * @ethnl_ctx: generic ethnl context 370 * @ifindex: For Filtered DUMP requests, the ifindex of the targeted netdev 371 * @pos_phyindex: iterator position for multi-msg DUMP 372 */ 373 struct ethnl_perphy_dump_ctx { 374 struct ethnl_dump_ctx ethnl_ctx; 375 unsigned int ifindex; 376 unsigned long pos_phyindex; 377 }; 378 379 static const struct ethnl_request_ops * 380 ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { 381 [ETHTOOL_MSG_STRSET_GET] = ðnl_strset_request_ops, 382 [ETHTOOL_MSG_LINKINFO_GET] = ðnl_linkinfo_request_ops, 383 [ETHTOOL_MSG_LINKINFO_SET] = ðnl_linkinfo_request_ops, 384 [ETHTOOL_MSG_LINKMODES_GET] = ðnl_linkmodes_request_ops, 385 [ETHTOOL_MSG_LINKMODES_SET] = ðnl_linkmodes_request_ops, 386 [ETHTOOL_MSG_LINKSTATE_GET] = ðnl_linkstate_request_ops, 387 [ETHTOOL_MSG_DEBUG_GET] = ðnl_debug_request_ops, 388 [ETHTOOL_MSG_DEBUG_SET] = ðnl_debug_request_ops, 389 [ETHTOOL_MSG_WOL_GET] = ðnl_wol_request_ops, 390 [ETHTOOL_MSG_WOL_SET] = ðnl_wol_request_ops, 391 [ETHTOOL_MSG_FEATURES_GET] = ðnl_features_request_ops, 392 [ETHTOOL_MSG_PRIVFLAGS_GET] = ðnl_privflags_request_ops, 393 [ETHTOOL_MSG_PRIVFLAGS_SET] = ðnl_privflags_request_ops, 394 [ETHTOOL_MSG_RINGS_GET] = ðnl_rings_request_ops, 395 [ETHTOOL_MSG_RINGS_SET] = ðnl_rings_request_ops, 396 [ETHTOOL_MSG_CHANNELS_GET] = ðnl_channels_request_ops, 397 [ETHTOOL_MSG_CHANNELS_SET] = ðnl_channels_request_ops, 398 [ETHTOOL_MSG_COALESCE_GET] = ðnl_coalesce_request_ops, 399 [ETHTOOL_MSG_COALESCE_SET] = ðnl_coalesce_request_ops, 400 [ETHTOOL_MSG_PAUSE_GET] = ðnl_pause_request_ops, 401 [ETHTOOL_MSG_PAUSE_SET] = ðnl_pause_request_ops, 402 [ETHTOOL_MSG_EEE_GET] = ðnl_eee_request_ops, 403 [ETHTOOL_MSG_EEE_SET] = ðnl_eee_request_ops, 404 [ETHTOOL_MSG_FEC_GET] = ðnl_fec_request_ops, 405 [ETHTOOL_MSG_FEC_SET] = ðnl_fec_request_ops, 406 [ETHTOOL_MSG_TSINFO_GET] = ðnl_tsinfo_request_ops, 407 [ETHTOOL_MSG_MODULE_EEPROM_GET] = ðnl_module_eeprom_request_ops, 408 [ETHTOOL_MSG_STATS_GET] = ðnl_stats_request_ops, 409 [ETHTOOL_MSG_PHC_VCLOCKS_GET] = ðnl_phc_vclocks_request_ops, 410 [ETHTOOL_MSG_MODULE_GET] = ðnl_module_request_ops, 411 [ETHTOOL_MSG_MODULE_SET] = ðnl_module_request_ops, 412 [ETHTOOL_MSG_PSE_GET] = ðnl_pse_request_ops, 413 [ETHTOOL_MSG_PSE_SET] = ðnl_pse_request_ops, 414 [ETHTOOL_MSG_RSS_GET] = ðnl_rss_request_ops, 415 [ETHTOOL_MSG_RSS_SET] = ðnl_rss_request_ops, 416 [ETHTOOL_MSG_PLCA_GET_CFG] = ðnl_plca_cfg_request_ops, 417 [ETHTOOL_MSG_PLCA_SET_CFG] = ðnl_plca_cfg_request_ops, 418 [ETHTOOL_MSG_PLCA_GET_STATUS] = ðnl_plca_status_request_ops, 419 [ETHTOOL_MSG_MM_GET] = ðnl_mm_request_ops, 420 [ETHTOOL_MSG_MM_SET] = ðnl_mm_request_ops, 421 [ETHTOOL_MSG_TSCONFIG_GET] = ðnl_tsconfig_request_ops, 422 [ETHTOOL_MSG_TSCONFIG_SET] = ðnl_tsconfig_request_ops, 423 [ETHTOOL_MSG_PHY_GET] = ðnl_phy_request_ops, 424 [ETHTOOL_MSG_MSE_GET] = ðnl_mse_request_ops, 425 }; 426 427 static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) 428 { 429 return (struct ethnl_dump_ctx *)cb->ctx; 430 } 431 432 static struct ethnl_perphy_dump_ctx * 433 ethnl_perphy_dump_context(struct netlink_callback *cb) 434 { 435 return (struct ethnl_perphy_dump_ctx *)cb->ctx; 436 } 437 438 /** 439 * ethnl_default_parse() - Parse request message 440 * @req_info: pointer to structure to put data into 441 * @info: genl_info from the request 442 * @request_ops: struct request_ops for request type 443 * @require_dev: fail if no device identified in header 444 * 445 * Parse universal request header and call request specific ->parse_request() 446 * callback (if defined) to parse the rest of the message. 447 * 448 * Return: 0 on success or negative error code 449 */ 450 static int ethnl_default_parse(struct ethnl_req_info *req_info, 451 const struct genl_info *info, 452 const struct ethnl_request_ops *request_ops, 453 bool require_dev) 454 { 455 struct nlattr **tb = info->attrs; 456 int ret; 457 458 ret = ethnl_parse_header_dev_get(req_info, tb[request_ops->hdr_attr], 459 genl_info_net(info), info->extack, 460 require_dev); 461 if (ret < 0) 462 return ret; 463 464 if (request_ops->parse_request) { 465 ret = request_ops->parse_request(req_info, info, tb, 466 info->extack); 467 if (ret < 0) 468 goto err_dev; 469 } 470 471 return 0; 472 473 err_dev: 474 netdev_put(req_info->dev, &req_info->dev_tracker); 475 req_info->dev = NULL; 476 return ret; 477 } 478 479 /** 480 * ethnl_init_reply_data() - Initialize reply data for GET request 481 * @reply_data: pointer to embedded struct ethnl_reply_data 482 * @ops: instance of struct ethnl_request_ops describing the layout 483 * @dev: network device to initialize the reply for 484 * 485 * Fills the reply data part with zeros and sets the dev member. Must be called 486 * before calling the ->fill_reply() callback (for each iteration when handling 487 * dump requests). 488 */ 489 static void ethnl_init_reply_data(struct ethnl_reply_data *reply_data, 490 const struct ethnl_request_ops *ops, 491 struct net_device *dev) 492 { 493 memset(reply_data, 0, ops->reply_data_size); 494 reply_data->dev = dev; 495 } 496 497 /* default ->doit() handler for GET type requests */ 498 static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info) 499 { 500 struct ethnl_reply_data *reply_data = NULL; 501 struct ethnl_req_info *req_info = NULL; 502 const u8 cmd = info->genlhdr->cmd; 503 const struct ethnl_request_ops *ops; 504 int hdr_len, reply_len; 505 struct sk_buff *rskb; 506 void *reply_payload; 507 int ret; 508 509 ops = ethnl_default_requests[cmd]; 510 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", cmd)) 511 return -EOPNOTSUPP; 512 if (GENL_REQ_ATTR_CHECK(info, ops->hdr_attr)) 513 return -EINVAL; 514 515 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 516 if (!req_info) 517 return -ENOMEM; 518 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 519 if (!reply_data) { 520 kfree(req_info); 521 return -ENOMEM; 522 } 523 524 ret = ethnl_default_parse(req_info, info, ops, !ops->allow_nodev_do); 525 if (ret < 0) 526 goto err_free; 527 ethnl_init_reply_data(reply_data, ops, req_info->dev); 528 529 rtnl_lock(); 530 if (req_info->dev) 531 netdev_lock_ops(req_info->dev); 532 ret = ops->prepare_data(req_info, reply_data, info); 533 if (req_info->dev) 534 netdev_unlock_ops(req_info->dev); 535 rtnl_unlock(); 536 if (ret < 0) 537 goto err_dev; 538 ret = ops->reply_size(req_info, reply_data); 539 if (ret < 0) 540 goto err_cleanup; 541 reply_len = ret; 542 ret = -ENOMEM; 543 rskb = ethnl_reply_init(reply_len + ethnl_reply_header_size(), 544 req_info->dev, ops->reply_cmd, 545 ops->hdr_attr, info, &reply_payload); 546 if (!rskb) 547 goto err_cleanup; 548 hdr_len = rskb->len; 549 ret = ops->fill_reply(rskb, req_info, reply_data); 550 if (ret < 0) 551 goto err_msg; 552 WARN_ONCE(rskb->len - hdr_len > reply_len, 553 "ethnl cmd %d: calculated reply length %d, but consumed %d\n", 554 cmd, reply_len, rskb->len - hdr_len); 555 if (ops->cleanup_data) 556 ops->cleanup_data(reply_data); 557 558 genlmsg_end(rskb, reply_payload); 559 netdev_put(req_info->dev, &req_info->dev_tracker); 560 kfree(reply_data); 561 kfree(req_info); 562 return genlmsg_reply(rskb, info); 563 564 err_msg: 565 WARN_ONCE(ret == -EMSGSIZE, "calculated message payload length (%d) not sufficient\n", reply_len); 566 nlmsg_free(rskb); 567 err_cleanup: 568 if (ops->cleanup_data) 569 ops->cleanup_data(reply_data); 570 err_dev: 571 netdev_put(req_info->dev, &req_info->dev_tracker); 572 err_free: 573 kfree(reply_data); 574 kfree(req_info); 575 return ret; 576 } 577 578 static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev, 579 const struct ethnl_dump_ctx *ctx, 580 const struct genl_info *info) 581 { 582 void *ehdr; 583 int ret; 584 585 ehdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 586 ðtool_genl_family, NLM_F_MULTI, 587 ctx->ops->reply_cmd); 588 if (!ehdr) 589 return -EMSGSIZE; 590 591 ethnl_init_reply_data(ctx->reply_data, ctx->ops, dev); 592 rtnl_lock(); 593 netdev_lock_ops(dev); 594 ret = ctx->ops->prepare_data(ctx->req_info, ctx->reply_data, info); 595 netdev_unlock_ops(dev); 596 rtnl_unlock(); 597 if (ret < 0) 598 goto out_cancel; 599 ret = ethnl_fill_reply_header(skb, dev, ctx->ops->hdr_attr); 600 if (ret < 0) 601 goto out; 602 ret = ctx->ops->fill_reply(skb, ctx->req_info, ctx->reply_data); 603 604 out: 605 if (ctx->ops->cleanup_data) 606 ctx->ops->cleanup_data(ctx->reply_data); 607 out_cancel: 608 ctx->reply_data->dev = NULL; 609 if (ret < 0) 610 genlmsg_cancel(skb, ehdr); 611 else 612 genlmsg_end(skb, ehdr); 613 return ret; 614 } 615 616 /* Default ->dumpit() handler for GET requests. */ 617 static int ethnl_default_dumpit(struct sk_buff *skb, 618 struct netlink_callback *cb) 619 { 620 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 621 struct net *net = sock_net(skb->sk); 622 netdevice_tracker dev_tracker; 623 struct net_device *dev; 624 int ret = 0; 625 626 rcu_read_lock(); 627 for_each_netdev_dump(net, dev, ctx->pos_ifindex) { 628 netdev_hold(dev, &dev_tracker, GFP_ATOMIC); 629 rcu_read_unlock(); 630 631 ret = ethnl_default_dump_one(skb, dev, ctx, genl_info_dump(cb)); 632 633 rcu_read_lock(); 634 netdev_put(dev, &dev_tracker); 635 636 if (ret < 0 && ret != -EOPNOTSUPP) { 637 if (likely(skb->len)) 638 ret = skb->len; 639 break; 640 } 641 ret = 0; 642 } 643 rcu_read_unlock(); 644 645 return ret; 646 } 647 648 /* generic ->start() handler for GET requests */ 649 static int ethnl_default_start(struct netlink_callback *cb) 650 { 651 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 652 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 653 struct ethnl_reply_data *reply_data; 654 const struct ethnl_request_ops *ops; 655 struct ethnl_req_info *req_info; 656 struct genlmsghdr *ghdr; 657 int ret; 658 659 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); 660 661 ghdr = nlmsg_data(cb->nlh); 662 ops = ethnl_default_requests[ghdr->cmd]; 663 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd)) 664 return -EOPNOTSUPP; 665 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 666 if (!req_info) 667 return -ENOMEM; 668 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 669 if (!reply_data) { 670 ret = -ENOMEM; 671 goto free_req_info; 672 } 673 674 ret = ethnl_default_parse(req_info, &info->info, ops, false); 675 if (ret < 0) 676 goto free_reply_data; 677 if (req_info->dev) { 678 /* We ignore device specification in dump requests but as the 679 * same parser as for non-dump (doit) requests is used, it 680 * would take reference to the device if it finds one 681 */ 682 netdev_put(req_info->dev, &req_info->dev_tracker); 683 req_info->dev = NULL; 684 } 685 686 ctx->ops = ops; 687 ctx->req_info = req_info; 688 ctx->reply_data = reply_data; 689 ctx->pos_ifindex = 0; 690 691 return 0; 692 693 free_reply_data: 694 kfree(reply_data); 695 free_req_info: 696 kfree(req_info); 697 698 return ret; 699 } 700 701 /* per-PHY ->start() handler for GET requests */ 702 static int ethnl_perphy_start(struct netlink_callback *cb) 703 { 704 struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb); 705 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 706 struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx; 707 struct ethnl_reply_data *reply_data; 708 const struct ethnl_request_ops *ops; 709 struct ethnl_req_info *req_info; 710 struct genlmsghdr *ghdr; 711 int ret; 712 713 BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); 714 715 ghdr = nlmsg_data(cb->nlh); 716 ops = ethnl_default_requests[ghdr->cmd]; 717 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd)) 718 return -EOPNOTSUPP; 719 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 720 if (!req_info) 721 return -ENOMEM; 722 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 723 if (!reply_data) { 724 ret = -ENOMEM; 725 goto free_req_info; 726 } 727 728 /* Unlike per-dev dump, don't ignore dev. The dump handler 729 * will notice it and dump PHYs from given dev. We only keep track of 730 * the dev's ifindex, .dumpit() will grab and release the netdev itself. 731 */ 732 ret = ethnl_default_parse(req_info, &info->info, ops, false); 733 if (ret < 0) 734 goto free_reply_data; 735 if (req_info->dev) { 736 phy_ctx->ifindex = req_info->dev->ifindex; 737 netdev_put(req_info->dev, &req_info->dev_tracker); 738 req_info->dev = NULL; 739 } 740 741 ctx->ops = ops; 742 ctx->req_info = req_info; 743 ctx->reply_data = reply_data; 744 ctx->pos_ifindex = 0; 745 746 return 0; 747 748 free_reply_data: 749 kfree(reply_data); 750 free_req_info: 751 kfree(req_info); 752 753 return ret; 754 } 755 756 static int ethnl_perphy_dump_one_dev(struct sk_buff *skb, 757 struct ethnl_perphy_dump_ctx *ctx, 758 const struct genl_info *info) 759 { 760 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 761 struct net_device *dev = ethnl_ctx->req_info->dev; 762 struct phy_device_node *pdn; 763 int ret; 764 765 if (!dev->link_topo) 766 return 0; 767 768 xa_for_each_start(&dev->link_topo->phys, ctx->pos_phyindex, pdn, 769 ctx->pos_phyindex) { 770 ethnl_ctx->req_info->phy_index = ctx->pos_phyindex; 771 772 /* We can re-use the original dump_one as ->prepare_data in 773 * commands use ethnl_req_get_phydev(), which gets the PHY from 774 * the req_info->phy_index 775 */ 776 ret = ethnl_default_dump_one(skb, dev, ethnl_ctx, info); 777 if (ret) 778 return ret; 779 } 780 781 ctx->pos_phyindex = 0; 782 783 return 0; 784 } 785 786 static int ethnl_perphy_dump_all_dev(struct sk_buff *skb, 787 struct ethnl_perphy_dump_ctx *ctx, 788 const struct genl_info *info) 789 { 790 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 791 struct net *net = sock_net(skb->sk); 792 netdevice_tracker dev_tracker; 793 struct net_device *dev; 794 int ret = 0; 795 796 rcu_read_lock(); 797 for_each_netdev_dump(net, dev, ethnl_ctx->pos_ifindex) { 798 netdev_hold(dev, &dev_tracker, GFP_ATOMIC); 799 rcu_read_unlock(); 800 801 /* per-PHY commands use ethnl_req_get_phydev(), which needs the 802 * net_device in the req_info 803 */ 804 ethnl_ctx->req_info->dev = dev; 805 ret = ethnl_perphy_dump_one_dev(skb, ctx, info); 806 807 rcu_read_lock(); 808 netdev_put(dev, &dev_tracker); 809 ethnl_ctx->req_info->dev = NULL; 810 811 if (ret < 0 && ret != -EOPNOTSUPP) { 812 if (likely(skb->len)) 813 ret = skb->len; 814 break; 815 } 816 ret = 0; 817 } 818 rcu_read_unlock(); 819 820 return ret; 821 } 822 823 /* per-PHY ->dumpit() handler for GET requests. */ 824 static int ethnl_perphy_dumpit(struct sk_buff *skb, 825 struct netlink_callback *cb) 826 { 827 struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb); 828 const struct genl_dumpit_info *info = genl_dumpit_info(cb); 829 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 830 int ret = 0; 831 832 if (ctx->ifindex) { 833 netdevice_tracker dev_tracker; 834 struct net_device *dev; 835 836 dev = netdev_get_by_index(genl_info_net(&info->info), 837 ctx->ifindex, &dev_tracker, 838 GFP_KERNEL); 839 if (!dev) 840 return -ENODEV; 841 842 ethnl_ctx->req_info->dev = dev; 843 ret = ethnl_perphy_dump_one_dev(skb, ctx, genl_info_dump(cb)); 844 845 if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len)) 846 ret = skb->len; 847 848 netdev_put(dev, &dev_tracker); 849 } else { 850 ret = ethnl_perphy_dump_all_dev(skb, ctx, genl_info_dump(cb)); 851 } 852 853 return ret; 854 } 855 856 /* per-PHY ->done() handler for GET requests */ 857 static int ethnl_perphy_done(struct netlink_callback *cb) 858 { 859 struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb); 860 struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; 861 862 kfree(ethnl_ctx->reply_data); 863 kfree(ethnl_ctx->req_info); 864 865 return 0; 866 } 867 868 /* default ->done() handler for GET requests */ 869 static int ethnl_default_done(struct netlink_callback *cb) 870 { 871 struct ethnl_dump_ctx *ctx = ethnl_dump_context(cb); 872 873 kfree(ctx->reply_data); 874 kfree(ctx->req_info); 875 876 return 0; 877 } 878 879 static int ethnl_default_set_doit(struct sk_buff *skb, struct genl_info *info) 880 { 881 const struct ethnl_request_ops *ops; 882 const u8 cmd = info->genlhdr->cmd; 883 struct ethnl_req_info *req_info; 884 struct net_device *dev; 885 int ret; 886 887 ops = ethnl_default_requests[cmd]; 888 if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", cmd)) 889 return -EOPNOTSUPP; 890 if (GENL_REQ_ATTR_CHECK(info, ops->hdr_attr)) 891 return -EINVAL; 892 893 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 894 if (!req_info) 895 return -ENOMEM; 896 897 ret = ethnl_default_parse(req_info, info, ops, true); 898 if (ret < 0) 899 goto out_free_req; 900 901 if (ops->set_validate) { 902 ret = ops->set_validate(req_info, info); 903 /* 0 means nothing to do */ 904 if (ret <= 0) 905 goto out_dev; 906 } 907 908 dev = req_info->dev; 909 910 rtnl_lock(); 911 netdev_lock_ops(dev); 912 dev->cfg_pending = kmemdup(dev->cfg, sizeof(*dev->cfg), 913 GFP_KERNEL_ACCOUNT); 914 if (!dev->cfg_pending) { 915 ret = -ENOMEM; 916 goto out_tie_cfg; 917 } 918 919 ret = ethnl_ops_begin(dev); 920 if (ret < 0) 921 goto out_free_cfg; 922 923 ret = ops->set(req_info, info); 924 if (ret < 0) 925 goto out_ops; 926 927 swap(dev->cfg, dev->cfg_pending); 928 if (!ret) 929 goto out_ops; 930 ethnl_notify(dev, ops->set_ntf_cmd, req_info); 931 932 ret = 0; 933 out_ops: 934 ethnl_ops_complete(dev); 935 out_free_cfg: 936 kfree(dev->cfg_pending); 937 out_tie_cfg: 938 dev->cfg_pending = dev->cfg; 939 netdev_unlock_ops(dev); 940 rtnl_unlock(); 941 out_dev: 942 ethnl_parse_header_dev_put(req_info); 943 out_free_req: 944 kfree(req_info); 945 return ret; 946 } 947 948 static const struct ethnl_request_ops * 949 ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = { 950 [ETHTOOL_MSG_LINKINFO_NTF] = ðnl_linkinfo_request_ops, 951 [ETHTOOL_MSG_LINKMODES_NTF] = ðnl_linkmodes_request_ops, 952 [ETHTOOL_MSG_DEBUG_NTF] = ðnl_debug_request_ops, 953 [ETHTOOL_MSG_WOL_NTF] = ðnl_wol_request_ops, 954 [ETHTOOL_MSG_FEATURES_NTF] = ðnl_features_request_ops, 955 [ETHTOOL_MSG_PRIVFLAGS_NTF] = ðnl_privflags_request_ops, 956 [ETHTOOL_MSG_RINGS_NTF] = ðnl_rings_request_ops, 957 [ETHTOOL_MSG_CHANNELS_NTF] = ðnl_channels_request_ops, 958 [ETHTOOL_MSG_COALESCE_NTF] = ðnl_coalesce_request_ops, 959 [ETHTOOL_MSG_PAUSE_NTF] = ðnl_pause_request_ops, 960 [ETHTOOL_MSG_EEE_NTF] = ðnl_eee_request_ops, 961 [ETHTOOL_MSG_FEC_NTF] = ðnl_fec_request_ops, 962 [ETHTOOL_MSG_MODULE_NTF] = ðnl_module_request_ops, 963 [ETHTOOL_MSG_PLCA_NTF] = ðnl_plca_cfg_request_ops, 964 [ETHTOOL_MSG_MM_NTF] = ðnl_mm_request_ops, 965 [ETHTOOL_MSG_RSS_NTF] = ðnl_rss_request_ops, 966 [ETHTOOL_MSG_RSS_CREATE_NTF] = ðnl_rss_request_ops, 967 }; 968 969 /* default notification handler */ 970 static void ethnl_default_notify(struct net_device *dev, unsigned int cmd, 971 const struct ethnl_req_info *orig_req_info) 972 { 973 struct ethnl_reply_data *reply_data; 974 const struct ethnl_request_ops *ops; 975 struct ethnl_req_info *req_info; 976 struct genl_info info; 977 struct sk_buff *skb; 978 void *reply_payload; 979 int reply_len; 980 int ret; 981 982 genl_info_init_ntf(&info, ðtool_genl_family, cmd); 983 984 if (WARN_ONCE(cmd > ETHTOOL_MSG_KERNEL_MAX || 985 !ethnl_default_notify_ops[cmd], 986 "unexpected notification type %u\n", cmd)) 987 return; 988 ops = ethnl_default_notify_ops[cmd]; 989 req_info = kzalloc(ops->req_info_size, GFP_KERNEL); 990 if (!req_info) 991 return; 992 reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); 993 if (!reply_data) { 994 kfree(req_info); 995 return; 996 } 997 998 req_info->dev = dev; 999 req_info->flags |= ETHTOOL_FLAG_COMPACT_BITSETS; 1000 if (orig_req_info) { 1001 req_info->phy_index = orig_req_info->phy_index; 1002 memcpy(&req_info[1], &orig_req_info[1], 1003 ops->req_info_size - sizeof(*req_info)); 1004 } 1005 1006 netdev_ops_assert_locked(dev); 1007 1008 ethnl_init_reply_data(reply_data, ops, dev); 1009 ret = ops->prepare_data(req_info, reply_data, &info); 1010 if (ret < 0) 1011 goto err_rep; 1012 ret = ops->reply_size(req_info, reply_data); 1013 if (ret < 0) 1014 goto err_cleanup; 1015 reply_len = ret + ethnl_reply_header_size(); 1016 skb = genlmsg_new(reply_len, GFP_KERNEL); 1017 if (!skb) 1018 goto err_cleanup; 1019 reply_payload = ethnl_bcastmsg_put(skb, cmd); 1020 if (!reply_payload) 1021 goto err_skb; 1022 ret = ethnl_fill_reply_header(skb, dev, ops->hdr_attr); 1023 if (ret < 0) 1024 goto err_msg; 1025 ret = ops->fill_reply(skb, req_info, reply_data); 1026 if (ret < 0) 1027 goto err_msg; 1028 if (ops->cleanup_data) 1029 ops->cleanup_data(reply_data); 1030 1031 genlmsg_end(skb, reply_payload); 1032 kfree(reply_data); 1033 kfree(req_info); 1034 ethnl_multicast(skb, dev); 1035 return; 1036 1037 err_msg: 1038 WARN_ONCE(ret == -EMSGSIZE, 1039 "calculated message payload length (%d) not sufficient\n", 1040 reply_len); 1041 err_skb: 1042 nlmsg_free(skb); 1043 err_cleanup: 1044 if (ops->cleanup_data) 1045 ops->cleanup_data(reply_data); 1046 err_rep: 1047 kfree(reply_data); 1048 kfree(req_info); 1049 return; 1050 } 1051 1052 /* notifications */ 1053 1054 typedef void (*ethnl_notify_handler_t)(struct net_device *dev, unsigned int cmd, 1055 const struct ethnl_req_info *req_info); 1056 1057 static const ethnl_notify_handler_t ethnl_notify_handlers[] = { 1058 [ETHTOOL_MSG_LINKINFO_NTF] = ethnl_default_notify, 1059 [ETHTOOL_MSG_LINKMODES_NTF] = ethnl_default_notify, 1060 [ETHTOOL_MSG_DEBUG_NTF] = ethnl_default_notify, 1061 [ETHTOOL_MSG_WOL_NTF] = ethnl_default_notify, 1062 [ETHTOOL_MSG_FEATURES_NTF] = ethnl_default_notify, 1063 [ETHTOOL_MSG_PRIVFLAGS_NTF] = ethnl_default_notify, 1064 [ETHTOOL_MSG_RINGS_NTF] = ethnl_default_notify, 1065 [ETHTOOL_MSG_CHANNELS_NTF] = ethnl_default_notify, 1066 [ETHTOOL_MSG_COALESCE_NTF] = ethnl_default_notify, 1067 [ETHTOOL_MSG_PAUSE_NTF] = ethnl_default_notify, 1068 [ETHTOOL_MSG_EEE_NTF] = ethnl_default_notify, 1069 [ETHTOOL_MSG_FEC_NTF] = ethnl_default_notify, 1070 [ETHTOOL_MSG_MODULE_NTF] = ethnl_default_notify, 1071 [ETHTOOL_MSG_PLCA_NTF] = ethnl_default_notify, 1072 [ETHTOOL_MSG_MM_NTF] = ethnl_default_notify, 1073 [ETHTOOL_MSG_RSS_NTF] = ethnl_default_notify, 1074 [ETHTOOL_MSG_RSS_CREATE_NTF] = ethnl_default_notify, 1075 }; 1076 1077 void ethnl_notify(struct net_device *dev, unsigned int cmd, 1078 const struct ethnl_req_info *req_info) 1079 { 1080 if (unlikely(!ethnl_ok)) 1081 return; 1082 ASSERT_RTNL(); 1083 1084 if (likely(cmd < ARRAY_SIZE(ethnl_notify_handlers) && 1085 ethnl_notify_handlers[cmd])) 1086 ethnl_notify_handlers[cmd](dev, cmd, req_info); 1087 else 1088 WARN_ONCE(1, "notification %u not implemented (dev=%s)\n", 1089 cmd, netdev_name(dev)); 1090 } 1091 1092 void ethtool_notify(struct net_device *dev, unsigned int cmd) 1093 { 1094 ethnl_notify(dev, cmd, NULL); 1095 } 1096 EXPORT_SYMBOL(ethtool_notify); 1097 1098 static void ethnl_notify_features(struct netdev_notifier_info *info) 1099 { 1100 struct net_device *dev = netdev_notifier_info_to_dev(info); 1101 1102 ethtool_notify(dev, ETHTOOL_MSG_FEATURES_NTF); 1103 } 1104 1105 static int ethnl_netdev_event(struct notifier_block *this, unsigned long event, 1106 void *ptr) 1107 { 1108 struct netdev_notifier_info *info = ptr; 1109 struct netlink_ext_ack *extack; 1110 struct net_device *dev; 1111 1112 dev = netdev_notifier_info_to_dev(info); 1113 extack = netdev_notifier_info_to_extack(info); 1114 1115 switch (event) { 1116 case NETDEV_FEAT_CHANGE: 1117 ethnl_notify_features(ptr); 1118 break; 1119 case NETDEV_PRE_UP: 1120 if (dev->ethtool->module_fw_flash_in_progress) { 1121 NL_SET_ERR_MSG(extack, "Can't set port up while flashing module firmware"); 1122 return NOTIFY_BAD; 1123 } 1124 } 1125 1126 return NOTIFY_DONE; 1127 } 1128 1129 static struct notifier_block ethnl_netdev_notifier = { 1130 .notifier_call = ethnl_netdev_event, 1131 }; 1132 1133 /* genetlink setup */ 1134 1135 static const struct genl_ops ethtool_genl_ops[] = { 1136 { 1137 .cmd = ETHTOOL_MSG_STRSET_GET, 1138 .doit = ethnl_default_doit, 1139 .start = ethnl_default_start, 1140 .dumpit = ethnl_default_dumpit, 1141 .done = ethnl_default_done, 1142 .policy = ethnl_strset_get_policy, 1143 .maxattr = ARRAY_SIZE(ethnl_strset_get_policy) - 1, 1144 }, 1145 { 1146 .cmd = ETHTOOL_MSG_LINKINFO_GET, 1147 .doit = ethnl_default_doit, 1148 .start = ethnl_default_start, 1149 .dumpit = ethnl_default_dumpit, 1150 .done = ethnl_default_done, 1151 .policy = ethnl_linkinfo_get_policy, 1152 .maxattr = ARRAY_SIZE(ethnl_linkinfo_get_policy) - 1, 1153 }, 1154 { 1155 .cmd = ETHTOOL_MSG_LINKINFO_SET, 1156 .flags = GENL_UNS_ADMIN_PERM, 1157 .doit = ethnl_default_set_doit, 1158 .policy = ethnl_linkinfo_set_policy, 1159 .maxattr = ARRAY_SIZE(ethnl_linkinfo_set_policy) - 1, 1160 }, 1161 { 1162 .cmd = ETHTOOL_MSG_LINKMODES_GET, 1163 .doit = ethnl_default_doit, 1164 .start = ethnl_default_start, 1165 .dumpit = ethnl_default_dumpit, 1166 .done = ethnl_default_done, 1167 .policy = ethnl_linkmodes_get_policy, 1168 .maxattr = ARRAY_SIZE(ethnl_linkmodes_get_policy) - 1, 1169 }, 1170 { 1171 .cmd = ETHTOOL_MSG_LINKMODES_SET, 1172 .flags = GENL_UNS_ADMIN_PERM, 1173 .doit = ethnl_default_set_doit, 1174 .policy = ethnl_linkmodes_set_policy, 1175 .maxattr = ARRAY_SIZE(ethnl_linkmodes_set_policy) - 1, 1176 }, 1177 { 1178 .cmd = ETHTOOL_MSG_LINKSTATE_GET, 1179 .doit = ethnl_default_doit, 1180 .start = ethnl_default_start, 1181 .dumpit = ethnl_default_dumpit, 1182 .done = ethnl_default_done, 1183 .policy = ethnl_linkstate_get_policy, 1184 .maxattr = ARRAY_SIZE(ethnl_linkstate_get_policy) - 1, 1185 }, 1186 { 1187 .cmd = ETHTOOL_MSG_DEBUG_GET, 1188 .doit = ethnl_default_doit, 1189 .start = ethnl_default_start, 1190 .dumpit = ethnl_default_dumpit, 1191 .done = ethnl_default_done, 1192 .policy = ethnl_debug_get_policy, 1193 .maxattr = ARRAY_SIZE(ethnl_debug_get_policy) - 1, 1194 }, 1195 { 1196 .cmd = ETHTOOL_MSG_DEBUG_SET, 1197 .flags = GENL_UNS_ADMIN_PERM, 1198 .doit = ethnl_default_set_doit, 1199 .policy = ethnl_debug_set_policy, 1200 .maxattr = ARRAY_SIZE(ethnl_debug_set_policy) - 1, 1201 }, 1202 { 1203 .cmd = ETHTOOL_MSG_WOL_GET, 1204 .flags = GENL_UNS_ADMIN_PERM, 1205 .doit = ethnl_default_doit, 1206 .start = ethnl_default_start, 1207 .dumpit = ethnl_default_dumpit, 1208 .done = ethnl_default_done, 1209 .policy = ethnl_wol_get_policy, 1210 .maxattr = ARRAY_SIZE(ethnl_wol_get_policy) - 1, 1211 }, 1212 { 1213 .cmd = ETHTOOL_MSG_WOL_SET, 1214 .flags = GENL_UNS_ADMIN_PERM, 1215 .doit = ethnl_default_set_doit, 1216 .policy = ethnl_wol_set_policy, 1217 .maxattr = ARRAY_SIZE(ethnl_wol_set_policy) - 1, 1218 }, 1219 { 1220 .cmd = ETHTOOL_MSG_FEATURES_GET, 1221 .doit = ethnl_default_doit, 1222 .start = ethnl_default_start, 1223 .dumpit = ethnl_default_dumpit, 1224 .done = ethnl_default_done, 1225 .policy = ethnl_features_get_policy, 1226 .maxattr = ARRAY_SIZE(ethnl_features_get_policy) - 1, 1227 }, 1228 { 1229 .cmd = ETHTOOL_MSG_FEATURES_SET, 1230 .flags = GENL_UNS_ADMIN_PERM, 1231 .doit = ethnl_set_features, 1232 .policy = ethnl_features_set_policy, 1233 .maxattr = ARRAY_SIZE(ethnl_features_set_policy) - 1, 1234 }, 1235 { 1236 .cmd = ETHTOOL_MSG_PRIVFLAGS_GET, 1237 .doit = ethnl_default_doit, 1238 .start = ethnl_default_start, 1239 .dumpit = ethnl_default_dumpit, 1240 .done = ethnl_default_done, 1241 .policy = ethnl_privflags_get_policy, 1242 .maxattr = ARRAY_SIZE(ethnl_privflags_get_policy) - 1, 1243 }, 1244 { 1245 .cmd = ETHTOOL_MSG_PRIVFLAGS_SET, 1246 .flags = GENL_UNS_ADMIN_PERM, 1247 .doit = ethnl_default_set_doit, 1248 .policy = ethnl_privflags_set_policy, 1249 .maxattr = ARRAY_SIZE(ethnl_privflags_set_policy) - 1, 1250 }, 1251 { 1252 .cmd = ETHTOOL_MSG_RINGS_GET, 1253 .doit = ethnl_default_doit, 1254 .start = ethnl_default_start, 1255 .dumpit = ethnl_default_dumpit, 1256 .done = ethnl_default_done, 1257 .policy = ethnl_rings_get_policy, 1258 .maxattr = ARRAY_SIZE(ethnl_rings_get_policy) - 1, 1259 }, 1260 { 1261 .cmd = ETHTOOL_MSG_RINGS_SET, 1262 .flags = GENL_UNS_ADMIN_PERM, 1263 .doit = ethnl_default_set_doit, 1264 .policy = ethnl_rings_set_policy, 1265 .maxattr = ARRAY_SIZE(ethnl_rings_set_policy) - 1, 1266 }, 1267 { 1268 .cmd = ETHTOOL_MSG_CHANNELS_GET, 1269 .doit = ethnl_default_doit, 1270 .start = ethnl_default_start, 1271 .dumpit = ethnl_default_dumpit, 1272 .done = ethnl_default_done, 1273 .policy = ethnl_channels_get_policy, 1274 .maxattr = ARRAY_SIZE(ethnl_channels_get_policy) - 1, 1275 }, 1276 { 1277 .cmd = ETHTOOL_MSG_CHANNELS_SET, 1278 .flags = GENL_UNS_ADMIN_PERM, 1279 .doit = ethnl_default_set_doit, 1280 .policy = ethnl_channels_set_policy, 1281 .maxattr = ARRAY_SIZE(ethnl_channels_set_policy) - 1, 1282 }, 1283 { 1284 .cmd = ETHTOOL_MSG_COALESCE_GET, 1285 .doit = ethnl_default_doit, 1286 .start = ethnl_default_start, 1287 .dumpit = ethnl_default_dumpit, 1288 .done = ethnl_default_done, 1289 .policy = ethnl_coalesce_get_policy, 1290 .maxattr = ARRAY_SIZE(ethnl_coalesce_get_policy) - 1, 1291 }, 1292 { 1293 .cmd = ETHTOOL_MSG_COALESCE_SET, 1294 .flags = GENL_UNS_ADMIN_PERM, 1295 .doit = ethnl_default_set_doit, 1296 .policy = ethnl_coalesce_set_policy, 1297 .maxattr = ARRAY_SIZE(ethnl_coalesce_set_policy) - 1, 1298 }, 1299 { 1300 .cmd = ETHTOOL_MSG_PAUSE_GET, 1301 .doit = ethnl_default_doit, 1302 .start = ethnl_default_start, 1303 .dumpit = ethnl_default_dumpit, 1304 .done = ethnl_default_done, 1305 .policy = ethnl_pause_get_policy, 1306 .maxattr = ARRAY_SIZE(ethnl_pause_get_policy) - 1, 1307 }, 1308 { 1309 .cmd = ETHTOOL_MSG_PAUSE_SET, 1310 .flags = GENL_UNS_ADMIN_PERM, 1311 .doit = ethnl_default_set_doit, 1312 .policy = ethnl_pause_set_policy, 1313 .maxattr = ARRAY_SIZE(ethnl_pause_set_policy) - 1, 1314 }, 1315 { 1316 .cmd = ETHTOOL_MSG_EEE_GET, 1317 .doit = ethnl_default_doit, 1318 .start = ethnl_default_start, 1319 .dumpit = ethnl_default_dumpit, 1320 .done = ethnl_default_done, 1321 .policy = ethnl_eee_get_policy, 1322 .maxattr = ARRAY_SIZE(ethnl_eee_get_policy) - 1, 1323 }, 1324 { 1325 .cmd = ETHTOOL_MSG_EEE_SET, 1326 .flags = GENL_UNS_ADMIN_PERM, 1327 .doit = ethnl_default_set_doit, 1328 .policy = ethnl_eee_set_policy, 1329 .maxattr = ARRAY_SIZE(ethnl_eee_set_policy) - 1, 1330 }, 1331 { 1332 .cmd = ETHTOOL_MSG_TSINFO_GET, 1333 .doit = ethnl_default_doit, 1334 .start = ethnl_tsinfo_start, 1335 .dumpit = ethnl_tsinfo_dumpit, 1336 .done = ethnl_tsinfo_done, 1337 .policy = ethnl_tsinfo_get_policy, 1338 .maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1, 1339 }, 1340 { 1341 .cmd = ETHTOOL_MSG_CABLE_TEST_ACT, 1342 .flags = GENL_UNS_ADMIN_PERM, 1343 .doit = ethnl_act_cable_test, 1344 .policy = ethnl_cable_test_act_policy, 1345 .maxattr = ARRAY_SIZE(ethnl_cable_test_act_policy) - 1, 1346 }, 1347 { 1348 .cmd = ETHTOOL_MSG_CABLE_TEST_TDR_ACT, 1349 .flags = GENL_UNS_ADMIN_PERM, 1350 .doit = ethnl_act_cable_test_tdr, 1351 .policy = ethnl_cable_test_tdr_act_policy, 1352 .maxattr = ARRAY_SIZE(ethnl_cable_test_tdr_act_policy) - 1, 1353 }, 1354 { 1355 .cmd = ETHTOOL_MSG_TUNNEL_INFO_GET, 1356 .doit = ethnl_tunnel_info_doit, 1357 .start = ethnl_tunnel_info_start, 1358 .dumpit = ethnl_tunnel_info_dumpit, 1359 .policy = ethnl_tunnel_info_get_policy, 1360 .maxattr = ARRAY_SIZE(ethnl_tunnel_info_get_policy) - 1, 1361 }, 1362 { 1363 .cmd = ETHTOOL_MSG_FEC_GET, 1364 .doit = ethnl_default_doit, 1365 .start = ethnl_default_start, 1366 .dumpit = ethnl_default_dumpit, 1367 .done = ethnl_default_done, 1368 .policy = ethnl_fec_get_policy, 1369 .maxattr = ARRAY_SIZE(ethnl_fec_get_policy) - 1, 1370 }, 1371 { 1372 .cmd = ETHTOOL_MSG_FEC_SET, 1373 .flags = GENL_UNS_ADMIN_PERM, 1374 .doit = ethnl_default_set_doit, 1375 .policy = ethnl_fec_set_policy, 1376 .maxattr = ARRAY_SIZE(ethnl_fec_set_policy) - 1, 1377 }, 1378 { 1379 .cmd = ETHTOOL_MSG_MODULE_EEPROM_GET, 1380 .flags = GENL_UNS_ADMIN_PERM, 1381 .doit = ethnl_default_doit, 1382 .start = ethnl_default_start, 1383 .dumpit = ethnl_default_dumpit, 1384 .done = ethnl_default_done, 1385 .policy = ethnl_module_eeprom_get_policy, 1386 .maxattr = ARRAY_SIZE(ethnl_module_eeprom_get_policy) - 1, 1387 }, 1388 { 1389 .cmd = ETHTOOL_MSG_STATS_GET, 1390 .doit = ethnl_default_doit, 1391 .start = ethnl_default_start, 1392 .dumpit = ethnl_default_dumpit, 1393 .done = ethnl_default_done, 1394 .policy = ethnl_stats_get_policy, 1395 .maxattr = ARRAY_SIZE(ethnl_stats_get_policy) - 1, 1396 }, 1397 { 1398 .cmd = ETHTOOL_MSG_PHC_VCLOCKS_GET, 1399 .doit = ethnl_default_doit, 1400 .start = ethnl_default_start, 1401 .dumpit = ethnl_default_dumpit, 1402 .done = ethnl_default_done, 1403 .policy = ethnl_phc_vclocks_get_policy, 1404 .maxattr = ARRAY_SIZE(ethnl_phc_vclocks_get_policy) - 1, 1405 }, 1406 { 1407 .cmd = ETHTOOL_MSG_MODULE_GET, 1408 .doit = ethnl_default_doit, 1409 .start = ethnl_default_start, 1410 .dumpit = ethnl_default_dumpit, 1411 .done = ethnl_default_done, 1412 .policy = ethnl_module_get_policy, 1413 .maxattr = ARRAY_SIZE(ethnl_module_get_policy) - 1, 1414 }, 1415 { 1416 .cmd = ETHTOOL_MSG_MODULE_SET, 1417 .flags = GENL_UNS_ADMIN_PERM, 1418 .doit = ethnl_default_set_doit, 1419 .policy = ethnl_module_set_policy, 1420 .maxattr = ARRAY_SIZE(ethnl_module_set_policy) - 1, 1421 }, 1422 { 1423 .cmd = ETHTOOL_MSG_PSE_GET, 1424 .doit = ethnl_default_doit, 1425 .start = ethnl_perphy_start, 1426 .dumpit = ethnl_perphy_dumpit, 1427 .done = ethnl_perphy_done, 1428 .policy = ethnl_pse_get_policy, 1429 .maxattr = ARRAY_SIZE(ethnl_pse_get_policy) - 1, 1430 }, 1431 { 1432 .cmd = ETHTOOL_MSG_PSE_SET, 1433 .flags = GENL_UNS_ADMIN_PERM, 1434 .doit = ethnl_default_set_doit, 1435 .policy = ethnl_pse_set_policy, 1436 .maxattr = ARRAY_SIZE(ethnl_pse_set_policy) - 1, 1437 }, 1438 { 1439 .cmd = ETHTOOL_MSG_RSS_GET, 1440 .doit = ethnl_default_doit, 1441 .start = ethnl_rss_dump_start, 1442 .dumpit = ethnl_rss_dumpit, 1443 .policy = ethnl_rss_get_policy, 1444 .maxattr = ARRAY_SIZE(ethnl_rss_get_policy) - 1, 1445 }, 1446 { 1447 .cmd = ETHTOOL_MSG_PLCA_GET_CFG, 1448 .doit = ethnl_default_doit, 1449 .start = ethnl_perphy_start, 1450 .dumpit = ethnl_perphy_dumpit, 1451 .done = ethnl_perphy_done, 1452 .policy = ethnl_plca_get_cfg_policy, 1453 .maxattr = ARRAY_SIZE(ethnl_plca_get_cfg_policy) - 1, 1454 }, 1455 { 1456 .cmd = ETHTOOL_MSG_PLCA_SET_CFG, 1457 .flags = GENL_UNS_ADMIN_PERM, 1458 .doit = ethnl_default_set_doit, 1459 .policy = ethnl_plca_set_cfg_policy, 1460 .maxattr = ARRAY_SIZE(ethnl_plca_set_cfg_policy) - 1, 1461 }, 1462 { 1463 .cmd = ETHTOOL_MSG_PLCA_GET_STATUS, 1464 .doit = ethnl_default_doit, 1465 .start = ethnl_perphy_start, 1466 .dumpit = ethnl_perphy_dumpit, 1467 .done = ethnl_perphy_done, 1468 .policy = ethnl_plca_get_status_policy, 1469 .maxattr = ARRAY_SIZE(ethnl_plca_get_status_policy) - 1, 1470 }, 1471 { 1472 .cmd = ETHTOOL_MSG_MM_GET, 1473 .doit = ethnl_default_doit, 1474 .start = ethnl_default_start, 1475 .dumpit = ethnl_default_dumpit, 1476 .done = ethnl_default_done, 1477 .policy = ethnl_mm_get_policy, 1478 .maxattr = ARRAY_SIZE(ethnl_mm_get_policy) - 1, 1479 }, 1480 { 1481 .cmd = ETHTOOL_MSG_MM_SET, 1482 .flags = GENL_UNS_ADMIN_PERM, 1483 .doit = ethnl_default_set_doit, 1484 .policy = ethnl_mm_set_policy, 1485 .maxattr = ARRAY_SIZE(ethnl_mm_set_policy) - 1, 1486 }, 1487 { 1488 .cmd = ETHTOOL_MSG_MODULE_FW_FLASH_ACT, 1489 .flags = GENL_UNS_ADMIN_PERM, 1490 .doit = ethnl_act_module_fw_flash, 1491 .policy = ethnl_module_fw_flash_act_policy, 1492 .maxattr = ARRAY_SIZE(ethnl_module_fw_flash_act_policy) - 1, 1493 }, 1494 { 1495 .cmd = ETHTOOL_MSG_PHY_GET, 1496 .doit = ethnl_default_doit, 1497 .start = ethnl_perphy_start, 1498 .dumpit = ethnl_perphy_dumpit, 1499 .done = ethnl_perphy_done, 1500 .policy = ethnl_phy_get_policy, 1501 .maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1, 1502 }, 1503 { 1504 .cmd = ETHTOOL_MSG_TSCONFIG_GET, 1505 .doit = ethnl_default_doit, 1506 .start = ethnl_default_start, 1507 .dumpit = ethnl_default_dumpit, 1508 .done = ethnl_default_done, 1509 .policy = ethnl_tsconfig_get_policy, 1510 .maxattr = ARRAY_SIZE(ethnl_tsconfig_get_policy) - 1, 1511 }, 1512 { 1513 .cmd = ETHTOOL_MSG_TSCONFIG_SET, 1514 .flags = GENL_UNS_ADMIN_PERM, 1515 .doit = ethnl_default_set_doit, 1516 .policy = ethnl_tsconfig_set_policy, 1517 .maxattr = ARRAY_SIZE(ethnl_tsconfig_set_policy) - 1, 1518 }, 1519 { 1520 .cmd = ETHTOOL_MSG_RSS_SET, 1521 .flags = GENL_UNS_ADMIN_PERM, 1522 .doit = ethnl_default_set_doit, 1523 .policy = ethnl_rss_set_policy, 1524 .maxattr = ARRAY_SIZE(ethnl_rss_set_policy) - 1, 1525 }, 1526 { 1527 .cmd = ETHTOOL_MSG_RSS_CREATE_ACT, 1528 .flags = GENL_UNS_ADMIN_PERM, 1529 .doit = ethnl_rss_create_doit, 1530 .policy = ethnl_rss_create_policy, 1531 .maxattr = ARRAY_SIZE(ethnl_rss_create_policy) - 1, 1532 }, 1533 { 1534 .cmd = ETHTOOL_MSG_RSS_DELETE_ACT, 1535 .flags = GENL_UNS_ADMIN_PERM, 1536 .doit = ethnl_rss_delete_doit, 1537 .policy = ethnl_rss_delete_policy, 1538 .maxattr = ARRAY_SIZE(ethnl_rss_delete_policy) - 1, 1539 }, 1540 { 1541 .cmd = ETHTOOL_MSG_MSE_GET, 1542 .doit = ethnl_default_doit, 1543 .start = ethnl_perphy_start, 1544 .dumpit = ethnl_perphy_dumpit, 1545 .done = ethnl_perphy_done, 1546 .policy = ethnl_mse_get_policy, 1547 .maxattr = ARRAY_SIZE(ethnl_mse_get_policy) - 1, 1548 }, 1549 }; 1550 1551 static const struct genl_multicast_group ethtool_nl_mcgrps[] = { 1552 [ETHNL_MCGRP_MONITOR] = { .name = ETHTOOL_MCGRP_MONITOR_NAME }, 1553 }; 1554 1555 static struct genl_family ethtool_genl_family __ro_after_init = { 1556 .name = ETHTOOL_GENL_NAME, 1557 .version = ETHTOOL_GENL_VERSION, 1558 .netnsok = true, 1559 .parallel_ops = true, 1560 .ops = ethtool_genl_ops, 1561 .n_ops = ARRAY_SIZE(ethtool_genl_ops), 1562 .resv_start_op = ETHTOOL_MSG_MODULE_GET + 1, 1563 .mcgrps = ethtool_nl_mcgrps, 1564 .n_mcgrps = ARRAY_SIZE(ethtool_nl_mcgrps), 1565 .sock_priv_size = sizeof(struct ethnl_sock_priv), 1566 .sock_priv_destroy = ethnl_sock_priv_destroy, 1567 }; 1568 1569 /* module setup */ 1570 1571 static int __init ethnl_init(void) 1572 { 1573 int ret; 1574 1575 ret = genl_register_family(ðtool_genl_family); 1576 if (WARN(ret < 0, "ethtool: genetlink family registration failed")) 1577 return ret; 1578 ethnl_ok = true; 1579 1580 ret = register_netdevice_notifier(ðnl_netdev_notifier); 1581 WARN(ret < 0, "ethtool: net device notifier registration failed"); 1582 return ret; 1583 } 1584 1585 subsys_initcall(ethnl_init); 1586