@@ -17,6 +17,8 @@ struct stats_reply_data {
1717 struct ethtool_eth_phy_stats phy_stats ;
1818 struct ethtool_eth_mac_stats mac_stats ;
1919 struct ethtool_eth_ctrl_stats ctrl_stats ;
20+ struct ethtool_rmon_stats rmon_stats ;
21+ const struct ethtool_rmon_hist_range * rmon_ranges ;
2022};
2123
2224#define STATS_REPDATA (__reply_base ) \
@@ -26,6 +28,7 @@ const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN] = {
2628 [ETHTOOL_STATS_ETH_PHY ] = "eth-phy" ,
2729 [ETHTOOL_STATS_ETH_MAC ] = "eth-mac" ,
2830 [ETHTOOL_STATS_ETH_CTRL ] = "eth-ctrl" ,
31+ [ETHTOOL_STATS_RMON ] = "rmon" ,
2932};
3033
3134const 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]
6366 [ETHTOOL_A_STATS_ETH_CTRL_5_RX_UNSUP ] = "UnsupportedOpcodesReceived" ,
6467};
6568
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+
6676const struct nla_policy ethnl_stats_get_policy [ETHTOOL_A_STATS_GROUPS + 1 ] = {
6777 [ETHTOOL_A_STATS_HEADER ] =
6878 NLA_POLICY_NESTED (ethnl_header_policy ),
@@ -107,6 +117,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
107117 memset (& data -> phy_stats , 0xff , sizeof (data -> phy_stats ));
108118 memset (& data -> mac_stats , 0xff , sizeof (data -> mac_stats ));
109119 memset (& data -> ctrl_stats , 0xff , sizeof (data -> mac_stats ));
120+ memset (& data -> rmon_stats , 0xff , sizeof (data -> rmon_stats ));
110121
111122 if (test_bit (ETHTOOL_STATS_ETH_PHY , req_info -> stat_mask ) &&
112123 dev -> ethtool_ops -> get_eth_phy_stats )
@@ -117,6 +128,10 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
117128 if (test_bit (ETHTOOL_STATS_ETH_CTRL , req_info -> stat_mask ) &&
118129 dev -> ethtool_ops -> get_eth_ctrl_stats )
119130 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 );
120135
121136 ethnl_ops_complete (dev );
122137 return 0 ;
@@ -141,6 +156,16 @@ static int stats_reply_size(const struct ethnl_req_info *req_base,
141156 n_stats += sizeof (struct ethtool_eth_ctrl_stats ) / sizeof (u64 );
142157 n_grps ++ ;
143158 }
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+ }
144169
145170 len += n_grps * (nla_total_size (0 ) + /* _A_STATS_GRP */
146171 nla_total_size (4 ) + /* _A_STATS_GRP_ID */
@@ -258,6 +283,65 @@ static int stats_put_ctrl_stats(struct sk_buff *skb,
258283 return 0 ;
259284}
260285
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+
261345static int stats_put_stats (struct sk_buff * skb ,
262346 const struct stats_reply_data * data ,
263347 u32 id , u32 ss_id ,
@@ -305,6 +389,9 @@ static int stats_fill_reply(struct sk_buff *skb,
305389 ret = stats_put_stats (skb , data , ETHTOOL_STATS_ETH_CTRL ,
306390 ETH_SS_STATS_ETH_CTRL ,
307391 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 );
308395
309396 return ret ;
310397}
0 commit comments