From bffd2b39944330b0ffbaba62036a73d2c5e23bfb Mon Sep 17 00:00:00 2001 From: Hu Wang Date: Thu, 26 Oct 2023 01:51:38 -0700 Subject: [PATCH] nl80211: Skip interface down/up when setting MAC address A driver may not support setting MAC address when interface is UP, so wpa_supplicant used to always sets the interface down for MAC address change. Try to change the address first without setting the interface down and then fall back to DOWN/set addr/UP if the first attempt failed. This can reduce the interface setup time for time-critical use cases. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index a375c74f7..25bae2805 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -11609,6 +11609,15 @@ static int nl80211_set_mac_addr(void *priv, const u8 *addr) if (!addr) addr = drv->perm_addr; + /* + * Try to change the address first without setting the interface + * down and then fall back to DOWN/set addr/UP if the first + * attempt failed. This can reduce the interface setup time + * significantly with some drivers. + */ + if (!linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr)) + goto done; + if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0) return -1; @@ -11625,18 +11634,19 @@ static int nl80211_set_mac_addr(void *priv, const u8 *addr) return -1; } - wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR, - bss->ifname, MAC2STR(addr)); - drv->addr_changed = new_addr; - os_memcpy(bss->prev_addr, bss->addr, ETH_ALEN); - os_memcpy(bss->addr, addr, ETH_ALEN); - if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0) { wpa_printf(MSG_DEBUG, "nl80211: Could not restore interface UP after set_mac_addr"); } +done: + wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR, + bss->ifname, MAC2STR(addr)); + drv->addr_changed = new_addr; + os_memcpy(bss->prev_addr, bss->addr, ETH_ALEN); + os_memcpy(bss->addr, addr, ETH_ALEN); + return 0; }