diff -pru -x '*.o' iproute2-2.6.14-051107.orig/include/linux/pkt_sched.h iproute2-2.6.14-051107/include/linux/pkt_sched.h --- iproute2-2.6.14-051107.orig/include/linux/pkt_sched.h 2005-08-08 13:24:41.000000000 -0700 +++ iproute2-2.6.14-051107/include/linux/pkt_sched.h 2005-12-17 17:33:23.000000000 -0800 @@ -136,6 +136,9 @@ struct tc_sfq_qopt __u32 limit; /* Maximal packets in queue */ unsigned divisor; /* Hash divisor */ unsigned flows; /* Maximal number of flows */ + unsigned flags; +#define TC_SFQ_NOPORTS (1) /* ignore src/dst ports in hash */ +#define TC_SFQ_NOSRCIP (2) /* ignore src ip address in hash */ }; /* diff -pru -x '*.o' iproute2-2.6.14-051107.orig/man/man8/tc-sfq.8 iproute2-2.6.14-051107/man/man8/tc-sfq.8 --- iproute2-2.6.14-051107.orig/man/man8/tc-sfq.8 2004-06-08 13:34:17.000000000 -0700 +++ iproute2-2.6.14-051107/man/man8/tc-sfq.8 2005-12-17 17:45:26.000000000 -0800 @@ -6,6 +6,11 @@ sfq \- Stochastic Fairness Queueing seconds .B quantum bytes +.B [ limit +packets +.B ] +.B [ noports ] +.B [ nosrcip ] .SH DESCRIPTION @@ -22,21 +27,13 @@ This may in fact have some effect in mit SFQ is work-conserving and therefore always delivers a packet if it has one available. .SH ALGORITHM -On enqueueing, each packet is assigned to a hash bucket, based on -.TP -(i) -Source address -.TP -(ii) -Destination address -.TP -(iii) -Source port -.P -If these are available. SFQ knows about ipv4 and ipv6 and also UDP, TCP and ESP. -Packets with other protocols are hashed based on the 32bits representation of their -destination and the socket they belong to. A flow corresponds mostly to a TCP/IP -connection. +On enqueueing, each packet is assigned to a hash bucket, based on a function of +source address, source port, destination address, and destination port. + +SFQ knows about ipv4 and ipv6 and also UDP, TCP and ESP. Packets with +other protocols are hashed based on the 32bits representation of their +destination and the socket they belong to. A flow corresponds mostly to +a TCP/IP connection. Each of these buckets should represent a unique flow. Because multiple flows may get hashed to the same bucket, the hashing algorithm is perturbed at configurable @@ -59,6 +56,25 @@ reordering. Advised value: 10 quantum Amount of bytes a flow is allowed to dequeue during a round of the round robin process. Defaults to the MTU of the interface which is also the advised value and the minimum value. +.TP +limit +Number of packets permitted in the SFQ at one time. Must be at least 1, and at +most 128. +.TP +noports +If specified then the source/destination ports are not included in the hash +function. This will force all flows for a particular source/destination address +pair to be placed in the same bucket. It may be useful for defeating so-called +"download accelerators". These "accelerators" use HTTP range-requests in order +to issue multiple simultaneous requests to a webserver in an attempt to get +an unfair share of available bandwidth. Note that this option does unfairly +penalize hosts sharing an IP address, such as hosts behind a shared NAT. +.TP +nosrcip +If specified then the source address is not considered in the hash function. +This is useful for when you wish all outbound traffic for a particular +destination to be considered without consideration for which source address +generated it. .SH EXAMPLE & USAGE diff -pru -x '*.o' iproute2-2.6.14-051107.orig/tc/q_sfq.c iproute2-2.6.14-051107/tc/q_sfq.c --- iproute2-2.6.14-051107.orig/tc/q_sfq.c 2004-09-28 11:35:49.000000000 -0700 +++ iproute2-2.6.14-051107/tc/q_sfq.c 2005-12-17 17:26:52.000000000 -0800 @@ -25,7 +25,7 @@ static void explain(void) { - fprintf(stderr, "Usage: ... sfq [ limit NUMBER ] [ perturb SECS ] [ quantum BYTES ]\n"); + fprintf(stderr, "Usage: ... sfq [ limit NUMBER ] [ perturb SECS ] [ quantum BYTES ] [ noports ] [ nosrcip ]\n"); } #define usage() return(-1) @@ -63,6 +63,12 @@ static int sfq_parse_opt(struct qdisc_ut return -1; } ok++; + } else if (strcmp(*argv, "noports") == 0) { + opt.flags |= TC_SFQ_NOPORTS; + ok++; + } else if (strcmp(*argv, "nosrcip") == 0) { + opt.flags |= TC_SFQ_NOSRCIP; + ok++; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; @@ -97,6 +103,10 @@ static int sfq_print_opt(struct qdisc_ut } if (qopt->perturb_period) fprintf(f, "perturb %dsec ", qopt->perturb_period); + if (qopt->flags & TC_SFQ_NOPORTS) + fprintf(f, "noports "); + if (qopt->flags & TC_SFQ_NOSRCIP) + fprintf(f, "nosrcip "); return 0; }