: Time cleanups + nano-second clock resolution support
Subsystems (2)
cover : Time cleanups + nano-second clock resolution support
This patchset consists of four parts:
- minor TBF time conversion fix
- consolidation of time calculations: consolidate commonly used expressions with the goal of making it easier to audit for integer overflows when increasing the internally used clock resolution.
- support for detecting the clock resolution used by the kernel and converting time values as necessary.
- finally, increase the internally used clock resolution to nano-seconds
These patches have been tested (well, TBF and HFSC) with both old kernels and patched kernels using nano-second resolution.
tc/m_estimator.c | 4 +-- tc/m_police.c | 2 - tc/q_cbq.c | 15 +++++++------ tc/q_hfsc.c | 18 +++++++-------- tc/q_htb.c | 4 +-- tc/q_netem.c | 14 +++--------- tc/q_tbf.c | 22 +++++++++---------- tc/tc_cbq.c | 8 +++---- tc/tc_core.c | 61 ++++++++++++++++++++++++++++++++++++++---------------- tc/tc_core.h | 13 +++++++---- tc/tc_estimator.c | 2 - tc/tc_red.c | 2 - tc/tc_util.c | 40 ++++++++++++++++++++++------------- tc/tc_util.h | 7 +++--- 14 files changed, 125 insertions(+), 87 deletions(-)
Patrick McHardy:
[IPROUTE]: tbf: fix latency printing
[IPROUTE]: Use tc_calc_xmittime() where appropriate
[IPROUTE]: Introduce tc_calc_xmitsize and use where appropriate [IPROUTE]: Introduce TIME_UNITS_PER_SEC to represent internal clock resolution [IPROUTE]: Replace "usec" by "time" in function names
[IPROUTE]: Add sprint_ticks() function and use in CBQ
[IPROUTE]: Handle different kernel clock resolutions
[IPROUTE]: Increase internal clock resolution to nsec
RFC 1/8 : tbf: fix latency printing
[IPROUTE]: tbf: fix latency printing
The calculated latency is already in usecs, the additional tick2usec conversion breaks the calculation with jiffies or tsc clock source.
Example:
# tc qdisc add dev dummy0 root tbf latency 20ms burst 10k rate 50mbit # tc qdisc show dev dummy0 qdisc tbf 8002: rate 50000Kbit burst 10Kb lat 15.4ms
Fixed:
# tc qdisc show dev dummy0 qdisc tbf 8002: rate 50000Kbit burst 10Kb lat 20ms
---
commit b17ff630348093476b7679b421aba1797f3d6466
tree 95acccdac41e6eeeb0a9b270b43d8e0c747f2524
parent 40076f622e0aacb2b792d3ac1b5d12aa97c4da9c
author Patrick McHardy <[email protected]> Sat, 03 Mar 2007 19:31:16 +0100 committer Patrick McHardy <[email protected]> Sat, 03 Mar 2007 19:31:16 +0100
tc/q_tbf.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
tc/q_tbf.c +1 -1
@@ -251,7 +251,7 @@ static int tbf_print_opt(struct qdisc_utif (lat2 > latency) latency = lat2; } -fprintf (f,"lat %s " ,sprint_usecs (tc_core_tick2usec (latency), b1)); +fprintf (f,"lat %s " ,sprint_usecs (latency, b1));return 0 ; }
RFC 2/8 : Use tc_calc_xmittime() where appropriate
In reply to Patrick McHardy[IPROUTE]: Use tc_calc_xmittime() where appropriate
Replace expressions of the form "tc_core_usec2tick(1000000 * size/rate)" by tc_calc_xmittime().
The CBQ case deserves an extra comment: when called with bnwd=rate, tc_cbq_calc_maxidle() behaves identical to tc_calc_xmittime():
unsigned tc_cbq_calc_maxidle(...)
{
double g = 1.0 - 1.0/(1<<ewma_log);
double xmt = (double)avpkt/bndw;
maxidle = xmt*(1-g);
if (bndw != rate && maxburst) {
...
}
return tc_core_usec2tick(maxidle*(1<<ewma_log)*1000000);
}which comes down to:
maxidle = xmt * (1 - g)
= xmt * (1 - (1.0 - 1.0/(1 << ewma_log)) = xmt * (1.0/(1 << ewma_log))
so:
maxidle * (1 << ewma_log) * 1000000
= xmt * (1.0/(1 << ewma_log)) * (1 << ewma_log) * 1000000 = xmt * 1000000 = avpkt/bndw * 1000000
Which means tc_core_usec2tick(maxidle*(1<<ewma_log)*1000000) is identical to tc_calc_xmittime(bndw, avpkt). Use it directly since its a lot easier to understand its limits.
---
commit a367af8046d31e986740aac45677c8fe8910c293
tree 056436a16da372e602f43259609e54bb3e7dce16
parent b17ff630348093476b7679b421aba1797f3d6466
author Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:47 +0100 committer Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:47 +0100
tc/q_cbq.c | 2 +- tc/tc_core.c | 2 +- tc/tc_red.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
tc/q_cbq.c +1 -1
@@ -147,7 +147,7 @@ static int cbq_parse_opt(struct qdisc_utif (ewma_log <0 ) ewma_log =TC_CBQ_DEF_EWMA ; lss.ewma_log = ewma_log; - lss.maxidle =tc_cbq_calc_maxidle (r.rate, r.rate, avpkt, lss.ewma_log,0 ); + lss.maxidle =tc_calc_xmittime (r.rate, avpkt); lss.change =TCF_CBQ_LSS_MAXIDLE |TCF_CBQ_LSS_EWMA |TCF_CBQ_LSS_AVPKT ; lss.avpkt = avpkt;
tc/tc_core.c +1 -1
@@ -76,7 +76,7 @@ int tc_calc_rtable(unsigned bps, __u32 * sz += overhead;if (sz < mpu) sz = mpu; - rtab[i] =tc_core_usec2tick (1000000 *((double )sz/bps)); + rtab[i] =tc_calc_xmittime (bps, sz); }return cell_log; }
tc/tc_red.c +1 -1
@@ -71,7 +71,7 @@ int tc_red_eval_ewma(unsigned qmin, unsiint tc_red_eval_idle_damping (int Wlog,unsigned avpkt,unsigned bps,__u8 *sbuf) { -double xmit_time =tc_core_usec2tick (1000000 *(double )avpkt/bps); +double xmit_time =tc_calc_xmittime (bps, avpkt);double lW = -log (1.0 -1.0 /(1 <<Wlog))/xmit_time;double maxtime =31 /lW;int clog;
RFC 3/8 : Introduce tc_calc_xmitsize and use where appropriate
In reply to Patrick McHardy[IPROUTE]: Introduce tc_calc_xmitsize and use where appropriate
Add tc_calc_xmitsize() as complement to tc_calc_xmittime(), which calculates the size that can be transmitted at a given rate during a given time.
Replace all expressions of the form "size = rate*tc_core_tick2usec(time))/1000000" by tc_calc_xmitsize() calls.
---
commit 8b41013e2abb8eb6d3c960911d2ce137b40ccd50
tree 85068a3019ad77563ae82b9277bd13f3a6de19ba
parent a367af8046d31e986740aac45677c8fe8910c293
author Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100 committer Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100
tc/m_police.c | 2 +- tc/q_htb.c | 4 ++-- tc/q_tbf.c | 4 ++-- tc/tc_core.c | 5 +++++ tc/tc_core.h | 1 + 5 files changed, 11 insertions(+), 5 deletions(-)
tc/m_police.c +1 -1
@@ -331,7 +331,7 @@ #endiffprintf (f," police 0x%x " , p->index);fprintf (f,"rate %s " ,sprint_rate (p->rate.rate, b1)); - buffer = ((double )p->rate.rate*tc_core_tick2usec (p->burst))/1000000 ; + buffer =tc_calc_xmitsize (p->rate.rate, p->burst);fprintf (f,"burst %s " ,sprint_size (buffer, b1));fprintf (f,"mtu %s " ,sprint_size (p->mtu, b1));if (show_raw)
tc/q_htb.c +2 -2
@@ -259,9 +259,9 @@ static int htb_print_opt(struct qdisc_utfprintf (f,"quantum %d " , (int )hopt->quantum); }fprintf (f,"rate %s " ,sprint_rate (hopt->rate.rate, b1)); - buffer = ((double )hopt->rate.rate*tc_core_tick2usec (hopt->buffer))/1000000 ; + buffer =tc_calc_xmitsize (hopt->rate.rate, hopt->buffer);fprintf (f,"ceil %s " ,sprint_rate (hopt->ceil.rate, b1)); - cbuffer = ((double )hopt->ceil.rate*tc_core_tick2usec (hopt->cbuffer))/1000000 ; + cbuffer =tc_calc_xmitsize (hopt->ceil.rate, hopt->cbuffer);if (show_details) { fprintf(f, "burst %s/%u mpu %s overhead %s ", sprint_size(buffer, b1),
tc/q_tbf.c +2 -2
@@ -218,7 +218,7 @@ static int tbf_print_opt(struct qdisc_utif (RTA_PAYLOAD (tb[TCA_TBF_PARMS ]) <sizeof (*qopt))return -1 ;fprintf (f,"rate %s " ,sprint_rate (qopt->rate.rate, b1)); - buffer = ((double )qopt->rate.rate*tc_core_tick2usec (qopt->buffer))/1000000 ; + buffer =tc_calc_xmitsize (qopt->rate.rate, qopt->buffer);if (show_details) {fprintf (f,"burst %s/%u mpu %s " ,sprint_size (buffer, b1),1 <<qopt->rate.cell_log,sprint_size (qopt->rate.mpu, b2));
@@ -230,7 +230,7 @@ static int tbf_print_opt(struct qdisc_utif (qopt->peakrate.rate) {fprintf (f,"peakrate %s " ,sprint_rate (qopt->peakrate.rate, b1));if (qopt->mtu || qopt->peakrate.mpu) { - mtu = ((double )qopt->peakrate.rate*tc_core_tick2usec (qopt->mtu))/1000000 ; + mtu =tc_calc_xmitsize (qopt->peakrate.rate, qopt->mtu);if (show_details) {fprintf (f,"mtu %s/%u mpu %s " ,sprint_size (mtu, b1),1 <<qopt->peakrate.cell_log,sprint_size (qopt->peakrate.mpu, b2));
tc/tc_core.c +5 -0
@@ -51,6 +51,11 @@ unsigned tc_calc_xmittime(unsigned rate,return tc_core_usec2tick (1000000 *((double )size/rate)); } +unsigned tc_calc_xmitsize (unsigned rate,unsigned ticks) +{ +return ((double )rate*tc_core_tick2usec (ticks))/1000000 ; +} +/* rtab[pkt_len>>cell_log] = pkt_xmit_time */
tc/tc_core.h +1 -0
@@ -8,6 +8,7 @@ int tc_core_usec2big(long usec);long tc_core_usec2tick (long usec);long tc_core_tick2usec (long tick);unsigned tc_calc_xmittime (unsigned rate,unsigned size); +unsigned tc_calc_xmitsize (unsigned rate,unsigned ticks);int tc_calc_rtable (unsigned bps,__u32 *rtab,int cell_log,unsigned mtu,unsigned mpu);int tc_setup_estimator (unsigned A ,unsigned time_const,struct tc_estimator *est);
RFC 4/8 : Introduce TIME_UNITS_PER_SEC to represent internal clock resolution
In reply to Patrick McHardy[IPROUTE]: Introduce TIME_UNITS_PER_SEC to represent internal clock resolution
Introduce TIME_UNITS_PER_SEC and conversion functions between internal resolution and resolution expected by the kernel (currently implemented as NOPs, only needed by HFSC, which currently always uses microseconds).
---
commit d81b168f4017e45343cdd723e653401058f728e9
tree 7e28041ff488f863e79d8745fde85aaed30dd4ac
parent 8b41013e2abb8eb6d3c960911d2ce137b40ccd50
author Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100 committer Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100
tc/q_hfsc.c | 12 ++++++------ tc/q_tbf.c | 8 ++++---- tc/tc_cbq.c | 4 ++-- tc/tc_core.c | 14 ++++++++++++-- tc/tc_core.h | 4 ++++ tc/tc_estimator.c | 2 +- tc/tc_util.c | 14 +++++++------- 7 files changed, 36 insertions(+), 22 deletions(-)
tc/q_hfsc.c +6 -6
@@ -226,7 +226,7 @@ hfsc_print_sc(FILE *f, char *name, strucfprintf (f,"%s " , name);fprintf (f,"m1 %s " ,sprint_rate (sc->m1, b1)); -fprintf (f,"d %s " ,sprint_usecs (sc->d, b1)); +fprintf (f,"d %s " ,sprint_usecs (tc_core_ktime2time (sc->d), b1));fprintf (f,"m2 %s " ,sprint_rate (sc->m2, b1)); }
@@ -320,7 +320,7 @@ hfsc_get_sc1(int *argcp, char ***argvp,return -1 ; sc->m1 = m1; - sc->d = d; + sc->d =tc_core_time2ktime (d); sc->m2 = m2; *argvp = argv;
@@ -367,13 +367,13 @@ hfsc_get_sc2(int *argcp, char ***argvp,return -1 ; } -if (dmax !=0 &&ceil (umax *1000000.0 / dmax) > rate) { +if (dmax !=0 &&ceil (1.0 * umax *TIME_UNITS_PER_SEC / dmax) > rate) {/* * concave curve, slope of first segment is umax/dmax, * intersection is at dmax */ - sc->m1 =ceil (umax *1000000.0 / dmax);/* in bps */ - sc->d = dmax; + sc->m1 =ceil (1.0 * umax *TIME_UNITS_PER_SEC / dmax);/* in bps */ + sc->d =tc_core_time2ktime (dmax); sc->m2 = rate; }else {/*
@@ -381,7 +381,7 @@ hfsc_get_sc2(int *argcp, char ***argvp,* is at dmax - umax / rate */ sc->m1 =0 ; - sc->d =ceil (dmax - umax *1000000.0 / rate);/* in usec */ + sc->d =tc_core_time2ktime (ceil (dmax - umax *TIME_UNITS_PER_SEC / rate)); sc->m2 = rate; }
tc/q_tbf.c +4 -4
@@ -161,9 +161,9 @@ static int tbf_parse_opt(struct qdisc_ut }if (opt.limit ==0 ) { -double lim = opt.rate.rate*(double )latency/1000000 + buffer; +double lim = opt.rate.rate*(double )latency/TIME_UNITS_PER_SEC + buffer;if (opt.peakrate.rate) { -double lim2 = opt.peakrate.rate*(double )latency/1000000 + mtu; +double lim2 = opt.peakrate.rate*(double )latency/TIME_UNITS_PER_SEC + mtu;if (lim2 < lim) lim = lim2; }
@@ -245,9 +245,9 @@ static int tbf_print_opt(struct qdisc_utif (show_raw)fprintf (f,"limit %s " ,sprint_size (qopt->limit, b1)); - latency =1000000 *(qopt->limit/(double )qopt->rate.rate) -tc_core_tick2usec (qopt->buffer); + latency =TIME_UNITS_PER_SEC *(qopt->limit/(double )qopt->rate.rate) -tc_core_tick2usec (qopt->buffer);if (qopt->peakrate.rate) { -double lat2 =1000000 *(qopt->limit/(double )qopt->peakrate.rate) -tc_core_tick2usec (qopt->mtu); +double lat2 =TIME_UNITS_PER_SEC *(qopt->limit/(double )qopt->peakrate.rate) -tc_core_tick2usec (qopt->mtu);if (lat2 > latency) latency = lat2; }
tc/tc_cbq.c +2 -2
@@ -38,7 +38,7 @@ unsigned tc_cbq_calc_maxidle(unsigned bnif (vxmt > maxidle) maxidle = vxmt; } -return tc_core_usec2tick (maxidle*(1 <<ewma_log)*1000000 ); +return tc_core_usec2tick (maxidle*(1 <<ewma_log)*TIME_UNITS_PER_SEC ); } unsigned tc_cbq_calc_offtime(unsigned bndw, unsigned rate, unsigned avpkt,
@@ -53,5 +53,5 @@ unsigned tc_cbq_calc_offtime(unsigned bn offtime *=pow (g, -(double )minburst) -1 ; else offtime *= 1 + (pow(g, -(double)(minburst-1)) - 1)/(1-g); -return tc_core_usec2tick (offtime*1000000 ); +return tc_core_usec2tick (offtime*TIME_UNITS_PER_SEC ); }
tc/tc_core.c +12 -2
@@ -46,14 +46,24 @@ long tc_core_tick2usec(long tick)return tick/tick_in_usec; } +long tc_core_time2ktime (long time) +{ +return time; +} + +long tc_core_ktime2time (long ktime) +{ +return ktime; +} +unsigned tc_calc_xmittime (unsigned rate,unsigned size) { -return tc_core_usec2tick (1000000 *((double )size/rate)); +return tc_core_usec2tick (TIME_UNITS_PER_SEC *((double )size/rate)); }unsigned tc_calc_xmitsize (unsigned rate,unsigned ticks) { -return ((double )rate*tc_core_tick2usec (ticks))/1000000 ; +return ((double )rate*tc_core_tick2usec (ticks))/TIME_UNITS_PER_SEC ; }/*
tc/tc_core.h +4 -0
@@ -4,9 +4,13 @@ #define _TC_CORE_H_ 1#include <asm/types.h> #include <linux/pkt_sched.h> +#define TIME_UNITS_PER_SEC 1000000 +int tc_core_usec2big (long usec);long tc_core_usec2tick (long usec);long tc_core_tick2usec (long tick); +long tc_core_time2ktime (long time); +long tc_core_ktime2time (long ktime);unsigned tc_calc_xmittime (unsigned rate,unsigned size);unsigned tc_calc_xmitsize (unsigned rate,unsigned ticks);int tc_calc_rtable (unsigned bps,__u32 *rtab,int cell_log,unsigned mtu,unsigned mpu);
tc/tc_estimator.c +1 -1
@@ -26,7 +26,7 @@ #include "tc_core.h"int tc_setup_estimator (unsigned A ,unsigned time_const,struct tc_estimator *est) {for (est->interval=0 ; est->interval<=5 ; est->interval++) { -if (A <= (1 <<est->interval)*(1000000 /4 )) +if (A <= (1 <<est->interval)*(TIME_UNITS_PER_SEC /4 ))break ; }if (est->interval >5 )
tc/tc_util.c +7 -7
@@ -221,13 +221,13 @@ int get_usecs(unsigned *usecs, const chaif (*p) {if (strcasecmp (p,"s" ) ==0 ||strcasecmp (p,"sec" )==0 ||strcasecmp (p,"secs" )==0 ) - t *=1000000 ; + t *=TIME_UNITS_PER_SEC ;else if (strcasecmp (p,"ms" ) ==0 ||strcasecmp (p,"msec" )==0 ||strcasecmp (p,"msecs" ) ==0 ) - t *=1000 ; + t *=TIME_UNITS_PER_SEC /1000 ;else if (strcasecmp (p,"us" ) ==0 ||strcasecmp (p,"usec" )==0 ||strcasecmp (p,"usecs" ) ==0 ) - t *=1 ; + t *=TIME_UNITS_PER_SEC /1000000 ;else return -1 ; }
@@ -241,10 +241,10 @@ void print_usecs(char *buf, int len, __u {double tmp = usec; -if (tmp >=1000000 ) -snprintf (buf, len,"%.1fs" , tmp/1000000 ); -else if (tmp >=1000 ) -snprintf (buf, len,"%.1fms" , tmp/1000 ); +if (tmp >=TIME_UNITS_PER_SEC ) +snprintf (buf, len,"%.1fs" , tmp/TIME_UNITS_PER_SEC ); +else if (tmp >=TIME_UNITS_PER_SEC /1000 ) +snprintf (buf, len,"%.1fms" , tmp/(TIME_UNITS_PER_SEC /1000 ));else snprintf (buf, len,"%uus" , usec); }
RFC 5/8 : Replace "usec" by "time" in function names
In reply to Patrick McHardy[IPROUTE]: Replace "usec" by "time" in function names
Rename functions containing "usec" since they don't necessarily return usec units anymore.
---
commit c2cf24282b2a051942b18fbf894a9c1b490d925c
tree 128aa960a599aee0725d723b621db651e02ffa74
parent d81b168f4017e45343cdd723e653401058f728e9
author Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100 committer Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100
tc/m_estimator.c | 4 ++-- tc/q_cbq.c | 6 +++--- tc/q_hfsc.c | 6 +++--- tc/q_netem.c | 8 ++++---- tc/q_tbf.c | 8 ++++---- tc/tc_cbq.c | 4 ++-- tc/tc_core.c | 14 +++++++------- tc/tc_core.h | 6 +++--- tc/tc_util.c | 14 +++++++------- tc/tc_util.h | 6 +++--- 10 files changed, 38 insertions(+), 38 deletions(-)
tc/m_estimator.c +2 -2
@@ -45,12 +45,12 @@ int parse_estimator(int *p_argc, char **duparg ("estimator" , *argv);if (matches (*argv,"help" ) ==0 )est_help (); -if (get_usecs (&A , *argv)) +if (get_time (&A , *argv))invarg ("estimator" ,"invalid estimator interval" );NEXT_ARG ();if (matches (*argv,"help" ) ==0 )est_help (); -if (get_usecs (&time_const, *argv)) +if (get_time (&time_const, *argv))invarg ("estimator" ,"invalid estimator time constant" );if (tc_setup_estimator (A , time_const, est) <0 ) {fprintf (stderr,"Error: estimator parameters are out of range.\n" );
tc/q_cbq.c +3 -3
@@ -500,17 +500,17 @@ static int cbq_print_opt(struct qdisc_utif (lss && show_details) {fprintf (f,"\nlevel %u ewma %u avpkt %ub " , lss->level, lss->ewma_log, lss->avpkt);if (lss->maxidle) { -fprintf (f,"maxidle %luus " ,tc_core_tick2usec (lss->maxidle>>lss->ewma_log)); +fprintf (f,"maxidle %luus " ,tc_core_tick2time (lss->maxidle>>lss->ewma_log));if (show_raw)fprintf (f,"[%08x] " , lss->maxidle); }if (lss->minidle!=0x7fffffff ) { -fprintf (f,"minidle %luus " ,tc_core_tick2usec (lss->minidle>>lss->ewma_log)); +fprintf (f,"minidle %luus " ,tc_core_tick2time (lss->minidle>>lss->ewma_log));if (show_raw)fprintf (f,"[%08x] " , lss->minidle); }if (lss->offtime) { -fprintf (f,"offtime %luus " ,tc_core_tick2usec (lss->offtime)); +fprintf (f,"offtime %luus " ,tc_core_tick2time (lss->offtime));if (show_raw)fprintf (f,"[%08x] " , lss->offtime); }
tc/q_hfsc.c +3 -3
@@ -226,7 +226,7 @@ hfsc_print_sc(FILE *f, char *name, strucfprintf (f,"%s " , name);fprintf (f,"m1 %s " ,sprint_rate (sc->m1, b1)); -fprintf (f,"d %s " ,sprint_usecs (tc_core_ktime2time (sc->d), b1)); +fprintf (f,"d %s " ,sprint_time (tc_core_ktime2time (sc->d), b1));fprintf (f,"m2 %s " ,sprint_rate (sc->m2, b1)); }
@@ -303,7 +303,7 @@ hfsc_get_sc1(int *argcp, char ***argvp,if (matches (*argv,"d" ) ==0 ) {NEXT_ARG (); -if (get_usecs (&d, *argv) <0 ) { +if (get_time (&d, *argv) <0 ) {explain1 ("d" );return -1 ; }
@@ -346,7 +346,7 @@ hfsc_get_sc2(int *argcp, char ***argvp,if (matches (*argv,"dmax" ) ==0 ) {NEXT_ARG (); -if (get_usecs (&dmax, *argv) <0 ) { +if (get_time (&dmax, *argv) <0 ) {explain1 ("dmax" );return -1 ; }
tc/q_netem.c +4 -4
@@ -108,15 +108,15 @@ static int get_ticks(__u32 *ticks, const {unsigned t; -if (get_usecs (&t, str)) +if (get_time (&t, str))return -1 ; -if (tc_core_usec2big (t)) { -fprintf (stderr,"Illegal %d usecs (too large)\n" , t); +if (tc_core_time2big (t)) { +fprintf (stderr,"Illegal %u time (too large)\n" , t);return -1 ; } - *ticks =tc_core_usec2tick (t); + *ticks =tc_core_time2tick (t);return 0 ; }
tc/q_tbf.c +4 -4
@@ -67,7 +67,7 @@ static int tbf_parse_opt(struct qdisc_utfprintf (stderr,"Double \"limit/latency\" spec\n" );return -1 ; } -if (get_usecs (&latency, *argv)) { +if (get_time (&latency, *argv)) {explain1 ("latency" );return -1 ; }
@@ -245,13 +245,13 @@ static int tbf_print_opt(struct qdisc_utif (show_raw)fprintf (f,"limit %s " ,sprint_size (qopt->limit, b1)); - latency =TIME_UNITS_PER_SEC *(qopt->limit/(double )qopt->rate.rate) -tc_core_tick2usec (qopt->buffer); + latency =TIME_UNITS_PER_SEC *(qopt->limit/(double )qopt->rate.rate) -tc_core_tick2time (qopt->buffer);if (qopt->peakrate.rate) { -double lat2 =TIME_UNITS_PER_SEC *(qopt->limit/(double )qopt->peakrate.rate) -tc_core_tick2usec (qopt->mtu); +double lat2 =TIME_UNITS_PER_SEC *(qopt->limit/(double )qopt->peakrate.rate) -tc_core_tick2time (qopt->mtu);if (lat2 > latency) latency = lat2; } -fprintf (f,"lat %s " ,sprint_usecs (latency, b1)); +fprintf (f,"lat %s " ,sprint_time (latency, b1));return 0 ; }
tc/tc_cbq.c +2 -2
@@ -38,7 +38,7 @@ unsigned tc_cbq_calc_maxidle(unsigned bnif (vxmt > maxidle) maxidle = vxmt; } -return tc_core_usec2tick (maxidle*(1 <<ewma_log)*TIME_UNITS_PER_SEC ); +return tc_core_time2tick (maxidle*(1 <<ewma_log)*TIME_UNITS_PER_SEC ); } unsigned tc_cbq_calc_offtime(unsigned bndw, unsigned rate, unsigned avpkt,
@@ -53,5 +53,5 @@ unsigned tc_cbq_calc_offtime(unsigned bn offtime *=pow (g, -(double )minburst) -1 ; else offtime *= 1 + (pow(g, -(double)(minburst-1)) - 1)/(1-g); -return tc_core_usec2tick (offtime*TIME_UNITS_PER_SEC ); +return tc_core_time2tick (offtime*TIME_UNITS_PER_SEC ); }
tc/tc_core.c +7 -7
@@ -27,21 +27,21 @@ static __u32 t2us=1;static __u32 us2t=1 ;static double tick_in_usec =1 ; -int tc_core_usec2big (long usec) +int tc_core_time2big (long time) { -__u64 t = usec; +__u64 t = time; t *= tick_in_usec;return (t >>32 ) !=0 ; } -long tc_core_usec2tick (long usec) +long tc_core_time2tick (long time) { -return usec*tick_in_usec; +return time*tick_in_usec; } -long tc_core_tick2usec (long tick) +long tc_core_tick2time (long tick) {return tick/tick_in_usec; }
@@ -58,12 +58,12 @@ long tc_core_ktime2time(long ktime)unsigned tc_calc_xmittime (unsigned rate,unsigned size) { -return tc_core_usec2tick (TIME_UNITS_PER_SEC *((double )size/rate)); +return tc_core_time2tick (TIME_UNITS_PER_SEC *((double )size/rate)); }unsigned tc_calc_xmitsize (unsigned rate,unsigned ticks) { -return ((double )rate*tc_core_tick2usec (ticks))/TIME_UNITS_PER_SEC ; +return ((double )rate*tc_core_tick2time (ticks))/TIME_UNITS_PER_SEC ; }/*
tc/tc_core.h +3 -3
@@ -6,9 +6,9 @@ #include <linux/pkt_sched.h>#define TIME_UNITS_PER_SEC 1000000 -int tc_core_usec2big (long usec); -long tc_core_usec2tick (long usec); -long tc_core_tick2usec (long tick); +int tc_core_time2big (long time); +long tc_core_time2tick (long time); +long tc_core_tick2time (long tick);long tc_core_time2ktime (long time);long tc_core_ktime2time (long ktime);unsigned tc_calc_xmittime (unsigned rate,unsigned size);
tc/tc_util.c +7 -7
@@ -209,7 +209,7 @@ char * sprint_rate(__u32 rate, char *bufreturn buf; } -int get_usecs (unsigned *usecs,const char *str) +int get_time (unsigned *time,const char *str) {double t;char *p;
@@ -232,26 +232,26 @@ int get_usecs(unsigned *usecs, const chareturn -1 ; } - *usecs = t; + *time = t;return 0 ; } -void print_usecs (char *buf,int len,__u32 usec) +void print_time (char *buf,int len,__u32 time) { -double tmp = usec; +double tmp = time;if (tmp >=TIME_UNITS_PER_SEC )snprintf (buf, len,"%.1fs" , tmp/TIME_UNITS_PER_SEC );else if (tmp >=TIME_UNITS_PER_SEC /1000 )snprintf (buf, len,"%.1fms" , tmp/(TIME_UNITS_PER_SEC /1000 ));else -snprintf (buf, len,"%uus" , usec); +snprintf (buf, len,"%uus" , time); } -char *sprint_usecs (__u32 usecs,char *buf) +char *sprint_time (__u32 time,char *buf) { -print_usecs (buf,SPRINT_BSIZE -1 , usecs); +print_time (buf,SPRINT_BSIZE -1 , time);return buf; }
tc/tc_util.h +3 -3
@@ -46,17 +46,17 @@ extern int get_rate(unsigned *rate, consextern int get_percent (unsigned *percent,const char *str);extern int get_size (unsigned *size,const char *str);extern int get_size_and_cell (unsigned *size,int *cell_log,char *str); -extern int get_usecs (unsigned *usecs,const char *str); +extern int get_time (unsigned *time,const char *str);extern void print_rate (char *buf,int len,__u32 rate);extern void print_size (char *buf,int len,__u32 size);extern void print_percent (char *buf,int len,__u32 percent);extern void print_qdisc_handle (char *buf,int len,__u32 h); -extern void print_usecs (char *buf,int len,__u32 usecs); +extern void print_time (char *buf,int len,__u32 time);extern char *sprint_rate (__u32 rate,char *buf);extern char *sprint_size (__u32 size,char *buf);extern char *sprint_qdisc_handle (__u32 h,char *buf);extern char *sprint_tc_classid (__u32 h,char *buf); -extern char *sprint_usecs (__u32 usecs,char *buf); +extern char *sprint_time (__u32 time,char *buf);extern char *sprint_percent (__u32 percent,char *buf);extern void print_tcstats_attr (FILE *fp,struct rtattr *tb[],char *prefix,struct rtattr **xstats);
RFC 6/8 : Add sprint_ticks() function and use in CBQ
In reply to Patrick McHardy[IPROUTE]: Add sprint_ticks() function and use in CBQ
Add helper function to print ticks to avoid assumptions about clock resolution in CBQ.
---
commit 5950296ff76ba81593928a2ee89757d69b2acba9
tree aca072937195b2011c9f64a305716ddfc1b40c66
parent c2cf24282b2a051942b18fbf894a9c1b490d925c
author Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100 committer Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100
tc/q_cbq.c | 7 ++++--- tc/q_netem.c | 6 ------ tc/tc_util.c | 5 +++++ tc/tc_util.h | 1 + 4 files changed, 10 insertions(+), 9 deletions(-)
tc/q_cbq.c +4 -3
@@ -418,6 +418,7 @@ static int cbq_print_opt(struct qdisc_utstruct tc_cbq_wrropt *wrr =NULL ;struct tc_cbq_fopt *fopt =NULL ;struct tc_cbq_ovl *ovl =NULL ; +SPRINT_BUF (b1);if (opt ==NULL )return 0 ;
@@ -500,17 +501,17 @@ static int cbq_print_opt(struct qdisc_utif (lss && show_details) {fprintf (f,"\nlevel %u ewma %u avpkt %ub " , lss->level, lss->ewma_log, lss->avpkt);if (lss->maxidle) { -fprintf (f,"maxidle %luus " ,tc_core_tick2time (lss->maxidle>>lss->ewma_log)); +fprintf (f,"maxidle %s " ,sprint_ticks (lss->maxidle>>lss->ewma_log, b1));if (show_raw)fprintf (f,"[%08x] " , lss->maxidle); }if (lss->minidle!=0x7fffffff ) { -fprintf (f,"minidle %luus " ,tc_core_tick2time (lss->minidle>>lss->ewma_log)); +fprintf (f,"minidle %s " ,sprint_ticks (lss->minidle>>lss->ewma_log, b1));if (show_raw)fprintf (f,"[%08x] " , lss->minidle); }if (lss->offtime) { -fprintf (f,"offtime %luus " ,tc_core_tick2time (lss->offtime)); +fprintf (f,"offtime %s " ,sprint_ticks (lss->offtime, b1));if (show_raw)fprintf (f,"[%08x] " , lss->offtime); }
tc/q_netem.c +0 -6
@@ -120,12 +120,6 @@ static int get_ticks(__u32 *ticks, constreturn 0 ; } -static char *sprint_ticks (__u32 ticks,char *buf) -{ -return sprint_usecs (tc_core_tick2usec (ticks), buf); -} - -static int netem_parse_opt (struct qdisc_util *qu,int argc,char **argv,struct nlmsghdr *n) {
tc/tc_util.c +5 -0
@@ -255,6 +255,11 @@ char * sprint_time(__u32 time, char *bufreturn buf; } +char *sprint_ticks (__u32 ticks,char *buf) +{ +return sprint_time (tc_core_tick2time (ticks), buf); +} +int get_size (unsigned *size,const char *str) {double sz;
tc/tc_util.h +1 -0
@@ -57,6 +57,7 @@ extern char * sprint_size(__u32 size, chextern char *sprint_qdisc_handle (__u32 h,char *buf);extern char *sprint_tc_classid (__u32 h,char *buf);extern char *sprint_time (__u32 time,char *buf); +extern char *sprint_ticks (__u32 ticks,char *buf);extern char *sprint_percent (__u32 percent,char *buf);extern void print_tcstats_attr (FILE *fp,struct rtattr *tb[],char *prefix,struct rtattr **xstats);
RFC 7/8 : Handle different kernel clock resolutions
In reply to Patrick McHardy[IPROUTE]: Handle different kernel clock resolutions
---
commit 0e0db5d408bdac33eadd9d947c0e6904df26ab8f
tree 950a6f47287bec01e5996bec3f1141b60f3f6f6a
parent 5950296ff76ba81593928a2ee89757d69b2acba9
author Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100 committer Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100
tc/tc_core.c | 26 +++++++++++++++++++------- 1 files changed, 19 insertions(+), 7 deletions(-)
tc/tc_core.c +19 -7
@@ -23,9 +23,8 @@ #include <string.h>#include "tc_core.h" -static __u32 t2us=1 ; -static __u32 us2t=1 ;static double tick_in_usec =1 ; +static double clock_factor =1 ;int tc_core_time2big (long time) {
@@ -48,12 +47,12 @@ long tc_core_tick2time(long tick)long tc_core_time2ktime (long time) { -return time; +return time * clock_factor; }long tc_core_ktime2time (long ktime) { -return ktime; +return ktime / clock_factor; }unsigned tc_calc_xmittime (unsigned rate,unsigned size)
@@ -98,16 +97,29 @@ int tc_calc_rtable(unsigned bps, __u32 *int tc_core_init () { -FILE *fp =fopen ("/proc/net/psched" ,"r" ); +FILE *fp; +__u32 clock_res; +__u32 t2us; +__u32 us2t; + fp =fopen ("/proc/net/psched" ,"r" );if (fp ==NULL )return -1 ; -if (fscanf (fp,"%08x%08x" , &t2us, &us2t) !=2 ) { +if (fscanf (fp,"%08x%08x%08x" , &t2us, &us2t, &clock_res) !=3 ) {fclose (fp);return -1 ; }fclose (fp); - tick_in_usec = (double )t2us/us2t; + +/* compatibility hack: for old iproute binaries (ignoring +* the kernel clock resolution) the kernel advertises a +* tick multiplier of 1000 in case of nano-second resolution, +* which really is 1. */ +if (clock_res ==1000000000 ) + t2us = us2t; + + clock_factor = (double )clock_res /TIME_UNITS_PER_SEC ; + tick_in_usec = (double )t2us / us2t * clock_factor;return 0 ; }
RFC 8/8 : Increase internal clock resolution to nsec
In reply to Patrick McHardy[IPROUTE]: Increase internal clock resolution to nsec
---
commit 8a76c51f61dd3881bba35f8c73aaa92eabaf50da
tree d4b252b801a14ee19ed77d4a06daaacd8c17b495
parent 0e0db5d408bdac33eadd9d947c0e6904df26ab8f
author Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100 committer Patrick McHardy <[email protected]> Sat, 03 Mar 2007 20:30:50 +0100
tc/tc_core.h | 2 +- tc/tc_util.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-)
tc/tc_core.h +1 -1
@@ -4,7 +4,7 @@ #define _TC_CORE_H_ 1#include <asm/types.h> #include <linux/pkt_sched.h> -#define TIME_UNITS_PER_SEC 1000000 +#define TIME_UNITS_PER_SEC 1000000000int tc_core_time2big (long time);long tc_core_time2tick (long time);
tc/tc_util.c +6 -1
@@ -228,6 +228,9 @@ int get_time(unsigned *time, const charelse if (strcasecmp (p,"us" ) ==0 ||strcasecmp (p,"usec" )==0 ||strcasecmp (p,"usecs" ) ==0 ) t *=TIME_UNITS_PER_SEC /1000000 ; +else if (strcasecmp (p,"ns" ) ==0 ||strcasecmp (p,"nsec" )==0 || +strcasecmp (p,"nsecs" ) ==0 ) + t *=TIME_UNITS_PER_SEC /1000000000 ;else return -1 ; }
@@ -245,8 +248,10 @@ void print_time(char *buf, int len, __u3snprintf (buf, len,"%.1fs" , tmp/TIME_UNITS_PER_SEC ); else if (tmp >= TIME_UNITS_PER_SEC/1000) snprintf(buf, len, "%.1fms", tmp/(TIME_UNITS_PER_SEC/1000)); + else if (tmp >= TIME_UNITS_PER_SEC/1000000) + snprintf(buf, len, "%.1fus", tmp/(TIME_UNITS_PER_SEC/1000000)); else - snprintf(buf, len, "%uus", time); + snprintf(buf, len, "%uns", time); }char *sprint_time (__u32 time,char *buf)
Quoted 33 lines · On Sun, 4 Mar 2007 20:14:53 +0100 (MET) Patrick McHardy <[email protected]>…
This patchset consists of four parts:
- minor TBF time conversion fix
- consolidation of time calculations: consolidate commonly used expressions with the goal of making it easier to audit for integer overflows when increasing the internally used clock resolution.
- support for detecting the clock resolution used by the kernel and converting time values as necessary.
- finally, increase the internally used clock resolution to nano-seconds
These patches have been tested (well, TBF and HFSC) with both old kernels and patched kernels using nano-second resolution.
tc/m_estimator.c | 4 +-- tc/m_police.c | 2 - tc/q_cbq.c | 15 +++++++------ tc/q_hfsc.c | 18 +++++++-------- tc/q_htb.c | 4 +-- tc/q_netem.c | 14 +++--------- tc/q_tbf.c | 22 +++++++++---------- tc/tc_cbq.c | 8 +++---- tc/tc_core.c | 61 ++++++++++++++++++++++++++++++++++++++---------------- tc/tc_core.h | 13 +++++++---- tc/tc_estimator.c | 2 - tc/tc_red.c | 2 - tc/tc_util.c | 40 ++++++++++++++++++++++------------- tc/tc_util.h | 7 +++--- 14 files changed, 125 insertions(+), 87 deletions(-)
Quoted 9 lines
Patrick McHardy:
[IPROUTE]: tbf: fix latency printing
[IPROUTE]: Usetc_calc_xmittime()where appropriate
[IPROUTE]: Introducetc_calc_xmitsizeand use where appropriate [IPROUTE]: IntroduceTIME_UNITS_PER_SECto represent internal clock resolution [IPROUTE]: Replace "usec" by "time" in function names
[IPROUTE]: Addsprint_ticks()function and use in CBQ
[IPROUTE]: Handle different kernel clock resolutions
[IPROUTE]: Increase internal clock resolution to nsec
applied all
Signature · 1 line
Stephen Hemminger <[email protected]>
Quoted 14 lines · Stephen Hemminger
Quoted 9 lines · On Sun, 4 Mar 2007 20:14:53 +0100 (MET) Patrick McHardy <[email protected]>…
Patrick McHardy:
[IPROUTE]: tbf: fix latency printing
[IPROUTE]: Usetc_calc_xmittime()where appropriate
[IPROUTE]: Introducetc_calc_xmitsizeand use where appropriate [IPROUTE]: IntroduceTIME_UNITS_PER_SECto represent internal clock resolution [IPROUTE]: Replace "usec" by "time" in function names
[IPROUTE]: Addsprint_ticks()function and use in CBQ
[IPROUTE]: Handle different kernel clock resolutions
[IPROUTE]: Increase internal clock resolution to nsec
Quoted 1 line
applied all
Thanks Stephen, but actually I think the last patch (increase clock resolution) shouldn't go in yet. I'm not done yet looking at all the compatibility issues and it does change the range of valid values for everything dealing with times. Most places I looked at still accept reasonable ranges, but I would feel more comfortable to make sure everything is fine first.