]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
Fixes for tc hash sample.
authorshemminger <shemminger>
Tue, 14 Mar 2006 19:36:31 +0000 (19:36 +0000)
committershemminger <shemminger>
Tue, 14 Mar 2006 19:36:31 +0000 (19:36 +0000)
ChangeLog
tc/f_u32.c

index 883eb82679154188fc1b4949fce7c16f170c43a2..f9eb6520967f081d5f9d033bc304099a1cae0971 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2006-03-14  Russell Stuart <russell-lartc@stuart.id.au>
+       
+       * Fix missing memset in tc sample
+       * Fixes for tc hash samples
+       * Add sample divisor
+
 2006-03-10  Alpt <alpt@freaknet.org>
 
        * Add more rt_proto values
@@ -10,9 +16,6 @@
 
        * Fix endless loop in netlink error handling
 
-2006-03-10  Russell Stuart <russell-lartc@stuart.id.au>
-
-       * Fix missing memset in tc sample
 
 2006-03-10  Stephen Hemminger  <shemminger@osdl.org>
 
index eedb092883cfd026957fa901c99b36ed62145792..8af8e900b96058c71d6b343fd82c03c3eff2d70b 100644 (file)
@@ -17,6 +17,7 @@
 #include <syslog.h>
 #include <fcntl.h>
 #include <sys/socket.h>
+#include <sys/utsname.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <string.h>
@@ -34,7 +35,7 @@ static void explain(void)
        fprintf(stderr, "or         u32 divisor DIVISOR\n");
        fprintf(stderr, "\n");
        fprintf(stderr, "Where: SELECTOR := SAMPLE SAMPLE ...\n");
-       fprintf(stderr, "       SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark } SAMPLE_ARGS\n");
+       fprintf(stderr, "       SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} | mark } SAMPLE_ARGS [divisor DIVISOR]\n");
        fprintf(stderr, "       FILTERID := X:Y:Z\n");
 }
 
@@ -834,7 +835,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                        unsigned divisor;
                        NEXT_ARG();
                        if (get_unsigned(&divisor, *argv, 0) || divisor == 0 ||
-                           divisor > 0x100) {
+                           divisor > 0x100 || (divisor - 1 & divisor)) {
                                fprintf(stderr, "Illegal \"divisor\"\n");
                                return -1;
                        }
@@ -874,6 +875,8 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                                htid = (handle&0xFFFFF000);
                } else if (strcmp(*argv, "sample") == 0) {
                        __u32 hash;
+                       unsigned divisor = 0x100;
+                       struct utsname utsname;
                        struct {
                                struct tc_u32_sel sel;
                                struct tc_u32_key keys[4];
@@ -888,10 +891,30 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                                fprintf(stderr, "\"sample\" must contain exactly ONE key.\n");
                                return -1;
                        }
+                       if (*argv != 0 && strcmp(*argv, "divisor") == 0) {
+                               NEXT_ARG();
+                               if (get_unsigned(&divisor, *argv, 0) || divisor == 0 ||
+                                   divisor > 0x100 || (divisor - 1 & divisor)) {
+                                       fprintf(stderr, "Illegal sample \"divisor\"\n");
+                                       return -1;
+                               }
+                               NEXT_ARG();
+                       }
                        hash = sel2.sel.keys[0].val&sel2.sel.keys[0].mask;
-                       hash ^= hash>>16;
-                       hash ^= hash>>8;
-                       htid = ((hash<<12)&0xFF000)|(htid&0xFFF00000);
+                       uname(&utsname);
+                       if (strncmp(utsname.release, "2.4.", 4) == 0) {
+                               hash ^= hash>>16;
+                               hash ^= hash>>8;
+                       }
+                       else {
+                               __u32 mask = sel2.sel.keys[0].mask;
+                               while (mask && !(mask & 1)) {
+                                       mask >>= 1;
+                                       hash >>= 1;
+                               }
+                               hash &= 0xFF;
+                       }
+                       htid = ((hash%divisor)<<12)|(htid&0xFFF00000);
                        sample_ok = 1;
                        continue;
                } else if (strcmp(*argv, "indev") == 0) {