• No results found

Understanding Priority-Based Queues (priq)

The basic concept for priority-based queues (priq) is fairly straightforward and perhaps the easiest one to understand. Within the total bandwidth allocated to the main queue, all that matters is traffic priority. You assign queues a priority value in the range 0 through 15, where a higher value means that the queue’s requests for traffic are serviced sooner.

For a real-world example, we can look to Daniel Hartmeier. He discovered a simple yet effective way to improve the throughput for his home network by using ALTQ. Like many people, Daniel’s home network was on an asymmetric connection, with total usable bandwidth low enough that he felt a strong desire to get better bandwidth utilization.

In addition, when the line was running at or near capacity, some odd- ities started appearing. One symptom in particular seemed to indicate that there was room for improvement: Incoming traffic (downloads, incoming email, and such) slowed down disproportionately whenever outgoing traffic started, more than could be explained by measuring the raw amount of data transferred. It all came back to a basic feature of TCP.

W H A T I S Y O U R T O T A L U S A B L E B A N D W I T H ?

It can be difficult to determine actual usable bandwidth on a specific interface for queuing. If you do not specify a total bandwidth, the total bandwidth available will be used to calculate the allocations. However, some types of interfaces cannot reliably report the actual bandwidth value. One common example of this discrepancy is if your gateway’s external interface is a 100Mb Ethernet interface, attached to a line that actually offers only 8Mb download and 1Mb upload.* The Ethernet interface will then confidently report the 100Mb bandwidth, not the DSL values.

For that reason it usually makes sense to set the total bandwidth to a fixed value. Just what value to specify unfortunately has no fixed relationship with what your bandwidth supplier tells you. There will always be some overhead that varies slightly among the various technologies and implementations. In typical TCP/IP over wired Ethernets, overhead can be as low as single-digit percentages, while TCP/IP over ATM and ADSL have been known to have overhead in the 20- to 25-percent range. If your bandwidth supplier is not cooperative, you will need to make an educated guess at the start value for your experimentation. In any case, you should be acutely aware that the total bandwidth available is never larger than the bandwidth of the weakest link in your network path.

It is also worth noting that queues are supported only for outbound connections relative to the system doing the queuing. When planning your bandwidth manage- ment, you should consider the actual usable bandwidth to be equal to the weakest (lowest bandwidth) link in the connection’s path, even if your queues are set up on a different interface.

When a TCP packet is sent, the sender expects acknowledgment (in the form of an ACK packet) from the receiving end and will wait for a specified time for it to arrive. If the ACK does not arrive within the specified time, the sender assumes that the packet has not been received and resends the packet it originally sent.

The problem is that, in a default setup, packets are serviced sequentially by the interface as they arrive. This inevitably means that the ACK packets, with essentially no data payload, wait in line while the larger data packets are transferred.

A testable hypothesis formed: If the tiny, practically dataless ACK packets were able to slip in between the larger data packets, this would lead to a more efficient use of available bandwidth. The simplest practical way to implement and test the theory was to set up two queues with different priorities and inte- grate them into the rule set.

These lines show the relevant parts of the rule set:

ext_if="kue0"

altq on $ext_if priq bandwidth 100Kb queue { q_pri, q_def } queue q_pri priority 7

queue q_def priority 1 priq(default)

pass out on $ext_if proto tcp from $ext_if to any flags S/SA \ keep state queue (q_def, q_pri)

pass in on $ext_if proto tcp from any to $ext_if flags S/SA \ keep state queue (q_def, q_pri)

Here we see that the priority-based queue is set up on the external inter- face, with two subordinate queues. The first subqueue, q_pri, has a high priority value of 7, while the other, q_def, has a significantly lower priority value of 1.

This seemingly simple rule set works by exploiting how ALTQ treats queues with different priorities. Once a connection is assigned to the main queue, ALTQ inspects each packet’s type of service (ToS) field. ACK packets have the ToS Delay bit set to low, which indicates that the sender wanted the speediest delivery possible. When ALTQ sees a low-delay packet and queues of differing priorities are available, it will assign the packet to the higher- priority queue.

This means that the ACK packets skip ahead of the lower-priority queue and are delivered more quickly, which in turn means that data packets are serviced more quickly too. The net result is that a configuration like this provides better performance than a pure FIFO configuration with the same hardware and available bandwidth.2