Merge branch 'master' into next

Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
David Ahern 2019-12-11 17:13:49 +00:00
commit f39da545b6
25 changed files with 105 additions and 30 deletions

View File

@ -323,6 +323,7 @@ _tc_qdisc_options()
_tc_once_attr 'limit target tupdate alpha beta' _tc_once_attr 'limit target tupdate alpha beta'
_tc_one_of_list 'bytemode nobytemode' _tc_one_of_list 'bytemode nobytemode'
_tc_one_of_list 'ecn noecn' _tc_one_of_list 'ecn noecn'
_tc_one_of_list 'dq_rate_estimator no_dq_rate_estimator'
return 0 return 0
;; ;;
red) red)

View File

@ -94,5 +94,6 @@
#define ZSMALLOC_MAGIC 0x58295829 #define ZSMALLOC_MAGIC 0x58295829
#define DMA_BUF_MAGIC 0x444d4142 /* "DMAB" */ #define DMA_BUF_MAGIC 0x444d4142 /* "DMAB" */
#define Z3FOLD_MAGIC 0x33 #define Z3FOLD_MAGIC 0x33
#define PPC_CMM_MAGIC 0xc7571590
#endif /* __LINUX_MAGIC_H__ */ #endif /* __LINUX_MAGIC_H__ */

View File

@ -56,6 +56,7 @@ RT \- realtime
LS \- linkshare LS \- linkshare
UL \- upperlimit UL \- upperlimit
SC \- service curve SC \- service curve
.RE
.fi .fi
. .
.SH "BASICS OF HFSC" .SH "BASICS OF HFSC"

View File

@ -262,6 +262,7 @@ Preparing to flash
Flashing 100% Flashing 100%
.br .br
Flashing done Flashing done
.RE
.SH SEE ALSO .SH SEE ALSO
.BR devlink (8), .BR devlink (8),

View File

@ -116,6 +116,7 @@ Split the specified devlink port into four ports.
devlink port unsplit pci/0000:01:00.0/1 devlink port unsplit pci/0000:01:00.0/1
.RS 4 .RS 4
Unplit the specified previously split devlink port. Unplit the specified previously split devlink port.
.RE
.SH SEE ALSO .SH SEE ALSO
.BR devlink (8), .BR devlink (8),

View File

@ -119,6 +119,7 @@ Dump the snapshot taken from cr-space address region with ID 1
devlink region read pci/0000:00:05.0/cr-space snapshot 1 address 0x10 legth 16 devlink region read pci/0000:00:05.0/cr-space snapshot 1 address 0x10 legth 16
.RS 4 .RS 4
Read from address 0x10, 16 Bytes of snapshot ID 1 taken from cr-space address region Read from address 0x10, 16 Bytes of snapshot ID 1 taken from cr-space address region
.RE
.SH SEE ALSO .SH SEE ALSO
.BR devlink (8), .BR devlink (8),

View File

@ -66,6 +66,7 @@ Shows the resources of the specified devlink device.
devlink resource set pci/0000:01:00.0 /kvd/linear 98304 devlink resource set pci/0000:01:00.0 /kvd/linear 98304
.RS 4 .RS 4
Sets the size of the specified resource for the specified devlink device. Sets the size of the specified resource for the specified devlink device.
.RE
.SH SEE ALSO .SH SEE ALSO
.BR devlink (8), .BR devlink (8),

View File

@ -310,6 +310,7 @@ Show occupancy for specified port from the snapshot.
sudo devlink sb occupancy clearmax pci/0000:03:00.0 sudo devlink sb occupancy clearmax pci/0000:03:00.0
.RS 4 .RS 4
Clear watermarks for shared buffer of specified devlink device. Clear watermarks for shared buffer of specified devlink device.
.RE
.SH SEE ALSO .SH SEE ALSO

View File

@ -127,6 +127,7 @@ Show attributes and statistics of a specific packet trap group.
devlink trap set pci/0000:01:00.0 trap source_mac_is_multicast action trap devlink trap set pci/0000:01:00.0 trap source_mac_is_multicast action trap
.RS 4 .RS 4
Set the action of a specific packet trap to 'trap'. Set the action of a specific packet trap to 'trap'.
.RE
.SH SEE ALSO .SH SEE ALSO
.BR devlink (8), .BR devlink (8),

View File

@ -253,6 +253,7 @@ the prefix selecting the neighbour to query.
.TP .TP
.BI dev " NAME" .BI dev " NAME"
get neighbour entry attached to this device. get neighbour entry attached to this device.
.RE
.SH EXAMPLES .SH EXAMPLES
.PP .PP

View File

@ -130,7 +130,6 @@ create a blackhole nexthop
.TP .TP
ip nexthop delete id ID ip nexthop delete id ID
delete nexthop with given id. delete nexthop with given id.
.RE
.TP .TP
ip nexthop show ip nexthop show
@ -154,7 +153,6 @@ show only nexthop groups
ip nexthop flush ip nexthop flush
flushes nexthops selected by some criteria. Criteria options are the same flushes nexthops selected by some criteria. Criteria options are the same
as show. as show.
.RE
.TP .TP
ip nexthop get id ID ip nexthop get id ID

View File

@ -382,7 +382,6 @@ Bring up interface x.
.RE .RE
.PP .PP
ip link set x down ip link set x down
.RE
.RS 4 .RS 4
Bring down interface x. Bring down interface x.
.RE .RE

View File

@ -162,6 +162,7 @@ List all currently allocated MR's and their counters.
rdma statistic show mr mrn 6 rdma statistic show mr mrn 6
.RS 4 .RS 4
Dump a specific MR statistics with mrn 6. Dumps nothing if does not exists. Dump a specific MR statistics with mrn 6. Dumps nothing if does not exists.
.RE
.SH SEE ALSO .SH SEE ALSO
.BR rdma (8), .BR rdma (8),

View File

@ -161,6 +161,7 @@ tc -s filter show dev eth0
Sent 32890260 bytes 120441 pkt (dropped 0, overlimits 0 requeues 0) Sent 32890260 bytes 120441 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0 backlog 0b 0p requeues 0
.br .br
.RE
.SH SEE ALSO .SH SEE ALSO
.BR tc (8), .BR tc (8),
.BR tc-cake (8) .BR tc-cake (8)

View File

@ -21,6 +21,10 @@ int ] [
.B bytemode .B bytemode
| |
.B nobytemode .B nobytemode
] [
.B dq_rate_estimator
|
.B no_dq_rate_estimator
] ]
.SH DESCRIPTION .SH DESCRIPTION
@ -71,7 +75,7 @@ alpha and beta are parameters chosen to control the drop probability. These
should be in the range between 0 and 32. should be in the range between 0 and 32.
.SS ecn | noecn .SS ecn | noecn
is used to mark packets instead of dropping is used to mark packets instead of dropping.
.B ecn .B ecn
to turn on ecn mode, to turn on ecn mode,
.B noecn .B noecn
@ -80,7 +84,7 @@ to turn off ecn mode. By default,
is turned off. is turned off.
.SS bytemode | nobytemode .SS bytemode | nobytemode
is used to scale drop probability proportional to packet size is used to scale drop probability proportional to packet size.
.B bytemode .B bytemode
to turn on bytemode, to turn on bytemode,
.B nobytemode .B nobytemode
@ -88,21 +92,38 @@ to turn off bytemode. By default,
.B bytemode .B bytemode
is turned off. is turned off.
.SS dq_rate_estimator | no_dq_rate_estimator
is used to calculate delay using Little's law.
.B dq_rate_estimator
to turn on dq_rate_estimator,
.B no_dq_rate_estimator
to turn off no_dq_rate_estimator. By default,
.B dq_rate_estimator
is turned off.
.SH EXAMPLES .SH EXAMPLES
# tc qdisc add dev eth0 root pie # tc qdisc add dev eth0 root pie
# tc -s qdisc show # tc -s qdisc show
qdisc pie 8036: dev eth0 root refcnt 2 limit 1000p target 15.0ms tupdate 16.0ms alpha 2 beta 20 qdisc pie 8036: dev eth0 root refcnt 2 limit 1000p target 15.0ms tupdate 16.0ms alpha 2 beta 20
Sent 31216108 bytes 20800 pkt (dropped 80, overlimits 0 requeues 0) Sent 31216108 bytes 20800 pkt (dropped 80, overlimits 0 requeues 0)
backlog 16654b 11p requeues 0 backlog 16654b 11p requeues 0
prob 0.006161 delay 15666us avg_dq_rate 1159667 prob 0.006161 delay 15666us
pkts_in 20811 overlimit 0 dropped 80 maxq 50 ecn_mark 0 pkts_in 20811 overlimit 0 dropped 80 maxq 50 ecn_mark 0
# tc qdisc add dev eth0 root pie dq_rate_estimator
# tc -s qdisc show
qdisc pie 8036: dev eth0 root refcnt 2 limit 1000p target 15.0ms tupdate 16.0ms alpha 2 beta 20
Sent 63947420 bytes 42414 pkt (dropped 41, overlimits 0 requeues 0)
backlog 271006b 179p requeues 0
prob 0.000092 delay 22200us avg_dq_rate 12145996
pkts_in 41 overlimit 343 dropped 0 maxq 50 ecn_mark 0
# tc qdisc add dev eth0 root pie limit 100 target 20ms tupdate 30ms ecn # tc qdisc add dev eth0 root pie limit 100 target 20ms tupdate 30ms ecn
# tc -s qdisc show # tc -s qdisc show
qdisc pie 8036: dev eth0 root refcnt 2 limit 100p target 20.0ms tupdate 32.0ms alpha 2 beta 20 ecn qdisc pie 8036: dev eth0 root refcnt 2 limit 100p target 20.0ms tupdate 32.0ms alpha 2 beta 20 ecn
Sent 6591724 bytes 4442 pkt (dropped 27, overlimits 0 requeues 0) Sent 6591724 bytes 4442 pkt (dropped 27, overlimits 0 requeues 0)
backlog 18168b 12p requeues 0 backlog 18168b 12p requeues 0
prob 0.008845 delay 11348us avg_dq_rate 1342773 prob 0.008845 delay 11348us
pkts_in 4454 overlimit 0 dropped 27 maxq 65 ecn_mark 0 pkts_in 4454 overlimit 0 dropped 27 maxq 65 ecn_mark 0
# tc qdisc add dev eth0 root pie limit 100 target 50ms tupdate 30ms bytemode # tc qdisc add dev eth0 root pie limit 100 target 50ms tupdate 30ms bytemode
@ -110,7 +131,7 @@ is turned off.
qdisc pie 8036: dev eth0 root refcnt 2 limit 100p target 50.0ms tupdate 32.0ms alpha 2 beta 20 bytemode qdisc pie 8036: dev eth0 root refcnt 2 limit 100p target 50.0ms tupdate 32.0ms alpha 2 beta 20 bytemode
Sent 1616274 bytes 1137 pkt (dropped 0, overlimits 0 requeues 0) Sent 1616274 bytes 1137 pkt (dropped 0, overlimits 0 requeues 0)
backlog 13626b 9p requeues 0 backlog 13626b 9p requeues 0
prob 0.000000 delay 0us avg_dq_rate 0 prob 0.000000 delay 0us
pkts_in 1146 overlimit 0 dropped 0 maxq 23 ecn_mark 0 pkts_in 1146 overlimit 0 dropped 0 maxq 23 ecn_mark 0
.SH SEE ALSO .SH SEE ALSO

View File

@ -116,6 +116,7 @@ continue with the next filter in line (if any). This is the default for
exceeding packets. exceeding packets.
.IP pipe .IP pipe
Pass the packet to the next action in line. Pass the packet to the next action in line.
.RE
.SH EXAMPLES .SH EXAMPLES
A typical application of the police action is to enforce ingress traffic rate A typical application of the police action is to enforce ingress traffic rate
by dropping exceeding packets. Although better done on the sender's side, by dropping exceeding packets. Although better done on the sender's side,

View File

@ -67,7 +67,6 @@ group
.TP .TP
.BI PSAMPLE_ATTR_SAMPLE_RATE .BI PSAMPLE_ATTR_SAMPLE_RATE
The rate the packet was sampled with The rate the packet was sampled with
.RE
.SH OPTIONS .SH OPTIONS
.TP .TP
@ -117,8 +116,6 @@ tc filter add dev eth1 parent ffff: matchall \\
.EE .EE
.RE .RE
.EE
.RE
.SH SEE ALSO .SH SEE ALSO
.BR tc (8), .BR tc (8),
.BR tc-matchall (8) .BR tc-matchall (8)

View File

@ -54,7 +54,6 @@ grep the logs to see the logged message
.IP 6) 4 .IP 6) 4
display stats again and observe increment by 1 display stats again and observe increment by 1
.RE
.EX .EX
hadi@noma1:$ tc qdisc add dev eth0 ingress hadi@noma1:$ tc qdisc add dev eth0 ingress
hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \\ hadi@noma1:$tc filter add dev eth0 parent ffff: protocol ip prio 5 \\

View File

@ -75,6 +75,7 @@ Continue classification with the next filter in line.
.B pass .B pass
Finish classification process and return to calling qdisc for further packet Finish classification process and return to calling qdisc for further packet
processing. This is the default. processing. This is the default.
.RE
.SH EXAMPLES .SH EXAMPLES
To start, observe the following filter with a pedit action: To start, observe the following filter with a pedit action:

View File

@ -490,6 +490,7 @@ Match on source or destination ethernet address. This is dangerous: It assumes
an ethernet header is present at the start of the packet. This will probably an ethernet header is present at the start of the packet. This will probably
lead to unexpected things if used with layer three interfaces like e.g. tun or lead to unexpected things if used with layer three interfaces like e.g. tun or
ppp. ppp.
.RE
.SH EXAMPLES .SH EXAMPLES
.RS .RS
.EX .EX

View File

@ -828,6 +828,7 @@ Shows classes as ASCII graph on eth0 interface.
tc -g -s class show dev eth0 tc -g -s class show dev eth0
.RS 4 .RS 4
Shows classes as ASCII graph with stats info under each class. Shows classes as ASCII graph with stats info under each class.
.RE
.SH HISTORY .SH HISTORY
.B tc .B tc

View File

@ -1290,6 +1290,11 @@ static void render(void)
token = buf_token_next(token); token = buf_token_next(token);
} }
/* Deal with final end-of-line when the last non-empty field printed
* is not the last field.
*/
if (line_started)
printf("\n");
buf_free_all(); buf_free_all();
current_field = columns; current_field = columns;

View File

@ -359,7 +359,7 @@ static void ct_print_nat(int ct_action, struct rtattr **tb)
{ {
size_t done = 0; size_t done = 0;
char out[256] = ""; char out[256] = "";
bool nat; bool nat = false;
if (!(ct_action & TCA_CT_ACT_NAT)) if (!(ct_action & TCA_CT_ACT_NAT))
return; return;

View File

@ -31,9 +31,10 @@
static void explain(void) static void explain(void)
{ {
fprintf(stderr, fprintf(stderr,
"Usage: ... pie [ limit PACKETS ][ target TIME us]\n" "Usage: ... pie [ limit PACKETS ] [ target TIME ]\n"
" [ tupdate TIME us][ alpha ALPHA ]" " [ tupdate TIME ] [ alpha ALPHA ] [ beta BETA ]\n"
"[beta BETA ][bytemode | nobytemode][ecn | noecn ]\n"); " [ bytemode | nobytemode ] [ ecn | noecn ]\n"
" [ dq_rate_estimator | no_dq_rate_estimator ]\n");
} }
#define ALPHA_MAX 32 #define ALPHA_MAX 32
@ -49,6 +50,7 @@ static int pie_parse_opt(struct qdisc_util *qu, int argc, char **argv,
unsigned int beta = 0; unsigned int beta = 0;
int ecn = -1; int ecn = -1;
int bytemode = -1; int bytemode = -1;
int dq_rate_estimator = -1;
struct rtattr *tail; struct rtattr *tail;
while (argc > 0) { while (argc > 0) {
@ -92,6 +94,10 @@ static int pie_parse_opt(struct qdisc_util *qu, int argc, char **argv,
bytemode = 1; bytemode = 1;
} else if (strcmp(*argv, "nobytemode") == 0) { } else if (strcmp(*argv, "nobytemode") == 0) {
bytemode = 0; bytemode = 0;
} else if (strcmp(*argv, "dq_rate_estimator") == 0) {
dq_rate_estimator = 1;
} else if (strcmp(*argv, "no_dq_rate_estimator") == 0) {
dq_rate_estimator = 0;
} else if (strcmp(*argv, "help") == 0) { } else if (strcmp(*argv, "help") == 0) {
explain(); explain();
return -1; return -1;
@ -120,6 +126,9 @@ static int pie_parse_opt(struct qdisc_util *qu, int argc, char **argv,
if (bytemode != -1) if (bytemode != -1)
addattr_l(n, 1024, TCA_PIE_BYTEMODE, &bytemode, addattr_l(n, 1024, TCA_PIE_BYTEMODE, &bytemode,
sizeof(bytemode)); sizeof(bytemode));
if (dq_rate_estimator != -1)
addattr_l(n, 1024, TCA_PIE_DQ_RATE_ESTIMATOR,
&dq_rate_estimator, sizeof(dq_rate_estimator));
addattr_nest_end(n, tail); addattr_nest_end(n, tail);
return 0; return 0;
@ -135,6 +144,7 @@ static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
unsigned int beta; unsigned int beta;
unsigned int ecn; unsigned int ecn;
unsigned int bytemode; unsigned int bytemode;
unsigned int dq_rate_estimator;
SPRINT_BUF(b1); SPRINT_BUF(b1);
@ -182,6 +192,14 @@ static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
fprintf(f, "bytemode "); fprintf(f, "bytemode ");
} }
if (tb[TCA_PIE_DQ_RATE_ESTIMATOR] &&
RTA_PAYLOAD(tb[TCA_PIE_DQ_RATE_ESTIMATOR]) >= sizeof(__u32)) {
dq_rate_estimator =
rta_getattr_u32(tb[TCA_PIE_DQ_RATE_ESTIMATOR]);
if (dq_rate_estimator)
fprintf(f, "dq_rate_estimator ");
}
return 0; return 0;
} }
@ -198,9 +216,14 @@ static int pie_print_xstats(struct qdisc_util *qu, FILE *f,
st = RTA_DATA(xstats); st = RTA_DATA(xstats);
/*prob is returned as a fracion of maximum integer value */ /*prob is returned as a fracion of maximum integer value */
fprintf(f, "prob %f delay %uus avg_dq_rate %u\n", fprintf(f, "prob %f delay %uus",
(double)st->prob / UINT64_MAX, st->delay, (double)st->prob / (double)UINT64_MAX, st->delay);
st->avg_dq_rate);
if (st->dq_rate_estimating)
fprintf(f, " avg_dq_rate %u\n", st->avg_dq_rate);
else
fprintf(f, "\n");
fprintf(f, "pkts_in %u overlimit %u dropped %u maxq %u ecn_mark %u\n", fprintf(f, "pkts_in %u overlimit %u dropped %u maxq %u ecn_mark %u\n",
st->packets_in, st->overlimit, st->dropped, st->maxq, st->packets_in, st->overlimit, st->dropped, st->maxq,
st->ecn_mark); st->ecn_mark);

View File

@ -809,17 +809,28 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat
if (tbs[TCA_STATS_BASIC]) { if (tbs[TCA_STATS_BASIC]) {
struct gnet_stats_basic bs = {0}; struct gnet_stats_basic bs = {0};
__u64 packets64 = 0;
memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]), sizeof(bs))); if (tbs[TCA_STATS_PKT64])
packets64 = rta_getattr_u64(tbs[TCA_STATS_PKT64]);
memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]),
MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]), sizeof(bs)));
print_string(PRINT_FP, NULL, "%s", prefix); print_string(PRINT_FP, NULL, "%s", prefix);
print_lluint(PRINT_ANY, "bytes", "Sent %llu bytes", bs.bytes); print_lluint(PRINT_ANY, "bytes", "Sent %llu bytes", bs.bytes);
print_uint(PRINT_ANY, "packets", " %u pkt", bs.packets); if (packets64)
print_lluint(PRINT_ANY, "packets",
" %llu pkt", packets64);
else
print_uint(PRINT_ANY, "packets",
" %u pkt", bs.packets);
} }
if (tbs[TCA_STATS_QUEUE]) { if (tbs[TCA_STATS_QUEUE]) {
struct gnet_stats_queue q = {0}; struct gnet_stats_queue q = {0};
memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q))); memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]),
MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
print_uint(PRINT_ANY, "drops", " (dropped %u", q.drops); print_uint(PRINT_ANY, "drops", " (dropped %u", q.drops);
print_uint(PRINT_ANY, "overlimits", ", overlimits %u", print_uint(PRINT_ANY, "overlimits", ", overlimits %u",
q.overlimits); q.overlimits);
@ -855,7 +866,8 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat
if (tbs[TCA_STATS_QUEUE]) { if (tbs[TCA_STATS_QUEUE]) {
struct gnet_stats_queue q = {0}; struct gnet_stats_queue q = {0};
memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q))); memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]),
MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
if (!tbs[TCA_STATS_RATE_EST]) if (!tbs[TCA_STATS_RATE_EST])
print_string(PRINT_FP, NULL, "\n", ""); print_string(PRINT_FP, NULL, "\n", "");
print_uint(PRINT_JSON, "backlog", NULL, q.backlog); print_uint(PRINT_JSON, "backlog", NULL, q.backlog);
@ -870,7 +882,8 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat
*xstats = tbs[TCA_STATS_APP] ? : NULL; *xstats = tbs[TCA_STATS_APP] ? : NULL;
} }
void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix, struct rtattr **xstats) void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix,
struct rtattr **xstats)
{ {
SPRINT_BUF(b1); SPRINT_BUF(b1);
@ -885,25 +898,29 @@ void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix, struct rtat
struct tc_stats st = {}; struct tc_stats st = {};
/* handle case where kernel returns more/less than we know about */ /* handle case where kernel returns more/less than we know about */
memcpy(&st, RTA_DATA(tb[TCA_STATS]), MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st))); memcpy(&st, RTA_DATA(tb[TCA_STATS]),
MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st)));
fprintf(fp, "%sSent %llu bytes %u pkts (dropped %u, overlimits %u) ", fprintf(fp,
prefix, (unsigned long long)st.bytes, st.packets, st.drops, "%sSent %llu bytes %u pkts (dropped %u, overlimits %u) ",
st.overlimits); prefix, (unsigned long long)st.bytes,
st.packets, st.drops, st.overlimits);
if (st.bps || st.pps || st.qlen || st.backlog) { if (st.bps || st.pps || st.qlen || st.backlog) {
fprintf(fp, "\n%s", prefix); fprintf(fp, "\n%s", prefix);
if (st.bps || st.pps) { if (st.bps || st.pps) {
fprintf(fp, "rate "); fprintf(fp, "rate ");
if (st.bps) if (st.bps)
fprintf(fp, "%s ", sprint_rate(st.bps, b1)); fprintf(fp, "%s ",
sprint_rate(st.bps, b1));
if (st.pps) if (st.pps)
fprintf(fp, "%upps ", st.pps); fprintf(fp, "%upps ", st.pps);
} }
if (st.qlen || st.backlog) { if (st.qlen || st.backlog) {
fprintf(fp, "backlog "); fprintf(fp, "backlog ");
if (st.backlog) if (st.backlog)
fprintf(fp, "%s ", sprint_size(st.backlog, b1)); fprintf(fp, "%s ",
sprint_size(st.backlog, b1));
if (st.qlen) if (st.qlen)
fprintf(fp, "%up ", st.qlen); fprintf(fp, "%up ", st.qlen);
} }