kernel/5227: In pf using a 2nd queue for lowdelay does not match all lowdelay packets
>Synopsis: In pf using a 2nd queue for lowdelay does not match all lowdelay packets
>Arrival-Date: Tue Sep 05 17:40:01 GMT 2006
>Originator: Steve Welham
>Release: OpenBSD 3.9-stable (GENERIC) #1: Wed Aug 30 21:49:15 BST 2006
System : OpenBSD 3.9
Machine : i386
The option of specifying dual queues to separate traffic requesting lowdelay is defined in "man pf.conf" as follows:
Packets can be assigned to queues based on filter rules by using the queue keyword. Normally only one queue is specified; when a second one is specified it will instead be used for packets which have a TOS of lowdelay and for TCP ACKs with no data payload.
The dual queue lowdelay tos check is done by an equality comparison with IPTOS_LOWDELAY which is defined in netinet/ip.h as 0x10. The desired meaning of "lowdelay" depends on which RFC we subscribe to:
RFC791 - cares only about the existence of the lowdelay bit, so correct comparison would be a bitwise AND
RFC1349 - cares about the value of bits 3-6 (where MSB is 0 and LSB is 7), so correct comparison would be a bitwise AND with the mask 0x1E and then equality comparison with IPTOS_LOWDELAY (0x10).
RFC2474 - completely redefines the TOS field and makes the lowdelay bit meaningless. (Diffserv)
So the current operation - a full 8 bit field comparison - is incorrect for both RFC 791 and 1349 definitions. For instance a packet with TOS of 0xF0 - requests low delay and IP precedence of 7 but is not treated as low-delay because it does not match 0x10.
Install hping from ports (/usr/ports/net/hping/) to reproduce packets easily.
This cannot be demo'ed with pflog - we will need to use the queue counters.
Here's the commands and output:
# cat /etc/pf.conf
Above we tested with 3 hpings - with tos set to 0x10, 0x0 and 0xF0. Only 0x10 is matching as lowdelay and queued as https_fast - however our 0xF0 is also lowdelay under both the RFC791 and RFC1349 definitions and is not matching.
The issue is fixed in pf.c depending on the RFC we subscribe to. Since lowdelay is nonsense to Diffserv RFC2474 we may as well assume that people using this dual queue are doing old-style ToS.
if (pqid || pd.tos == IPTOS_LOWDELAY)
if (pqid || pd.tos & IPTOS_LOWDELAY)
if (pqid || (pd.tos & 0x1E)== IPTOS_LOWDELAY)
Below is a patch to resolve according to RFC791:
--- pf.c.orig Wed Aug 30 21:08:33 2006
+++ pf.c.issue2 Thu Aug 31 11:46:10 2006
@@ -6030,7 +6030,7 @@