"Damian Higgins" wrote:
Hi Stuart,
First off, thank you for the feedback you provided. Unfortunately, you
misunderstood the issue I'm encountering because you haven't read my
entire post. So, I'll try to make a brief post of the previous
message, to make it easier to read, and hope you will have the
patience to read it this time :).
Perhaps you are misunderstanding how pf works. Instead of trying to
solve *your* problem, I will try to describe how pf+altq works, and it
will be up to you to figure out how to accomplish what you want to do.
First, some concepts of queueing/policing I learned from my previous
experience in other environments(correct me if I'm wrong) :
First forget about other environments, especially Linux. I have deleted
the rest of your post, since it does not really matter what you or other
environments think about how traffic shaping should be done. If you are
using OpenBSD, try to understand how it is done with pf+altq.
Here are the basic rules for pf. You may already know some of them, but
please bear with me. You may learn something new:
# Filtering is stateful in pf, and it is strongly recommended to keep it
that way (ie. use 'no state' only if you really know what you are
doing). The S/SA flags being default also have strong reasons.
# Think of 'state' as a 'connection'. This is especially true for TCP.
Use systat(1) or pftop (from ports) to see the states. A state *sees*
packets in *both* directions that belong to a particular traffic.
# If a packet matches a state, no rules are evaluated *hint*
# If a packet does not match an existing state but matches a rule, a
state is created. Further packets of this 'connection' will just match
the state, and bypass ruleset evaluation.
# Loading pf rules with 'pfctl -f pf.conf' does not clear existing
states (unless you also use the proper flush command line switch) *hint*
# A connection that traverses an OpenBSD router usually enters pf twice
(at inbound and outbound interface) and provided there are appropriate
pass rules, it will create states on both interfaces. That is, every
packet of a connection both inbound and outbound will have two states
associated with it.
# A connection that originates from or terminates on an OpenBSD box will
have a single state associated with it.
# NAT/RDR rules are evaluated before filter rules, and address
translation happens *before* rules are evaluated, so rules are always
checked against translated packets (NAT on incoming, RDR on outgoing).
And the basic rules for altq:
# altq *only* filters *outbound* packets on an interface. This is
usually not related to the direction of the connection itself.
## Example: if you want to restrict internal hosts HTTP downloads from
outside servers, these *incoming* HTTP payloads have to be filtered at
the interface facing the hosts. This also means there is no way to apply
altq to limit downloads that are initiated from the OpenBSD gateway itself.
## Example: if you want to increase the priority of the e-mails that
your mail server sends, use the interface facing your ISP.
# Each packet, as it passes through the network stack can be assigned a
'queue-id'. This queue id determines which queue the packet is placed as
it *leaves* the box. If a packet has no queue-id, then it is assigned to
the default queue.
# The queue ids are mapped to queue names, that is, queues that carry
the same name have the same id.
And this is how PF assigns packets to queues:
# Each rule has two queue ids, one for normal one for high-priority
packets as specified by the rule definition (see pf.conf for details).
If you specified a single queue in your rule definition, that means both
ids are equal.
# By default the packet has no queue-id assigned.
# If a packet matches a rule, and that rule specifies a queue, the
packet queue-id is replaced by the queue id specified by the rule. If
the rule has no queue specified, the packet queue-id is not changed
(does not revert back to default).
# If a packet matches a state, the rule that created the state is
consulted (as above).
# Since a packet can match up to two rules/states as it traverses a
router, the last assigned queue wins (as the queues only take effect as
the packet exits the router).
# Note that, since a state matches packets in both directions, packets
in both directions will be assigned queue ids by a given state. That
makes it possible to create a state with a rule on one interface, and
have the reply packets assigned to the same queue specified by that rule
on a different interface.
Finally, here are some additional things to think about or investigate:
# You can do a lot of creative and flexible stuff with 'tag' and
'tagged' keywords in your ruleset. Assigning queues by 'pass quick
tagged XYZZY queue MAGIC' type of rules is much easier to keep track of.
# What happens if you change the ruleset while traffic is flowing?
Hint: existing states will point to a default 'empty' rule.
# What happens when states are synchronized by pfsync(4) between two
carp(4)'ed firewalls? Hint: The mapping used to get lost, so if the
firewall failed over queues would not work for 'synced' states although
they would work nor new states. How this is handled now in -current is
left as an exercise.
Now, armed with the above, you should be able to explain the behaviour
you see, and design a filter that does what you want.
Have fun ...
Can
PS: pflog, tcpdump and pftop/systat are your friends.
PPS: You can always look at the source code to see how things work.
PPPS: When asking questions, give as much context information as possible.
PPPPS: Some of the above rules may have changed slightly after the
recent overhaul of pf state handling. There may also be bugs and/or
regressions, so a good bug report really helps a lot. A report that says
"it works with 4.3 but not with 4.4 or -current" goes a long way to
point out a regression.