The tc filter framework provides the infrastructure to another extensible set of tools as well, namely tc actions. As the name suggests, they allow to do things with packets (or associated data). (The list of) Actions are part of a given filter. If it matches, each action it contains is executed in order before returning the classification result. Since the action has direct access to the latter, it is in theory possible for an action to react upon or even change the filtering result - as long as the packet matched, of course. Yet none of the currently in-tree actions make use of this.
The Generic Actions framework originally evolved out of the filters' ability to police traffic to a given maximum bandwidth. One common use case for that is to limit ingress traffic, dropping packets which exceed the threshold. A classic setup example is like so:
# tc qdisc add dev eth0 handle ffff: ingress
# tc filter add dev eth0 parent ffff: u32 \
match u32 0 0
police rate 1mbit burst 100k
The ingress qdisc is not a real one, but merely a point of reference for filters
to attach to which should get applied to incoming traffic. The u32 filter added
above matches on any packet and therefore limits the total incoming bandwidth to
1mbit/s, allowing bursts of up to 100kbytes. Using the new syntax, the filter
command changes slightly:
# tc filter add dev eth0 parent ffff: u32 \
match u32 0 0 \
action police rate 1mbit burst 100k
The important detail is that this syntax allows to define multiple actions.
E.g. for testing purposes, it is possible to redirect exceeding traffic to the
loopback interface instead of dropping it:
# tc filter add dev eth0 parent ffff: u32 \
match u32 0 0 \
action police rate 1mbit burst 100k conform-exceed pipe \
action mirred egress redirect dev lo
The added parameter conform-exceed pipe tells the police action to allow for
further actions to handle the exceeding packet.
Apart from police and mirred actions, there are a few more. Here's a full list of the currently implemented ones: