Most devices maintain RMON (RFC 2819) stats - particularly the "histogram" of packets received by size. Unlike other RFCs which duplicate IEEE stats, the short/oversized frame counters in RMON don't seem to match IEEE stats 1-to-1 either, so expose those, too. Do not expose basic packet, CRC errors etc - those are already otherwise covered. Because standard defines packet ranges only up to 1518, and everything above that should theoretically be "oversized" - devices often create their own ranges. Going beyond what the RFC defines - expose the "histogram" in the Tx direction (assume for now that the ranges will be the same).
Unified · Split
| @@ -346,6 +346,44 @@ struct ethtool_fec_stats { · 345 unmodified lines | |||
| 346 | } corrected_blocks, uncorrectable_blocks, corrected_bits; | 346 | } corrected_blocks, uncorrectable_blocks, corrected_bits; |
| 347 | }; | 347 | }; |
| 348 | 348 | ||
| 349 | /** | ||
| 350 | * struct ethtool_rmon_hist_range - byte range for histogram statistics | ||
| 351 | * @low: low bound of the bucket (inclusive) | ||
| 352 | * @high: high bound of the bucket (inclusive) | ||
| 353 | */ | ||
| 354 | struct ethtool_rmon_hist_range { | ||
| 355 | u16 low; | ||
| 356 | u16 high; | ||
| 357 | }; | ||
| 358 | |||
| 359 | #define ETHTOOL_RMON_HIST_MAX 10 | ||
| 360 | |||
| 361 | /** | ||
| 362 | * struct ethtool_rmon_stats - selected RMON (RFC 2819) statistics | ||
| 363 | * @undersize_pkts: Equivalent to `etherStatsUndersizePkts` from the RFC. | ||
| 364 | * @oversize_pkts: Equivalent to `etherStatsOversizePkts` from the RFC. | ||
| 365 | * @fragments: Equivalent to `etherStatsFragments` from the RFC. | ||
| 366 | * @jabbers: Equivalent to `etherStatsJabbers` from the RFC. | ||
| 367 | * @hist: Packet counter for packet length buckets (e.g. | ||
| 368 | * `etherStatsPkts128to255Octets` from the RFC). | ||
| 369 | * @hist_tx: Tx counters in similar form to @hist, not defined in the RFC. | ||
| 370 | * | ||
| 371 | * Selection of RMON (RFC 2819) statistics which are not exposed via different | ||
| 372 | * APIs, primarily the packet-length-based counters. | ||
| 373 | * Unfortunately different designs choose different buckets beyond | ||
| 374 | * the 1024B mark (jumbo frame teritory), so the definition of the bucket | ||
| 375 | * ranges is left to the driver. | ||
| 376 | */ | ||
| 377 | struct ethtool_rmon_stats { | ||
| 378 | u64 undersize_pkts; | ||
| 379 | u64 oversize_pkts; | ||
| 380 | u64 fragments; | ||
| 381 | u64 jabbers; | ||
| 382 | |||
| 383 | u64 hist[ETHTOOL_RMON_HIST_MAX]; | ||
| 384 | u64 hist_tx[ETHTOOL_RMON_HIST_MAX]; | ||
| 385 | }; | ||
| 386 | |||
| 349 | #define ETH_MODULE_EEPROM_PAGE_LEN 128 | 387 | #define ETH_MODULE_EEPROM_PAGE_LEN 128 |
| 350 | #define ETH_MODULE_MAX_I2C_ADDRESS 0x7f | 388 | #define ETH_MODULE_MAX_I2C_ADDRESS 0x7f |
| 351 | 389 | ||
| @@ -534,6 +572,8 @@ struct ethtool_module_eeprom { · 182 unmodified lines | |||
| 534 | * @get_eth_phy_stats: Query some of the IEEE 802.3 PHY statistics. | 572 | * @get_eth_phy_stats: Query some of the IEEE 802.3 PHY statistics. |
| 535 | * @get_eth_mac_stats: Query some of the IEEE 802.3 MAC statistics. | 573 | * @get_eth_mac_stats: Query some of the IEEE 802.3 MAC statistics. |
| 536 | * @get_eth_ctrl_stats: Query some of the IEEE 802.3 MAC Ctrl statistics. | 574 | * @get_eth_ctrl_stats: Query some of the IEEE 802.3 MAC Ctrl statistics. |
| 575 | * @get_rmon_stats: Query some of the RMON (RFC 2819) statistics. | ||
| 576 | * Set %ranges to a pointer to zero-terminated array of byte ranges. | ||
| 537 | * | 577 | * |
| 538 | * All operations are optional (i.e. the function pointer may be set | 578 | * All operations are optional (i.e. the function pointer may be set |
| 539 | * to %NULL) and callers must take this into account. Callers must | 579 | * to %NULL) and callers must take this into account. Callers must |
| @@ -650,6 +690,9 @@ struct ethtool_ops { · 110 unmodified lines | |||
| 650 | struct ethtool_eth_mac_stats *mac_stats); | 690 | struct ethtool_eth_mac_stats *mac_stats); |
| 651 | void (*get_eth_ctrl_stats)(struct net_device *dev, | 691 | void (*get_eth_ctrl_stats)(struct net_device *dev, |
| 652 | struct ethtool_eth_ctrl_stats *ctrl_stats); | 692 | struct ethtool_eth_ctrl_stats *ctrl_stats); |
| 693 | void (*get_rmon_stats)(struct net_device *dev, | ||
| 694 | struct ethtool_rmon_stats *rmon_stats, | ||
| 695 | const struct ethtool_rmon_hist_range **ranges); | ||
| 653 | }; | 696 | }; |
| 654 | 697 | ||
| 655 | int ethtool_check_ops(const struct ethtool_ops *ops); | 698 | int ethtool_check_ops(const struct ethtool_ops *ops); |
| @@ -673,6 +673,7 @@ enum ethtool_link_ext_substate_cable_issue { · 672 unmodified lines | |||
| 673 | * @ETH_SS_STATS_ETH_PHY: names of IEEE 802.3 PHY statistics | 673 | * @ETH_SS_STATS_ETH_PHY: names of IEEE 802.3 PHY statistics |
| 674 | * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics | 674 | * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics |
| 675 | * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics | 675 | * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics |
| 676 | * @ETH_SS_STATS_RMON: names of RMON statistics | ||
| 676 | * | 677 | * |
| 677 | * @ETH_SS_COUNT: number of defined string sets | 678 | * @ETH_SS_COUNT: number of defined string sets |
| 678 | */ | 679 | */ |
| @@ -697,6 +698,7 @@ enum ethtool_stringset { · 18 unmodified lines | |||
| 697 | ETH_SS_STATS_ETH_PHY, | 698 | ETH_SS_STATS_ETH_PHY, |
| 698 | ETH_SS_STATS_ETH_MAC, | 699 | ETH_SS_STATS_ETH_MAC, |
| 699 | ETH_SS_STATS_ETH_CTRL, | 700 | ETH_SS_STATS_ETH_CTRL, |
| 701 | ETH_SS_STATS_RMON, | ||
| 700 | 702 | ||
| 701 | /* add new constants above here */ | 703 | /* add new constants above here */ |
| 702 | ETH_SS_COUNT | 704 | ETH_SS_COUNT |
| @@ -700,6 +700,7 @@ enum { · 699 unmodified lines | |||
| 700 | ETHTOOL_STATS_ETH_PHY, | 700 | ETHTOOL_STATS_ETH_PHY, |
| 701 | ETHTOOL_STATS_ETH_MAC, | 701 | ETHTOOL_STATS_ETH_MAC, |
| 702 | ETHTOOL_STATS_ETH_CTRL, | 702 | ETHTOOL_STATS_ETH_CTRL, |
| 703 | ETHTOOL_STATS_RMON, | ||
| 703 | 704 | ||
| 704 | /* add new constants above here */ | 705 | /* add new constants above here */ |
| 705 | __ETHTOOL_STATS_CNT | 706 | __ETHTOOL_STATS_CNT |
| @@ -714,6 +715,13 @@ enum { · 8 unmodified lines | |||
| 714 | 715 | ||
| 715 | ETHTOOL_A_STATS_GRP_STAT, /* nest */ | 716 | ETHTOOL_A_STATS_GRP_STAT, /* nest */ |
| 716 | 717 | ||
| 718 | ETHTOOL_A_STATS_GRP_HIST_RX, /* nest */ | ||
| 719 | ETHTOOL_A_STATS_GRP_HIST_TX, /* nest */ | ||
| 720 | |||
| 721 | ETHTOOL_A_STATS_GRP_HIST_BKT_LOW, /* u32 */ | ||
| 722 | ETHTOOL_A_STATS_GRP_HIST_BKT_HI, /* u32 */ | ||
| 723 | ETHTOOL_A_STATS_GRP_HIST_VAL, /* u64 */ | ||
| 724 | |||
| 717 | /* add new constants above here */ | 725 | /* add new constants above here */ |
| 718 | __ETHTOOL_A_STATS_GRP_CNT, | 726 | __ETHTOOL_A_STATS_GRP_CNT, |
| 719 | ETHTOOL_A_STATS_GRP_MAX = (__ETHTOOL_A_STATS_CNT - 1) | 727 | ETHTOOL_A_STATS_GRP_MAX = (__ETHTOOL_A_STATS_CNT - 1) |
| @@ -793,6 +801,21 @@ enum { · 73 unmodified lines | |||
| 793 | ETHTOOL_A_STATS_ETH_CTRL_MAX = (__ETHTOOL_A_STATS_ETH_CTRL_CNT - 1) | 801 | ETHTOOL_A_STATS_ETH_CTRL_MAX = (__ETHTOOL_A_STATS_ETH_CTRL_CNT - 1) |
| 794 | }; | 802 | }; |
| 795 | 803 | ||
| 804 | enum { | ||
| 805 | /* etherStatsUndersizePkts */ | ||
| 806 | ETHTOOL_A_STATS_RMON_UNDERSIZE, | ||
| 807 | /* etherStatsOversizePkts */ | ||
| 808 | ETHTOOL_A_STATS_RMON_OVERSIZE, | ||
| 809 | /* etherStatsFragments */ | ||
| 810 | ETHTOOL_A_STATS_RMON_FRAG, | ||
| 811 | /* etherStatsJabbers */ | ||
| 812 | ETHTOOL_A_STATS_RMON_JABBER, | ||
| 813 | |||
| 814 | /* add new constants above here */ | ||
| 815 | __ETHTOOL_A_STATS_RMON_CNT, | ||
| 816 | ETHTOOL_A_STATS_RMON_MAX = (__ETHTOOL_A_STATS_RMON_CNT - 1) | ||
| 817 | }; | ||
| 818 | |||
| 796 | /* generic netlink info */ | 819 | /* generic netlink info */ |
| 797 | #define ETHTOOL_GENL_NAME "ethtool" | 820 | #define ETHTOOL_GENL_NAME "ethtool" |
| 798 | #define ETHTOOL_GENL_VERSION 1 | 821 | #define ETHTOOL_GENL_VERSION 1 |
| @@ -405,5 +405,6 @@ extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN]; · 404 unmodified lines | |||
| 405 | extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN]; | 405 | extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN]; |
| 406 | extern const char stats_eth_mac_names[__ETHTOOL_A_STATS_ETH_MAC_CNT][ETH_GSTRING_LEN]; | 406 | extern const char stats_eth_mac_names[__ETHTOOL_A_STATS_ETH_MAC_CNT][ETH_GSTRING_LEN]; |
| 407 | extern const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN]; | 407 | extern const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN]; |
| 408 | extern const char stats_rmon_names[__ETHTOOL_A_STATS_RMON_CNT][ETH_GSTRING_LEN]; | ||
| 408 | 409 | ||
| 409 | #endif /* _NET_ETHTOOL_NETLINK_H */ | 410 | #endif /* _NET_ETHTOOL_NETLINK_H */ |
| @@ -17,6 +17,8 @@ struct stats_reply_data { · 16 unmodified lines | |||
| 17 | struct ethtool_eth_phy_stats phy_stats; | 17 | struct ethtool_eth_phy_stats phy_stats; |
| 18 | struct ethtool_eth_mac_stats mac_stats; | 18 | struct ethtool_eth_mac_stats mac_stats; |
| 19 | struct ethtool_eth_ctrl_stats ctrl_stats; | 19 | struct ethtool_eth_ctrl_stats ctrl_stats; |
| 20 | struct ethtool_rmon_stats rmon_stats; | ||
| 21 | const struct ethtool_rmon_hist_range *rmon_ranges; | ||
| 20 | }; | 22 | }; |
| 21 | 23 | ||
| 22 | #define STATS_REPDATA(__reply_base) \ | 24 | #define STATS_REPDATA(__reply_base) \ |
| @@ -26,6 +28,7 @@ const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = { · 3 unmodified lines | |||
| 26 | [ETHTOOL_STATS_ETH_PHY] = "eth-phy", | 28 | [ETHTOOL_STATS_ETH_PHY] = "eth-phy", |
| 27 | [ETHTOOL_STATS_ETH_MAC] = "eth-mac", | 29 | [ETHTOOL_STATS_ETH_MAC] = "eth-mac", |
| 28 | [ETHTOOL_STATS_ETH_CTRL] = "eth-ctrl", | 30 | [ETHTOOL_STATS_ETH_CTRL] = "eth-ctrl", |
| 31 | [ETHTOOL_STATS_RMON] = "rmon", | ||
| 29 | }; | 32 | }; |
| 30 | 33 | ||
| 31 | const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN] = { | 34 | const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN] = { |
| @@ -63,6 +66,13 @@ const char stats_eth_ctrl_names[__ETHTOOL_A_STATS_ETH_CTRL_CNT][ETH_GSTRING_LEN] · 31 unmodified lines | |||
| 63 | [ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP] = "UnsupportedOpcodesReceived", | 66 | [ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP] = "UnsupportedOpcodesReceived", |
| 64 | }; | 67 | }; |
| 65 | 68 | ||
| 69 | const char stats_rmon_names[__ETHTOOL_A_STATS_RMON_CNT][ETH_GSTRING_LEN] = { | ||
| 70 | [ETHTOOL_A_STATS_RMON_UNDERSIZE] = "etherStatsUndersizePkts", | ||
| 71 | [ETHTOOL_A_STATS_RMON_OVERSIZE] = "etherStatsOversizePkts", | ||
| 72 | [ETHTOOL_A_STATS_RMON_FRAG] = "etherStatsFragments", | ||
| 73 | [ETHTOOL_A_STATS_RMON_JABBER] = "etherStatsJabbers", | ||
| 74 | }; | ||
| 75 | |||
| 66 | const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_GROUPS + 1] = { | 76 | const struct nla_policy ethnl_stats_get_policy[ETHTOOL_A_STATS_GROUPS + 1] = { |
| 67 | [ETHTOOL_A_STATS_HEADER] = | 77 | [ETHTOOL_A_STATS_HEADER] = |
| 68 | NLA_POLICY_NESTED(ethnl_header_policy), | 78 | NLA_POLICY_NESTED(ethnl_header_policy), |
| @@ -107,6 +117,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base, · 38 unmodified lines | |||
| 107 | memset(&data->phy_stats, 0xff, sizeof(data->phy_stats)); | 117 | memset(&data->phy_stats, 0xff, sizeof(data->phy_stats)); |
| 108 | memset(&data->mac_stats, 0xff, sizeof(data->mac_stats)); | 118 | memset(&data->mac_stats, 0xff, sizeof(data->mac_stats)); |
| 109 | memset(&data->ctrl_stats, 0xff, sizeof(data->mac_stats)); | 119 | memset(&data->ctrl_stats, 0xff, sizeof(data->mac_stats)); |
| 120 | memset(&data->rmon_stats, 0xff, sizeof(data->rmon_stats)); | ||
| 110 | 121 | ||
| 111 | if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) && | 122 | if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) && |
| 112 | dev->ethtool_ops->get_eth_phy_stats) | 123 | dev->ethtool_ops->get_eth_phy_stats) |
| @@ -117,6 +128,10 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base, · 4 unmodified lines | |||
| 117 | if (test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask) && | 128 | if (test_bit(ETHTOOL_STATS_ETH_CTRL, req_info->stat_mask) && |
| 118 | dev->ethtool_ops->get_eth_ctrl_stats) | 129 | dev->ethtool_ops->get_eth_ctrl_stats) |
| 119 | dev->ethtool_ops->get_eth_ctrl_stats(dev, &data->ctrl_stats); | 130 | dev->ethtool_ops->get_eth_ctrl_stats(dev, &data->ctrl_stats); |
| 131 | if (test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask) && | ||
| 132 | dev->ethtool_ops->get_rmon_stats) | ||
| 133 | dev->ethtool_ops->get_rmon_stats(dev, &data->rmon_stats, | ||
| 134 | &data->rmon_ranges); | ||
| 120 | 135 | ||
| 121 | ethnl_ops_complete(dev); | 136 | ethnl_ops_complete(dev); |
| 122 | return 0; | 137 | return 0; |
| @@ -141,6 +156,16 @@ static int stats_reply_size(const struct ethnl_req_info *req_base, · 18 unmodified lines | |||
| 141 | n_stats += sizeof(struct ethtool_eth_ctrl_stats) / sizeof(u64); | 156 | n_stats += sizeof(struct ethtool_eth_ctrl_stats) / sizeof(u64); |
| 142 | n_grps++; | 157 | n_grps++; |
| 143 | } | 158 | } |
| 159 | if (test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask)) { | ||
| 160 | n_stats += sizeof(struct ethtool_rmon_stats) / sizeof(u64); | ||
| 161 | n_grps++; | ||
| 162 | /* Above includes the space for _A_STATS_GRP_HIST_VALs */ | ||
| 163 | |||
| 164 | len += (nla_total_size(0) + /* _A_STATS_GRP_HIST */ | ||
| 165 | nla_total_size(4) + /* _A_STATS_GRP_HIST_BKT_LOW */ | ||
| 166 | nla_total_size(4)) * /* _A_STATS_GRP_HIST_BKT_HI */ | ||
| 167 | ETHTOOL_RMON_HIST_MAX * 2; | ||
| 168 | } | ||
| 144 | 169 | ||
| 145 | len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */ | 170 | len += n_grps * (nla_total_size(0) + /* _A_STATS_GRP */ |
| 146 | nla_total_size(4) + /* _A_STATS_GRP_ID */ | 171 | nla_total_size(4) + /* _A_STATS_GRP_ID */ |
| @@ -258,6 +283,65 @@ static int stats_put_ctrl_stats(struct sk_buff *skb, · 111 unmodified lines | |||
| 258 | return 0; | 283 | return 0; |
| 259 | } | 284 | } |
| 260 | 285 | ||
| 286 | static int stats_put_rmon_hist(struct sk_buff *skb, u32 attr, const u64 *hist, | ||
| 287 | const struct ethtool_rmon_hist_range *ranges) | ||
| 288 | { | ||
| 289 | struct nlattr *nest; | ||
| 290 | int i; | ||
| 291 | |||
| 292 | if (!ranges) | ||
| 293 | return 0; | ||
| 294 | |||
| 295 | for (i = 0; i < ETHTOOL_RMON_HIST_MAX; i++) { | ||
| 296 | if (!ranges[i].low && !ranges[i].high) | ||
| 297 | break; | ||
| 298 | if (hist[i] == ETHTOOL_STAT_NOT_SET) | ||
| 299 | continue; | ||
| 300 | |||
| 301 | nest = nla_nest_start(skb, attr); | ||
| 302 | if (!nest) | ||
| 303 | return -EMSGSIZE; | ||
| 304 | |||
| 305 | if (nla_put_u32(skb, ETHTOOL_A_STATS_GRP_HIST_BKT_LOW, | ||
| 306 | ranges[i].low) || | ||
| 307 | nla_put_u32(skb, ETHTOOL_A_STATS_GRP_HIST_BKT_HI, | ||
| 308 | ranges[i].high) || | ||
| 309 | nla_put_u64_64bit(skb, ETHTOOL_A_STATS_GRP_HIST_VAL, | ||
| 310 | hist[i], ETHTOOL_A_STATS_GRP_PAD)) | ||
| 311 | goto err_cancel_hist; | ||
| 312 | |||
| 313 | nla_nest_end(skb, nest); | ||
| 314 | } | ||
| 315 | |||
| 316 | return 0; | ||
| 317 | |||
| 318 | err_cancel_hist: | ||
| 319 | nla_nest_cancel(skb, nest); | ||
| 320 | return -EMSGSIZE; | ||
| 321 | } | ||
| 322 | |||
| 323 | static int stats_put_rmon_stats(struct sk_buff *skb, | ||
| 324 | const struct stats_reply_data *data) | ||
| 325 | { | ||
| 326 | if (stats_put_rmon_hist(skb, ETHTOOL_A_STATS_GRP_HIST_RX, | ||
| 327 | data->rmon_stats.hist, data->rmon_ranges) || | ||
| 328 | stats_put_rmon_hist(skb, ETHTOOL_A_STATS_GRP_HIST_TX, | ||
| 329 | data->rmon_stats.hist_tx, data->rmon_ranges)) | ||
| 330 | return -EMSGSIZE; | ||
| 331 | |||
| 332 | if (stat_put(skb, ETHTOOL_A_STATS_RMON_UNDERSIZE, | ||
| 333 | data->rmon_stats.undersize_pkts) || | ||
| 334 | stat_put(skb, ETHTOOL_A_STATS_RMON_OVERSIZE, | ||
| 335 | data->rmon_stats.oversize_pkts) || | ||
| 336 | stat_put(skb, ETHTOOL_A_STATS_RMON_FRAG, | ||
| 337 | data->rmon_stats.fragments) || | ||
| 338 | stat_put(skb, ETHTOOL_A_STATS_RMON_JABBER, | ||
| 339 | data->rmon_stats.jabbers)) | ||
| 340 | return -EMSGSIZE; | ||
| 341 | |||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 261 | static int stats_put_stats(struct sk_buff *skb, | 345 | static int stats_put_stats(struct sk_buff *skb, |
| 262 | const struct stats_reply_data *data, | 346 | const struct stats_reply_data *data, |
| 263 | u32 id, u32 ss_id, | 347 | u32 id, u32 ss_id, |
| @@ -305,6 +389,9 @@ static int stats_fill_reply(struct sk_buff *skb, · 41 unmodified lines | |||
| 305 | ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_CTRL, | 389 | ret = stats_put_stats(skb, data, ETHTOOL_STATS_ETH_CTRL, |
| 306 | ETH_SS_STATS_ETH_CTRL, | 390 | ETH_SS_STATS_ETH_CTRL, |
| 307 | stats_put_ctrl_stats); | 391 | stats_put_ctrl_stats); |
| 392 | if (!ret && test_bit(ETHTOOL_STATS_RMON, req_info->stat_mask)) | ||
| 393 | ret = stats_put_stats(skb, data, ETHTOOL_STATS_RMON, | ||
| 394 | ETH_SS_STATS_RMON, stats_put_rmon_stats); | ||
| 308 | 395 | ||
| 309 | return ret; | 396 | return ret; |
| 310 | } | 397 | } |
| @@ -100,6 +100,11 @@ static const struct strset_info info_template[] = { · 99 unmodified lines | |||
| 100 | .count = __ETHTOOL_A_STATS_ETH_CTRL_CNT, | 100 | .count = __ETHTOOL_A_STATS_ETH_CTRL_CNT, |
| 101 | .strings = stats_eth_ctrl_names, | 101 | .strings = stats_eth_ctrl_names, |
| 102 | }, | 102 | }, |
| 103 | [ETH_SS_STATS_RMON] = { | ||
| 104 | .per_dev = false, | ||
| 105 | .count = __ETHTOOL_A_STATS_RMON_CNT, | ||
| 106 | .strings = stats_rmon_names, | ||
| 107 | }, | ||
| 103 | }; | 108 | }; |
| 104 | 109 | ||
| 105 | struct strset_req_info { | 110 | struct strset_req_info { |