From: shemminger Date: Tue, 14 Mar 2006 19:36:31 +0000 (+0000) Subject: Fixes for tc hash sample. X-Git-Tag: ss-060314~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3925ad811940c391dee973dd2f842c7b322556ef;p=thirdparty%2Fiproute2.git Fixes for tc hash sample. --- diff --git a/ChangeLog b/ChangeLog index 883eb8267..f9eb65209 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-03-14 Russell Stuart + + * Fix missing memset in tc sample + * Fixes for tc hash samples + * Add sample divisor + 2006-03-10 Alpt * Add more rt_proto values @@ -10,9 +16,6 @@ * Fix endless loop in netlink error handling -2006-03-10 Russell Stuart - - * Fix missing memset in tc sample 2006-03-10 Stephen Hemminger diff --git a/tc/f_u32.c b/tc/f_u32.c index eedb09288..8af8e900b 100644 --- a/tc/f_u32.c +++ b/tc/f_u32.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -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) {