Home / Alt manpages / tc-mpls(8)

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

Build and Inspect tc MPLS Actions Safely

The tc mpls action pushes, pops or edits an MPLS header on a Linux box, letting you fake up label-switched traffic without real LSR hardware nearby. You'll attach the filter, inspect what it built, then remove it cleanly. Allow 15 to 30 minutes for a lab interface and a test path. The commands below describe the installed Ubuntu iproute2 6.1.0 package; packet forwarding and switch behaviour still depend on the interfaces and the rest of your network.

This guide assumes two interfaces: an input interface that receives packets and an output interface to which matching packets are redirected. Replace IFACE_IN and IFACE_OUT with real names. Run inspection commands as your normal user where possible; the commands that change qdiscs or filters need root, so they use sudo.

1. Check the installed syntax

The mpls action is part of tc, from the iproute2 package. Confirm the binary and version before copying a command into a script:

$ command -v tc
/usr/sbin/tc
$ tc -V
tc utility, iproute2-6.1.0, libbpf 1.3.0
$ dpkg-query -W -f='${Package} ${Version}\n' iproute2
iproute2 6.1.0-1ubuntu6.4

The installed manual describes four modes:

  • push needs a label.
  • pop needs the protocol of the header that follows MPLS.
  • modify can change selected fields on an existing header.
  • dec_ttl takes no field arguments at all.

Checkpoint

Make sure the interfaces are the ones you intend to affect. This is read-only:

$ ip -br link show IFACE_IN IFACE_OUT
Device names and state are printed here

2. Add a temporary ingress hook

Incoming filters need an ingress qdisc. Adding one changes live packet processing, so use a test host or a maintenance window. The qdisc isn't a permanent configuration file, but it stays active until you remove it or reset the interface.

$ sudo tc qdisc add dev IFACE_IN handle ffff: ingress

If the interface already has an ingress qdisc, this command reports that one exists. Do not blindly replace it: inspect it first, because another filter may be serving production traffic.

$ tc qdisc show dev IFACE_IN
qdisc ingress ffff: parent ffff:fff1 ----------------

The handle ffff: is the parent used by the examples in the tc-mpls manual. It is not an MPLS label.

3. Push an MPLS label onto IP traffic

This filter matches IPv4 packets on the ingress interface, adds an MPLS unicast header with label 123, and redirects the result to the output interface. The flower classifier and mirred redirect are separate actions from the MPLS operation:

$ sudo tc filter add dev IFACE_IN protocol ip parent ffff: flower \
    action mpls push protocol mpls_uc label 123 \
    action mirred egress redirect dev IFACE_OUT

mpls_uc is the default protocol for a push, but spelling it out makes the wire format easier to review. The label is an unsigned 20-bit value, and the default traffic-class value is 0. If you omit ttl, the implementation picks a non-zero default, so specify it when the value matters:

$ sudo tc filter add dev IFACE_IN protocol ip parent ffff: flower \
    action mpls push protocol mpls_uc tc 0 ttl 64 label 123 \
    action mirred egress redirect dev IFACE_OUT

Do not add both versions: two filters can make packet counts confusing. Delete the first before installing the second, or use a fresh test interface.

4. Inspect the installed filter

Ask tc to print the filter and its action chain. Counters depend on traffic, so an empty packet count is not a syntax failure:

$ sudo tc -s filter show dev IFACE_IN parent ffff:
filter protocol ip pref 49152 flower chain 0
  action order 1: mpls
    push protocol mpls_uc label 123
  action order 2: mirred ... redirect dev IFACE_OUT
    Sent ... packets ...

Preference numbers and counter formatting can vary. Look for the MPLS action, label 123, the redirect device and a successful command exit status. If no filter appears, check the interface name and parent handle before sending test traffic.

5. Pop or modify an existing MPLS header

For incoming MPLS unicast packets whose next header is IPv4, swap the push action for pop protocol ipv4. The protocol tells tc which Ethernet protocol to restore once the outer MPLS header is gone:

$ sudo tc filter add dev IFACE_IN protocol mpls_uc parent ffff: flower \
    action mpls pop protocol ipv4 \
    action mirred egress redirect dev IFACE_OUT

For an existing MPLS header, modify changes only the fields you supply. This example changes the label and TTL, leaving other fields under the action's existing behaviour:

$ sudo tc filter add dev IFACE_IN protocol mpls_uc parent ffff: flower \
    mpls_label 123 mpls_bos 1 \
    action mpls modify label 456 ttl 64 \
    action mirred egress redirect dev IFACE_OUT

The protocol option cannot be used with modify. The classifier's mpls_label and mpls_bos match fields select the packet; the action's label and ttl fields change it.

6. Decrement TTL only when the packet has MPLS

dec_ttl subtracts one from the outer MPLS TTL and takes no label, protocol or TTL value:

$ sudo tc filter add dev IFACE_IN protocol mpls_uc parent ffff: flower \
    action mpls dec_ttl \
    action mirred egress redirect dev IFACE_OUT

Apply this only to traffic whose outer header is already MPLS. A plain IP filter doesn't create an MPLS header for this action to edit. Treat TTL handling as a forwarding policy decision, not a harmless display option.

7. Remove the test configuration

Warning

Deleting a filter or qdisc immediately changes packet handling. List the filters first and record anything belonging to another workload:

$ sudo tc filter show dev IFACE_IN parent ffff:

On a disposable interface, remove all filters from this parent, then remove the ingress qdisc:

$ sudo tc filter del dev IFACE_IN parent ffff:
$ sudo tc qdisc del dev IFACE_IN ingress
$ tc qdisc show dev IFACE_IN

If the interface had pre-existing filters, do not use the broad delete command. Remove the particular filter using the selector shown by tc filter show, or restore the configuration from the system's network-management tool. The examples here create no persistent service or configuration file, so a reboot also clears them, but relying on a reboot is a poor recovery plan for a live forwarding path.

Common failure checks

  • File or protocol errors: check that mpls_uc, ipv4 or another protocol matches the packet after the operation. A pop needs the following protocol; a push accepts mpls_uc or mpls_mc.
  • Invalid values: labels must fit an unsigned 20-bit value, traffic class is decimal 0 to 7, and TTL is 0 to 255. The bottom-of-stack bit can be supplied with bos, but normally the action determines it from the next header.
  • No packets redirected: inspect the filter's counters, then check that the classifier protocol and input interface match real traffic. A successful filter installation does not prove traffic matches.
  • Unexpected traffic loss: remove the test filter first. If the qdisc was created only for this test, remove the ingress qdisc afterwards. Preserve any filters that another service owns.

Done means

  • Version and interfaces confirmed. You checked the installed iproute2 version and selected real test interfaces.
  • Mode is deliberate. You know whether the action is pushing, popping, modifying or decrementing an MPLS header.
  • Filter inspected. You checked the filter and its counters after installation.
  • Values understood. You specified a label and understood the protocol, TTL, traffic-class and bottom-of-stack defaults.
  • Cleanup done or documented. You removed the temporary filter and ingress qdisc, or recorded the exact configuration that must remain.