netifd: redesigning UCI config & interfaces

Rafał Miłecki zajec5 at
Fri May 14 00:51:36 PDT 2021

On 13.05.2021 17:47, Felix Fietkau wrote:
> On 2021-05-13 15:58, Rafał Miłecki wrote:
>> Current /etc/config/network design and netifd implementation are quite a
>> bit messy:
>> 1. There is no clear layer 2 vs. layer 3 distinction
> I think aside from a few legacy compatibility hacks (e.g. the infamous
> interface option type bridge, which we really should phase out at some
> point), there actually is a clear distinction.
> The device refers to the underlying layer 2 linux device
> The interface refers to a logical layer 3 configuration on top of that,
> which may or may not have its own layer 3 netdev.
> It may not seem as clear when viewing the whole thing through the lens
> of just looking at the individual linux netdevs, but that's because it's
> different data model.
>> 2. UCI sections are inconsistent
>> 3. For some setups there are few ways of defining them
>> 4. A lot of netifd states are implicit (magic behaviour)
>> 5. It's really hard to handle all above with a simple & clear UI
> I think this strongly depends on your definition of 'simple' and the
> level of abstraction. If your definition of a simple UI is simply a
> fancier display of netdev stats and individual linux netdev
> configurations, then your statement makes some sense to me.
> For something more high level than that, I don't think it makes things
> any easier.

I posted few arguments, if we agree at least on some of them, I hope
you're still OK to proceed with some refactoring.

As for the UI simplicity I'm just going to quote Jo:
[2021-05-06] [16:15:09 CEST] <jow> the underlying uci config is such an extreme clusterfuck that I pretty much gave up trying to visualize it

>> I'm working on network & netifd cleanup and wanted to describe my plans.
>> Please review my following ideas.
>> *** ubus objects ***
>> Linux uses interfaces (e.g. eth0, br-lan) for laver 2 devices as well as
>> layer 3 interfaces. Tools like ifconfig, brctl, ip work on top of such
>> interfaces.
>> OpenWrt tools ifup & ifdown are expected to work on Linux interfaces
>> just like ifconfig. They call ubus objects methods "up" & "down".
>> That's why we need network.interface.<foo> ubus object for every used
>> Linux interface. No matter if that Linux interface is layer 2 or layer
>> 3. Even if Linux interface "lan" is a bridge (layer 2) we still need a
>> way to bring it up & down (so network.interface.lan is required).
>> Adding a new set of ubus objects (like network.device.lan) would result
>> in duplication. We don't want that. E.g. both commands would do the same
>> 1. ubus call network.device.lan up
>> 1. ubus call network.interface.lan up
> In my opinion, forcing the interface to have the same name as the
> explicitly specified l3 device is a big step back in usability.
> In the current default config, interface sections are named after their
> logical function, e.g. lan or wan. Users can use ifup/ifdown wan having
> to worry about whether their wan device is a DSA port called wan, a
> pppoe interface called pppoe-wan, or a switch VLAN like switch0.1,
> eth0.1 or a named VLAN device like sw0-wan.
> It also makes it easy to bring up/down individual logical configurations
> on top of the same device.
> Your proposal wouldn't just affect what users need to write in the
> network config. We also have other services that refer to the logical
> configurations (and then look up the actual linux device later).
> Here's a simple example of how your proposed change would make things a
> lot more difficult for users and/or the UI:
> Let's assume a more modern target already using 'wan' as netdev for the
> WAN port via DSA. Let's also assume that it is currently configured to
> use DHCP on WAN and has a few services running that refer to the wan
> interface. Now the user has moved the device somewhere else and wants to
> use PPPoE for WAN.
> This means that the user doesn't just have to add an extra device
> section and change the 'device' option for the ifname, they also have to
> go through all config sections of services potentially depending on the
> old netdev name and rewrite those.

That was my misunderstanding and mistake. I didn't realize we have such
mappings. We should definitely keep logical names.

>> *** devices (layer 2) ***
>> We should have designed UCI sections for layer 2 devices. Use UCI
>> section types instead of "option type foo". Reasons:
>> 1. Each device requires different handling
>> 2. Options have different meaning depending on device type
>> While switching to new UCI sections we should also cleanup some UCI
>> options and behaviour.
>> Example:
>> config bridge
>> 	option name 'foo'
>> 	list ports 'lan1'
>> 	list ports 'lan2'
>> Above you can see new UCI section for bridge device with "ports" list
>> instead of "ifname" string.
>> Above config should result in creating "foo" bridge Linux interface and
>> ubus object for bringing it up / down.
>> Other devices would work similarly, e.g. "config vlan" for vlan.
> I'm not sure if this part is really worth the effort or makes things
> better in any meaningful way. Even if you get rid of most of the type
> dependent sets of accepted options, some will likely remain for tunnel
> devices, and interfaces will also still have varying options depending
> on the proto.

It's Jo that originally came with that idea (using UCI section types), I
thought it may be a nice small cleanup and a good opportunity to rework
some options (like the ifname → ports).

More information about the openwrt-devel mailing list