Rewriting a MAC address by hand with pedit means fiddling with byte offsets; skbmod lets you just say which field changes. You will finish with a traffic-control filter that changes a complete destination or source MAC address, swaps the two addresses, or marks eligible IP packets as Congestion Encountered. The examples use tc from iproute2 6.1.0-1ubuntu6.4, whose utility reports iproute2 6.1.0.
Allow about twenty minutes, including time to inspect the existing qdisc and filter layout. You need root or CAP_NET_ADMIN, the iproute2 package, and a test interface or maintenance window. Packet edits affect live traffic. Do not run the mutating examples on a production interface until you have a rollback command and have confirmed the matching packets.
Start with read-only checks. This step needs no elevation:
$ tc -V
$ tc action add skbmod help
The installed command shows set, swap and ecn. It also lists the controls reclassify, pipe, drop, continue, ok and goto chain. The local tc-skbmod(8) manpage describes the same three action types but calls the successful final control pass. Prefer the output from the installed binary when the two documents differ. In particular, do not copy a control word from another iproute2 release without checking it here.
Checkpoint: record the interface, parent and preference used by your existing traffic-control layout:
$ tc qdisc show dev ethX
$ tc filter show dev ethX ingress
$ tc filter show dev ethX parent 1:
Replace ethX and 1: with real values. If there is no suitable parent, stop here and design the qdisc separately. skbmod is an action attached to a filter; it does not create the qdisc or classifier that selects packets.
skbmod has three mutually exclusive modes. Use one mode per action:
set changes one or more Ethernet fields: dmac, smac and etype.swap mac exchanges the destination and source MAC addresses.ecn changes ECT IP packets to CE. Non-ECT packets are not changed.Do not combine set, swap and ecn in one action. The manpage marks that combination as undefined. If a packet needs separate operations, attach separate actions with a deliberate control between them.
These operations have different boundaries. set and swap operate on Ethernet packets, while ecn operates on IP packets. A filter that selects the wrong protocol can make a correct action appear to do nothing.
The following example uses the manpage's u32 classifier shape. It selects ICMP over IPv4 and replaces the destination MAC. It requires elevation because it changes kernel traffic-control state:
$ sudo tc filter add dev ethX parent 1: protocol ip prio 10 + u32 match ip protocol 1 0xff flowid 1:2 + action skbmod set dmac 02:15:15:15:15:15 pipe
02:15:15:15:15:15 is an example value, not a safe universal destination. Use the address appropriate to your network. The pipe control passes the packet to the next action attached to the same filter. Omit it when the action should finish normally on this iproute2 version, or choose another control only when the surrounding filter tree requires it.
For a combined rewrite, the supported fields can appear under one set:
$ sudo tc filter add dev ethX parent 1: protocol ip prio 20 + u32 match ip protocol 1 0xff flowid 1:2 + action skbmod set etype 0xBEEF dmac 02:12:13:14:15:16 smac 02:22:23:24:25:26
An arbitrary ethertype such as 0xBEEF is useful for demonstrating the syntax but is unlikely to be a valid production protocol. Do not use it merely to make a packet recognisable unless the receiver is prepared for it.
Immediately inspect the filter after adding it. This is read-only:
$ sudo tc -s filter show dev ethX parent 1:
Look for the expected preference, classifier and skbmod action. The statistics are the useful checkpoint: packet and byte counts should increase only when traffic matches the classifier. A zero count means the traffic did not match, the filter is attached at the wrong parent, or the path bypasses that qdisc. It does not prove that the MAC rewrite is correct.
Use a packet capture on the appropriate side of the interface when you need to prove the resulting frame. Remember that ingress and egress placement changes where the edit is observed, and hardware offload can make software counters and captures confusing. Test with a controlled packet before increasing scope.
To exchange Ethernet source and destination addresses, use swap mac and keep the classifier narrow:
$ sudo tc filter add dev ethX parent 1: protocol ip prio 30 + u32 match ip protocol 1 0xff flowid 1:2 + action skbmod swap mac
This is not a general routing operation. It edits the Ethernet header selected by the filter; it does not rewrite IP addresses, update neighbour state or make a route valid. Treat it as a lab or controlled forwarding technique unless the surrounding design explicitly accounts for those layers.
To mark ECT IP packets as CE, use the separate ecn mode:
$ sudo tc filter add dev ethX parent 1: protocol ip prio 40 + u32 match ip protocol 6 0xff flowid 1:2 + action skbmod ecn
This example selects TCP, but the ECN action is about the IP header, not TCP itself. The action does not change Non-ECT packets. Marking CE is a congestion signal and can alter transport behaviour, so use it only with a measured policy and a rollback window. It is not a harmless packet label.
There is no undo flag on skbmod. Remove the filter that owns the action. Before doing so, save its exact current definition:
$ sudo tc -s filter show dev ethX parent 1:
If a test rule was the only filter at preference 10, the matching removal is:
$ sudo tc filter del dev ethX parent 1: protocol ip pref 10
That command deletes the filter at that preference, including its classifier and actions. It is destructive to that filter's traffic policy, so do not use it when preference 10 belongs to shared configuration. Restore the saved rule or the configuration managed by your network system, then verify again with tc filter show.
skbmod edits complete supported fields, unlike the byte-oriented pedit examples it replaces.set, swap and ecn belongs in one action. Chain distinct actions only after confirming their order.