When you cannot mirror every packet without drowning your monitoring box, tc-sample skims a fraction of ingress traffic instead. You will attach the sample action to an ingress matchall filter, send an average of one packet in every 100 to psample group 12, and optionally cap the copied packet size. Allow about 15 minutes, since the examples change traffic-control state, and use an interface where a short-lived ingress rule is acceptable.
This guide describes the installed tc-sample(8) behaviour on this machine: iproute2 6.1.0-1ubuntu6.4, reported by tc -V as iproute2 6.1.0. Sampling is not a packet capture by itself. A userspace consumer must listen on the psample generic netlink channel to receive the sampled data and metadata.
Run these checks as your normal user first. Replace eth0 with the interface you intend to observe:
$ command -v tc
/usr/sbin/tc
$ tc -V
tc utility, iproute2-6.1.0, libbpf 1.3.0
$ ip link show dev eth0
The sample action needs a classifier match. The documented example uses a matchall filter on an ingress qdisc. If you need only selected traffic, replace matchall with a classifier you have reviewed; do not assume that sampling is restricted because a consumer later filters the received data.
Checkpoint: confirm the interface name and whether another ingress qdisc is already present:
$ tc qdisc show dev eth0
Do not continue blindly if another administrator owns the ingress configuration. The undo command later removes the ingress qdisc and its attached filters, not just the sample action.
Adding the qdisc and filter requires elevated privileges. The following commands create a sample action with index 19, rate 100 and psample group 12:
$ sudo tc qdisc add dev eth0 handle ffff: ingress
$ sudo tc filter add dev eth0 parent ffff: matchall \
action sample rate 100 group 12 index 19
rate 100 is a sampling ratio, not a packets-per-second limit. The action chooses packets randomly and aims for an average of one sampled packet for every 100 packets seen by this rule. A short test can therefore produce no sample, or several, and is not proof that the action is broken.
group 12 labels the samples on the psample channel. Pick a group number that your consumer and other sampling rules agree on. index 19 is the non-zero 32-bit action identifier. It makes the action instance addressable and allows the same instance to be referenced by another filter.
Checkpoint: inspect the filter and action. The exact formatting varies between tc releases, but the rule should show a sample action with rate 100, group 12 and index 19:
$ sudo tc filter show dev eth0 ingress
$ sudo tc actions ls action sample
By default, the sample contains the packet data available to the action. If a full packet is unnecessary, add trunc with a maximum size in bytes. This reduces traffic between the kernel and the psample consumer, while the metadata still includes the original packet size.
$ sudo tc qdisc del dev eth0 ingress
$ sudo tc qdisc add dev eth0 handle ffff: ingress
$ sudo tc filter add dev eth0 parent ffff: matchall \
action sample rate 100 group 12 trunc 128 index 19
This replacement briefly removes the ingress rule, so do it during a suitable maintenance window. The first command also removes any other filters on that ingress qdisc. If those filters are not yours, stop and restore the previous configuration instead of running it.
trunc 128 means that at most 128 bytes of packet data are sent in each sample. It does not change PSAMPLE_ATTR_ORIGSIZE, which reports the original packet length. Do not use a small truncation size when your analysis requires headers or payload bytes beyond that boundary.
An existing action can be referenced by its index instead of repeating its parameters. First create an ingress qdisc on the second interface, then refer to index 19:
$ sudo tc qdisc add dev eth1 handle ffff: ingress
$ sudo tc filter add dev eth1 parent ffff: matchall \
action sample index 19
Both filters now use the same action definition. Samples from both interfaces still carry input and output interface indexes where applicable, the original size, group number, sequence number and sampling rate. The group sequence number increments for sampled packets in the current psample group, so a consumer should not treat it as a global packet counter.
Checkpoint: list both filters and verify that the second one refers to the expected action rather than silently creating a different configuration:
$ sudo tc filter show dev eth0 ingress
$ sudo tc filter show dev eth1 ingress
$ sudo tc actions ls action sample
The tc action publishes samples through the psample generic netlink channel. The manpage documents the channel and attributes, but it does not provide a consumer command. Use a psample-aware monitoring or telemetry program already approved for your host, and configure it to listen for group 12.
Keep the two layers separate: a successful tc filter show proves that the rule is installed, while a consumer receiving records proves that the psample path is working. Generate enough ordinary traffic to make the expected ratio observable, then compare the consumer's records with the reported sample rate. Random selection means the observed count will vary.
If no records arrive, check the filter first, then confirm that the consumer is listening to the same group. Also check that the consumer supports the kernel's psample channel and that the interface is actually receiving traffic. Do not raise privileges or increase the sampling rate as a first response to a consumer configuration error.
Removing an ingress qdisc is a service-affecting operation for traffic-control rules on that interface. Before doing it, save any configuration you need to restore. For the isolated examples above, remove the second interface and then the first:
$ sudo tc qdisc del dev eth1 ingress
$ sudo tc qdisc del dev eth0 ingress
$ tc qdisc show dev eth0
$ tc qdisc show dev eth1
The delete commands remove the ingress qdiscs and the filters attached to them. They do not uninstall iproute2, change the kernel, or remove a userspace psample consumer. If the command reports that the qdisc does not exist, inspect the current state before retrying; another process may already have changed it.
trunc value is large enough for the metadata and packet fields the consumer needs.