trafficshaper: add nftables firewall backend#29830
Conversation
| command -v nft &>/dev/null || return 0 | ||
|
|
||
| d "Cleaning nftables" | ||
| $NFT delete table inet "$NFT_TABLE" &>/dev/null || : |
There was a problem hiding this comment.
changed it to use destroy table now.
| printf '%s\n' "delete table inet $NFT_TABLE" | ||
| printf '%s\n' \ | ||
| "add table inet $NFT_TABLE" \ | ||
| "add chain inet $NFT_TABLE forward { type filter hook forward priority -150; policy accept; }" \ |
There was a problem hiding this comment.
Given iptables code does -A you have to use priority mangle + (1...10) to perform the processing after the default hook. Even better you can make it completely independent from fw4 or fw3 or their mere presence altogether.
There was a problem hiding this comment.
Ah, ok, i changed the nft hook to use priority mangle + 10, so it runs after
the default mangle instead of at the same priority. It also checks just nft.
4a9716f to
5efcd9b
Compare
| CATEGORY:=Network | ||
| TITLE:=WAN traffic shaper based on LAN addresses | ||
| DEPENDS:=+tc +kmod-sched-core +kmod-sched-connmark +kmod-ifb +iptables +IPV6:ip6tables +kmod-sched-cake +iptables-mod-conntrack-extra | ||
| DEPENDS:=+tc +kmod-sched-core +kmod-sched-connmark +kmod-ifb +nftables +iptables +IPV6:ip6tables +kmod-sched-cake +iptables-mod-conntrack-extra |
There was a problem hiding this comment.
Please use "complex dependency" to shorten installed package list like
+(nftables||(iptables IP6:6tables ipt-mod-whatever)) /// syntax may not be top correct...
https://openwrt.org/docs/guide-developer/packages#dependency_types
In short - if nftables are satisfied like in 99% cases nothing is added, in other cases spmething additional is installed.
There was a problem hiding this comment.
I had no idea about this. This is good. I have now changed it to conditional instead of having both firewall stacks.
There was a problem hiding this comment.
A note for next reviewers - since priority of nft code path is skewed it can coexist (oredered predictably) with legacy tables hooks like fw3 or shorewalls. There is no need for more heuristics in default auto mode.
| *) die 2 "Unknown address family of network $class_net in class $class!" | ||
| esac | ||
| if [ "$class_reserved_uplink" ]; then | ||
| printf '%s\n' "add rule inet $NFT_TABLE classify meta mark & $mark_mask == 0x0 $nft_family saddr $class_net counter meta mark set (meta mark & $mark_mask_inv) | $xi comment \"$APPNAME-$class up\"" |
There was a problem hiding this comment.
Totally optional but you can compact multiple count(class_net) lines by using map ipo $xi
There was a problem hiding this comment.
Thanks, that would surely help, but I’ll leave it out for now to keep this PR
closer to the existing iptables path and easier to review.
I’ll certainly look into doing it as a follow-up once the basic nft backend
looks okay.
There was a problem hiding this comment.
Agree, while filter length before potential branching logic looks gross it consists of generally efficient meta integer comparisons.
There was a problem hiding this comment.
Got it, thanks. I’ll keep it simple in this PR then.
5efcd9b to
1795a12
Compare
brada4
left a comment
There was a problem hiding this comment.
LGTM (including directly applying to stable trains)
|
Thanks @dhrm1k for this PR. It looks pretty good. I'll test it in my lab and return ASAP. |
|
It is still installing iptables compatible tools: Openwrt has two nftables flavors: nftables-json-1.1.6-r4 x86_64 {feeds/base/network/utils/nftables} (GPL-2.0) [installed] Both provides nftables but Provides is not used during config but only during installation. This is menuconfig info: You'll need something like this to use either one of them: I also tested shaping and it is working as expected. |
| DEPENDS:=+tc +kmod-sched-core +kmod-sched-connmark +kmod-ifb \ | ||
| +PACKAGE_nftables:nftables +!PACKAGE_nftables:iptables \ | ||
| +(IPV6&&!PACKAGE_nftables):ip6tables \ | ||
| +kmod-sched-cake +!PACKAGE_nftables:iptables-mod-conntrack-extra |
There was a problem hiding this comment.
Use something like this as PACKAGE_nftables does not exist as config variable.
DEPENDS:=+tc +kmod-sched-core +kmod-sched-connmark +kmod-ifb \
+(PACKAGE_nftables-json||PACKAGE_nftables-nojson):nftables \
+!(PACKAGE_nftables-json||PACKAGE_nftables-nojson):iptables \
+(IPV6&&!(PACKAGE_nftables-json||PACKAGE_nftables-nojson)):ip6tables \
+kmod-sched-cake \
+!(PACKAGE_nftables-json||PACKAGE_nftables-nojson):iptables-mod-conntrack-extra
There was a problem hiding this comment.
I didn’t know there were two nftables flavours. Thanks.
I updated the dependency check to use the concrete nftables-json /
nftables-nojson package symbols instead of PACKAGE_nftables.
1795a12 to
0c81cb3
Compare
Thanks for putting your time into this. Since you already tested shaping, after you check the dependency part, if it |
|
Maybe this https://openwrt.org/docs/guide-developer/dependencies#using_boolean_operators |
|
I tested the current form with both In both cases the generated I think this is probably as compact as it can reasonably get, because the |
I tested shaping with both iptables-nft and pure nft. It’s great to see this package working smoothly after 8 years! Regarding the dependencies: it is still pulling some kmod-ipt-* packages, but this is an upstream inheritance from kmod-sched-connmark: define KernelPackage/sched-connmark
SUBMENU:=$(NETWORK_SUPPORT_MENU)
TITLE:=Traffic shaper conntrack mark support
DEPENDS:=+kmod-sched-core +kmod-ipt-core +kmod-ipt-conntrack-extraWhile we could theoretically drop kmod-sched-connmark, it is required by our script's architecture to restore conntrack marks at the WAN ingress stage before redirecting traffic to the IFB device. This is currently the only viable way to share a global QoS rule across multiple LAN/VLAN interfaces. Once the OpenWrt core drops legacy ipt- kernel modules for good, a native alternative will surely take over. For now, this is as optimized as it gets: userspace is 100% free of iptables binaries, and a few passive kernel modules won't hurt performance. Again, thanks for taking care of it. |
Remove iptables kmod dependency from kmod-sched-connmark. Both dependents package/network/config/qos-scripts ../packages/net/trafficshaper Already pull in ipt kmods via iptables-mod-conntrack-extra Permits "clean" nftables migration at openwrt/packages#29830 Signed-off-by: Andris PE <neandris@gmail.com>
|
@luizluca this can pass independently from main repo commit, just that ad interim kmod-sched- will pull those unnecessary ipt modules. iptables side will pull those modules just once. |
|
@BKPepe whenever you get time, please look into this. |
0c81cb3 to
b50b4c3
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds an nftables-based firewall backend to trafficshaper for packet marking (used by tc), while keeping the existing iptables-based backend available for older/non-nft systems, aligning the package with the ongoing firewall4/nftables migration.
Changes:
- Make the package dependencies conditional so
nftablesoriptablesis pulled in depending on the build selection. - Extend the init script to support
firewall_backendselection (auto/nftables/iptables) and implement nftables rule installation/cleanup. - Add
option firewall_backend 'auto'to the default UCI config and validation.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| net/trafficshaper/Makefile | Updates release and makes firewall backend dependencies conditional (nftables vs iptables). |
| net/trafficshaper/files/trafficshaper.init | Adds backend selection logic and a new nftables ruleset backend for marking + cleanup paths. |
| net/trafficshaper/files/trafficshaper.conf | Introduces a configurable firewall_backend defaulting to auto. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "add chain inet $NFT_TABLE forward { type filter hook forward priority mangle + 10; policy accept; }" \ | ||
| "add chain inet $NFT_TABLE classify" \ | ||
| "# Keep ct and packet marks in sync for tc fw filters." \ | ||
| "add rule inet $NFT_TABLE forward counter meta mark set ct mark comment \"Get previous class\"" \ |
There was a problem hiding this comment.
1/ proposed syntax does not work
2/ the exact original bits are copied back
| : $((i++)) | ||
| done | ||
|
|
||
| printf '%s\n' "add rule inet $NFT_TABLE classify counter ct mark set meta mark comment \"Save class\"" |
| stop_firewall_iptables() { | ||
| d "Cleaning iptables" | ||
| for IPT in "$IP4T" "$IP6T"; do | ||
| $IPT -t mangle -D FORWARD -j $IPT_CHAIN &>/dev/null || : | ||
| $IPT -t mangle -F $IPT_CHAIN &>/dev/null || : | ||
| $IPT -t mangle -X $IPT_CHAIN &>/dev/null || : | ||
| $IPT -t mangle -F $IPT_CHAIN-classify &>/dev/null || : | ||
| $IPT -t mangle -X $IPT_CHAIN-classify &>/dev/null || : | ||
| done | ||
| } |
|
@dhrm1k iptables-translate was wrong in this case ;-) With nftables you have to destroy one of 2 marks.... |
b50b4c3 to
4ce07e9
Compare
Ah yup, I get it now. I updated it to mask both directions, so only the |
|
@dhrm1k if you want to flex your skill more you can try this too https://github.com/tohojo/sqm-scripts/blob/20ba92639546075d8e39346dcb88a3cdfe8ee903/src/simple.qos#L39 |
|
@brada4 yes, sqm scripts is indeed a interesting project, though i checked tohojo/sqm-scripts#146 and saw upstream prefers relying on iptables-nft instead of adding nft support. I can work on adding native nft support while keeping iptables as fallback, but do you think it is worth sending upstream, or would you expect the same objection? Personally, I think there is still a practical case for it. One of my APs is very storage constrained: it has only around 3.5 MB usable space for extra packages. It already has firewall4/nftables, but not iptables-nft/xtables-nft, so every extra package matters there. |
|
@tohojo what do you think? |
You mean about sqm-scripts? Well, my main concern was not having to support both iptables and nftables; I don't think that's too much of an issue these days as it was four years ago when that discussion happened. So yeah, I would be OK with replacing iptables wholesale with nftables in upstream sqm-scripts :) |
|
@tohojo I was initially thinking of adding native nft support while keeping the current iptables path as fallback, mostly to avoid regressions on older/non-openwrt systems. I’ll prepare a PR against sqm-scripts and we can discuss the exact fallback vs replacement shape there. |
|
@tohojo this is even more elaborate keeping both code paths for full stone age compatibility. |
This package is openwrt-only, though, right? Why keep the compatibility here? Is it even possible to build an openwrt image without nftables support these days? :) |
|
fw3 is still kicking, you just give up luxuries of modern life like attended-sysupgrade |
Huh, right then. And why would anyone use it over fw4? :) |
|
u32, tarpit module, text scan modules, kilometer long ruleset converted from ufw ubuntu.... |
|
@dhrm1k I have tried quick port of sqm script port and it went "very well" https://bugzilla.netfilter.org/show_bug.cgi?id=1840 |
|
Yeah, I also have a first pass for sqm-scripts now. I have a PR open. I'd love if you'd take a look at that. Thanks for the DSCP / inet table note. I’ll look into splitting the ip/ip6 handling over the weekend. |
|
I think the review comments on the nft backend are addressed now. |
|
As for mine - yes, all resoved, I can not tap them away, just mark them resolved yourself.... |
|
You fell for clankers |
brada4
left a comment
There was a problem hiding this comment.
clankers broke the stuff
trafficshaper[INFO]: Starting trafficshaper
/dev/stdin:7:1-131: Error: Could not process rule: Not supported
add rule inet trafficshaper forward counter meta mark set (meta mark & 0xFFFFFF00) | (ct mark & 0xFF) comment "Get previous class"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/dev/stdin:21:1-122: Error: Could not process rule: Not supported
add rule inet trafficshaper classify counter ct mark set (ct mark & 0xFFFFFF00) | (meta mark & 0xFF) comment "Save class"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| "add chain inet $NFT_TABLE classify" \ | ||
| "# Keep ct and packet marks in sync for tc fw filters." \ | ||
| "add rule inet $NFT_TABLE forward counter meta mark set ct mark comment \"Get previous class\"" \ | ||
| "add rule inet $NFT_TABLE forward meta mark & $mark_mask == 0x0 counter jump classify comment \"If no class, try to classify\"" |
There was a problem hiding this comment.
+ meta mark & 0x000000ff ne 0x0 return
+ goto classify comment "If no class, try to classify"
- meta mark & 0x000000ff == 0x00000000 counter packets 0 bytes 0 jump classify comment "If no class, try to classify"
}
chain classify {
- meta mark & 0x000000ff == 0x00000000 ip saddr 192.168.1.0/24 counter packets 0 bytes 0 meta mark set meta mark & 0xffffff01 | 0x00000001 comment "trafficshaper-corp up"
+ ip saddr 192.168.1.0/24 counter packets 0 bytes 0 meta mark set meta mark & 0xffffff01 | 0x00000001 comment "trafficshaper-corp up"There was a problem hiding this comment.
(i can do retouching later, this shows iptable decorative logic remains)
| "add chain inet $NFT_TABLE forward { type filter hook forward priority mangle + 10; policy accept; }" \ | ||
| "add chain inet $NFT_TABLE classify" \ | ||
| "# Keep ct and packet marks in sync for tc fw filters." \ | ||
| "add rule inet $NFT_TABLE forward counter meta mark set ct mark comment \"Get previous class\"" \ |
There was a problem hiding this comment.
1/ proposed syntax does not work
2/ the exact original bits are copied back
4ce07e9 to
ef66fe8
Compare
Add an nftables firewall backend while keeping the existing iptables backend available. Use nftables on fw4 systems and fall back to iptables otherwise. Signed-off-by: Dharmik Parmar <dharmikparmar2004@yahoo.com>
ef66fe8 to
3340285
Compare
|
Ah, yes, I fell for that one. The masked I reworked this now. |
|
IMO could do away without extra chain. wdyt? we dont need a sane return to calling chain in iptables... counter packets 0 bytes 0 goto classify comment "If no class, try to classify"
}
chain classify { |
brada4
left a comment
There was a problem hiding this comment.
Great job, besides maintaining semantics identical to ip(6) tables also optimises away some slack processing present in ip(6) tables.
|
@BKPepe call in the machines, looks (very) nice to us humans. |
|
@GeorgeSapkin I am looking into the Test via Docker and I see there failure: Not sure how we are going to test this package, because it says: Anyway, I'd love to summon the machines, but you know, I got a bit carried away and blew through my entire new credit allowance in 4 days, and now I'm out. :-D If humans are okay with this, I will merge this soon. |
Remove iptables kmod dependency from kmod-sched-connmark. Both dependents package/network/config/qos-scripts ../packages/net/trafficshaper Already pull in ipt kmods via iptables-mod-conntrack-extra Permits "clean" nftables migration at openwrt/packages#29830 Signed-off-by: Andris PE <neandris@gmail.com> Link: openwrt#24019 Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
Add an nftables firewall backend while keeping the existing iptables backend
available.
Trafficshaper still works the same way: firewall rules mark forwarded packets,
and
tcuses those marks for the shaping classes.Part of the nftables migration work discussed in #16818.
📦 Package Details
Maintainer: Luiz Angelo Daros de Luca luizluca@gmail.com (@luizluca)
Description:
Add nftables support for the packet-marking part of trafficshaper. The existing
iptables backend remains available for older systems.
🧪 Run Testing Details
Tested on an OpenWrt VM with an Alpine LAN client behind it.
✅ Formalities
If your PR contains a patch: