Move rate and size parsing and output to lib
Subsystems (3)
PATCH v2 1/7 Move the use_iec declaration to the tools
In reply to Petr MachataThe tools "ip" and "tc" use a flag "use_iec", which indicates whether, when formatting rate values, the prefixes "K", "M", etc. should refer to powers of 1024, or powers of 1000. The flag is currently kept as a global variable in "ip" and "tc", but is nonetheless declared in util.h.
Instead, move the declaration to tool-specific headers ip/ip_common.h and tc/tc_common.h.
--- include/utils.h | 1 - ip/ip_common.h | 2 ++ tc/tc_common.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-)
include/utils.h +0 -1
@@ -20,7 +20,6 @@extern int preferred_family;extern int human_readable; -extern int use_iec;extern int show_stats;extern int show_details;extern int show_raw;
ip/ip_common.h +2 -0
@@ -6,6 +6,8 @@#include "json_print.h" +extern int use_iec; +struct link_filter {int ifindex;int family;
tc/tc_common.h +1 -0
@@ -27,3 +27,4 @@ int check_size_table_opts(struct tc_sizespec *s);extern int show_graph;extern bool use_names; +extern int use_iec;
Signature · 1 line
2.25.1
PATCH v2 3/7 lib: Move sprint_size() from tc here, add print_size()
In reply to Petr MachataWhen displaying sizes of various sorts, tc commonly uses the function sprint_size() to format the size into a buffer as a human-readable string. This string is then displayed either using print_string(), or in some code even fprintf(). As a result, a typical sequence of code when formatting a size is something like the following:
SPRINT_BUF(b); print_uint(PRINT_JSON, "foo", NULL, foo); print_string(PRINT_FP, NULL, "foo %s ", sprint_size(foo, b));
For a concept as broadly useful as size, it would be better to have a dedicated function in json_print.
To that end, move sprint_size() from tc_util to json_print. Add helpers print_size() and print_color_size() that wrap arount sprint_size() and provide the JSON dispatch as appropriate.
Since print_size() should be the preferred interface, convert vast majority of uses of sprint_size() to print_size(). Two notable exceptions are:
- q_tbf, which does not show the size as such, but uses the string "$human_readable_size/$cell_size" even in JSON. There is simply no way to have print_size() emit the same text, because print_size() in JSON mode should of course just use the raw number, without human-readable frills.
- q_cake, which relies on the existence of sprint_size() in its macro-based formatting helpers. There might be ways to convert this particular case, but given q_tbf simply cannot be converted, leave it as is.
--- include/json_print.h | 4 ++++ lib/json_print.c | 28 ++++++++++++++++++++++++++++ tc/m_gate.c | 6 ++---- tc/m_police.c | 5 ++--- tc/q_cake.c | 16 ++++++---------- tc/q_drr.c | 10 +++------- tc/q_fifo.c | 10 +++------- tc/q_fq.c | 9 +++------ tc/q_fq_codel.c | 5 ++--- tc/q_fq_pie.c | 9 +++------ tc/q_gred.c | 39 ++++++++------------------------------- tc/q_hhf.c | 9 +++------ tc/q_htb.c | 19 ++++++++----------- tc/q_red.c | 13 +++---------- tc/q_sfq.c | 15 +++------------ tc/q_tbf.c | 25 +++++++------------------ tc/tc_util.c | 29 +++-------------------------- tc/tc_util.h | 1 - 18 files changed, 91 insertions(+), 161 deletions(-)
include/json_print.h +4 -0
@@ -69,6 +69,7 @@ _PRINT_FUNC(on_off, bool) _PRINT_FUNC(null, const char*) _PRINT_FUNC(string, const char*) _PRINT_FUNC(uint, unsigned int) +_PRINT_FUNC(size, __u32) _PRINT_FUNC(u64, uint64_t) _PRINT_FUNC(hhu, unsigned char) _PRINT_FUNC(hu, unsigned short)
@@ -96,4 +97,7 @@ static inline int print_rate(bool use_iec, enum output_type t, return print_color_rate(use_iec, t, COLOR_NONE, key, fmt, rate); } +/* A backdoor to the size formatter. Please use print_size() instead. */ +char *sprint_size (__u32 sz,char *buf); +#endif /* _JSON_PRINT_H_ */
lib/json_print.c +28 -0
@@ -11,6 +11,7 @@#include <stdarg.h> #include <stdio.h> +#include <math.h> #include "utils.h" #include "json_print.h"
@@ -340,3 +341,30 @@ int print_color_rate(bool use_iec, enum output_type type, enum color_attr color,free (buf);return rc; } + +char *sprint_size (__u32 sz,char *buf) +{ +size_t len =SPRINT_BSIZE -1 ; +double tmp = sz; + +if (sz >=1024 *1024 &&fabs (1024 *1024 *rint (tmp/(1024 *1024 )) - sz) <1024 ) +snprintf (buf, len,"%gMb" ,rint (tmp/(1024 *1024 ))); +else if (sz >=1024 &&fabs (1024 *rint (tmp/1024 ) - sz) <16 ) +snprintf (buf, len,"%gKb" ,rint (tmp/1024 )); +else +snprintf (buf, len,"%ub" , sz); + +return buf; +} + +int print_color_size (enum output_type type,enum color_attr color, +const char *key,const char *fmt,__u32 sz) +{ +SPRINT_BUF (buf); + +if (_IS_JSON_CONTEXT (type)) +return print_color_uint (type, color, key,"%u" , sz); + +sprint_size (sz, buf); +return print_color_string (type, color, key, fmt, buf); +}
tc/m_gate.c +2 -4
@@ -465,10 +465,8 @@ static int print_gate_list(struct rtattr *list) }if (maxoctets !=-1 ) { -memset (buf,0 ,sizeof (buf)); -print_uint (PRINT_JSON ,"max_octets" ,NULL , maxoctets); -print_string (PRINT_FP ,NULL ,"\t max-octets %s" , -sprint_size (maxoctets, buf)); +print_size (PRINT_ANY ,"max_octets" ,"\t max-octets %s" , + maxoctets); }else {print_string (PRINT_FP ,NULL ,"\t max-octets %s" ,"wildcard" );
tc/m_police.c +2 -3
@@ -238,7 +238,6 @@ int parse_police(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)static int print_police (struct action_util *a,FILE *f,struct rtattr *arg) { -SPRINT_BUF (b1);SPRINT_BUF (b2);struct tc_police *p;struct rtattr *tb[TCA_POLICE_MAX +1 ];
@@ -271,8 +270,8 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg)fprintf (f," police 0x%x " , p->index);tc_print_rate (PRINT_FP ,NULL ,"rate %s " , rate64); buffer =tc_calc_xmitsize (rate64, p->burst); -fprintf (f,"burst %s " ,sprint_size (buffer, b1)); -fprintf (f,"mtu %s " ,sprint_size (p->mtu, b1)); +print_size (PRINT_FP ,NULL ,"burst %s " , buffer); +print_size (PRINT_FP ,NULL ,"mtu %s " , p->mtu);if (show_raw)fprintf (f,"[%08x] " , p->burst);
tc/q_cake.c +6 -10
@@ -434,7 +434,6 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)int atm =0 ;int nat =0 ; -SPRINT_BUF (b1);SPRINT_BUF (b2);if (opt ==NULL )
@@ -573,11 +572,8 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (mpu)print_uint (PRINT_ANY ,"mpu" ,"mpu %u " , mpu); -if (memlimit) { -print_uint (PRINT_JSON ,"memlimit" ,NULL , memlimit); -print_string (PRINT_FP ,NULL ,"memlimit %s " , -sprint_size (memlimit, b1)); - } +if (memlimit) +print_size (PRINT_ANY ,"memlimit" ,"memlimit %s " , memlimit);if (fwmark)print_uint (PRINT_FP ,NULL ,"fwmark 0x%x " , fwmark);
@@ -637,11 +633,11 @@ static int cake_print_xstats(struct qdisc_util *qu, FILE *f,if (st[TCA_CAKE_STATS_MEMORY_USED ] && st[TCA_CAKE_STATS_MEMORY_LIMIT ]) { -print_string (PRINT_FP ,NULL ," memory used: %s" , -sprint_size (GET_STAT_U32 (MEMORY_USED ), b1)); +print_size (PRINT_FP ,NULL ," memory used: %s" , +GET_STAT_U32 (MEMORY_USED )); -print_string (PRINT_FP ,NULL ," of %s\n" , -sprint_size (GET_STAT_U32 (MEMORY_LIMIT ), b1)); +print_size (PRINT_FP ,NULL ," of %s\n" , +GET_STAT_U32 (MEMORY_LIMIT ));print_uint (PRINT_JSON ,"memory_used" ,NULL ,GET_STAT_U32 (MEMORY_USED ));
tc/q_drr.c +3 -7
@@ -84,16 +84,14 @@ static int drr_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) {struct rtattr *tb[TCA_DRR_MAX +1 ]; -SPRINT_BUF (b1); -if (opt ==NULL )return 0 ;parse_rtattr_nested (tb,TCA_DRR_MAX , opt);if (tb[TCA_DRR_QUANTUM ]) -fprintf (f,"quantum %s " , -sprint_size (rta_getattr_u32 (tb[TCA_DRR_QUANTUM ]), b1)); +print_size (PRINT_FP ,NULL ,"quantum %s " , +rta_getattr_u32 (tb[TCA_DRR_QUANTUM ]));return 0 ; }
@@ -101,15 +99,13 @@ static int drr_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstat {struct tc_drr_stats *x; -SPRINT_BUF (b1); -if (xstats ==NULL )return 0 ;if (RTA_PAYLOAD (xstats) <sizeof (*x))return -1 ; x =RTA_DATA (xstats); -fprintf (f," deficit %s " ,sprint_size (x->deficit, b1)); +print_size (PRINT_FP ,NULL ," deficit %s " , x->deficit);return 0 ; }
tc/q_fifo.c +3 -7
@@ -67,14 +67,10 @@ static int fifo_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (RTA_PAYLOAD (opt) <sizeof (*qopt))return -1 ; qopt =RTA_DATA (opt); -if (strcmp (qu->id,"bfifo" ) ==0 ) { -SPRINT_BUF (b1); -print_uint (PRINT_JSON ,"limit" ,NULL , qopt->limit); -print_string (PRINT_FP ,NULL ,"limit %s" , -sprint_size (qopt->limit, b1)); - }else { +if (strcmp (qu->id,"bfifo" ) ==0 ) +print_size (PRINT_ANY ,"limit" ,"limit %s" , qopt->limit); +else print_uint (PRINT_ANY ,"limit" ,"limit %up" , qopt->limit); - }return 0 ; }
tc/q_fq.c +3 -6
@@ -315,16 +315,13 @@ static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (tb[TCA_FQ_QUANTUM ] &&RTA_PAYLOAD (tb[TCA_FQ_QUANTUM ]) >=sizeof (__u32)) { quantum =rta_getattr_u32 (tb[TCA_FQ_QUANTUM ]); -print_uint (PRINT_JSON ,"quantum" ,NULL , quantum); -print_string (PRINT_FP ,NULL ,"quantum %s " , -sprint_size (quantum, b1)); +print_size (PRINT_ANY ,"quantum" ,"quantum %s " , quantum); }if (tb[TCA_FQ_INITIAL_QUANTUM ] &&RTA_PAYLOAD (tb[TCA_FQ_INITIAL_QUANTUM ]) >=sizeof (__u32)) { quantum =rta_getattr_u32 (tb[TCA_FQ_INITIAL_QUANTUM ]); -print_uint (PRINT_JSON ,"initial_quantum" ,NULL , quantum); -print_string (PRINT_FP ,NULL ,"initial_quantum %s " , -sprint_size (quantum, b1)); +print_size (PRINT_ANY ,"initial_quantum" ,"initial_quantum %s " , + quantum); }if (tb[TCA_FQ_FLOW_MAX_RATE ] &&RTA_PAYLOAD (tb[TCA_FQ_FLOW_MAX_RATE ]) >=sizeof (__u32)) {
tc/q_fq_codel.c +2 -3
@@ -221,9 +221,8 @@ static int fq_codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *optif (tb[TCA_FQ_CODEL_MEMORY_LIMIT ] &&RTA_PAYLOAD (tb[TCA_FQ_CODEL_MEMORY_LIMIT ]) >=sizeof (__u32)) { memory_limit =rta_getattr_u32 (tb[TCA_FQ_CODEL_MEMORY_LIMIT ]); -print_uint (PRINT_JSON ,"memory_limit" ,NULL , memory_limit); -print_string (PRINT_FP ,NULL ,"memory_limit %s " , -sprint_size (memory_limit, b1)); +print_size (PRINT_ANY ,"memory_limit" ,"memory_limit %s " , + memory_limit); }if (tb[TCA_FQ_CODEL_ECN ] &&RTA_PAYLOAD (tb[TCA_FQ_CODEL_ECN ]) >=sizeof (__u32)) {
tc/q_fq_pie.c +3 -6
@@ -232,16 +232,13 @@ static int fq_pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (tb[TCA_FQ_PIE_QUANTUM ] &&RTA_PAYLOAD (tb[TCA_FQ_PIE_QUANTUM ]) >=sizeof (__u32)) { quantum =rta_getattr_u32 (tb[TCA_FQ_PIE_QUANTUM ]); -print_uint (PRINT_JSON ,"quantum" ,NULL , quantum); -print_string (PRINT_FP ,NULL ,"quantum %s " , -sprint_size (quantum, b1)); +print_size (PRINT_ANY ,"quantum" ,"quantum %s " , quantum); }if (tb[TCA_FQ_PIE_MEMORY_LIMIT ] &&RTA_PAYLOAD (tb[TCA_FQ_PIE_MEMORY_LIMIT ]) >=sizeof (__u32)) { memory_limit =rta_getattr_u32 (tb[TCA_FQ_PIE_MEMORY_LIMIT ]); -print_uint (PRINT_JSON ,"memory_limit" ,NULL , memory_limit); -print_string (PRINT_FP ,NULL ,"memory_limit %s " , -sprint_size (memory_limit, b1)); +print_size (PRINT_ANY ,"memory_limit" ,"memory_limit %s " , + memory_limit); }if (tb[TCA_FQ_PIE_ECN_PROB ] &&RTA_PAYLOAD (tb[TCA_FQ_PIE_ECN_PROB ]) >=sizeof (__u32)) {
tc/q_gred.c +8 -31
@@ -373,18 +373,11 @@ gred_print_stats(struct tc_gred_info *info, struct tc_gred_qopt *qopt) {__u64 bytes = info ? info->bytes : qopt->bytesin; -SPRINT_BUF (b1); -if (!is_json_context ())printf ("\n Queue size: " ); -print_uint (PRINT_JSON ,"qave" ,NULL , qopt->qave); -print_string (PRINT_FP ,NULL ,"average %s " , -sprint_size (qopt->qave, b1)); - -print_uint (PRINT_JSON ,"backlog" ,NULL , qopt->backlog); -print_string (PRINT_FP ,NULL ,"current %s " , -sprint_size (qopt->backlog, b1)); +print_size (PRINT_ANY ,"qave" ,"average %s " , qopt->qave); +print_size (PRINT_ANY ,"backlog" ,"current %s " , qopt->backlog);if (!is_json_context ())printf ("\n Dropped packets: " );
@@ -415,9 +408,7 @@ gred_print_stats(struct tc_gred_info *info, struct tc_gred_qopt *qopt)printf ("\n Total packets: " );print_uint (PRINT_ANY ,"packets" ,"%u " , qopt->packets); - -print_uint (PRINT_JSON ,"bytes" ,NULL , bytes); -print_string (PRINT_FP ,NULL ,"(%s) " ,sprint_size (bytes, b1)); +print_size (PRINT_ANY ,"bytes" ,"(%s) " , bytes); }static int gred_print_opt (struct qdisc_util *qu,FILE *f,struct rtattr *opt)
@@ -431,8 +422,6 @@ static int gred_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)__u32 *limit =NULL ;unsigned int i; -SPRINT_BUF (b1); -if (opt ==NULL )return 0 ;
@@ -470,11 +459,8 @@ static int gred_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)else print_bool (PRINT_ANY ,"grio" ,NULL , false); -if (limit) { -print_uint (PRINT_JSON ,"limit" ,NULL , *limit); -print_string (PRINT_FP ,NULL ,"limit %s " , -sprint_size (*limit, b1)); - } +if (limit) +print_size (PRINT_ANY ,"limit" ,"limit %s " , *limit);tc_red_print_flags (sopt->flags);
@@ -487,18 +473,9 @@ static int gred_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)print_uint (PRINT_ANY ,"vq" ,"\n vq %u " , qopt->DP);print_hhu (PRINT_ANY ,"prio" ,"prio %hhu " , qopt->prio); - -print_uint (PRINT_JSON ,"limit" ,NULL , qopt->limit); -print_string (PRINT_FP ,NULL ,"limit %s " , -sprint_size (qopt->limit, b1)); - -print_uint (PRINT_JSON ,"min" ,NULL , qopt->qth_min); -print_string (PRINT_FP ,NULL ,"min %s " , -sprint_size (qopt->qth_min, b1)); - -print_uint (PRINT_JSON ,"max" ,NULL , qopt->qth_max); -print_string (PRINT_FP ,NULL ,"max %s " , -sprint_size (qopt->qth_max, b1)); +print_size (PRINT_ANY ,"limit" ,"limit %s " , qopt->limit); +print_size (PRINT_ANY ,"min" ,"min %s " , qopt->qth_min); +print_size (PRINT_ANY ,"max" ,"max %s " , qopt->qth_max);if (infos[i].flags_present)tc_red_print_flags (infos[i].flags);
tc/q_hhf.c +3 -6
@@ -143,9 +143,7 @@ static int hhf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (tb[TCA_HHF_QUANTUM ] &&RTA_PAYLOAD (tb[TCA_HHF_QUANTUM ]) >=sizeof (__u32)) { quantum =rta_getattr_u32 (tb[TCA_HHF_QUANTUM ]); -print_uint (PRINT_JSON ,"quantum" ,NULL , quantum); -print_string (PRINT_FP ,NULL ,"quantum %s " , -sprint_size (quantum, b1)); +print_size (PRINT_ANY ,"quantum" ,"quantum %s " , quantum); }if (tb[TCA_HHF_HH_FLOWS_LIMIT ] &&RTA_PAYLOAD (tb[TCA_HHF_HH_FLOWS_LIMIT ]) >=sizeof (__u32)) {
@@ -162,9 +160,8 @@ static int hhf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (tb[TCA_HHF_ADMIT_BYTES ] &&RTA_PAYLOAD (tb[TCA_HHF_ADMIT_BYTES ]) >=sizeof (__u32)) { admit_bytes =rta_getattr_u32 (tb[TCA_HHF_ADMIT_BYTES ]); -print_uint (PRINT_JSON ,"admit_bytes" ,NULL , admit_bytes); -print_string (PRINT_FP ,NULL ,"admit_bytes %s " , -sprint_size (admit_bytes, b1)); +print_size (PRINT_ANY ,"admit_bytes" ,"admit_bytes %s " , + admit_bytes); }if (tb[TCA_HHF_EVICT_TIMEOUT ] &&RTA_PAYLOAD (tb[TCA_HHF_EVICT_TIMEOUT ]) >=sizeof (__u32)) {
tc/q_htb.c +8 -11
@@ -269,7 +269,6 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)__u64 rate64, ceil64;SPRINT_BUF (b1); -SPRINT_BUF (b2);SPRINT_BUF (b3);if (opt ==NULL )
@@ -310,18 +309,16 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (linklayer >TC_LINKLAYER_ETHERNET || show_details)fprintf (f,"linklayer %s " ,sprint_linklayer (linklayer, b3));if (show_details) { -fprintf (f,"burst %s/%u mpu %s " , -sprint_size (buffer, b1), -1 <<hopt->rate.cell_log, -sprint_size (hopt->rate.mpu, b2)); -fprintf (f,"cburst %s/%u mpu %s " , -sprint_size (cbuffer, b1), -1 <<hopt->ceil.cell_log, -sprint_size (hopt->ceil.mpu, b2)); +print_size (PRINT_FP ,NULL ,"burst %s/" , buffer); +fprintf (f,"%u " ,1 <<hopt->rate.cell_log); +print_size (PRINT_FP ,NULL ,"mpu %s " , hopt->rate.mpu); +print_size (PRINT_FP ,NULL ,"cburst %s/" , cbuffer); +fprintf (f,"%u " ,1 <<hopt->ceil.cell_log); +print_size (PRINT_FP ,NULL ,"mpu %s " , hopt->ceil.mpu);fprintf (f,"level %d " , (int )hopt->level); }else { -fprintf (f,"burst %s " ,sprint_size (buffer, b1)); -fprintf (f,"cburst %s " ,sprint_size (cbuffer, b1)); +print_size (PRINT_FP ,NULL ,"burst %s " , buffer); +print_size (PRINT_FP ,NULL ,"cburst %s " , cbuffer); }if (show_raw) fprintf(f, "buffer [%08x] cbuffer [%08x] ",
tc/q_red.c +3 -10
@@ -192,10 +192,6 @@ static int red_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)struct tc_red_qopt *qopt;__u32 max_P =0 ; -SPRINT_BUF (b1); -SPRINT_BUF (b2); -SPRINT_BUF (b3); -if (opt ==NULL )return 0 ;
@@ -217,12 +213,9 @@ static int red_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) qopt->flags = flags_bf->value; } -print_uint (PRINT_JSON ,"limit" ,NULL , qopt->limit); -print_string (PRINT_FP ,NULL ,"limit %s " ,sprint_size (qopt->limit, b1)); -print_uint (PRINT_JSON ,"min" ,NULL , qopt->qth_min); -print_string (PRINT_FP ,NULL ,"min %s " ,sprint_size (qopt->qth_min, b2)); -print_uint (PRINT_JSON ,"max" ,NULL , qopt->qth_max); -print_string (PRINT_FP ,NULL ,"max %s " ,sprint_size (qopt->qth_max, b3)); +print_size (PRINT_ANY ,"limit" ,"limit %s " , qopt->limit); +print_size (PRINT_ANY ,"min" ,"min %s " , qopt->qth_min); +print_size (PRINT_ANY ,"max" ,"max %s " , qopt->qth_max);tc_red_print_flags (qopt->flags);
tc/q_sfq.c +3 -12
@@ -206,9 +206,6 @@ static int sfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)struct tc_sfq_qopt *qopt;struct tc_sfq_qopt_v1 *qopt_ext =NULL ; -SPRINT_BUF (b1); -SPRINT_BUF (b2); -SPRINT_BUF (b3);if (opt ==NULL )return 0 ;
@@ -219,9 +216,7 @@ static int sfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) qopt =RTA_DATA (opt);print_uint (PRINT_ANY ,"limit" ,"limit %up " , qopt->limit); -print_uint (PRINT_JSON ,"quantum" ,NULL , qopt->quantum); -print_string (PRINT_FP ,NULL ,"quantum %s " , -sprint_size (qopt->quantum, b1)); +print_size (PRINT_ANY ,"quantum" ,"quantum %s " , qopt->quantum);if (qopt_ext && qopt_ext->depth)print_uint (PRINT_ANY ,"depth" ,"depth %u " , qopt_ext->depth);
@@ -237,12 +232,8 @@ static int sfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) qopt->perturb_period);if (qopt_ext && qopt_ext->qth_min) {print_uint (PRINT_ANY ,"ewma" ,"ewma %u " , qopt_ext->Wlog); -print_uint (PRINT_JSON ,"min" ,NULL , qopt_ext->qth_min); -print_string (PRINT_FP ,NULL ,"min %s " , -sprint_size (qopt_ext->qth_min, b2)); -print_uint (PRINT_JSON ,"max" ,NULL , qopt_ext->qth_max); -print_string (PRINT_FP ,NULL ,"max %s " , -sprint_size (qopt_ext->qth_max, b3)); +print_size (PRINT_ANY ,"min" ,"min %s " , qopt_ext->qth_min); +print_size (PRINT_ANY ,"max" ,"max %s " , qopt_ext->qth_max);print_float (PRINT_ANY ,"probability" ,"probability %lg " , qopt_ext->max_P /pow (2 ,32 ));tc_red_print_flags (qopt_ext->flags);
tc/q_tbf.c +7 -18
@@ -292,13 +292,9 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)sprintf (b1,"%s/%u" ,sprint_size (buffer, b2),1 << qopt->rate.cell_log);print_string (PRINT_ANY ,"burst" ,"burst %s " , b1); -print_uint (PRINT_JSON ,"mpu" ,NULL , qopt->rate.mpu); -print_string (PRINT_FP ,NULL ,"mpu %s " , -sprint_size (qopt->rate.mpu, b1)); +print_size (PRINT_ANY ,"mpu" ,"mpu %s " , qopt->rate.mpu); }else { -print_u64 (PRINT_JSON ,"burst" ,NULL , buffer); -print_string (PRINT_FP ,NULL ,"burst %s " , -sprint_size (buffer, b1)); +print_size (PRINT_ANY ,"burst" ,"burst %s " , buffer); }if (show_raw)print_hex (PRINT_ANY ,"burst_raw" ,"[%08x] " , qopt->buffer);
@@ -314,15 +310,11 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)sprintf (b1,"%s/%u" ,sprint_size (mtu, b2),1 << qopt->peakrate.cell_log);print_string (PRINT_ANY ,"mtu" ,"mtu %s " , b1); -print_uint (PRINT_JSON ,"mpu" ,NULL , +print_size (PRINT_ANY ,"mpu" ,"mpu %s " , qopt->peakrate.mpu); -print_string (PRINT_FP ,NULL ,"mpu %s " , -sprint_size (qopt->peakrate.mpu, - b1)); }else { -print_u64 (PRINT_JSON ,"minburst" ,NULL , mtu); -print_string (PRINT_FP ,NULL ,"minburst %s " , -sprint_size (mtu, b1)); +print_size (PRINT_ANY ,"minburst" , +"minburst %s " , mtu); }if (show_raw) print_hex(PRINT_ANY, "mtu_raw", "[%08x] ",
@@ -344,11 +336,8 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)print_string (PRINT_FP ,NULL ,"lat %s " ,sprint_time (latency, b1)); } -if (show_raw || latency <0.0 ) { -print_uint (PRINT_JSON ,"limit" ,NULL , qopt->limit); -print_string (PRINT_FP ,NULL ,"limit %s " , -sprint_size (qopt->limit, b1)); - } +if (show_raw || latency <0.0 ) +print_size (PRINT_ANY ,"limit" ,"limit %s " , qopt->limit);if (qopt->rate.overhead)print_int (PRINT_ANY ,"overhead" ,"overhead %d " , qopt->rate.overhead);
tc/tc_util.c +3 -26
@@ -412,24 +412,6 @@ void print_devname(enum output_type type, int ifindex) "dev", "%s ", ifname); } -static void print_size (char *buf,int len,__u32 sz) -{ -double tmp = sz; - -if (sz >=1024 *1024 &&fabs (1024 *1024 *rint (tmp/(1024 *1024 )) - sz) <1024 ) -snprintf (buf, len,"%gMb" ,rint (tmp/(1024 *1024 ))); -else if (sz >=1024 &&fabs (1024 *rint (tmp/1024 ) - sz) <16 ) -snprintf (buf, len,"%gKb" ,rint (tmp/1024 )); -else -snprintf (buf, len,"%ub" , sz); -} - -char *sprint_size (__u32 size,char *buf) -{ -print_size (buf,SPRINT_BSIZE -1 , size); -return buf; -} -static const char *action_n2a (int action) {static char buf[64 ];
@@ -786,7 +768,6 @@ static void print_tcstats_basic_hw(struct rtattr **tbs, char *prefix)void print_tcstats2_attr (FILE *fp,struct rtattr *rta,char *prefix,struct rtattr **xstats) { -SPRINT_BUF (b1);struct rtattr *tbs[TCA_STATS_MAX +1 ];parse_rtattr_nested (tbs,TCA_STATS_MAX , rta);
@@ -852,10 +833,8 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));if (!tbs[TCA_STATS_RATE_EST ])print_nl (); -print_uint (PRINT_JSON ,"backlog" ,NULL , q.backlog);print_string (PRINT_FP ,NULL ,"%s" , prefix); -print_string (PRINT_FP ,NULL ,"backlog %s" , -sprint_size (q.backlog, b1)); +print_size (PRINT_ANY ,"backlog" ,"backlog %s" , q.backlog);print_uint (PRINT_ANY ,"qlen" ," %up" , q.qlen);print_uint (PRINT_FP ,NULL ," requeues %u" , q.requeues); }
@@ -867,8 +846,6 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtatvoid print_tcstats_attr (FILE *fp,struct rtattr *tb[],char *prefix,struct rtattr **xstats) { -SPRINT_BUF (b1); -if (tb[TCA_STATS2 ]) {print_tcstats2_attr (fp, tb[TCA_STATS2 ], prefix, xstats);if (xstats && !*xstats)
@@ -901,8 +878,8 @@ void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix,if (st.qlen || st.backlog) {fprintf (fp,"backlog " );if (st.backlog) -fprintf (fp,"%s " , -sprint_size (st.backlog, b1)); +print_size (PRINT_FP ,NULL ,"%s " , + st.backlog);if (st.qlen)fprintf (fp,"%up " , st.qlen); }
tc/tc_util.h +0 -1
@@ -88,7 +88,6 @@ void tc_print_rate(enum output_type t, const char *key, const char *fmt, unsigned long long rate);void print_devname (enum output_type type,int ifindex); -char *sprint_size (__u32 size,char *buf);char *sprint_tc_classid (__u32 h,char *buf);char *sprint_ticks (__u32 ticks,char *buf);char *sprint_linklayer (unsigned int linklayer,char *buf);
Signature · 1 line
2.25.1
PATCH v2 4/7 lib: sprint_size(): Uncrustify the code a bit
In reply to Petr MachataIdeally this and the rate printing would both be converted to a common helper, but unfortunately the two format differently and this would break tests and scripts out there. So just make the code look less like a wad of hay.
---
Notes:
v2:
- This patch is new. It addresses a request from Stephen Hemminger to clean up the sprint_size() function.
lib/json_print.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
lib/json_print.c +6 -4
@@ -344,13 +344,15 @@ int print_color_rate(bool use_iec, enum output_type type, enum color_attr color,char *sprint_size (__u32 sz,char *buf) { +long kilo =1024 ; +long mega = kilo * kilo;size_t len =SPRINT_BSIZE -1 ;double tmp = sz; -if (sz >=1024 *1024 &&fabs (1024 *1024 *rint (tmp/(1024 *1024 )) - sz) <1024 ) -snprintf (buf, len,"%gMb" ,rint (tmp/(1024 *1024 ))); -else if (sz >=1024 &&fabs (1024 *rint (tmp/1024 ) - sz) <16 ) -snprintf (buf, len,"%gKb" ,rint (tmp/1024 )); +if (sz >= mega &&fabs (mega *rint (tmp / mega) - sz) <1024 ) +snprintf (buf, len,"%gMb" ,rint (tmp / mega)); +else if (sz >= kilo &&fabs (kilo *rint (tmp / kilo) - sz) <16 ) +snprintf (buf, len,"%gKb" ,rint (tmp / kilo));else snprintf (buf, len,"%ub" , sz);
Signature · 1 line
2.25.1
PATCH v2 5/7 lib: print_color_rate(): Fix formatting small rates in IEC mode
In reply to Petr MachataISO/IEC units are distinguished from the decadic ones by using a prefixes like "Ki", "Mi" instead of "K" and "M". The current code inserts the letter "i" after the decadic unit when in IEC mode. However it does so even when the prefix is an empty string, formatting 1Kbit in IEC mode as "1000ibit". Fix by omitting the letter if there is no prefix.
--- lib/json_print.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
lib/json_print.c +2 -1
@@ -333,7 +333,8 @@ int print_color_rate(bool use_iec, enum output_type type, enum color_attr color, rate /= kilo; } - rc =asprintf (&buf,"%.0f%s%sbit" , (double )rate, units[i], str); + rc =asprintf (&buf,"%.0f%s%sbit" , (double )rate, units[i], + i >0 ? str :"" );if (rc <0 )return -1 ;
Signature · 1 line
2.25.1
PATCH v2 6/7 lib: Move get_rate(), get_rate64() from tc here
In reply to Petr MachataThe functions get_rate() and get_rate64() are useful for parsing rate-like values. The DCB tool will find these useful in the maxrate subtool. Move them over to lib so that they can be easily reused.
--- include/utils.h | 2 ++ lib/utils.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ tc/tc_util.c | 79 ------------------------------------------------- tc/tc_util.h | 2 -- 4 files changed, 81 insertions(+), 81 deletions(-)
include/utils.h +2 -0
@@ -162,6 +162,8 @@ int get_be64(__be64 *val, const char *arg, int base);int get_be32 (__be32 *val,const char *arg,int base);int get_be16 (__be16 *val,const char *arg,int base);int get_addr64 (__u64 *ap,const char *cp); +int get_rate (unsigned int *rate,const char *str); +int get_rate64 (__u64 *rate,const char *str);int hex2mem (const char *buf,uint8_t *mem,int count);char *hexstring_n2a (const __u8 *str,int len,char *buf,int blen);
lib/utils.c +79 -0
85 lines not on this page · raw message
tc/tc_util.c +0 -79
91 lines not on this page · raw message
tc/tc_util.h +0 -2
@@ -76,9 +76,7 @@ struct qdisc_util *get_qdisc_kind(const char *str);struct filter_util *get_filter_kind (const char *str);int get_qdisc_handle (__u32 *h,const char *str); -int get_rate (unsigned int *rate,const char *str);int get_percent_rate (unsigned int *rate,const char *str,const char *dev); -int get_rate64 (__u64 *rate,const char *str);int get_percent_rate64 (__u64 *rate,const char *str,const char *dev);int get_size (unsigned int *size,const char *str);int get_size_and_cell (unsigned int *size,int *cell_log,char *str);
Signature · 1 line
2.25.1
PATCH v2 2/7 lib: Move print_rate() from tc here; modernize
In reply to Petr MachataThe functions print_rate() and sprint_rate() are useful for formatting rate-like values. The DCB tool would find these useful in the maxrate subtool. However, the current interface to these functions uses a global variable use_iec as a flag indicating whether 1024- or 1000-based powers should be used when formatting the rate value. For general use, a global variable is not a great way of passing arguments to a function. Besides, it is unlike most other printing functions in that it deals in buffers and ignores JSON.
Therefore make the interface to print_rate() explicit by converting use_iec to an ordinary parameter. Since the interface changes anyway, convert it to follow the pattern of other json_print functions (except for the now-explicit use_iec parameter). Move to json_print.c.
Add a wrapper to tc, so that all the call sites do not need to repeat the use_iec global variable argument, and convert all call sites.
In q_cake.c, the conversion is not straightforward due to usage of a macro that is shared across numerous data types. Simply hand-roll the corresponding code, which seems better than making an extra helper for one call site.
Drop sprint_rate() now that everybody just uses print_rate().
---
Notes:
v2:
- Adapt q_mqprio.c patch, the file changed since v1.
include/json_print.h | 10 ++++++++++ lib/json_print.c | 32 ++++++++++++++++++++++++++++++++ tc/m_police.c | 9 ++++----- tc/q_cake.c | 28 ++++++++++++++++------------ tc/q_cbq.c | 14 ++++---------- tc/q_fq.c | 25 +++++++++---------------- tc/q_hfsc.c | 4 ++-- tc/q_htb.c | 4 ++-- tc/q_mqprio.c | 6 ++---- tc/q_netem.c | 4 +--- tc/q_tbf.c | 7 ++----- tc/tc_util.c | 37 +++++++------------------------------ tc/tc_util.h | 4 ++-- 13 files changed, 93 insertions(+), 91 deletions(-)
include/json_print.h +10 -0
@@ -86,4 +86,14 @@ _PRINT_NAME_VALUE_FUNC(uint, unsigned int, u); _PRINT_NAME_VALUE_FUNC(string, const char*, s);#undef _PRINT_NAME_VALUE_FUNC +int print_color_rate (bool use_iec,enum output_type t,enum color_attr color, +const char *key,const char *fmt,unsigned long long rate); + +static inline int print_rate (bool use_iec,enum output_type t, +const char *key,const char *fmt, +unsigned long long rate) +{ +return print_color_rate (use_iec, t,COLOR_NONE , key, fmt, rate); +} +#endif /* _JSON_PRINT_H_ */
lib/json_print.c +32 -0
@@ -308,3 +308,35 @@ void print_nl(void)if (!_jw)printf ("%s" , _SL_); } + +int print_color_rate (bool use_iec,enum output_type type,enum color_attr color, +const char *key,const char *fmt,unsigned long long rate) +{ +unsigned long kilo = use_iec ?1024 :1000 ; +const char *str = use_iec ?"i" :"" ; +static char *units[5 ] = {"" ,"K" ,"M" ,"G" ,"T" }; +char *buf; +int rc; +int i; + +if (_IS_JSON_CONTEXT (type)) +return print_color_lluint (type, color, key,"%llu" , rate); + + rate <<=3 ;/* bytes/sec -> bits/sec */ + +for (i =0 ; i <ARRAY_SIZE (units) -1 ; i++) { +if (rate < kilo) +break ; +if (((rate % kilo) !=0 ) && rate <1000 *kilo) +break ; + rate /= kilo; + } + + rc =asprintf (&buf,"%.0f%s%sbit" , (double )rate, units[i], str); +if (rc <0 ) +return -1 ; + + rc =print_color_string (type, color, key, fmt, buf); +free (buf); +return rc; +}
tc/m_police.c +4 -5
@@ -269,7 +269,7 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg) rate64 =rta_getattr_u64 (tb[TCA_POLICE_RATE64 ]);fprintf (f," police 0x%x " , p->index); -fprintf (f,"rate %s " ,sprint_rate (rate64, b1)); +tc_print_rate (PRINT_FP ,NULL ,"rate %s " , rate64); buffer =tc_calc_xmitsize (rate64, p->burst);fprintf (f,"burst %s " ,sprint_size (buffer, b1));fprintf (f,"mtu %s " ,sprint_size (p->mtu, b1));
@@ -282,12 +282,11 @@ static int print_police(struct action_util *a, FILE *f, struct rtattr *arg) prate64 =rta_getattr_u64 (tb[TCA_POLICE_PEAKRATE64 ]);if (prate64) -fprintf (f,"peakrate %s " ,sprint_rate (prate64, b1)); +tc_print_rate (PRINT_FP ,NULL ,"peakrate %s " , prate64);if (tb[TCA_POLICE_AVRATE ]) -fprintf (f,"avrate %s " , -sprint_rate (rta_getattr_u32 (tb[TCA_POLICE_AVRATE ]), - b1)); +tc_print_rate (PRINT_FP ,NULL ,"avrate %s " , +rta_getattr_u32 (tb[TCA_POLICE_AVRATE ]));print_action_control (f,"action " , p->action,"" );
tc/q_cake.c +16 -12
@@ -445,11 +445,10 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (tb[TCA_CAKE_BASE_RATE64 ] &&RTA_PAYLOAD (tb[TCA_CAKE_BASE_RATE64 ]) >=sizeof (bandwidth)) { bandwidth =rta_getattr_u64 (tb[TCA_CAKE_BASE_RATE64 ]); -if (bandwidth) { -print_uint (PRINT_JSON ,"bandwidth" ,NULL , bandwidth); -print_string (PRINT_FP ,NULL ,"bandwidth %s " , -sprint_rate (bandwidth, b1)); - }else +if (bandwidth) +tc_print_rate (PRINT_ANY ,"bandwidth" ,"bandwidth %s " , + bandwidth); +else print_string (PRINT_ANY ,"bandwidth" ,"bandwidth %s " ,"unlimited" ); }
@@ -650,12 +649,10 @@ static int cake_print_xstats(struct qdisc_util *qu, FILE *f, GET_STAT_U32(MEMORY_LIMIT)); } -if (st[TCA_CAKE_STATS_CAPACITY_ESTIMATE64 ]) { -print_string (PRINT_FP ,NULL ," capacity estimate: %s\n" , -sprint_rate (GET_STAT_U64 (CAPACITY_ESTIMATE64 ), b1)); -print_uint (PRINT_JSON ,"capacity_estimate" ,NULL , -GET_STAT_U64 (CAPACITY_ESTIMATE64 )); - } +if (st[TCA_CAKE_STATS_CAPACITY_ESTIMATE64 ]) +tc_print_rate (PRINT_ANY ,"capacity_estimate" , +" capacity estimate: %s\n" , +GET_STAT_U64 (CAPACITY_ESTIMATE64 ));if (st[TCA_CAKE_STATS_MIN_NETLEN ] && st[TCA_CAKE_STATS_MAX_NETLEN ]) {
@@ -790,7 +787,14 @@ static int cake_print_xstats(struct qdisc_util *qu, FILE *f,#define PRINT_TSTAT_U64 (name, attr) PRINT_TSTAT( \ name, attr, "llu", rta_getattr_u64(GET_TSTAT(i, attr))) -SPRINT_TSTAT (rate, u64," thresh " ,THRESHOLD_RATE64 ); +if (GET_TSTAT (0 ,THRESHOLD_RATE64 )) { +fprintf (f," thresh " ); +for (i =0 ; i < num_tins; i++) +tc_print_rate (PRINT_FP ,NULL ," %12s" , +rta_getattr_u64 (GET_TSTAT (i,THRESHOLD_RATE64 ))); +fprintf (f,"%s" , _SL_); + } +SPRINT_TSTAT (time, u32," target " ,TARGET_US );SPRINT_TSTAT (time, u32," interval" ,INTERVAL_US );SPRINT_TSTAT (time, u32," pk_delay" ,PEAK_DELAY_US );
tc/q_cbq.c +4 -10
@@ -497,10 +497,7 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) }if (r) { -char buf[64 ]; - -print_rate (buf,sizeof (buf), r->rate); -fprintf (f,"rate %s " , buf); +tc_print_rate (PRINT_FP ,NULL ,"rate %s " , r->rate); linklayer = (r->linklayer &TC_LINKLAYER_MASK );if (linklayer >TC_LINKLAYER_ETHERNET || show_details)fprintf (f,"linklayer %s " ,sprint_linklayer (linklayer, b2));
@@ -533,13 +530,10 @@ static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)else fprintf (f,"prio no-transmit" );if (show_details) { -char buf[64 ]; -fprintf (f,"/%u " , wrr->cpriority); -if (wrr->weight !=1 ) { -print_rate (buf,sizeof (buf), wrr->weight); -fprintf (f,"weight %s " , buf); - } +if (wrr->weight !=1 ) +tc_print_rate (PRINT_FP ,NULL ,"weight %s " , + wrr->weight);if (wrr->allot)fprintf (f,"allot %ub " , wrr->allot); }
tc/q_fq.c +9 -16
@@ -330,32 +330,25 @@ static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) RTA_PAYLOAD(tb[TCA_FQ_FLOW_MAX_RATE]) >= sizeof(__u32)) { rate =rta_getattr_u32 (tb[TCA_FQ_FLOW_MAX_RATE ]); -if (rate != ~0U ) { -print_uint (PRINT_JSON ,"maxrate" ,NULL , rate); -print_string (PRINT_FP ,NULL ,"maxrate %s " , -sprint_rate (rate, b1)); - } +if (rate != ~0U ) +tc_print_rate (PRINT_ANY , +"maxrate" ,"maxrate %s " , rate); }if (tb[TCA_FQ_FLOW_DEFAULT_RATE ] &&RTA_PAYLOAD (tb[TCA_FQ_FLOW_DEFAULT_RATE ]) >=sizeof (__u32)) { rate =rta_getattr_u32 (tb[TCA_FQ_FLOW_DEFAULT_RATE ]); -if (rate !=0 ) { -print_uint (PRINT_JSON ,"defrate" ,NULL , rate); -print_string (PRINT_FP ,NULL ,"defrate %s " , -sprint_rate (rate, b1)); - } +if (rate !=0 ) +tc_print_rate (PRINT_ANY , +"defrate" ,"defrate %s " , rate); }if (tb[TCA_FQ_LOW_RATE_THRESHOLD ] &&RTA_PAYLOAD (tb[TCA_FQ_LOW_RATE_THRESHOLD ]) >=sizeof (__u32)) { rate =rta_getattr_u32 (tb[TCA_FQ_LOW_RATE_THRESHOLD ]); -if (rate !=0 ) { -print_uint (PRINT_JSON ,"low_rate_threshold" ,NULL , - rate); -print_string (PRINT_FP ,NULL ,"low_rate_threshold %s " , -sprint_rate (rate, b1)); - } +if (rate !=0 ) +tc_print_rate (PRINT_ANY ,"low_rate_threshold" , +"low_rate_threshold %s " , rate); }if (tb[TCA_FQ_FLOW_REFILL_DELAY ] &&RTA_PAYLOAD (tb[TCA_FQ_FLOW_REFILL_DELAY ]) >=sizeof (__u32)) {
tc/q_hfsc.c +2 -2
@@ -219,9 +219,9 @@ hfsc_print_sc(FILE *f, char *name, struct tc_service_curve *sc)SPRINT_BUF (b1);fprintf (f,"%s " , name); -fprintf (f,"m1 %s " ,sprint_rate (sc->m1, b1)); +tc_print_rate (PRINT_FP ,NULL ,"m1 %s " , sc->m1);fprintf (f,"d %s " ,sprint_time (tc_core_ktime2time (sc->d), b1)); -fprintf (f,"m2 %s " ,sprint_rate (sc->m2, b1)); +tc_print_rate (PRINT_FP ,NULL ,"m2 %s " , sc->m2); } static int
tc/q_htb.c +2 -2
@@ -299,12 +299,12 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) RTA_PAYLOAD(tb[TCA_HTB_CEIL64]) >= sizeof(ceil64)) ceil64 =rta_getattr_u64 (tb[TCA_HTB_CEIL64 ]); -fprintf (f,"rate %s " ,sprint_rate (rate64, b1)); +tc_print_rate (PRINT_FP ,NULL ,"rate %s " , rate64);if (hopt->rate.overhead)fprintf (f,"overhead %u " , hopt->rate.overhead); buffer =tc_calc_xmitsize (rate64, hopt->buffer); -fprintf (f,"ceil %s " ,sprint_rate (ceil64, b1)); +tc_print_rate (PRINT_FP ,NULL ,"ceil %s " , ceil64); cbuffer =tc_calc_xmitsize (ceil64, hopt->cbuffer); linklayer = (hopt->rate.linklayer &TC_LINKLAYER_MASK );if (linklayer >TC_LINKLAYER_ETHERNET || show_details)
tc/q_mqprio.c +2 -4
@@ -230,8 +230,6 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)__u64 max_rate64[TC_QOPT_MAX_QUEUE ] = {0 };int len; -SPRINT_BUF (b1); -if (opt ==NULL )return 0 ;
@@ -295,7 +293,7 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) }open_json_array (PRINT_ANY ,is_json_context () ?"min_rate" :" min_rate:" );for (i =0 ; i < qopt->num_tc; i++) -print_string (PRINT_ANY ,NULL ,"%s " ,sprint_rate (min_rate64[i], b1)); +tc_print_rate (PRINT_ANY ,NULL ,"%s " , min_rate64[i]);close_json_array (PRINT_ANY ,"" ); }
@@ -312,7 +310,7 @@ static int mqprio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) }open_json_array (PRINT_ANY ,is_json_context () ?"max_rate" :" max_rate:" );for (i =0 ; i < qopt->num_tc; i++) -print_string (PRINT_ANY ,NULL ,"%s " ,sprint_rate (max_rate64[i], b1)); +tc_print_rate (PRINT_ANY ,NULL ,"%s " , max_rate64[i]);close_json_array (PRINT_ANY ,"" ); } }
tc/q_netem.c +1 -3
@@ -800,9 +800,7 @@ static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (rate && rate->rate) {open_json_object ("rate" ); rate64 = rate64 ? : rate->rate; -print_string (PRINT_FP ,NULL ," rate %s" , -sprint_rate (rate64, b1)); -print_lluint (PRINT_JSON ,"rate" ,NULL , rate64); +tc_print_rate (PRINT_ANY ,"rate" ," rate %s" , rate64);PRINT_INT_OPT ("packetoverhead" , rate->packet_overhead); print_uint(PRINT_ANY, "cellsize", rate->cell_size ? " cellsize %u" : "",
tc/q_tbf.c +2 -5
@@ -286,8 +286,7 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)if (tb[TCA_TBF_RATE64 ] &&RTA_PAYLOAD (tb[TCA_TBF_RATE64 ]) >=sizeof (rate64)) rate64 =rta_getattr_u64 (tb[TCA_TBF_RATE64 ]); -print_u64 (PRINT_JSON ,"rate" ,NULL , rate64); -print_string (PRINT_FP ,NULL ,"rate %s " ,sprint_rate (rate64, b1)); +tc_print_rate (PRINT_ANY ,"rate" ,"rate %s " , rate64); buffer =tc_calc_xmitsize (rate64, qopt->buffer);if (show_details) { sprintf(b1, "%s/%u", sprint_size(buffer, b2),
@@ -308,9 +307,7 @@ static int tbf_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) RTA_PAYLOAD(tb[TCA_TBF_PRATE64]) >= sizeof(prate64)) prate64 =rta_getattr_u64 (tb[TCA_TBF_PRATE64 ]);if (prate64) { -print_u64 (PRINT_JSON ,"peakrate" ,NULL , prate64); -print_string (PRINT_FP ,NULL ,"peakrate %s " , -sprint_rate (prate64, b1)); +tc_print_rate (PRINT_FP ,"peakrate" ,"peakrate %s " , prate64);if (qopt->mtu || qopt->peakrate.mpu) { mtu =tc_calc_xmitsize (prate64, qopt->mtu);if (show_details) {
tc/tc_util.c +7 -30
@@ -326,31 +326,10 @@ int get_rate64(__u64 *rate, const char *str)return 0 ; } -void print_rate (char *buf,int len,__u64 rate) +void tc_print_rate (enum output_type t,const char *key,const char *fmt, +unsigned long long rate) { -extern int use_iec; -unsigned long kilo = use_iec ?1024 :1000 ; -const char *str = use_iec ?"i" :"" ; -static char *units[5 ] = {"" ,"K" ,"M" ,"G" ,"T" }; -int i; - - rate <<=3 ;/* bytes/sec -> bits/sec */ - -for (i =0 ; i <ARRAY_SIZE (units) -1 ; i++) { -if (rate < kilo) -break ; -if (((rate % kilo) !=0 ) && rate <1000 *kilo) -break ; - rate /= kilo; - } - -snprintf (buf, len,"%.0f%s%sbit" , (double )rate, units[i], str); -} - -char *sprint_rate (__u64 rate,char *buf) -{ -print_rate (buf,SPRINT_BSIZE -1 , rate); -return buf; +print_rate (use_iec, t, key, fmt, rate); }char *sprint_ticks (__u32 ticks,char *buf)
@@ -853,8 +832,7 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat sizeof(re)));print_string (PRINT_FP ,NULL ,"\n%s" , prefix);print_lluint (PRINT_JSON ,"rate" ,NULL , re.bps); -print_string (PRINT_FP ,NULL ,"rate %s" , -sprint_rate (re.bps, b1)); +tc_print_rate (PRINT_FP ,NULL ,"rate %s" , re.bps);print_lluint (PRINT_ANY ,"pps" ," %llupps" , re.pps); }else if (tbs[TCA_STATS_RATE_EST ]) {struct gnet_stats_rate_est re = {0 };
@@ -863,8 +841,7 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));print_string (PRINT_FP ,NULL ,"\n%s" , prefix);print_uint (PRINT_JSON ,"rate" ,NULL , re.bps); -print_string (PRINT_FP ,NULL ,"rate %s" , -sprint_rate (re.bps, b1)); +tc_print_rate (PRINT_FP ,NULL ,"rate %s" , re.bps);print_uint (PRINT_ANY ,"pps" ," %upps" , re.pps); }
@@ -916,8 +893,8 @@ void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix,if (st.bps || st.pps) {fprintf (fp,"rate " );if (st.bps) -fprintf (fp,"%s " , -sprint_rate (st.bps, b1)); +tc_print_rate (PRINT_FP ,NULL ,"%s " , + st.bps);if (st.pps)fprintf (fp,"%upps " , st.pps); }
tc/tc_util.h +2 -2
@@ -84,10 +84,10 @@ int get_size(unsigned int *size, const char *str);int get_size_and_cell (unsigned int *size,int *cell_log,char *str);int get_linklayer (unsigned int *val,const char *arg); -void print_rate (char *buf,int len,__u64 rate); +void tc_print_rate (enum output_type t,const char *key,const char *fmt, +unsigned long long rate);void print_devname (enum output_type type,int ifindex); -char *sprint_rate (__u64 rate,char *buf);char *sprint_size (__u32 size,char *buf);char *sprint_tc_classid (__u32 h,char *buf);char *sprint_ticks (__u32 ticks,char *buf);
Signature · 1 line
2.25.1
v2 cover Move rate and size parsing and output to lib
The DCB tool will have commands that deal with buffer sizes and traffic rates. TC is another tool that has a number of such commands, and functions to support them: get_size(), get_rate/64(), s/print_size() and s/print_rate(). In this patchset, these functions are moved from TC to lib/ for possible reuse and modernized.
s/print_rate() has a hidden parameter of a global variable use_iec, which made the conversion non-trivial. The parameter was made explicit, print_rate() converted to a mostly json_print-like function, and sprint_rate() retired in favor of the new print_rate. Patches #1 and #2 deal with this.
The intention was to treat s/print_size() similarly, but unfortunately two use cases of sprint_size() cannot be converted to a json_print-like print_size(), and the function sprint_size() had to remain as a discouraged backdoor to print_size(). This is done in patch #3.
Patch #4 then improves the code of sprint_size() a little bit.
Patch #5 fixes a buglet in formatting small rates in IEC mode.
Patches #6 and #7 handle a routine movement of, respectively, get_rate/64() and get_size() from tc to lib.
This patchset does not actually add any new uses of these functions. A follow-up patchset will add subtools for management of DCB buffer and DCB maxrate objects that will make use of them.
v2:
- Patch #2:
- Adapt q_mqprio.c patch, the file changed since v1.
- Patch #4:
- This patch is new. It addresses a request from Stephen Hemminger to clean up the sprint_size() function.
Petr Machata (7):
Move the use_iec declaration to the tools
lib: Move print_rate() from tc here; modernize
lib: Move sprint_size() from tc here, add print_size()
lib: sprint_size(): Uncrustify the code a bit
lib: print_color_rate(): Fix formatting small rates in IEC mode
lib: Move get_rate(), get_rate64() from tc here
lib: Move get_size() from tc here
include/json_print.h | 14 ++++ include/utils.h | 4 +- ip/ip_common.h | 2 + lib/json_print.c | 63 +++++++++++++++ lib/utils.c | 114 +++++++++++++++++++++++++++ tc/m_gate.c | 6 +- tc/m_police.c | 14 ++-- tc/q_cake.c | 44 +++++------ tc/q_cbq.c | 14 +--- tc/q_drr.c | 10 +-- tc/q_fifo.c | 10 +-- tc/q_fq.c | 34 +++----- tc/q_fq_codel.c | 5 +- tc/q_fq_pie.c | 9 +-- tc/q_gred.c | 39 ++-------- tc/q_hfsc.c | 4 +- tc/q_hhf.c | 9 +-- tc/q_htb.c | 23 +++--- tc/q_mqprio.c | 6 +- tc/q_netem.c | 4 +- tc/q_red.c | 13 +--- tc/q_sfq.c | 15 +--- tc/q_tbf.c | 32 +++----- tc/tc_common.h | 1 + tc/tc_util.c | 180 +++---------------------------------------- tc/tc_util.h | 8 +- 26 files changed, 307 insertions(+), 370 deletions(-)
Signature · 1 line
2.25.1
PATCH v2 7/7 lib: Move get_size() from tc here
The function get_size() serves for parsing of sizes using a handly notation that supports units and their prefixes, such as 10Kbit. This will be useful for the DCB buffer size parsing. Move the function from TC to the general library, so that it can be reused.
--- include/utils.h | 1 + lib/utils.c | 35 +++++++++++++++++++++++++++++++++++ tc/tc_util.c | 35 ----------------------------------- tc/tc_util.h | 1 - 4 files changed, 36 insertions(+), 36 deletions(-)
include/utils.h +1 -0
@@ -164,6 +164,7 @@ int get_be16(__be16 *val, const char *arg, int base);int get_addr64 (__u64 *ap,const char *cp);int get_rate (unsigned int *rate,const char *str);int get_rate64 (__u64 *rate,const char *str); +int get_size (unsigned int *size,const char *str);int hex2mem (const char *buf,uint8_t *mem,int count);char *hexstring_n2a (const __u8 *str,int len,char *buf,int blen);
lib/utils.c +35 -0
@@ -592,6 +592,41 @@ int get_rate64(__u64 *rate, const char *str)return 0 ; } +int get_size (unsigned int *size,const char *str) +{ +double sz; +char *p; + + sz =strtod (str, &p); +if (p == str) +return -1 ; + +if (*p) { +if (strcasecmp (p,"kb" ) ==0 ||strcasecmp (p,"k" ) ==0 ) + sz *=1024 ; +else if (strcasecmp (p,"gb" ) ==0 ||strcasecmp (p,"g" ) ==0 ) + sz *=1024 *1024 *1024 ; +else if (strcasecmp (p,"gbit" ) ==0 ) + sz *=1024 *1024 *1024 /8 ; +else if (strcasecmp (p,"mb" ) ==0 ||strcasecmp (p,"m" ) ==0 ) + sz *=1024 *1024 ; +else if (strcasecmp (p,"mbit" ) ==0 ) + sz *=1024 *1024 /8 ; +else if (strcasecmp (p,"kbit" ) ==0 ) + sz *=1024 /8 ; +else if (strcasecmp (p,"b" ) !=0 ) +return -1 ; + } + + *size = sz; + +/* detect if an overflow happened */ +if (*size !=floor (sz)) +return -1 ; + +return 0 ; +} +static void set_address_type (inet_prefix *addr) {switch (addr->family) {
tc/tc_util.c +0 -35
@@ -258,41 +258,6 @@ char *sprint_ticks(__u32 ticks, char *buf)return sprint_time (tc_core_tick2time (ticks), buf); } -int get_size (unsigned int *size,const char *str) -{ -double sz; -char *p; - - sz =strtod (str, &p); -if (p == str) -return -1 ; - -if (*p) { -if (strcasecmp (p,"kb" ) ==0 ||strcasecmp (p,"k" ) ==0 ) - sz *=1024 ; -else if (strcasecmp (p,"gb" ) ==0 ||strcasecmp (p,"g" ) ==0 ) - sz *=1024 *1024 *1024 ; -else if (strcasecmp (p,"gbit" ) ==0 ) - sz *=1024 *1024 *1024 /8 ; -else if (strcasecmp (p,"mb" ) ==0 ||strcasecmp (p,"m" ) ==0 ) - sz *=1024 *1024 ; -else if (strcasecmp (p,"mbit" ) ==0 ) - sz *=1024 *1024 /8 ; -else if (strcasecmp (p,"kbit" ) ==0 ) - sz *=1024 /8 ; -else if (strcasecmp (p,"b" ) !=0 ) -return -1 ; - } - - *size = sz; - -/* detect if an overflow happened */ -if (*size !=floor (sz)) -return -1 ; - -return 0 ; -} -int get_size_and_cell (unsigned int *size,int *cell_log,char *str) {char *slash =strchr (str,'/' );
tc/tc_util.h +0 -1
@@ -78,7 +78,6 @@ struct filter_util *get_filter_kind(const char *str);int get_qdisc_handle (__u32 *h,const char *str);int get_percent_rate (unsigned int *rate,const char *str,const char *dev);int get_percent_rate64 (__u64 *rate,const char *str,const char *dev); -int get_size (unsigned int *size,const char *str);int get_size_and_cell (unsigned int *size,int *cell_log,char *str);int get_linklayer (unsigned int *val,const char *arg);
Signature · 1 line
2.25.1
David Ahern
AppliedQuoted 28 lines · Petr Machata
The DCB tool will have commands that deal with buffer sizes and traffic rates. TC is another tool that has a number of such commands, and functions to support them:
get_size(), get_rate/64(), s/print_size() and s/print_rate(). In this patchset, these functions are moved from TC tolib/for possible reuse and modernized.s/print_rate() has a hidden parameter of a global variable
use_iec, which made the conversion non-trivial. The parameter was made explicit,print_rate()converted to a mostly json_print-like function, andsprint_rate()retired in favor of the newprint_rate. Patches #1 and #2 deal with this.The intention was to treat s/print_size() similarly, but unfortunately two use cases of
sprint_size()cannot be converted to a json_print-likeprint_size(), and the functionsprint_size()had to remain as a discouraged backdoor toprint_size(). This is done in patch #3.Patch #4 then improves the code of
sprint_size()a little bit.Patch #5 fixes a buglet in formatting small rates in IEC mode.
Patches #6 and #7 handle a routine movement of, respectively, get_rate/64() and
get_size()from tc to lib.This patchset does not actually add any new uses of these functions. A follow-up patchset will add subtools for management of DCB buffer and DCB maxrate objects that will make use of them.
Quoted 8 lines
v2:
- Patch #2:
- Adaptq_mqprio.cpatch, the file changed since v1.
- Patch #4:
- This patch is new. It addresses a request from Stephen Hemminger to clean up thesprint_size()function.
applied to iproute2-next. Thanks, Petr