mwan3rtmon rewrite in ucode (Re: ucode for scripts)

Florian Eckert fe at dev.tdt.de
Tue Nov 11 23:43:19 PST 2025


Hello Jonas,
Hello Etienne,
Hello Alex,

I would like to join the discussion. Due to time constraints, I still 
haven't
managed to port mwan3 to use native nftables and also replace the shell 
scripting
mess. I experimented with C last year, but didn't get very far [1].

I am currently considering using ucode to replace the shell scripting 
mess. There
was recently a merge that already converted the ubus backend into ucode 
[2].
@Etienne thanks for that.

I would be delighted if we could find a way to work together to make 
mwan3 fit
for nftables and replace shell script handling with ucode.

I included Alex in the discussion because he recently submitted a PR. It 
contained
a mini-mwan written in LUA.

Best regards

Florian

[1] https://github.com/feckert/mwan4
[2] 
https://github.com/openwrt/packages/commit/6423781254b9f3e52c6102fb2cbcd9f99f2445a3
[3] https://github.com/openwrt/packages/pull/27704


On 2025-11-09 07:38, Jonas Lochmann wrote:
> Am Sat, Nov 08, 2025 at 07:22:29PM -0500, schrieb Etienne Champetier:
>> Le sam. 8 nov. 2025 à 16:52, Jonas Lochmann <openwrt at jonaslochmann.de> 
>> a écrit :
>> >
>> > Am Sat, Nov 08, 2025 at 01:11:17PM -0500, schrieb Etienne Champetier:
>> > > I also had a look at rewriting mwan3rtmon in ucode recently and I'm
>> > > wondering if we could just get rid of it.
>> > > Basically this script watches the main routing table to copy all non
>> > > default routes, and also fill an ipset,
>> >
>> > It does this per interface and keeps the default rules of that
>> > particular interface while also removing source based routing in case
>> > of IPv6. (Well, this can be disabled, but I would not recommend that.)
>> 
>> Thanks for pointing that out, I missed that sed line
>> 
>> > > but I think using rules like 'lookup main suppress_prefixlength 0' we
>> > > should be able to remove mwan3rtmon.
>> >
>> > But where do we get the default routes from then?
>> 
>> We still need something for the default routes indeed, but we can 
>> simplify a bit
>> Have something like
>> ```
>> 1000: from all lookup main suppress_prefixlength 0
>> ```
>> and then in table 1 / 2 ... just have the default route of each wan
>> 
>> This would also remove the need for the mwan3_connected_ipv4/6 ipsets
>> as the mark doesn't matter if you match rule 1000 first.
> 
> I think that those ipsets are useless in any case as all local routes 
> are in
> all tables and thus you could pick any of them. But having first a 
> "lookup
> regular routes ignoring default routes" could simplify a few things.
> 
>> > I see no possibility to skip mwan3rtmon.
>> 
>> If we only have wans with static ips then we don't need mwan3rtmon 
>> anymore ...
>> so we would still need it :), but if it only handles default routes
>> that's way less work to do.
> 
> That would remove that theoretical route update delay for local routes.
> So I consider it an advantage. I would also go from the current 
> imperative
> implementation to a functional one: wait for changes; calculate new 
> interface
> specific tables; replace tables.
> 
>> Yep, there is very little explanation of why each piece is present
>> Example, the ip rule
>> ```
>> 1001:    from all iif wan1 lookup 1
>> ```
>> I think it is used if we bind to the ip of wan1 (and not the device)
>> to ensure the traffic goes out the right interface, but maybe it's for
>> something else :(
> 
> That's about the input interface. It prevents routing from one wan to
> another. But that's a task for the firewall and not mwan3.
> 
> I don't expect binding to an IP only to work correctly. There is a
> reason why "mwan3 use" sets the fwmark.
> 
> I just found some rough description of the mwan3 architecture at
> https://openwrt.org/docs/guide-user/network/wan/multiwan/mwan3



More information about the openwrt-devel mailing list