]> git.ipfire.org Git - thirdparty/libnl.git/commitdiff
Fix a bug when calculating ticks_per_usec
authorJose Ignacio Naranjo Hernández <joseignacio.naranjo@gmail.com>
Thu, 14 Jan 2010 17:10:10 +0000 (18:10 +0100)
committerThomas Graf <tgraf@suug.ch>
Wed, 10 Mar 2010 15:18:54 +0000 (16:18 +0100)
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.

lib/utils.c

index 263eb386591e3f58ff96e7b4e54b88a75799ef49..4007bee1adf838dd0b7d1ff9411ff64211d255f3 100644 (file)
@@ -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);
+               }
        }
 }