Home / Alt manpages / tc-route(8)

  • tc-route(8)
  • Admin command
  • linux

Classify Routed Traffic with the tc route Filter

The tc route classifier ignores source and destination addresses; it reads a realm that ip route already worked out for you. This guide uses that routing realm as input to the route classifier, then sends matching packets to a traffic-control class. Allow about fifteen minutes if the target qdisc and class already exist. You need the iproute2 package; the installed version used for this guide is 6.1.0-1ubuntu6.4.

The examples below use realm 2, interface enp0s31f6, and class 1:2 as placeholders. Replace them with values from your own routing and traffic-control design. Commands that alter routes or filters need elevated privileges; read-only inspection does not.

1. Understand what the classifier matches

The route filter runs a routing-table lookup for each packet and compares the returned realm. With from REALM it does a source route lookup; with to REALM it checks the ordinary destination lookup. On its own it does not match an arbitrary source address, destination address, or interface name.

The related fromif TAG form asks for source lookups tied to an interface name. That interface must exist when tc runs, so treat this as a configuration dependency: a renamed or not-yet-created interface makes the command fail outright, rather than silently matching nothing.

Checkpoint

Confirm the route and filter tools available on this host without changing anything.

ip -Version
tc filter help
tc filter show dev enp0s31f6

The version command reports the iproute2 version and lists route as a supported filter type. The final command may print no filters at all, which is still a valid result. Don't confuse an empty filter listing with a filter that's actually been tested.

2. Assign a realm to a route

A route needs a realm before the classifier has anything to compare against. This example adds a private subnet route with realm 2. It changes the live routing table, so only run it on a host where that subnet and gateway choice are actually correct.

sudo ip route add 192.168.2.0/24 dev enp0s31f6 realm 2

Verify the entry before adding a filter:

ip route show 192.168.2.0/24

Expect an entry containing dev enp0s31f6 and realm 2. If the route already exists, don't blindly repeat the command, inspect it and decide whether its existing realm is the one you actually want. To undo this exact example later:

sudo ip route del 192.168.2.0/24 dev enp0s31f6

Warning

That deletion is service-disrupting for anyone using the subnet. Keep the original route definition, plus any gateway, metric, scope or protocol details, so you can restore the previous state accurately. A route added manually is also normally lost on reboot unless your network configuration manages it.

3. Add a route filter to an existing classful qdisc

The filter attaches to a traffic-control parent. The manpage deliberately shows this part as ..., because the correct device, protocol, parent handle, priority and class hierarchy all depend on your own qdisc setup. The classifier-specific part is:

tc filter add ... route from 2 classid 1:2

That means a packet whose source route lookup returns realm 2 gets pushed into class 1:2. A complete command needs the parent and protocol from your existing setup. If your design uses an IPv4 class hierarchy rooted at 1: on enp0s31f6, the shape is:

sudo tc filter add dev enp0s31f6 parent 1: protocol ip route from 2 classid 1:2

Only use that command when parent 1: and class 1:2 genuinely exist. If they don't, the command should fail rather than quietly build the hierarchy for you. Check the current filters with the matching scope:

sudo tc filter show dev enp0s31f6 parent 1:

Look for a route filter and its realm and class settings. Formatting varies with the iproute2 build and with whatever other filters sit on the parent. If the filter is absent, stop and fix the parent, protocol or permissions before sending test traffic.

4. Match destination lookups instead

To classify traffic on the normal destination route instead, use to rather than from:

sudo tc filter add dev enp0s31f6 parent 1: protocol ip route to 2 classid 1:2

Don't add both forms just to make a match feel more specific, they represent different routing lookups. Pick the one that matches the traffic direction and policy you're actually implementing, then verify the resulting filter listing.

You can also apply a generic traffic-control action instead of, or alongside, a class assignment, using the route filter's action ACTION_SPEC field. That action syntax belongs to the generic actions framework, so select and test it separately. A route filter does not make an action safe, reversible, or correct for a production interface.

5. Use named realms when the host defines them

Realm values run from 0 through 255. The iproute2 tools can also accept a verbose name defined in /etc/iproute2/rt_realms. Read that file before using a name, and confirm every host running the command shares the same mapping:

sed -n '1,120p' /etc/iproute2/rt_realms

Don't assume a name is globally standard. A numeric realm is easier to audit in a small, self-contained example, while a named realm can make a larger policy easier to read once the configuration is managed consistently across hosts.

6. Remove the filter safely

Removing a filter changes how matching packets are classified immediately. Record the current listing first and identify the exact filter, including its parent and any handle or priority shown in your output. Then remove it using the same scope and identifying values. For a deliberately isolated example where this is the only route filter under parent 1:, the broad removal shape is:

sudo tc filter del dev enp0s31f6 parent 1: route

Warning

Don't run a broad deletion like that on a shared production parent. It can remove more policy than the example intended, depending on the installed command's filter selection and the surrounding configuration. Prefer the exact handle and priority from your inspection output when the hierarchy holds other filters.

After removal, verify the state:

sudo tc filter show dev enp0s31f6 parent 1:

Finally, remove the example route too, but only if this guide created it and it's no longer needed:

sudo ip route del 192.168.2.0/24 dev enp0s31f6

Done means

  • Realm assigned correctly: the intended route shows the expected realm.
  • Filter attached correctly: it sits on the intended parent and uses the right from, fromif, or to lookup.
  • Classification confirmed: the destination class or generic action shows up in the filter listing.
  • Baseline recorded: you noted the original route and filter state before changing a live interface.
  • Cleanup handled: any temporary route and filter have been removed, or their persistent owner is documented.