1

I am trying to configure my Raspberry Pi as a WiFi repeater. I have followed the awesome guide by @Ingo at Access point as WiFi router/repeater, optional with bridge and this works great when the WiFi uplink is connected. However when the uplink isn’t available (e.g. my Raspberry Pi isn’t near my home router) I can’t seem to connect reliably to the access point, as it keeps dropping the connection.

This would be really useful, since I’d like to be able to login to my Pi even when not near my router. Is this possible, and if so how would I modify my configuration to support this scenario?

I initially thought it might be the static DNS configuration causing an issue, but removing that part of the configuration didn’t help. Another idea I had was that the regular scanning being performed by wpa_supplicant might be interrupting the behaviour of the access point, but setting sched_scan_plans to a large interval in wpa_supplicant.conf didn’t seem to stop it attempting to scan event few seconds, although I’m not really sure what’s going on at this point, and just guessing.

  • I will have a look at it but takes some time. I have do setup my test environment. – Ingo Dec 09 '20 at 20:07
  • Thanks @Ingo, I think I might have just found a solution, or at least a workaround. I tried setting autoscan=periodic:300 in wpa_supplicant.conf and the connection now seems more stable. I've also set bgscan="", just in case that helps too. I'm beginning to suspect that wpa_supplicant and hostapd do not coexist properly in this context, as if I kill wpa_supplicant my access point seems perfectly stable. – matt-foundry Dec 10 '20 at 18:36
  • Have you downgraded the WiFi firmware as suggested at the beginning of the setup? You can also try to use the latest firmware. – Ingo Dec 10 '20 at 22:00
  • I can reproduce the problem. If there is no uplink on the RasPi the client on the AP connects but disconnects immediately with deauthenticated (Reason: 2=PREV_AUTH_NOT_VALID) ... what ever this means :-\ ... let's see – Ingo Dec 10 '20 at 23:27
  • Yes, I'm using the downgraded firmware. Trying with the newer firmware is a good idea too. I also saw Reason: 2=PREV_AUTH_NOT_VALID in my logs, so it sounds like you have reproduced the same issue. Thanks for taking the time to investigate. – matt-foundry Dec 11 '20 at 18:49

2 Answers2

2

Starting from the configuration given at Access point as WiFi router/repeater, optional with bridge your problem is reproducible. After digging some days, I think I have found the reason. It seems to be a performance problem with scanning for available WiFi networks.

Here is how I tested it: as device connected to the access point of the RasPi I use a Laptop with Debian Buster installed. The remote hotspot for the client uplink of the RasPi can simply be switched off and on. At the beginning the hotspot is online and the RasPi is connected to it with its client uplink on interface wlan0. The Laptop is connected to the access point of the RasPi and continue pinging the access points ip address:

laptop ~$ /bin/ping 192.168.4.1

Everything works fine, no problems seen so far. The ping get replies with 0% packet loss. If I switch off the hotspot, typically I get:

ping: sendmsg: Network is unreachable
64 bytes from 192.168.4.1: icmp_seq=18 ttl=64 time=0.972 ms
64 bytes from 192.168.4.1: icmp_seq=19 ttl=64 time=1.11 ms
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
64 bytes from 192.168.4.1: icmp_seq=25 ttl=64 time=1.05 ms
64 bytes from 192.168.4.1: icmp_seq=26 ttl=64 time=1.19 ms
64 bytes from 192.168.4.1: icmp_seq=28 ttl=64 time=8.100 ms
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
64 bytes from 192.168.4.1: icmp_seq=33 ttl=64 time=3.60 ms
64 bytes from 192.168.4.1: icmp_seq=34 ttl=64 time=1.31 ms
64 bytes from 192.168.4.1: icmp_seq=35 ttl=64 time=1.17 ms
64 bytes from 192.168.4.1: icmp_seq=36 ttl=64 time=1.40 ms
ping: sendmsg: Network is unreachable
^C
--- 192.168.4.1 ping statistics ---
39 packets transmitted, 12 received, 69.2308% packet loss, time 568ms
rtt min/avg/max/mdev = 0.972/2.428/8.995/2.358 ms

With testing various possibilities I also set option autoscan=periodic:30 in /etc/wpa_supplicant/wpa_supplicant-wlan0.conf. This means that scanning for available networks take place only every 30 seconds instead of default 5 seconds. If I switch off the hotspot then the laptop suddenly shows me a more stable connection:

64 bytes from 192.168.4.1: icmp_seq=331 ttl=64 time=0.978 ms
64 bytes from 192.168.4.1: icmp_seq=332 ttl=64 time=1.17 ms
64 bytes from 192.168.4.1: icmp_seq=333 ttl=64 time=0.928 ms
64 bytes from 192.168.4.1: icmp_seq=334 ttl=64 time=3.30 ms
64 bytes from 192.168.4.1: icmp_seq=335 ttl=64 time=1.17 ms
64 bytes from 192.168.4.1: icmp_seq=336 ttl=64 time=1.09 ms
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
ping: sendmsg: Network is unreachable
64 bytes from 192.168.4.1: icmp_seq=347 ttl=64 time=1.18 ms
64 bytes from 192.168.4.1: icmp_seq=348 ttl=64 time=1.11 ms
64 bytes from 192.168.4.1: icmp_seq=349 ttl=64 time=1.10 ms
64 bytes from 192.168.4.1: icmp_seq=350 ttl=64 time=2.97 ms
64 bytes from 192.168.4.1: icmp_seq=351 ttl=64 time=1.16 ms
64 bytes from 192.168.4.1: icmp_seq=352 ttl=64 time=1.11 ms
64 bytes from 192.168.4.1: icmp_seq=353 ttl=64 time=1.21 ms
64 bytes from 192.168.4.1: icmp_seq=354 ttl=64 time=1.16 ms
64 bytes from 192.168.4.1: icmp_seq=355 ttl=64 time=1.12 ms
64 bytes from 192.168.4.1: icmp_seq=356 ttl=64 time=1.15 ms
64 bytes from 192.168.4.1: icmp_seq=357 ttl=64 time=2.01 ms
64 bytes from 192.168.4.1: icmp_seq=358 ttl=64 time=1.17 ms
64 bytes from 192.168.4.1: icmp_seq=365 ttl=64 time=1.15 ms

This gives me the idea that the problem is the scan mode on the RasPis uplink client connection. If the hotspot is down the RasPi will scan for available WiFi networks. Because the access point is also managed with the same device (its only a virtual interface ap@wlan0 of it) this will reduce its performance during scanning for networks. This also explains that there is no problem, if the RasPi is connected to the remote hotspot. Then it does not scan for networks. Looking for matching options for wpa_supplicant I found scan_freq= that will limit the scanned frequencies. If I set it to scan_freq=2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472, means only scan the 2.4 GHz band, I get a stable connection of the Laptop to the access point of the RasPi. Depending on your connection it may be possible that you have to limit to less frequencies.

But there is another issue with the frequency. The access point always has the same frequency than the uplink connection to the hotspot. A channel (frequency) must be set in /etc/hostapd/hostapd.conf otherwise it will not start. If this channel, e.g. channel=1, does not match the client connection, e.g. channel=6, then the channel of the access point is silently set to 6. This may confuse the connected devices on the access point. The automatic channel selection is done if p2p devices are enabled by default. Before getting a knot in the brain about this options and the possible impact to the WiFi device I suggest to configure a fixed frequency. That creates clear relationships. Of course you are limited to the fixed frequency on the hotspot, but that is the price of stability on the limited Raspberry Pi WiFi device.

In this example I will use channel 6, that is frequency 2437. In /etc/hostapd/hostapd.conf set channel=6.

To avoid Automatic Channel Selection (ACS) disable p2p devices in /etc/wpa_supplicant/wpa_supplicant-wlan0.conf with option p2p_disabled=1 in the global section. This may also increase stability because we do not have additional devices we don't need.

To tell wpa_supplicant only to use frequency 2437 and only to scan for it, set the options freq_list=2437 and scan_freq=2437 in its config file so it should look like this (of course with your settings):

rpi ~$ cat /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
update_config=1
country=DE

p2p_disabled=1

# possible frequencies
#freq_list=2412 2417 2422 2427 2432 2437 2442 2447 2452 2457 2462 2467 2472
#freq_list=5170 5180 5190 5200 5210 5220 5230 5240 5260 5280 5300 5320 5500 5520 5540 5560 5580 5600 5620 5640 5660 5680 5700

network={
    ssid="TestNet"
    psk="verySecretPassword"
    freq_list=2437
    scan_freq=2437
}

Check interfaces and its connections with

rpi ~$ iw dev

Please respect that this all is only due to the limitations of the on-board WiFi device of the Raspberry Pi. If you like to avoid it and want to be much more flexible you may consider to use an additional USB/WiFi dongle as shown at Access point as WiFi router/repeater with additional WiFi-dongle.

Ingo
  • 40,606
  • 15
  • 76
  • 189
  • I've just tested this and it fixed my issue - thanks @Ingo! Also for not only solving the problem, but also explaining why it works :) – matt-foundry Dec 14 '20 at 13:41
  • One would have thought that deleting the network= section of wpa_supplicant.conf, in conjunction with setting p2p_disabled=1 would suffice. But it doesn't, for some reason. You need a network= section with the settings given. Brilliant answer. – Robin Davies Jul 28 '21 at 03:00
  • Credit to @Ingo for identifying the interaction with the WPA supplicant service and hosted Access Point connections. "systemctl mask wpa_supplicant.service" may be a better solution. See answer below. – Robin Davies Aug 13 '21 at 03:41
0

Edit:

The problem is caused by the DHCPCD daemon, which restarts the wpa_supplicant service, UNLESS you add the following line to /etc/dhcpcd.conf

nohook wpa_supplicant

After that, at a command prompt:

systemctl stop wpa_supplicant.service
systemctl mask wpa_supplicant.service

and reboot.

dhcpcd seems to fork the wpa_supplicant process if it cannot start the service. wpa_supplicant exits shortly thereafter, but manages to bork the access point before it completes. This appears to happen as a side-effect of reconfiguring the ethernet LAN, which in turn occurs because the wlan has been reconfigured when the access point starts up.

Official Raspbian docs for setting up an access point specify this setting as part of setting up a host access point. And it works! 100%.

I am uncertain as to whether the wpa_supplicant service also needs to be masked, or whether merely disabling it is sufficient. But masking it isn't wrong.

fwiw, the instructions given below are not sufficient to keep the access point alive.

Previous answer:

Better answer: systemctl disable wpa_supplicant doesn't actually disable the wpa supplicant service. Apparently, the network manager can start the WPA Supplicant service even though it's disabled in systemd. (See reference below). To entirely prevent the WPA Supplicant service from running, and breaking the Access Point connection, use systemctl mask wpa_supplicant.service instead.

The state of affairs before doing this: the first connection to the access point would succeed, but drop after about 20 seconds. A second attempt to connect would succeed, and remain connected. After using systemctl mask wpa_supplicant.service I get stable access point connections the first time, and every time.

A completely speculative theory as to why this might work: after an access point connection is established, there's a flurry of activity related to rebuilding iptables, and restarting (!) the mDNS service in order to start serving mDNS records on the new wlan0 interface. Something in that process must force a restart of wpa_supplicant as a dependent service; and the freshly started wpa_supplicant service then breaks the access point connection while conducting a scan for a wireless access point due to hardware constrains on the Raspberry Pi (as described in the @Ingo's previous answer). The wpa_supplicant instance must be transient, as it does not show up in ps -e. The empirical observation that masking the wpa_supplicant service cures the problem suggests that the wpa_supplicant service runs briefly. Disabled services can load if they are named as a dependent of another service; masked services cannot. It seems that "disable" is a misnomer. It really means something more akin to "don't auto-start"; whereas "mask" means "really really disable".

Reference for "disable doesn't prevent the service from running": https://unix.stackexchange.com/questions/306276/make-systemd-stop-starting-unwanted-wpa-supplicant-servi

Robin Davies
  • 101
  • 3
  • If a dependent service tries to start a mask service you will get an error message from systemd. Do yo find such a message? – Ingo Sep 06 '21 at 18:46
  • Thanks. I've been trying to find this post, so that I can correct it for ages. Your comment helped me locate it. System logs show that DHCPCD is forking wpa_supplicant briefly as part of the activity to reconfigure networks after the start of the access point connection. See the SUBSTANTIAL edit given above,. – Robin Davies Sep 20 '21 at 21:34