[Long Message Disclaimer] All:
I was just looking over Peter Hansteen's PF book -- It's a great reference, but the coverage on QUEUING is limited (6 pages of ~150). I was hoping to find an answer to a question there-in, that I had back in 2006 when I filed system/4574 -- but with behind me, I wanted to revisit a ALTQ design question: - What is the relationship between stateful pass rules and queue behavior? - Does the original direction of the initial SYN packet that creates a state affect the Golden Rule(R) behavior? The FAQ states: "You can't queue incoming traffic once that it has arrived at an interface" (Golden Rule): Which is reasonable. - If it's passing through your ALTQ packet forwarding engine, you could in theory queue it leaving an egress interface. - But, in most scenarios, you would be working with a queue sized for the media of the "downstream / egress interface", not the incoming/wan interface that you likely wish to traffic shape. - Or queue it at an adjacent upstream router (likely if you have traffic shaping on one router, you have it on all but your core/ border router) General rules: - Queuing happens _mostly_ on pass rules, so even if you you have a "default-pass" policy, stateless even, you still have to explicitly pass (and probably "keep state", unless core/border) on traffic to be queued. - Consider that the presence of a state prevents re-evaluation of rules when traffic matching a known state ingresses/egresses an interface on which the state was initially created - Potentially alternate interfaces as well, depending on state policy floating There are four example TCP connection scenarios / packet flow "disciplines" outlined below. To help explain my question, I put together a quick diagram with a greatly simplified network configuration and pf(4) rule set featuring queues -- but I've tried to use four real-world traffic flow permutations. Diagram: http://people.collaborativefusion.com/~seklecki/images/cf_OpenBSD_PF.png --------------------------------------------------------------------- 1) Workstation A initiates TCP connection to Server Y port 5999 (ephemeral source port) - TCP SYN from WS A ingress $ext_if, creates state - TCP SYN+ACK from SRV A egresses $ext_if back to WS A - Traffic is 5/95 ratio server->client (5% being all acks) - TCP data transfer from SRV A to to WS A is queued at specified rate Example: Passive FTP data channel stream of download from SRV A to WS A 2) Workstation A initiates TCP connection to Server Y on port 22 (ephemeral source port) - TCP SYN from WS A ingresses $ext_if, creates state - TCP SYN+ACK from SRV A egresses $ext_if back to WS A - Traffic is 95/5 ratio client->server (5% being all ACKs) - TCP data transfer from WS A to SRV Y is _not_ queued at specified rate because of Golden Rule(R) Example: SCP file, initiated on Client A, from Client A send to Server Y (B pushes to Y) 3) Server Y initiates TCP connection to Workstation A on negotiated FTP receiver port (src port 20) - TCP SYN from SRV Y egresses $ext_if, creates state - TCP SYN+ACK from WS A ingresses $ext_if back to SRV Y - Traffic is 95/5 ratio client->server (SRV Y as 'tcp client' - 5% acks from WS A) - TCP data transfer from SRV Y to WS A is queued at specified rate Example: Active FTP data connection (client specified data receiver port > 1024, SrvY src was P20) 4) Server Y initiates TCP connection to Workstation A on port 22 (ephemeral source port) - TCP SYN from SRV Y egresses $ext_if, create state - TCP SYN+ACK from WS A ingresses $ext_if back to SRV Y - Traffic is 5/95 ratio client->server sends (95% being TCP server sends, 5 being client ACKs from Y) - TCP data transfer from WS A to SRV Y Example: SCP file, initiated on Server Y, src Client A dst Server Y (Y pulls from B) --------------------------------------------------------------------- Here are my questions / comments: - Should "pass in keep state queue(foo)" be valid syntax? - If "pass in on $ext_if from any to $private queue(foo)" is valid, and the traffic flow discipline (DATA, non-ACK) is in the direction of the TCP client initiator, does traffic egressing the $exit_if get queued? My testing says Yes. - Conversely, if "pass in on $exit_if from any to $private queue(foo)" is valid, and the traffic discipline (DATA, non-ACK) is in the direction of the TCP server receiver, does traffic ingressing the interface get queued? My testing says No -- as expected. - Does this mean, then, that only traffic, ACK or DATA, egressing an interface (and this part is key): *** Regardless of the "original location of the TCP client initiator, in relation to the pass rule direction" (R) can be queued? **** Thus having less to do with the original "direction" of the initiating SYN packet, but with the nature (or "discipline") of the TCP connection built? And If I'm accurate insofar as articulating this relationship, wouldn't it also be accurate to suggest that: Further, does that mean, in a "host only" model (where no hypothetical queue on $int_if could exist, and no adjacent routers are available to do queueing), that if: - A TCP connection initiated by a remote host, with a TCP data flow "discipline" of "remote to local" (scenarios #2 and #4 below), cannot be queued on $ext_if (only the ACK packets)? Then, wouldn't that imply, as practical examples, then, the inability of a host-only system to rate limit: - How fast SSH users could scp(1) files _to_ your host? - How fast local users can initiate HTTP files downloads? Conclusions: 1) In conclusion, initiating TCP client location (in relation to stateful pass rules) is irrelevant, only traffic discipline. 2) The current implementation has some limitations for a host-only model (as described above). These limitations may not be ALQT/pf(4) specific -- I haven't worked with other QoS implementations (Cisco, this may be a general problem in all limitations)