epoch1970
Posts: 7047
Joined: Thu May 05, 2016 9:33 am
Location: France

Fast wifi interface configuration switching with network namespaces

Sun Nov 15, 2020 5:52 pm

While tinkering with something else I think I've found a recipe to alternate wireless client and AP modes on the built-in wireless interface of Pi3B. I am using the current release of Raspios with desktop.
This method seems quite fast and "clean"; apparently this is the effect of performing the reconfiguration of the interface within a temporary network namespace. In the host namespace, raspios simply sees the interface disappear and come back slightly disguised, and keeps happy.

Here is how to switch between a regular client configuration on "wlan0", and an access point on "ap0".
The AP is configured with wpa_supplicant, less powerful than hostapd but simple and sufficient for the demonstration.
Dhcpcd is configured to give a static IP address to "ap0"; by default wlan0 is configured via DHCP.
  • In /etc/wpa_supplicant/, in addition to the existing "wpa_supplicant.conf" file, create file "wpa_supplicant-ap0.conf":

    Code: Select all

    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    update_config=1
    country=FR
    ap_scan=2
    
    network={
        ssid="TestAccessPoint"
        mode=2
        key_mgmt=WPA-PSK
        proto=RSN
        group=CCMP TKIP
        psk="changethispassword"
        # See https://en.wikipedia.org/wiki/List_of_WLAN_channels
        frequency=2437
    }
    
    NB adapt country, ssid, pre-shared secret, channel to your needs. wpa_supplicant in AP mode does not bridge interfaces itself; you'd need to do that with "ip link set ap0 master <bridge_name>" once the interface is created.
  • In /etc/dhcpcd.conf, add to the end of the file:

    Code: Select all

    
    interface ap0
    static ip_address=192.168.9.9/24
    
    
    NB adapt the IP configuration to your needs.
  • I use the following script to toggle between an existing wireless interface name and a target name. By default the script alternates between "wlan0" and "ap0", but it tries to be smart about interfaces names you give it as arguments, and about errors it encounters. Possibly too smart for its own good... The important bit is the group of 4 lines at the end, really.

    Let's say you add the script as /home/pi/wtoggle.sh:

    Code: Select all

    #!/bin/sh -u
    wifs='wlan0 ap0'
    args="${@:-}"; phy=; owif=; nwif=
    
    cleanup(){
    	err=$?
    	case "${err}" in
    		0) echo "Success: [${phy}]${owif} -> ${nwif}" ;;
    		*) echo "Error ${err} at $0"
    		   grep --with-filename --line-number "exit ${err}" $0
    		;;
    	esac
    	ip netns pids tmp-$$ 2>/dev/null | xargs --no-run-if-empty kill
    	ip netns del tmp-$$ >/dev/null 2>&1
    }
    trap cleanup EXIT
    
    for wif in ${args} ${wifs}; do
    	[ -z "${owif}" ] && [ -e "/sys/class/net/${wif}" ] && owif="${wif}" && continue
    	[ -z "${nwif}" ] && ! [ -e "/sys/class/net/${wif}" ] && nwif="${wif}"
    done
    ([ -n "${owif}" ] && [ -n "${nwif}" ]) || exit 1
    phy="$(cat /sys/class/net/${owif}/phy80211/name 2>/dev/null)" || exit 2
    
    ip netns add tmp-$$ || exit 3
    iw ${phy} set netns name tmp-$$ || exit 4
    ip -n tmp-$$ link set ${owif} name ${nwif} || exit 5
    ip netns exec tmp-$$ iw ${phy} set netns 1 || exit 6
    
    exit 0
    
    NB Make the script executable with "chmod +x /home/pi/wtoggle.sh"
Now reboot or stop/start dhcpcd to make it reload its configuration.
Once done, and assuming an interface wlan0 is present on your machine, you can run "sudo /home/pi/wtoggle.sh" and the running wlan0 client interface will be replaced by an interface called ap0 running an access point. Run again the command and you'll be back to the previous configuration.

Apparently you can flip back and forth for a while without any problem. I've seen the interface fail to reconnect to the main AP a few times, another back and forth was enough to "fix" the problem.
HTH

PS. Here on my machine, STA -> AP -> STA in about 30 seconds. And still working in the end...

Code: Select all

pi@client:~ $ tail -n 0 -f /var/log/syslog&
[1] 5098
pi@client:~ $ sudo ./wtoggle.sh
Nov 15 18:09:53 client avahi-daemon[348]: Interface wlan0.IPv6 no longer relevant for mDNS.
Nov 15 18:09:53 client avahi-daemon[348]: Leaving mDNS multicast group on interface wlan0.IPv6 with address fe80::d048:ff6a:f422:8366.
Nov 15 18:09:53 client dhcpcd[426]: wlan0: carrier lost
Nov 15 18:09:54 client dhcpcd[426]: wlan0: deleting address fe80::d048:ff6a:f422:8366
Nov 15 18:09:54 client avahi-daemon[348]: Interface wlan0.IPv4 no longer relevant for mDNS.
Nov 15 18:09:54 client avahi-daemon[348]: Leaving mDNS multicast group on interface wlan0.IPv4 with address 172.17.255.157.
Nov 15 18:09:54 client avahi-daemon[348]: Withdrawing address record for fe80::d048:ff6a:f422:8366 on wlan0.
Nov 15 18:09:54 client avahi-daemon[348]: Withdrawing address record for 172.17.255.157 on wlan0.
Nov 15 18:09:54 client kernel: [ 7422.201980] brcmfmac mmc1:0001:1 ap0: renamed from wlan0
Success: [phy0]wlan0 -> ap0
Nov 15 18:09:54 client systemd-udevd[5117]: Using default interface naming scheme 'v240'.
Nov 15 18:09:54 client systemd-udevd[5117]: link_config: autonegotiation is unset or enabled, the speed and duplex are not writable.
Nov 15 18:09:54 client dhcpcd[426]: wlan0: deleting route to 172.17.0.0/16
Nov 15 18:09:54 client dhcpcd[426]: wlan0: deleting default route via 172.17.0.1
Nov 15 18:09:54 client systemd[1]: run-netns-tmp\x2d5100.mount: Succeeded.
Nov 15 18:09:54 client systemd[529]: run-netns-tmp\x2d5100.mount: Succeeded.
Nov 15 18:09:54 client systemd-udevd[5127]: Using default interface naming scheme 'v240'.
Nov 15 18:09:54 client dhcpcd[426]: wlan0: removing interface
Nov 15 18:09:54 client dhcpcd-run-hooks[5189]: wlan0: stopping wpa_supplicant
Nov 15 18:09:54 client dhcpcd-run-hooks[5203]: ap0: starting wpa_supplicant
Nov 15 18:09:54 client kernel: [ 7422.722080] brcmfmac: brcmf_cfg80211_set_power_mgmt: power save enabled
Nov 15 18:09:54 client dhcpcd[426]: ap0: connected to Access Point `'
Nov 15 18:09:55 client dhcpcd[426]: ap0: waiting for carrier
Nov 15 18:09:55 client dhcpcd[426]: ap0: waiting for carrier
Nov 15 18:09:55 client dhcpcd[426]: ap0: carrier acquired
Nov 15 18:09:55 client kernel: [ 7423.111301] IPv6: ADDRCONF(NETDEV_CHANGE): ap0: link becomes ready
Nov 15 18:09:55 client dhcpcd[426]: ap0: IAID eb:ad:42:e2
Nov 15 18:09:55 client dhcpcd[426]: ap0: adding address fe80::d81d:448e:fc53:2529
Nov 15 18:09:55 client avahi-daemon[348]: Joining mDNS multicast group on interface ap0.IPv6 with address fe80::d81d:448e:fc53:2529.
Nov 15 18:09:55 client avahi-daemon[348]: New relevant interface ap0.IPv6 for mDNS.
Nov 15 18:09:55 client dhcpcd[426]: ap0: probing address 192.168.9.9/24
Nov 15 18:09:55 client avahi-daemon[348]: Registering new address record for fe80::d81d:448e:fc53:2529 on ap0.*.
Nov 15 18:09:55 client dhcpcd[426]: ap0: soliciting an IPv6 router
Nov 15 18:10:00 client dhcpcd[426]: ap0: using static address 192.168.9.9/24
Nov 15 18:10:00 client avahi-daemon[348]: Joining mDNS multicast group on interface ap0.IPv4 with address 192.168.9.9.
Nov 15 18:10:00 client avahi-daemon[348]: New relevant interface ap0.IPv4 for mDNS.
Nov 15 18:10:00 client avahi-daemon[348]: Registering new address record for 192.168.9.9 on ap0.IPv4.
Nov 15 18:10:00 client dhcpcd[426]: ap0: adding route to 192.168.9.0/24
Nov 15 18:10:08 client dhcpcd[426]: ap0: no IPv6 Routers available

pi@client:~ $ sudo ./wtoggle.sh
Nov 15 18:10:11 client kernel: [ 7439.528562] ieee80211 phy0: brcmf_vif_set_mgmt_ie: vndr ie set error : -52
Nov 15 18:10:11 client kernel: [ 7439.533462] ieee80211 phy0: brcmf_vif_set_mgmt_ie: vndr ie set error : -52
Nov 15 18:10:11 client kernel: [ 7439.538442] ieee80211 phy0: brcmf_vif_set_mgmt_ie: vndr ie set error : -52
Nov 15 18:10:11 client avahi-daemon[348]: Interface ap0.IPv6 no longer relevant for mDNS.
Nov 15 18:10:11 client dhcpcd[426]: ap0: carrier lost
Nov 15 18:10:11 client avahi-daemon[348]: Leaving mDNS multicast group on interface ap0.IPv6 with address fe80::d81d:448e:fc53:2529.
Nov 15 18:10:12 client dhcpcd[426]: ap0: deleting address fe80::d81d:448e:fc53:2529
Nov 15 18:10:12 client avahi-daemon[348]: Interface ap0.IPv4 no longer relevant for mDNS.
Nov 15 18:10:12 client avahi-daemon[348]: Leaving mDNS multicast group on interface ap0.IPv4 with address 192.168.9.9.
Nov 15 18:10:12 client avahi-daemon[348]: Withdrawing address record for fe80::d81d:448e:fc53:2529 on ap0.
Nov 15 18:10:12 client avahi-daemon[348]: Withdrawing address record for 192.168.9.9 on ap0.
Nov 15 18:10:12 client kernel: [ 7440.243171] brcmfmac mmc1:0001:1 wlan0: renamed from ap0
Nov 15 18:10:12 client dhcpcd[426]: ap0: deleting route to 192.168.9.0/24
Nov 15 18:10:12 client dhcpcd[426]: ap0: removing interface
Nov 15 18:10:12 client systemd-udevd[5243]: Using default interface naming scheme 'v240'.
Success: [phy0]ap0 -> wlan0
Nov 15 18:10:12 client systemd-udevd[5243]: link_config: autonegotiation is unset or enabled, the speed and duplex are not writable.
Nov 15 18:10:12 client systemd[1]: run-netns-tmp\x2d5227.mount: Succeeded.
Nov 15 18:10:12 client systemd[529]: run-netns-tmp\x2d5227.mount: Succeeded.
Nov 15 18:10:12 client dhcpcd-run-hooks[5276]: ap0: stopping wpa_supplicant
Nov 15 18:10:12 client systemd-udevd[5260]: Using default interface naming scheme 'v240'.
Nov 15 18:10:12 client dhcpcd-run-hooks[5291]: wlan0: starting wpa_supplicant
Nov 15 18:10:12 client kernel: [ 7440.686186] brcmfmac: brcmf_cfg80211_set_power_mgmt: power save enabled
Nov 15 18:10:12 client dhcpcd[426]: wlan0: connected to Access Point `'
Nov 15 18:10:12 client dhcpcd[426]: wlan0: waiting for carrier
Nov 15 18:10:12 client dhcpcd[426]: wlan0: waiting for carrier
Nov 15 18:10:14 client kernel: [ 7442.154464] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
Nov 15 18:10:14 client dhcpcd[426]: wlan0: carrier acquired
Nov 15 18:10:14 client dhcpcd[426]: wlan0: connected to Access Point 'xxxxx'
Nov 15 18:10:14 client dhcpcd[426]: wlan0: IAID eb:ad:42:e2
Nov 15 18:10:14 client dhcpcd[426]: wlan0: adding address fe80::d048:ff6a:f422:8366
Nov 15 18:10:14 client avahi-daemon[348]: Joining mDNS multicast group on interface wlan0.IPv6 with address fe80::d048:ff6a:f422:8366.
Nov 15 18:10:14 client avahi-daemon[348]: New relevant interface wlan0.IPv6 for mDNS.
Nov 15 18:10:14 client avahi-daemon[348]: Registering new address record for fe80::d048:ff6a:f422:8366 on wlan0.*.
Nov 15 18:10:14 client dhcpcd[426]: wlan0: rebinding lease of 172.17.255.157
Nov 15 18:10:15 client dhcpcd[426]: wlan0: soliciting an IPv6 router
Nov 15 18:10:18 client dhcpcd[426]: wlan0: probing address 172.17.255.157/16
Nov 15 18:10:23 client dhcpcd[426]: wlan0: leased 172.17.255.157 for 3600 seconds
Nov 15 18:10:23 client avahi-daemon[348]: Joining mDNS multicast group on interface wlan0.IPv4 with address 172.17.255.157.
Nov 15 18:10:23 client avahi-daemon[348]: New relevant interface wlan0.IPv4 for mDNS.
Nov 15 18:10:23 client avahi-daemon[348]: Registering new address record for 172.17.255.157 on wlan0.IPv4.
Nov 15 18:10:23 client dhcpcd[426]: wlan0: adding route to 172.17.0.0/16
Nov 15 18:10:23 client dhcpcd[426]: wlan0: adding default route via 172.17.0.1
Nov 15 18:10:27 client dhcpcd[426]: wlan0: no IPv6 Routers available
"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème." Les Shadoks, J. Rouxel

velocedge
Posts: 51
Joined: Mon Mar 28, 2016 5:57 pm

Re: Fast wifi interface configuration switching with network namespaces

Thu Mar 04, 2021 9:07 pm

This worked perfectly... the first time. ;-) I made new image and went through these steps and it worked exactly like I needed it to work. So, I did the same thing to my working copy, backing out all the stuff we did, and tried it. When I tried to connect to ap0, it saw it, asked me for my password, but then got stuck on "acquiring IP address". So, I figured there were things I didn't back out so I went back to the fresh image and it did the same thing... stuck on acquiring IP address. I tried another image, same thing.

So what can I give you or do to get this going again. It was so nice!!

epoch1970
Posts: 7047
Joined: Thu May 05, 2016 9:33 am
Location: France

Re: Fast wifi interface configuration switching with network namespaces

Thu Mar 04, 2021 10:42 pm

Are you missing a DHCP server listening on ap0?
With dhcpcd you could start it when ap0 is up, by adding a custom run-hook (a script)
I guess you could also start it from a systemd unit reacting to the presence or absence of the network interface.
"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème." Les Shadoks, J. Rouxel

velocedge
Posts: 51
Joined: Mon Mar 28, 2016 5:57 pm

Re: Fast wifi interface configuration switching with network namespaces

Fri Mar 05, 2021 12:25 am

At the end of /etc/dhcpcd.conf I have

interface ap0
static ip_address=192.168.9.9/24

Anything else I can check?

As far as starting it, or hooks, or systemd... I don't know what any of that means... Otherwise, this is perfect!

epoch1970
Posts: 7047
Joined: Thu May 05, 2016 9:33 am
Location: France

Re: Fast wifi interface configuration switching with network namespaces

Fri Mar 05, 2021 9:44 am

https://manpages.debian.org/buster/dhcp ... .8.en.html

The standard wpa-supplicant script is a good example of stopping/starting an external process according to interface state.
"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème." Les Shadoks, J. Rouxel

velocedge
Posts: 51
Joined: Mon Mar 28, 2016 5:57 pm

Re: Fast wifi interface configuration switching with network namespaces

Fri Mar 05, 2021 11:20 am

Ok, that was a good read.. but I need to know explicitly what I need to do. If it's no obvious, very new to Pi/Linux.

Was the dhcpcd.conf file correct?

velocedge
Posts: 51
Joined: Mon Mar 28, 2016 5:57 pm

Re: Fast wifi interface configuration switching with network namespaces

Fri Mar 05, 2021 11:36 am

Making sure this is correct too.
pi@raspberrypi:~/ptweb $ cat /etc/wpa_supplicant/wpa_supplicant-ap0.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=US
ap_scan=2

network={
ssid="myssid"
mode=2
key_mgmt=WPA-PSK
proto=RSN
group=CCMP TKIP
psk="**********"
# See https://en.wikipedia.org/wiki/List_of_WLAN_channels
frequency=2437 #channel 6
}

wpa_supplicant.conf only has the wifi network content.

But where have I specified the IP address range from which the dhcp server can hand out?

epoch1970
Posts: 7047
Joined: Thu May 05, 2016 9:33 am
Location: France

Re: Fast wifi interface configuration switching with network namespaces

Fri Mar 05, 2021 1:20 pm

As far as I know the wpa_supplicant file I originally posted is correct. I don’t write that stuff, I use it and for this I read the documentation and then I try...
Wrt interface management (dhcpcd) and DHCP server (recommend you use dnsmasq) you could start by reading some paragraphs from this: https://www.raspberrypi.org/documentati ... -routed.md
Then search the forums, both dnsmasq and dhcpcd are frequently discussed. And open new topics if you have remaining questions.
"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème." Les Shadoks, J. Rouxel

velocedge
Posts: 51
Joined: Mon Mar 28, 2016 5:57 pm

Re: Fast wifi interface configuration switching with network namespaces

Fri Mar 05, 2021 5:38 pm

I went back to my original configuration and uninstalled hostapd, killed its directory, and added the following to dnsmasq.conf:

dhcp-range=192.168.9.10,192.168.9.20,24h

That fixed the issue of not obtaining an IP address. So, everything works nicely now. I'm not entirely sure why I have both dhcpcd an dnsmasq since they are both dhcp servers but it working so I don't really care at this point!

epoch1970
Posts: 7047
Joined: Thu May 05, 2016 9:33 am
Location: France

Re: Fast wifi interface configuration switching with network namespaces

Fri Mar 05, 2021 6:48 pm

Well done.

Dnsmasq is a DHCP+DNS server. ISC dhcpd is another well known DHCP server.

DhcpCd is a “DHCP client daemon”. It queries information from DHCP servers and configures interfaces. ISC also released a DHCP client program, called dhclient.
"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème." Les Shadoks, J. Rouxel

Return to “Raspberry Pi OS”