xref: /aosp_15_r20/external/bcc/tools/virtiostat.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports
3*387f9dfdSAndroid Build Coastguard Worker#
4*387f9dfdSAndroid Build Coastguard Worker# virtiostat    Show virtio devices input/output statistics.
5*387f9dfdSAndroid Build Coastguard Worker#               For Linux, uses BCC, eBPF.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: virtiostat [-h] [-T] [-D] [-d DRIVER] [-n DEVNAME] [INTERVAL] [COUNT]
8*387f9dfdSAndroid Build Coastguard Worker#
9*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2021 zhenwei pi
10*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
11*387f9dfdSAndroid Build Coastguard Worker#
12*387f9dfdSAndroid Build Coastguard Worker# 13-Feb-2021  zhenwei pi  Created this.
13*387f9dfdSAndroid Build Coastguard Worker
14*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
15*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
16*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime
17*387f9dfdSAndroid Build Coastguard Workerimport argparse
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Worker# arguments
20*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
21*387f9dfdSAndroid Build Coastguard Worker    ./virtiostat                 # print 3(default) second summaries
22*387f9dfdSAndroid Build Coastguard Worker    ./virtiostat  1  10          # print 1 second summaries, 10 times
23*387f9dfdSAndroid Build Coastguard Worker    ./virtiostat -T              # show timestamps
24*387f9dfdSAndroid Build Coastguard Worker    ./virtiostat -d virtio_blk   # only show virtio block devices
25*387f9dfdSAndroid Build Coastguard Worker    ./virtiostat -n virtio0      # only show virtio0 device
26*387f9dfdSAndroid Build Coastguard Worker    ./virtiostat -D              # show debug bpf text
27*387f9dfdSAndroid Build Coastguard Worker"""
28*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
29*387f9dfdSAndroid Build Coastguard Worker    description="Show virtio devices input/output statistics",
30*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
31*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
32*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("interval", nargs="?", default=3,
33*387f9dfdSAndroid Build Coastguard Worker    help="output interval, in seconds")
34*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("count", nargs="?", default=99999999,
35*387f9dfdSAndroid Build Coastguard Worker    help="number of outputs")
36*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--timestamp", action="store_true",
37*387f9dfdSAndroid Build Coastguard Worker    help="show timestamp on output")
38*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-d", "--driver",
39*387f9dfdSAndroid Build Coastguard Worker    help="filter for driver name")
40*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-n", "--devname",
41*387f9dfdSAndroid Build Coastguard Worker    help="filter for device name")
42*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-D", "--debug", action="store_true",
43*387f9dfdSAndroid Build Coastguard Worker    help="print BPF program before starting (for debugging purposes)")
44*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
45*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
46*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
47*387f9dfdSAndroid Build Coastguard Worker
48*387f9dfdSAndroid Build Coastguard Worker# define BPF program
49*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
50*387f9dfdSAndroid Build Coastguard Worker#include <linux/virtio.h>
51*387f9dfdSAndroid Build Coastguard Worker#include <bcc/proto.h>
52*387f9dfdSAndroid Build Coastguard Worker
53*387f9dfdSAndroid Build Coastguard Worker/* typically virtio scsi has max SGs of 6 */
54*387f9dfdSAndroid Build Coastguard Worker#define VIRTIO_MAX_SGS  6
55*387f9dfdSAndroid Build Coastguard Worker/* typically virtio blk has max SEG of 128 */
56*387f9dfdSAndroid Build Coastguard Worker#define SG_MAX          128
57*387f9dfdSAndroid Build Coastguard Worker
58*387f9dfdSAndroid Build Coastguard Worker/* local strcmp function, max length 16 to protect instruction loops */
59*387f9dfdSAndroid Build Coastguard Worker#define CMPMAX	16
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard Workerstatic int local_strcmp(const char *cs, const char *ct)
62*387f9dfdSAndroid Build Coastguard Worker{
63*387f9dfdSAndroid Build Coastguard Worker    int len = 0;
64*387f9dfdSAndroid Build Coastguard Worker    unsigned char c1, c2;
65*387f9dfdSAndroid Build Coastguard Worker
66*387f9dfdSAndroid Build Coastguard Worker    while (len++ < CMPMAX) {
67*387f9dfdSAndroid Build Coastguard Worker        c1 = *cs++;
68*387f9dfdSAndroid Build Coastguard Worker        c2 = *ct++;
69*387f9dfdSAndroid Build Coastguard Worker        if (c1 != c2)
70*387f9dfdSAndroid Build Coastguard Worker            return c1 < c2 ? -1 : 1;
71*387f9dfdSAndroid Build Coastguard Worker        if (!c1)
72*387f9dfdSAndroid Build Coastguard Worker            break;
73*387f9dfdSAndroid Build Coastguard Worker    }
74*387f9dfdSAndroid Build Coastguard Worker    return 0;
75*387f9dfdSAndroid Build Coastguard Worker}
76*387f9dfdSAndroid Build Coastguard Worker
77*387f9dfdSAndroid Build Coastguard Workertypedef struct virtio_stat {
78*387f9dfdSAndroid Build Coastguard Worker    char driver[16];
79*387f9dfdSAndroid Build Coastguard Worker    char dev[12];
80*387f9dfdSAndroid Build Coastguard Worker    char vqname[12];
81*387f9dfdSAndroid Build Coastguard Worker    u32 in_sgs;
82*387f9dfdSAndroid Build Coastguard Worker    u32 out_sgs;
83*387f9dfdSAndroid Build Coastguard Worker    u64 in_bw;
84*387f9dfdSAndroid Build Coastguard Worker    u64 out_bw;
85*387f9dfdSAndroid Build Coastguard Worker} virtio_stat_t;
86*387f9dfdSAndroid Build Coastguard Worker
87*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(stats, u64, virtio_stat_t);
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Workerstatic struct scatterlist *__sg_next(struct scatterlist *sgp)
90*387f9dfdSAndroid Build Coastguard Worker{
91*387f9dfdSAndroid Build Coastguard Worker    struct scatterlist sg;
92*387f9dfdSAndroid Build Coastguard Worker
93*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&sg, sizeof(sg), sgp);
94*387f9dfdSAndroid Build Coastguard Worker    if (sg_is_last(&sg))
95*387f9dfdSAndroid Build Coastguard Worker        return NULL;
96*387f9dfdSAndroid Build Coastguard Worker
97*387f9dfdSAndroid Build Coastguard Worker    sgp++;
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&sg, sizeof(sg), sgp);
100*387f9dfdSAndroid Build Coastguard Worker    if (unlikely(sg_is_chain(&sg)))
101*387f9dfdSAndroid Build Coastguard Worker        sgp = sg_chain_ptr(&sg);
102*387f9dfdSAndroid Build Coastguard Worker
103*387f9dfdSAndroid Build Coastguard Worker    return sgp;
104*387f9dfdSAndroid Build Coastguard Worker}
105*387f9dfdSAndroid Build Coastguard Worker
106*387f9dfdSAndroid Build Coastguard Workerstatic u64 count_len(struct scatterlist **sgs, unsigned int num)
107*387f9dfdSAndroid Build Coastguard Worker{
108*387f9dfdSAndroid Build Coastguard Worker    u64 length = 0;
109*387f9dfdSAndroid Build Coastguard Worker    unsigned int i, n;
110*387f9dfdSAndroid Build Coastguard Worker    struct scatterlist *sgp = NULL;
111*387f9dfdSAndroid Build Coastguard Worker
112*387f9dfdSAndroid Build Coastguard Worker    for (i = 0; (i < VIRTIO_MAX_SGS) && (i < num); i++) {
113*387f9dfdSAndroid Build Coastguard Worker        for (n = 0, sgp = sgs[i]; sgp && (n < SG_MAX); sgp = __sg_next(sgp)) {
114*387f9dfdSAndroid Build Coastguard Worker            length += sgp->length;
115*387f9dfdSAndroid Build Coastguard Worker            n++;
116*387f9dfdSAndroid Build Coastguard Worker        }
117*387f9dfdSAndroid Build Coastguard Worker
118*387f9dfdSAndroid Build Coastguard Worker        /* Suggested by Yonghong Song:
119*387f9dfdSAndroid Build Coastguard Worker         * IndVarSimplifyPass with clang 12 may cause verifier failure:
120*387f9dfdSAndroid Build Coastguard Worker         *   ; for (i = 0; (i < VIRTIO_MAX_SGS) && (i < num); i++) { // Line  60
121*387f9dfdSAndroid Build Coastguard Worker         *   90:   15 08 15 00 00 00 00 00 if r8 == 0 goto +21
122*387f9dfdSAndroid Build Coastguard Worker         *   91:   bf 81 00 00 00 00 00 00 r1 = r8
123*387f9dfdSAndroid Build Coastguard Worker         *   92:   07 01 00 00 ff ff ff ff r1 += -1
124*387f9dfdSAndroid Build Coastguard Worker         *   93:   67 01 00 00 20 00 00 00 r1 <<= 32
125*387f9dfdSAndroid Build Coastguard Worker         *   94:   77 01 00 00 20 00 00 00 r1 >>= 32
126*387f9dfdSAndroid Build Coastguard Worker         *   95:   b7 02 00 00 05 00 00 00 r2 = 5
127*387f9dfdSAndroid Build Coastguard Worker         *   96:   2d 12 01 00 00 00 00 00 if r2 > r1 goto +1
128*387f9dfdSAndroid Build Coastguard Worker         *   97:   b7 08 00 00 06 00 00 00 r8 = 6
129*387f9dfdSAndroid Build Coastguard Worker         *   98:   b7 02 00 00 00 00 00 00 r2 = 0
130*387f9dfdSAndroid Build Coastguard Worker         *   99:   b7 09 00 00 00 00 00 00 r9 = 0
131*387f9dfdSAndroid Build Coastguard Worker         *  100:   7b 8a 68 ff 00 00 00 00 *(u64 *)(r10 - 152) = r8
132*387f9dfdSAndroid Build Coastguard Worker         *  101:   05 00 35 00 00 00 00 00 goto +53
133*387f9dfdSAndroid Build Coastguard Worker         * Note that r1 is refined by r8 is saved to stack for later use.
134*387f9dfdSAndroid Build Coastguard Worker         * This will give verifier u64_max loop bound and eventually cause
135*387f9dfdSAndroid Build Coastguard Worker         * verification failure. Workaround with the below asm code.
136*387f9dfdSAndroid Build Coastguard Worker         */
137*387f9dfdSAndroid Build Coastguard Worker#if __clang_major__ >= 7
138*387f9dfdSAndroid Build Coastguard Worker        asm volatile("" : "=r"(i) : "0"(i));
139*387f9dfdSAndroid Build Coastguard Worker#endif
140*387f9dfdSAndroid Build Coastguard Worker    }
141*387f9dfdSAndroid Build Coastguard Worker
142*387f9dfdSAndroid Build Coastguard Worker    return length;
143*387f9dfdSAndroid Build Coastguard Worker}
144*387f9dfdSAndroid Build Coastguard Worker
145*387f9dfdSAndroid Build Coastguard Workerstatic void record(struct virtqueue *vq, struct scatterlist **sgs,
146*387f9dfdSAndroid Build Coastguard Worker                   unsigned int out_sgs, unsigned int in_sgs)
147*387f9dfdSAndroid Build Coastguard Worker{
148*387f9dfdSAndroid Build Coastguard Worker    virtio_stat_t newvs = {0};
149*387f9dfdSAndroid Build Coastguard Worker    virtio_stat_t *vs;
150*387f9dfdSAndroid Build Coastguard Worker    u64 key = (u64)vq;
151*387f9dfdSAndroid Build Coastguard Worker    u64 in_bw = 0;
152*387f9dfdSAndroid Build Coastguard Worker
153*387f9dfdSAndroid Build Coastguard Worker    DRIVERFILTER
154*387f9dfdSAndroid Build Coastguard Worker    DEVNAMEFILTER
155*387f9dfdSAndroid Build Coastguard Worker
156*387f9dfdSAndroid Build Coastguard Worker    /* Workaround: separate two count_len() calls, one here and the
157*387f9dfdSAndroid Build Coastguard Worker     * other below. Otherwise, compiler may generate some spills which
158*387f9dfdSAndroid Build Coastguard Worker     * harms verifier pruning. This happens in llvm12, but not llvm4.
159*387f9dfdSAndroid Build Coastguard Worker     * Below code works on both cases.
160*387f9dfdSAndroid Build Coastguard Worker     */
161*387f9dfdSAndroid Build Coastguard Worker    if (in_sgs)
162*387f9dfdSAndroid Build Coastguard Worker        in_bw = count_len(sgs + out_sgs, in_sgs);
163*387f9dfdSAndroid Build Coastguard Worker
164*387f9dfdSAndroid Build Coastguard Worker    vs = stats.lookup(&key);
165*387f9dfdSAndroid Build Coastguard Worker    if (!vs) {
166*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel_str(newvs.driver, sizeof(newvs.driver), vq->vdev->dev.driver->name);
167*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel_str(newvs.dev, sizeof(newvs.dev), vq->vdev->dev.kobj.name);
168*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel_str(newvs.vqname, sizeof(newvs.vqname), vq->name);
169*387f9dfdSAndroid Build Coastguard Worker        newvs.out_sgs = out_sgs;
170*387f9dfdSAndroid Build Coastguard Worker        newvs.in_sgs = in_sgs;
171*387f9dfdSAndroid Build Coastguard Worker        if (out_sgs)
172*387f9dfdSAndroid Build Coastguard Worker            newvs.out_bw = count_len(sgs, out_sgs);
173*387f9dfdSAndroid Build Coastguard Worker        newvs.in_bw = in_bw;
174*387f9dfdSAndroid Build Coastguard Worker        stats.update(&key, &newvs);
175*387f9dfdSAndroid Build Coastguard Worker    } else {
176*387f9dfdSAndroid Build Coastguard Worker        vs->out_sgs += out_sgs;
177*387f9dfdSAndroid Build Coastguard Worker        vs->in_sgs += in_sgs;
178*387f9dfdSAndroid Build Coastguard Worker        if (out_sgs)
179*387f9dfdSAndroid Build Coastguard Worker            vs->out_bw += count_len(sgs, out_sgs);
180*387f9dfdSAndroid Build Coastguard Worker        vs->in_bw += in_bw;
181*387f9dfdSAndroid Build Coastguard Worker    }
182*387f9dfdSAndroid Build Coastguard Worker}
183*387f9dfdSAndroid Build Coastguard Worker
184*387f9dfdSAndroid Build Coastguard Workerint trace_virtqueue_add_sgs(struct pt_regs *ctx, struct virtqueue *vq,
185*387f9dfdSAndroid Build Coastguard Worker                            struct scatterlist **sgs, unsigned int out_sgs,
186*387f9dfdSAndroid Build Coastguard Worker                            unsigned int in_sgs, void *data, gfp_t gfp)
187*387f9dfdSAndroid Build Coastguard Worker
188*387f9dfdSAndroid Build Coastguard Worker{
189*387f9dfdSAndroid Build Coastguard Worker    record(vq, sgs, out_sgs, in_sgs);
190*387f9dfdSAndroid Build Coastguard Worker
191*387f9dfdSAndroid Build Coastguard Worker    return 0;
192*387f9dfdSAndroid Build Coastguard Worker}
193*387f9dfdSAndroid Build Coastguard Worker
194*387f9dfdSAndroid Build Coastguard Workerint trace_virtqueue_add_outbuf(struct pt_regs *ctx, struct virtqueue *vq,
195*387f9dfdSAndroid Build Coastguard Worker                              struct scatterlist *sg, unsigned int num,
196*387f9dfdSAndroid Build Coastguard Worker                              void *data, gfp_t gfp)
197*387f9dfdSAndroid Build Coastguard Worker{
198*387f9dfdSAndroid Build Coastguard Worker    record(vq, &sg, 1, 0);
199*387f9dfdSAndroid Build Coastguard Worker
200*387f9dfdSAndroid Build Coastguard Worker    return 0;
201*387f9dfdSAndroid Build Coastguard Worker}
202*387f9dfdSAndroid Build Coastguard Worker
203*387f9dfdSAndroid Build Coastguard Workerint trace_virtqueue_add_inbuf(struct pt_regs *ctx, struct virtqueue *vq,
204*387f9dfdSAndroid Build Coastguard Worker                             struct scatterlist *sg, unsigned int num,
205*387f9dfdSAndroid Build Coastguard Worker                             void *data, gfp_t gfp)
206*387f9dfdSAndroid Build Coastguard Worker{
207*387f9dfdSAndroid Build Coastguard Worker    record(vq, &sg, 0, 1);
208*387f9dfdSAndroid Build Coastguard Worker
209*387f9dfdSAndroid Build Coastguard Worker    return 0;
210*387f9dfdSAndroid Build Coastguard Worker}
211*387f9dfdSAndroid Build Coastguard Worker
212*387f9dfdSAndroid Build Coastguard Workerint trace_virtqueue_add_inbuf_ctx(struct pt_regs *ctx, struct virtqueue *vq,
213*387f9dfdSAndroid Build Coastguard Worker                                  struct scatterlist *sg, unsigned int num,
214*387f9dfdSAndroid Build Coastguard Worker                                  void *data, void *_ctx, gfp_t gfp)
215*387f9dfdSAndroid Build Coastguard Worker{
216*387f9dfdSAndroid Build Coastguard Worker    record(vq, &sg, 0, 1);
217*387f9dfdSAndroid Build Coastguard Worker
218*387f9dfdSAndroid Build Coastguard Worker    return 0;
219*387f9dfdSAndroid Build Coastguard Worker}
220*387f9dfdSAndroid Build Coastguard Worker"""
221*387f9dfdSAndroid Build Coastguard Worker
222*387f9dfdSAndroid Build Coastguard Worker# filter for driver name
223*387f9dfdSAndroid Build Coastguard Workerif args.driver:
224*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('DRIVERFILTER',
225*387f9dfdSAndroid Build Coastguard Worker        """char filter_driver[] = \"%s\";
226*387f9dfdSAndroid Build Coastguard Worker        char driver[16];
227*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel_str(driver, sizeof(driver), vq->vdev->dev.driver->name);
228*387f9dfdSAndroid Build Coastguard Worker        if (local_strcmp(filter_driver, driver))
229*387f9dfdSAndroid Build Coastguard Worker        return;""" % (args.driver))
230*387f9dfdSAndroid Build Coastguard Workerelse:
231*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('DRIVERFILTER', '')
232*387f9dfdSAndroid Build Coastguard Worker
233*387f9dfdSAndroid Build Coastguard Worker# filter for dev name
234*387f9dfdSAndroid Build Coastguard Workerif args.devname:
235*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('DEVNAMEFILTER',
236*387f9dfdSAndroid Build Coastguard Worker        """char filter_devname[] = \"%s\";
237*387f9dfdSAndroid Build Coastguard Worker        char devname[16];
238*387f9dfdSAndroid Build Coastguard Worker        bpf_probe_read_kernel_str(devname, sizeof(devname), vq->vdev->dev.kobj.name);
239*387f9dfdSAndroid Build Coastguard Worker        if (local_strcmp(filter_devname, devname))
240*387f9dfdSAndroid Build Coastguard Worker        return;""" % (args.devname))
241*387f9dfdSAndroid Build Coastguard Workerelse:
242*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('DEVNAMEFILTER', '')
243*387f9dfdSAndroid Build Coastguard Worker
244*387f9dfdSAndroid Build Coastguard Worker
245*387f9dfdSAndroid Build Coastguard Worker# debug mode: print bpf text
246*387f9dfdSAndroid Build Coastguard Workerif args.debug:
247*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
248*387f9dfdSAndroid Build Coastguard Worker
249*387f9dfdSAndroid Build Coastguard Worker# dump mode: print bpf text and exit
250*387f9dfdSAndroid Build Coastguard Workerif args.ebpf:
251*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
252*387f9dfdSAndroid Build Coastguard Worker    exit()
253*387f9dfdSAndroid Build Coastguard Worker
254*387f9dfdSAndroid Build Coastguard Worker# load BPF program
255*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
256*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="virtqueue_add_sgs", fn_name="trace_virtqueue_add_sgs")
257*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="virtqueue_add_outbuf", fn_name="trace_virtqueue_add_outbuf")
258*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="virtqueue_add_inbuf", fn_name="trace_virtqueue_add_inbuf")
259*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="virtqueue_add_inbuf_ctx", fn_name="trace_virtqueue_add_inbuf_ctx")
260*387f9dfdSAndroid Build Coastguard Worker
261*387f9dfdSAndroid Build Coastguard Workerprint("Tracing virtio devices statistics ... Hit Ctrl-C to end.")
262*387f9dfdSAndroid Build Coastguard Worker
263*387f9dfdSAndroid Build Coastguard Worker# start main loop
264*387f9dfdSAndroid Build Coastguard Workerexiting = 0 if args.interval else 1
265*387f9dfdSAndroid Build Coastguard Workerseconds = 0
266*387f9dfdSAndroid Build Coastguard Workerwhile (1):
267*387f9dfdSAndroid Build Coastguard Worker    try:
268*387f9dfdSAndroid Build Coastguard Worker        sleep(int(args.interval))
269*387f9dfdSAndroid Build Coastguard Worker        seconds = seconds + int(args.interval)
270*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
271*387f9dfdSAndroid Build Coastguard Worker        exiting = 1
272*387f9dfdSAndroid Build Coastguard Worker
273*387f9dfdSAndroid Build Coastguard Worker    if args.timestamp:
274*387f9dfdSAndroid Build Coastguard Worker        print("%-8s\n" % strftime("%H:%M:%S"), end="")
275*387f9dfdSAndroid Build Coastguard Worker    else:
276*387f9dfdSAndroid Build Coastguard Worker        print("--------", end="\n")
277*387f9dfdSAndroid Build Coastguard Worker
278*387f9dfdSAndroid Build Coastguard Worker    print("%14s %8s %10s %7s %7s %14s %14s" % ("Driver", "Device", "VQ Name", "In SGs", "Out SGs", "In BW", "Out BW"))
279*387f9dfdSAndroid Build Coastguard Worker    stats = b.get_table("stats")
280*387f9dfdSAndroid Build Coastguard Worker    for k, v in sorted(stats.items(), key=lambda vs: vs[1].dev):
281*387f9dfdSAndroid Build Coastguard Worker        print("%14s %8s %10s %7d %7d %14d %14d" % (v.driver, v.dev, v.vqname, v.in_sgs, v.out_sgs, v.in_bw, v.out_bw))
282*387f9dfdSAndroid Build Coastguard Worker
283*387f9dfdSAndroid Build Coastguard Worker    stats.clear()
284*387f9dfdSAndroid Build Coastguard Worker
285*387f9dfdSAndroid Build Coastguard Worker    if exiting or seconds >= int(args.count):
286*387f9dfdSAndroid Build Coastguard Worker        exit()
287