Bug 76077

Summary: systemd-networkd: VLAN on bond fails due to incorrect order of enslavement
Product: systemd Reporter: Malte Starostik <bugs>
Component: generalAssignee: Tom Gundersen <teg>
Status: RESOLVED NOTOURBUG QA Contact: systemd-bugs
Severity: normal    
Priority: medium CC: jay
Version: unspecified   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:

Description Malte Starostik 2014-03-12 12:55:31 UTC
Trying to setup VLAN on top of a bond, systemd-networkd attempts to create the VLAN links before the bond has any slaves.  This is rejected by the kernel:

Mar 12 13:45:57 jmbvirt04 systemd[1]: Starting Network Service...
Mar 12 13:45:57 jmbvirt04 systemd-udevd[4529]: Could not apply link config to lan
Mar 12 13:45:57 jmbvirt04 systemd-networkd[4552]: lan: could not enslave: Operation not supported
Mar 12 13:45:57 jmbvirt04 systemd[1]: Started Network Service.
Mar 12 13:45:57 jmbvirt04 systemd-networkd[4552]: lan: failed
Mar 12 13:45:57 jmbvirt04 kernel: 8021q: VLANs not supported on lan


If the bond is taken out of the picture (VLAN directly on one of the interfaces), the VLAN is setup properly.
If systemd-networkd is started with the VLAN=... line in 00-lan.network commented out, the bond is brought up fine.  If systemd-networkd is then restarted with the VLAN=... line commented in again, the VLAN is setup fine as well.
But when both bonding and VLAN are to be set up from scratch in one go, the ordering is broken.

Happens on Gentoo with both 210 and 211.

Configuration:

===== 00-lan.netdev
[NetDev]
Name=lan
Kind=bond

===== 00-lan.network
[Match]
Name=lan

[Network]
VLAN=mgmt.hosts

===== 01-mgmt.hosts.netdev
[NetDev]
Name=mgmt.hosts
Kind=vlan

[VLAN]
Id=20

===== 01-mgmt.hosts.network
[Match]
Name=mgmt.hosts

[Network]
Address=10.0.20.4/24
Gateway=10.0.20.254

===== 99-bond-slaves.network
[Match]
Name=en*

[Network]
Bond=lan
Comment 1 Brian "Redbeard" Harrington 2014-05-19 22:14:28 UTC
We were able to reproduce this bug, we were also able to solve it by doing a one-shot exec before systemd-networkd runs where we did a modprobe 8021q.  Try that and see if it resolves the issue.  If so, it's just dependant on loading the correct support.
Comment 2 Tom Gundersen 2014-06-02 14:06:08 UTC
If loading the module manually solves the problem, then a newer kernel should hopefully fix it.

If not, can you confirm that the problem is still precent in a recent kernel?
Comment 3 Malte Starostik 2014-06-03 12:34:59 UTC
Force-loading 8021q and/or bonding doesn't help.  In the odd case it works, most of times it doesn't.
Tested with 3.12.20, will try with 3.14 tomorrow to check if that does any good.
Comment 4 Malte Starostik 2014-06-04 13:48:56 UTC
Nope, Just checked with 3.14.5 and still the same.  Whether bonding and/or 8021q modules are explicitly loaded in modules-load.d or not, there's still a race.  If the NICs are enslaved to the bond before creating VLANs it works (the rare case).  In most of the cases, the VLAN creation precedes the enslavement of the NICs, and that still failes with:

kernel: 8021q: VLANs not supported on lan

and the VLAN interfaces are missing.  Trying this manually confirms that VLANs cannot be created on a bond before it has any slaves:

# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
19: eno1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:54 brd ff:ff:ff:ff:ff:ff
20: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:55 brd ff:ff:ff:ff:ff:ff
21: eno3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:56 brd ff:ff:ff:ff:ff:ff
22: eno4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:57 brd ff:ff:ff:ff:ff:ff

# ip link add test type bond
# ip link add test950 link test type vlan id 950
8021q: VLANs not supported on test
RTNETLINK answers: Operation not supported
# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
19: eno1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:54 brd ff:ff:ff:ff:ff:ff
20: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:55 brd ff:ff:ff:ff:ff:ff
21: eno3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:56 brd ff:ff:ff:ff:ff:ff
22: eno4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:57 brd ff:ff:ff:ff:ff:ff
23: test: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN mode DEFAULT 
    link/ether d8:9d:67:21:29:54 brd ff:ff:ff:ff:ff:ff

# ip link set eno1 master test
IPv6: ADDRCONF(NETDEV_UP): eno1: link is not ready
bonding: test: enslaving eno1 as a backup interface with a down link.
tg3 0000:03:00.0 eno1: Link is up at 1000 Mbps, full duplex
tg3 0000:03:00.0 eno1: Flow control is off for TX and off for RX
tg3 0000:03:00.0 eno1: EEE is disabled

# ip link add test950 link test type vlan id 950
# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
19: eno1: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc mq master test state UP mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:54 brd ff:ff:ff:ff:ff:ff
20: eno2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:55 brd ff:ff:ff:ff:ff:ff
21: eno3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:56 brd ff:ff:ff:ff:ff:ff
22: eno4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
    link/ether d8:9d:67:21:29:57 brd ff:ff:ff:ff:ff:ff
23: test: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN mode DEFAULT 
    link/ether d8:9d:67:21:29:54 brd ff:ff:ff:ff:ff:ff
24: test950@test: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT 
    link/ether d8:9d:67:21:29:54 brd ff:ff:ff:ff:ff:ff


This behaviour can be reproduced after deleting and recreating the bond.
Comment 5 Tom Gundersen 2014-06-04 14:21:48 UTC
Finally got around to looking into this properly. It appears Malte's analysis in comment #4 is spot on.

The situation is that VLAN's cannot be created on devices that has the feature NETIF_F_VLAN_CHALLENGED (some feature...) set. Annoyingly that includes empty bonds (but I don't know why[0]), and I have so far not figured out an elegant way for us to get notified about when this flag changes.

I think we should do one of two things (preferably both):

1) hook up the feature flag with rtnetlink so we get notified about changes
2) figure out if empty bonds can be made to work with vlans (then the order will no longer matter).

We could attempt to work around this in networkd by trying to add the VLAN every time the number of slaves of a bond changes, but that feels too hacky (I have already applied such hacks only to revert them four times in the past few months), so I'd really prefer if we could fix this in the kernel.

[0]: <http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/net/bonding/bond_main.c#n1005>
Comment 6 Jay Faulkner 2014-06-18 22:09:52 UTC
I can confirm this bug. Workaround in my environment currently is writing out configs, restarting systemd-networkd, then waiting for 15 seconds, and restarting systemd-networkd again.
Comment 7 Tom Gundersen 2014-06-30 16:58:25 UTC
This is being fixed in the kernel. Explanation and patch can be found in this thread: <http://www.spinics.net/lists/netdev/msg287573.html>.

Closing for now, but please reopen if any action is required on the systemd side.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.