(This is some notes I'm jotting down while I'm working on this, I intend to come back and clean this up later)
ifup dummy0 tc filter add dev $DEV parent ffff: protocol ip <i>filter-rule</i> flowid 1:2 action mirred egress mirror dev dummy0 tcpdump -i dummy0
To match PPPoE discovery ethertype:
$TC filter add dev $DEV \ pref 10 parent $Q_ROOT: \ protocol all \ basic match "cmp(u16 at 12 layer 2 eq $ETH_P_PPPOED)" \ flowid $Q_ROOT:$C_PPPoE
tc qdisc add dev $DEV \ root handle 1: \ sfq tc filter add dev $DEV \ pref 1 parent 1:1 handle 100 \ protocol all \ flow hash keys dst divisor 1024
This will be fair across all destination IP addresses. We have a set of patches to allow this across src/dst mac addresses.
Some barely documented, but useful help commands:
./tc filter add dev eth1 basic match help
basic is anything but. It allows complicated matches to be built up from boolean operations on various criteria (called extended matches, or "ematches"). The syntax for this is "criteria(arguments)". You can use brackets to force precedence, as well as "and","or" and "not" to combine criteria. Supported extended match modules are "cmp","meta","nbyte" and "u32". see tc filter add dev lo basic match cmp(help), tc filter add dev lo basic match meta(help), tc filter add dev lo basic match meta(list), tc filter add dev lo basic match nbyte(help) and tc filter add dev lo basic match u32(help) for suggested syntaxes.
the cmp extended basic match appears to be the recommended way to match on layer 2 fields (ref)
This ematch module lets you match on various 8,16 or 32 bit quantities relative to layer 2, layer 3 or transport headers.
An example (that we didn't have time to get to work properly, but it shows a valid syntax), this should match IP packets inside PPPoE sourced from 192.0.2.0/24.:
$TC filter add dev $DEV \ parent 1: prio 10 \ protocol all \ basic match "cmp(u16 at 12 layer 2 eq 0x8864) and cmp(u32 at 34 layer 2 mask 0xFFFFFF00 eq 0xC0000200)" \ flowid 1:10
This ematch module lets you match on various attributes of the system (such as load average), or metadata about the packet (such as the firewall mark). tc filter add dev lo basic match meta(list) lists all the possible attributes.
When you want to match on a string inside a packet, nbyte is the module for you.
u32 is the same as the normal u32 match. Being an ematch it allows for lt,gt or eq matches as well as the usual matches. You can also use the "basic" system to allow for combining this with other ematches in one single rule.
The u32 match appears to be the most frequently used match. It appears that having multiple u32 matches on the same "prio" will be attempted to be "stack" into a single hash table. Errors can occur if they can't be "stacked". Try giving them a unique prio. u32 always matches from the "network" (aka IP/IP6) header. To get at the link layer header, negative offsets can be used as a hack.
This matches on the skb->tc_index. I don't know what this is used for? (ref)
Match on RSVP flow labels. (ref)
This is an extremely useful classifier that allows classifying packets into queues inside a SFQ.
Example:
$TC filter add dev $DEV \ parent 1: prio 1 \ handle 2 \ protocol all \ flow hash keys dst divisor 1024
This rule will change the SFQ classifier from the Internal one, to using one that only matches on destination address. This will fairly share bandwidth between destination IP's, instead of between 5 tuple flows.
One caveat discovered with the sfq classifier is that if a packet doesn't match, it will get dropped from the sfq, where as the default behavior of the SFQ's internal hashing algorithm is for packets it can't classify, to place them in bucket 0. While the external sfq classifier makes this obvious during testing (100% packet loss), the internal classifier will only show horrible performance when the sfq is under load (and there are many other buckets used).
The divisor is the divisor of a modulo operation. It must be equal or smaller than the hash size configured in the SFQ that this is classifying for. The SFQ size is defined at compile time, by default to be 1,024 elements in size. So set the divisor to 1024.
the flow keys can be src (source ip), dst (destination ip), proto (ip protocol), proto-src (transport protocol source address), proto-dst (transport protocol destination address), iif (input interface), priority (?), mark (firewall mark), nfct (netfilter conntrack?), nfct-src (original netfilter source), nfct-dst (original netfilter destination), nfct-proto-src (original netfilter conntrack transport protocol src), nfct-proto-dst (and so on), rt-classid (?), sk-uid (uid from the skbuff), sk-gid (gid from the skbuff), vlan-tag. At WAND we have extended this to include mac-src, mac-dst, mac-proto.
This also supports or/and/xor/rshift/append <i>NUM<i>. I don't know why this is here, possibly to allow you to attach multiple classifiers to the same sfq, and then limit them to different parts of the hash table?
This match module matches only on the fwmark. It uses the "handle" to select which firewall mark to match. Internally this uses a hash table, so having multiple fwmarks at the same prio appear to able to "stack".
Example:
$TC filter add dev $DEV \ parent 1: prio 2 \ protocol ip \ handle $FWMARK \ fw \ flowid 1:10
This match module allows matching on "realms". realms are tags that can be applied to routes. Supports matching from realm, fromif tag, to realm. I've not experimented with this match, but several other people have. This seems to be the easiest way to match routes from quagga. (eg national vs international)
No page links to TrafficControl.