The tc filter add command is failing because the kernel’s traffic control subsystem is rejecting the filter definition, most commonly due to a mismatch between the filter’s protocol, parent, or intended action, or because the necessary kernel modules aren’t loaded.
Here are the most common reasons this command fails and how to fix them:
1. Invalid Parent Interface:
- Diagnosis: You’re trying to attach a filter to a non-existent or incorrectly specified network interface. The kernel expects a valid
devargument pointing to a real network device. - Common Causes & Fixes:
- Typo in Interface Name: Double-check
eth0,ens192,wlan0, etc.- Command:
ip link show - Fix: Correct the interface name in your
tccommand. For example, ifip link showlistsens192but you typedens193, change your command. - Why it works:
tcoperates on network devices. An invalid name means no device is found for the filter to attach to.
- Command:
- Filter Attached to a Loopback/Virtual Interface: Some virtual interfaces or loopback devices (
lo) might not support the kind of traffic control you’re trying to apply.- Fix: Attach the filter to a physical interface that handles the traffic you intend to shape.
- Why it works: Traffic control is typically implemented at the network device driver level. Not all drivers expose the necessary hooks.
- Filter Attached to a Non-Existent Qdisc: If you’re trying to attach a filter to a specific qdisc (e.g.,
parent 1:) that hasn’t been created yet on the interface,tcwill error.- Diagnosis:
tc qdisc show dev <interface> - Fix: Ensure the parent qdisc exists. Often, you’ll need to add a root qdisc first (like
htboringress) before adding filters.tc qdisc add dev eth0 root handle 1: htb default 1 tc filter add dev eth0 parent 1: ... - Why it works: Filters are children of qdiscs. A filter cannot exist without a parent qdisc to attach to.
- Diagnosis:
- Typo in Interface Name: Double-check
2. Incorrect Protocol Specification:
- Diagnosis: The
protocolargument (e.g.,ip,ipv6,ether) does not match the actual traffic passing through the interface or the filter’s matching criteria. - Common Causes & Fixes:
- Mismatched IP Version: Trying to filter IPv4 traffic with
protocol ipv6or vice-versa.- Fix: Use
protocol ipfor IPv4 andprotocol ipv6for IPv6. If you want to match all IP traffic,protocol ipis often sufficient as it can catch IPv6 too depending on the kernel version and configuration. - Why it works: The kernel uses the protocol field to know which header parsing and matching routines to invoke.
- Fix: Use
- Using
etherfor IP-level Filtering: Theetherprotocol is for Layer 2 (MAC address) filtering. If you’re trying to match IP addresses, ports, or protocols, useiporipv6.- Fix: Change
protocol ethertoprotocol ipif you’re specifying IP addresses or ports. - Why it works:
etherfilters operate on the Ethernet frame header, whileipfilters operate on the IP packet header.
- Fix: Change
- Mismatched IP Version: Trying to filter IPv4 traffic with
3. Invalid Filter Type or Action:
- Diagnosis: The
handleoractionspecified for the filter is not understood by the kernel or is incompatible with the parent qdisc. - Common Causes & Fixes:
- Using
flowidwith non-prioorhtbqdiscs:flowidis specific toprioandhtbqdiscs.- Fix: Ensure your parent qdisc is
htborprioif you’re usingflowid.tc qdisc add dev eth0 root handle 1: htb default 1 tc filter add dev eth0 parent 1: protocol ip prio 1 flowid 1:1 - Why it works:
flowidis an identifier used by these specific qdisc types to route packets to sub-classes or bands.
- Fix: Ensure your parent qdisc is
- Unsupported
action: Trying to use anaction(likemirred,tunnel_key,nat) that isn’t compiled into your kernel or isn’t supported by the qdisc.- Diagnosis: Check
/proc/net/ip_tables_matchesor kernel configuration. - Fix: Ensure the necessary kernel modules are loaded (e.g.,
xt_mirred). If not available, you might need to recompile the kernel or use a different approach.sudo modprobe xt_mirred - Why it works:
tcactions are implemented as kernel modules. If the module isn’t present or loaded, the action is unknown.
- Diagnosis: Check
- Incorrect
handleFormat: Thehandlefor a filter, especially when it’s directly under the root qdisc, needs to be unique and follow themajor:minorconvention.- Fix: Use a unique handle, often
1:,2:, etc., for filters directly attached to the root. For filters attached to secondary qdiscs, use the qdisc’s handle as the parent (e.g.,parent 1:1). - Why it works: Handles are internal identifiers the kernel uses to manage qdiscs and filters.
- Fix: Use a unique handle, often
- Using
4. Missing Kernel Modules:
- Diagnosis: The specific traffic control classifier or action you’re trying to use requires a kernel module that isn’t loaded.
- Common Causes & Fixes:
- Missing
cls_u32orcls_fw: For basic packet matching.- Fix: Load the module:
sudo modprobe cls_u32orsudo modprobe cls_fw. - Why it works: These modules provide the logic for classifying packets based on various criteria.
- Fix: Load the module:
- Missing
act_mirred: For redirecting traffic.- Fix: Load the module:
sudo modprobe act_mirred. - Why it works: This module implements the
mirredaction, allowing packets to be mirrored or redirected.
- Fix: Load the module:
- Missing
ematchmodules: For extended matching (e.g.,ematch_meta).- Fix: Load relevant modules:
sudo modprobe ematch_meta. - Why it works:
ematchmodules extend the matching capabilities beyond basicu32orfwclassifiers.
- Fix: Load relevant modules:
- General Check: If you’re unsure, try loading modules related to the specific classifier or action you’re using. Check
lsmod | grep schorlsmod | grep cls.
- Missing
5. Filter Specification Ambiguity or Conflict:
- Diagnosis: The filter’s matching rules are too broad, too narrow, or conflict with existing filters.
- Common Causes & Fixes:
- Overlapping
u32Matches: If you have multipleu32filters with overlapping match criteria, the kernel might pick the first one it encounters or reject the addition due to ambiguity, depending on thepriorityandclassid.- Diagnosis: Carefully review your
tc filter show dev <interface>output. - Fix: Assign distinct priorities (
prio) to your filters, or refine the match criteria (u32) to be mutually exclusive.tc filter add dev eth0 parent 1: protocol ip prio 1 u32 ... tc filter add dev eth0 parent 1: protocol ip prio 2 u32 ... - Why it works: Priorities determine the order in which filters are evaluated. Distinct criteria ensure each packet matches only one intended filter.
- Diagnosis: Carefully review your
- Invalid
classid: Theclassidspecified in the filter’s action (e.g.,flowid 1:10) does not correspond to an existing class within the parent qdisc.- Fix: Ensure you have created the class using
tc class add.tc class add dev eth0 parent 1: classid 1:10 htb rate 100kbit tc filter add dev eth0 parent 1: protocol ip prio 1 u32 flowid 1:10 ... - Why it works: Filters direct traffic to classes. If the target class doesn’t exist, the filter cannot be applied.
- Fix: Ensure you have created the class using
- Overlapping
The next error you’ll likely encounter after fixing these is related to tc not being able to establish a connection to the netlink socket, often due to insufficient permissions or a deeply corrupted network stack state.