diff options
author | Jose Ignacio Naranjo Hernández <joseignacio.naranjo@gmail.com> | 2010-01-14 17:10:10 (GMT) |
---|---|---|
committer | Thomas Graf <tgraf@suug.ch> | 2010-03-10 15:18:54 (GMT) |
commit | 52d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0 (patch) | |
tree | 07e18539be867fe1ed8c09af1c52962d4cd392e1 | |
parent | cafdaa4e065a2ee658d7e361158100f4c7abe445 (diff) | |
download | libnl-52d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0.zip libnl-52d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0.tar.gz libnl-52d6b8b9ee21b4bc112cc8a5d6f440536dd7fde0.tar.bz2 |
Fix a bug when calculating ticks_per_usec
I've noticed a wrong behavior when setting up some delays in a netem
qdisc. I will try to make the things easier for the reader describing
the calls path.
To set up a delay (or jitter...) I use 'rtnl_netem_set_delay' which
requires an int parameter that tells the delay in micro seconds. Inside
this func, the delay is set up with the help of 'nl_us2ticks', which is
just an arithmetic operation (us * ticks_per_usec), where us is the
input parameter and ticks_per_usec is a global variable initialized in
'get_psched_settings'. And here is the problem:
If this variable is going to be calculated using '/proc/net/psched', I
think the file scan is not done properly.
I don't understand what the meaning of the asterisk is here:
int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom);
if (4 == r && nom == 1000000 && !got_tick)
ticks_per_usec = (double)tick/(double)us;
The execution path never gets in the if statement, because r is always
3, and if the fourth parameter is read (avoiding the asterisk), there is
no variable to store it in, so it comes a segv. In my opinion we can get
rid of the if statement, because I think the proc psched file has always
a fixed format of 4 parameters, and 'nom' is always 1000000
(http://lxr.linux.no/#linux+v2.6.32/net/sched/sch_api.c#L1678).
Find attached a patch I did, if I am correct.
-rw-r--r-- | lib/utils.c | 35 |
1 files changed, 16 insertions, 19 deletions
diff --git a/lib/utils.c b/lib/utils.c index 263eb38..4007bee 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -285,7 +285,7 @@ static void __init get_psched_settings(void) { char name[FILENAME_MAX]; FILE *fd; - int got_hz = 0, got_tick = 0; + int got_hz = 0; if (getenv("HZ")) { long hz = strtol(getenv("HZ"), NULL, 0); @@ -301,28 +301,25 @@ static void __init get_psched_settings(void) if (getenv("TICKS_PER_USEC")) { double t = strtod(getenv("TICKS_PER_USEC"), NULL); - ticks_per_usec = t; - got_tick = 1; } + else { + if (getenv("PROC_NET_PSCHED")) + snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED")); + else if (getenv("PROC_ROOT")) + snprintf(name, sizeof(name), "%s/net/psched", + getenv("PROC_ROOT")); + else + strncpy(name, "/proc/net/psched", sizeof(name) - 1); - - if (getenv("PROC_NET_PSCHED")) - snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED")); - else if (getenv("PROC_ROOT")) - snprintf(name, sizeof(name), "%s/net/psched", - getenv("PROC_ROOT")); - else - strncpy(name, "/proc/net/psched", sizeof(name) - 1); - - if ((fd = fopen(name, "r"))) { - uint32_t tick, us, nom; - int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom); - - if (4 == r && nom == 1000000 && !got_tick) + if ((fd = fopen(name, "r"))) { + uint32_t tick, us; + /* the file contains 4 hexadecimals, but we just use + the first two of them */ + int r = fscanf(fd, "%08x %08x", &tick, &us); ticks_per_usec = (double)tick/(double)us; - - fclose(fd); + fclose(fd); + } } } |