Now that Henning fixed the altq problem, something I wanted to try for a very long time actually works.
I have an ADSL (asymmetric) link with 512 kbps downstream and 128 kbps upstream capacity. One very annoying problem is that downloads suffer when the upstream is saturated. The reason is that when I download through TCP, I still need to send ACKs regularly to keep the peer sending. Those ACKs are empty (they have no data payload). When the uplink gets saturated, the empty ACKs get delayed, and the effect is that the download speed decreases dramatically (from 50 to 7 KB/s). Now, the idea is to priorize the empty ACKs with pf/altq. The code is already there. You can specify two queues in a rule, one for normal packets and one for priorized packets. Currently, only packets with tos (type of service) 'lowdelay' get priorized. The small patch below makes pf use the priority queue for empty ACKs as well. I use the following rules in pf.conf: altq on kue0 cbq bandwidth 100Kb queue { q_std } queue q_std bandwidth 100% cbq(default) { q_pri, q_def } queue q_pri priority 7 queue q_def priority 1 cbq(red ecn) pass out on $ext_if inet proto tcp from $ext_if to any \ flags S/SA keep state queue(q_def, q_pri) pass in on $ext_if inet proto tcp from any to $ext_if port $services_tcp \ flags S/SA keep state queue (q_def, q_pri) When I now start a download, it starts with the full 50 KB/s. When I start a concurrent upload, the cool thing is that the download speed stays that high, even if the upstream gets saturated. The outgoing empty ACKs related to the download are just priorized over the outgoing packets with payload related to the upload. Let me know if this works as well for you. :) Daniel Index: pf.c =================================================================== RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.322 diff -u -r1.322 pf.c --- pf.c 25 Feb 2003 17:54:06 -0000 1.322 +++ pf.c 26 Feb 2003 22:37:17 -0000 @@ -4229,6 +4229,7 @@ struct pf_state *s = NULL; struct pf_pdesc pd; int off; + int pqid = 0; if (!pf_status.running || (m_tag_find(m, PACKET_TAG_PF_GENERATED, NULL) != NULL)) @@ -4293,6 +4294,8 @@ goto done; } pd.p_len = pd.tot_len - off - (th.th_off << 2); + if (th.th_flags & TH_ACK && !pd.p_len) + pqid = 1; action = pf_normalize_tcp(dir, ifp, m, 0, off, h, &pd); if (action == PF_DROP) break; @@ -4402,7 +4405,7 @@ mtag = m_tag_get(PACKET_TAG_PF_QID, sizeof(*atag), M_NOWAIT); if (mtag != NULL) { atag = (struct altq_tag *)(mtag + 1); - if (pd.tos == IPTOS_LOWDELAY) + if (pqid || pd.tos == IPTOS_LOWDELAY) atag->qid = r->pqid; else atag->qid = r->qid;