netifd: redesigning UCI config & interfaces
nbd at nbd.name
Thu May 13 08:47:27 PDT 2021
Thanks for the proposal
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
> 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
> 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.
> *** 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.
> 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
> network.interface.foo 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.
More information about the openwrt-devel