This commit was generated by cvs2svn to compensate for changes in r2587,
[iproute2.git] / tc / f_u32.c
index 50dc4df..9d527fc 100644 (file)
@@ -34,7 +34,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");
 }
 
@@ -495,7 +495,7 @@ static int parse_ip6(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
        }
        if (strcmp(*argv, "priority") == 0) {
                NEXT_ARG();
-               res = parse_u8(&argc, &argv, sel, 0, 0);
+               res = parse_u8(&argc, &argv, sel, 4, 0);
                goto done;
        }
        if (strcmp(*argv, "protocol") == 0) {
@@ -833,8 +833,9 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                } else if (matches(*argv, "divisor") == 0) {
                        unsigned divisor;
                        NEXT_ARG();
-                       if (get_unsigned(&divisor, *argv, 0) || divisor == 0 ||
-                           divisor > 0x100) {
+                       if (get_unsigned(&divisor, *argv, 0) || 
+                           divisor == 0 ||
+                           divisor > 0x100 || ((divisor - 1) & divisor)) {
                                fprintf(stderr, "Illegal \"divisor\"\n");
                                return -1;
                        }
@@ -874,10 +875,13 @@ 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 {
                                struct tc_u32_sel sel;
                                struct tc_u32_key keys[4];
                        } sel2;
+                       memset(&sel2, 0, sizeof(sel2));
                        NEXT_ARG();
                        if (parse_selector(&argc, &argv, &sel2.sel, n)) {
                                fprintf(stderr, "Illegal \"sample\"\n");
@@ -887,10 +891,19 @@ 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);
+                       htid = ((hash%divisor)<<12)|(htid&0xFFF00000);
                        sample_ok = 1;
                        continue;
                } else if (strcmp(*argv, "indev") == 0) {