7

I have two ethernet ports and one wireless port on a router I am setting up. I am using systemd-networkd. I am renaming the ports first then creating a bridge then am bridging one of the the ethernet ports and the wireless board to create on combined lan port with a single IP and DHCP/DNSMASQ. The other ethernet being the wan port. Here you see the the networkctl output. lan is the bridge. You see wlan has same status as lan2 (which is the NIC and is working fine). So the bridge and all the routing is fine.

IDX LINK             TYPE               OPERATIONAL SETUP     
  1 lo               loopback           carrier     unmanaged 
  2 wan              ether              routable    configured
  3 lan2             ether              carrier     configuring
  4 wlan             wlan               carrier     configuring
  5 lan              ether              routable    configured

So.....I am pretty close. It's only getting hostapd to start at the right time using systemd-networkd. The AP comes up but it looks like the wireless interface is not getting bound to the bridge. A client can enter WPA password and it is accepted but then it never connects. The logs aren't helping me to identify the issue but I am pretty sure the wireless port is not getting fixed to the bridge. That would explain why the AP functions seems fine but then there is not actual connection with an IP address being given out.

Anyone with some experience have some tips? As you can see the hostapd.service I wrote tries to delay starting hostapd until networkd is done, in particular until the bridge has been created. Maybe it's something to do with hostapd delaying for networkd but networkd adding wlan to the lan bridge before hostapd has started...kinda a catch22.

hostapd.conf

interface=wlan
# the interface used by the AP
hw_mode=g
# g simply means 2.4GHz band
channel=10
# the channel to use
#ieee80211d=1          
# limit the frequencies used to those allowed in the country
#country_code=US       
# the country code
ieee80211n=1
# 802.11n support
#wmm_enabled=1
# QoS support
#ignore_broadcast_ssid=0
ssid=645-gateway
# the name of the AP
auth_algs=1
# 1=wpa, 2=wep, 3=both
wpa=2
# WPA2 only
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
wpa_passphrase=elf645Keb1920

hostapd.service

[Unit]
Description=Hostapd IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
Wants=network-online.target
After=systemd-networkd.service
After=sys-subsystem-net-devices-wlan.device
After=sys-subsystem-net-devices-lan.device
BindsTo=sys-subsystem-net-devices-lan.device

[Service]
Type=forking
PIDFile=/run/hostapd.pid
ExecStart=/usr/sbin/hostapd /etc/hostapd/hostapd.conf -P /run/hostapd.pid -B

[Install]
WantedBy=multi-user.target

30-br-wlan-lan.network

[Match]
Name=wlan
[Network]
Bridge=lan
2

2 Answers 2

5

You were close and I was in the same situation. After years of fiddling, I finally figured out the right configuration.

systemd-networkd configuration

For your systemd-networkd configuration in /etc/systemd/network/, you need the following files:

  1. one .netdev for your bridge device
  2. one .network for your bridge device
  3. one or more .network for your Ethernet devices (LAN and WAN)
  4. one .network for your wifi device
  5. optionally, more .network for additional wifi SSIDs, if in case you are running more than one SSID on the same device.

bridge device

Here is my bridge device configuration, nothing special here. However, it took me years to find out I was missing the .netdev file because the network functioned apparently correctly even though networkctl reported br0 as failed.

cat /etc/systemd/network/10-bridge.netdev
[NetDev]
Name=br0
Kind=bridge
cat /etc/systemd/network/20-bridge.network 
[Match]
Name=br0

[Network]
Description=...
Address=...
Address=...

Ethernet and wifi devices added to the bridge

Each device participating in br0 must declare Bridge=br0, obviously.

cat /etc/systemd/network/21-enp2s0_bridged.network
[Match]
Name=enp2s0

[Link]
RequiredForOnline=no

[Network]
Description=Add enp2s0 to the bridge
Bridge=br0
cat /etc/systemd/network/21-wlp5s0_bridged.network
[Match]
Name=wlp5s0

[Link]
RequiredForOnline=no

[Network]
Description=Add wlp5s0 to the bridge
Bridge=br0

hostapd service unit

For starting hostapd at the right time, it needs to have the following dependencies in hostapd.service:

  1. in the [Unit] section
    After=network.target
    BindsTo=sys-subsystem-net-devices-%i.device
    
    replacing %i with your wifi device's name
  2. in the [Install] section
    WantedBy=multi-user.target
    WantedBy=sys-subsystem-net-devices-%i.device
    
    again replacing %i with your wifi device's name.

No other dependencies are necessary. In particular, Wants=network-online.target should not be used in this case as you want hostapd to start before the network becomes online. See the definitions of network.target and network-online.target.

There is a good example unit file in /lib/systemd/system/[email protected] on Debian systems and the above configuration is copied from it. You don't need the unit templating if you have only one SSID or multiple SSIDs configured on the same instance of hostapd, but you do need the BindsTo with the device (the shipped non-templated /lib/systemd/system/hostapd.service lacks it on Debian). Also note that dependencies on sys-subsystem-net-devices-%i.device are only needed on the "primary" wifi interface when no have multiple SSIDs.

Result

# networkctl
IDX LINK         TYPE      OPERATIONAL SETUP
  1 lo           loopback  carrier     unmanaged
  2 enp1s0       ether     routable    configured
  3 enp2s0       ether     enslaved    configured
  4 enp3s0       ether     no-carrier  configuring
  5 enp4s0       ether     off         unmanaged
  6 br0          bridge    routable    configured
  7 wg0          wireguard routable    configured
  8 sit0         sit       off         unmanaged
  9 he-ipv6      sit       routable    configured
 10 wlp5s0       wlan      enslaved    configured
 11 wlan-iot     wlan      routable    configured
 12 wlan-guest   wlan      routable    configured

12 links listed.

and a happy sysadmin! :)

It can still happen that networkctl reports wlp5s0 as failed and systemd-networkd logs:

wlp5s0: Could not join netdev: Device does not allow enslaving to a bridge. Operation not supported wlp5s0: Failed

This appears to cause no network failure though and a systemctl restart systemd-networkd.service makes networkctl green again. I suspect that's an interaction with the way I have hostapd configured using bridge=br0. Maybe that line should be removed.

1
  • my question is quite old and I did eventually make it work only I can't find my notes so thx for this! If I need to do this again I won't have to figure it out from that old install so I'm marking it as the answer
    – DKebler
    Mar 19, 2022 at 15:23
1

Adding as an answer since I can't comment yet... This is a followup to Kolargo00's excellent answer.

The reason for the Device does not allow enslaving to a bridge. failure is that wlan devices in station mode can't be added to a systemd-networkd bridge. If you start hostapd before systemd-networkd.service and network.target the wlan interface should be in ap mode and be enslavable by the bridge.

So change After=network.target in the hostapd.service unit file to Before=network.target systemd-networkd.service and everything should go smoothly.

Otherwise, his answer is the right one.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .