Skip to content

Commit

Permalink
Merge branch 'add-tx-stop-wake-counters'
Browse files Browse the repository at this point in the history
Daniel Jurgens says:

====================
Add TX stop/wake counters

Several drivers provide TX stop and wake counters via ethtool stats. Add
those to the netdev queue stats, and use them in virtio_net.
====================

Link: https://lore.kernel.org/r/20240510201927.1821109-1-danielj@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed May 13, 2024
2 parents c084ebd + c39add9 commit e5a2802
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 3 deletions.
14 changes: 14 additions & 0 deletions Documentation/netlink/specs/netdev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,20 @@ attribute-sets:
Number of the packets dropped by the device due to the transmit
packets bitrate exceeding the device rate limit.
type: uint
-
name: tx-stop
doc: |
Number of times driver paused accepting new tx packets
from the stack to this queue, because the queue was full.
Note that if BQL is supported and enabled on the device
the networking stack will avoid queuing a lot of data at once.
type: uint
-
name: tx-wake
doc: |
Number of times driver re-started accepting send
requests to this queue from the stack.
type: uint

operations:
list:
Expand Down
28 changes: 26 additions & 2 deletions drivers/net/virtio_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ struct virtnet_sq_stats {
u64_stats_t xdp_tx_drops;
u64_stats_t kicks;
u64_stats_t tx_timeouts;
u64_stats_t stop;
u64_stats_t wake;
};

struct virtnet_rq_stats {
Expand Down Expand Up @@ -145,6 +147,8 @@ static const struct virtnet_stat_desc virtnet_rq_stats_desc[] = {
static const struct virtnet_stat_desc virtnet_sq_stats_desc_qstat[] = {
VIRTNET_SQ_STAT_QSTAT("packets", packets),
VIRTNET_SQ_STAT_QSTAT("bytes", bytes),
VIRTNET_SQ_STAT_QSTAT("stop", stop),
VIRTNET_SQ_STAT_QSTAT("wake", wake),
};

static const struct virtnet_stat_desc virtnet_rq_stats_desc_qstat[] = {
Expand Down Expand Up @@ -1014,6 +1018,9 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
*/
if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
netif_stop_subqueue(dev, qnum);
u64_stats_update_begin(&sq->stats.syncp);
u64_stats_inc(&sq->stats.stop);
u64_stats_update_end(&sq->stats.syncp);
if (use_napi) {
if (unlikely(!virtqueue_enable_cb_delayed(sq->vq)))
virtqueue_napi_schedule(&sq->napi, sq->vq);
Expand All @@ -1022,6 +1029,9 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
free_old_xmit(sq, false);
if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
netif_start_subqueue(dev, qnum);
u64_stats_update_begin(&sq->stats.syncp);
u64_stats_inc(&sq->stats.wake);
u64_stats_update_end(&sq->stats.syncp);
virtqueue_disable_cb(sq->vq);
}
}
Expand Down Expand Up @@ -2322,8 +2332,14 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
free_old_xmit(sq, true);
} while (unlikely(!virtqueue_enable_cb_delayed(sq->vq)));

if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS)
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) {
if (netif_tx_queue_stopped(txq)) {
u64_stats_update_begin(&sq->stats.syncp);
u64_stats_inc(&sq->stats.wake);
u64_stats_update_end(&sq->stats.syncp);
}
netif_tx_wake_queue(txq);
}

__netif_tx_unlock(txq);
}
Expand Down Expand Up @@ -2473,8 +2489,14 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
virtqueue_disable_cb(sq->vq);
free_old_xmit(sq, true);

if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS)
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) {
if (netif_tx_queue_stopped(txq)) {
u64_stats_update_begin(&sq->stats.syncp);
u64_stats_inc(&sq->stats.wake);
u64_stats_update_end(&sq->stats.syncp);
}
netif_tx_wake_queue(txq);
}

opaque = virtqueue_enable_cb_prepare(sq->vq);

Expand Down Expand Up @@ -4789,6 +4811,8 @@ static void virtnet_get_base_stats(struct net_device *dev,

tx->bytes = 0;
tx->packets = 0;
tx->stop = 0;
tx->wake = 0;

if (vi->device_stats_cap & VIRTIO_NET_STATS_TYPE_TX_BASIC) {
tx->hw_drops = 0;
Expand Down
3 changes: 3 additions & 0 deletions include/net/netdev_queues.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ struct netdev_queue_stats_tx {
u64 hw_gso_wire_bytes;

u64 hw_drop_ratelimits;

u64 stop;
u64 wake;
};

/**
Expand Down
2 changes: 2 additions & 0 deletions include/uapi/linux/netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ enum {
NETDEV_A_QSTATS_TX_HW_GSO_WIRE_PACKETS,
NETDEV_A_QSTATS_TX_HW_GSO_WIRE_BYTES,
NETDEV_A_QSTATS_TX_HW_DROP_RATELIMITS,
NETDEV_A_QSTATS_TX_STOP,
NETDEV_A_QSTATS_TX_WAKE,

__NETDEV_A_QSTATS_MAX,
NETDEV_A_QSTATS_MAX = (__NETDEV_A_QSTATS_MAX - 1)
Expand Down
4 changes: 3 additions & 1 deletion net/core/netdev-genl.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,9 @@ netdev_nl_stats_write_tx(struct sk_buff *rsp, struct netdev_queue_stats_tx *tx)
netdev_stat_put(rsp, NETDEV_A_QSTATS_TX_HW_GSO_BYTES, tx->hw_gso_bytes) ||
netdev_stat_put(rsp, NETDEV_A_QSTATS_TX_HW_GSO_WIRE_PACKETS, tx->hw_gso_wire_packets) ||
netdev_stat_put(rsp, NETDEV_A_QSTATS_TX_HW_GSO_WIRE_BYTES, tx->hw_gso_wire_bytes) ||
netdev_stat_put(rsp, NETDEV_A_QSTATS_TX_HW_DROP_RATELIMITS, tx->hw_drop_ratelimits))
netdev_stat_put(rsp, NETDEV_A_QSTATS_TX_HW_DROP_RATELIMITS, tx->hw_drop_ratelimits) ||
netdev_stat_put(rsp, NETDEV_A_QSTATS_TX_STOP, tx->stop) ||
netdev_stat_put(rsp, NETDEV_A_QSTATS_TX_WAKE, tx->wake))
return -EMSGSIZE;
return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions tools/include/uapi/linux/netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ enum {
NETDEV_A_QSTATS_TX_HW_GSO_WIRE_PACKETS,
NETDEV_A_QSTATS_TX_HW_GSO_WIRE_BYTES,
NETDEV_A_QSTATS_TX_HW_DROP_RATELIMITS,
NETDEV_A_QSTATS_TX_STOP,
NETDEV_A_QSTATS_TX_WAKE,

__NETDEV_A_QSTATS_MAX,
NETDEV_A_QSTATS_MAX = (__NETDEV_A_QSTATS_MAX - 1)
Expand Down

0 comments on commit e5a2802

Please sign in to comment.