@@ -708,25 +708,66 @@ netdev_nl_stats_by_queue(struct net_device *netdev, struct sk_buff *rsp,
708708 return 0 ;
709709}
710710
711+ /**
712+ * netdev_stat_queue_sum() - add up queue stats from range of queues
713+ * @netdev: net_device
714+ * @rx_start: index of the first Rx queue to query
715+ * @rx_end: index after the last Rx queue (first *not* to query)
716+ * @rx_sum: output Rx stats, should be already initialized
717+ * @tx_start: index of the first Tx queue to query
718+ * @tx_end: index after the last Tx queue (first *not* to query)
719+ * @tx_sum: output Tx stats, should be already initialized
720+ *
721+ * Add stats from [start, end) range of queue IDs to *x_sum structs.
722+ * The sum structs must be already initialized. Usually this
723+ * helper is invoked from the .get_base_stats callbacks of drivers
724+ * to account for stats of disabled queues. In that case the ranges
725+ * are usually [netdev->real_num_*x_queues, netdev->num_*x_queues).
726+ */
727+ void netdev_stat_queue_sum (struct net_device * netdev ,
728+ int rx_start , int rx_end ,
729+ struct netdev_queue_stats_rx * rx_sum ,
730+ int tx_start , int tx_end ,
731+ struct netdev_queue_stats_tx * tx_sum )
732+ {
733+ const struct netdev_stat_ops * ops ;
734+ struct netdev_queue_stats_rx rx ;
735+ struct netdev_queue_stats_tx tx ;
736+ int i ;
737+
738+ ops = netdev -> stat_ops ;
739+
740+ for (i = rx_start ; i < rx_end ; i ++ ) {
741+ memset (& rx , 0xff , sizeof (rx ));
742+ if (ops -> get_queue_stats_rx )
743+ ops -> get_queue_stats_rx (netdev , i , & rx );
744+ netdev_nl_stats_add (rx_sum , & rx , sizeof (rx ));
745+ }
746+ for (i = tx_start ; i < tx_end ; i ++ ) {
747+ memset (& tx , 0xff , sizeof (tx ));
748+ if (ops -> get_queue_stats_tx )
749+ ops -> get_queue_stats_tx (netdev , i , & tx );
750+ netdev_nl_stats_add (tx_sum , & tx , sizeof (tx ));
751+ }
752+ }
753+ EXPORT_SYMBOL (netdev_stat_queue_sum );
754+
711755static int
712756netdev_nl_stats_by_netdev (struct net_device * netdev , struct sk_buff * rsp ,
713757 const struct genl_info * info )
714758{
715- struct netdev_queue_stats_rx rx_sum , rx ;
716- struct netdev_queue_stats_tx tx_sum , tx ;
717- const struct netdev_stat_ops * ops ;
759+ struct netdev_queue_stats_rx rx_sum ;
760+ struct netdev_queue_stats_tx tx_sum ;
718761 void * hdr ;
719- int i ;
720762
721- ops = netdev -> stat_ops ;
722763 /* Netdev can't guarantee any complete counters */
723- if (!ops -> get_base_stats )
764+ if (!netdev -> stat_ops -> get_base_stats )
724765 return 0 ;
725766
726767 memset (& rx_sum , 0xff , sizeof (rx_sum ));
727768 memset (& tx_sum , 0xff , sizeof (tx_sum ));
728769
729- ops -> get_base_stats (netdev , & rx_sum , & tx_sum );
770+ netdev -> stat_ops -> get_base_stats (netdev , & rx_sum , & tx_sum );
730771
731772 /* The op was there, but nothing reported, don't bother */
732773 if (!memchr_inv (& rx_sum , 0xff , sizeof (rx_sum )) &&
@@ -739,18 +780,8 @@ netdev_nl_stats_by_netdev(struct net_device *netdev, struct sk_buff *rsp,
739780 if (nla_put_u32 (rsp , NETDEV_A_QSTATS_IFINDEX , netdev -> ifindex ))
740781 goto nla_put_failure ;
741782
742- for (i = 0 ; i < netdev -> real_num_rx_queues ; i ++ ) {
743- memset (& rx , 0xff , sizeof (rx ));
744- if (ops -> get_queue_stats_rx )
745- ops -> get_queue_stats_rx (netdev , i , & rx );
746- netdev_nl_stats_add (& rx_sum , & rx , sizeof (rx ));
747- }
748- for (i = 0 ; i < netdev -> real_num_tx_queues ; i ++ ) {
749- memset (& tx , 0xff , sizeof (tx ));
750- if (ops -> get_queue_stats_tx )
751- ops -> get_queue_stats_tx (netdev , i , & tx );
752- netdev_nl_stats_add (& tx_sum , & tx , sizeof (tx ));
753- }
783+ netdev_stat_queue_sum (netdev , 0 , netdev -> real_num_rx_queues , & rx_sum ,
784+ 0 , netdev -> real_num_tx_queues , & tx_sum );
754785
755786 if (netdev_nl_stats_write_rx (rsp , & rx_sum ) ||
756787 netdev_nl_stats_write_tx (rsp , & tx_sum ))
0 commit comments