]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
tc: Fix rounding in tc_calc_xmittime and tc_calc_xmitsize.
authorJonathan Lennox <jonathan.lennox42@gmail.com>
Wed, 26 Feb 2025 18:53:21 +0000 (18:53 +0000)
committerDavid Ahern <dsahern@kernel.org>
Fri, 28 Feb 2025 15:47:23 +0000 (15:47 +0000)
Currently, tc_calc_xmittime and tc_calc_xmitsize round from double to
int three times — once when they call tc_core_time2tick /
tc_core_tick2time (whose argument is int), once when those functions
return (their return value is int), and then finally when the tc_calc_*
functions return.  This leads to extremely granular and inaccurate
conversions.

As a result, for example, on my test system (where tick_in_usec=15.625,
clock_factor=1, and hz=1000000000) for a bitrate of 1Gbps, all tc htb
burst values between 0 and 999 bytes get encoded as 0 ticks; all values
between 1000 and 1999 bytes get encoded as 15 ticks (equivalent to 960
bytes); all values between 2000 and 2999 bytes as 31 ticks (1984 bytes);
etc.

The patch changes the code so these calculations are done internally in
floating-point, and only rounded to integer values when the value is
returned. It also changes tc_calc_xmittime to round its calculated value
up, rather than down, to ensure that the calculated time is actually
sufficient for the requested size.

Signed-off-by: Jonathan Lennox <jonathan.lennox@8x8.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
tc/tc_core.c
tc/tc_core.h

index 37547e9b33952334bbfa78894dd50e3cf534d7ea..32fd094f6a05049d3c3f755a3445717affd85555 100644 (file)
 static double tick_in_usec = 1;
 static double clock_factor = 1;
 
-static unsigned int tc_core_time2tick(unsigned int time)
+static double tc_core_time2tick(double time)
 {
        return time * tick_in_usec;
 }
 
-unsigned int tc_core_tick2time(unsigned int tick)
+double tc_core_tick2time(double tick)
 {
        return tick / tick_in_usec;
 }
@@ -45,7 +45,7 @@ unsigned int tc_core_ktime2time(unsigned int ktime)
 
 unsigned int tc_calc_xmittime(__u64 rate, unsigned int size)
 {
-       return tc_core_time2tick(TIME_UNITS_PER_SEC*((double)size/(double)rate));
+       return ceil(tc_core_time2tick(TIME_UNITS_PER_SEC*((double)size/(double)rate)));
 }
 
 unsigned int tc_calc_xmitsize(__u64 rate, unsigned int ticks)
index 7a986ac27a44d82dd4eb69c3a4cfa78daf2e31a6..c0fb7481420aec5655829d23287c1f4a7f04a8cf 100644 (file)
@@ -12,7 +12,7 @@ enum link_layer {
 };
 
 
-unsigned tc_core_tick2time(unsigned tick);
+double tc_core_tick2time(double tick);
 unsigned tc_core_time2ktime(unsigned time);
 unsigned tc_core_ktime2time(unsigned ktime);
 unsigned tc_calc_xmittime(__u64 rate, unsigned size);