Bug 213207 - ath: Unable to set device MAC in FreeBSD 11
Summary: ath: Unable to set device MAC in FreeBSD 11
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: wireless (show other bugs)
Version: 11.0-STABLE
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-wireless (Nobody)
: 230654 (view as bug list)
Depends on:
Reported: 2016-10-04 19:32 UTC by Teran McKinney
Modified: 2021-09-26 11:39 UTC (History)
7 users (show)

See Also:

wlanaddr fix (1.20 KB, patch)
2016-10-12 18:31 UTC, Andriy Voskoboinyk
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Teran McKinney 2016-10-04 19:32:46 UTC

I can't see how to set my ath0 device MAC address in FreeBSD 11. ifconfig used to let me do this, but now I can only set it for wlan0. If I do that, I can scan, but not associate. Not sure if this is a bug in the wlan -> ath interface where it should be propagating the MAC, or if it's something else.

Seems like it might be related to this: https://lists.freebsd.org/pipermail/freebsd-current/2015-August/056956.html

More details here: https://forums.freebsd.org/threads/57874/

Comment 1 Andriy Voskoboinyk freebsd_committer 2016-10-04 19:45:23 UTC

You should use 'wlanaddr' argument for wireless interfaces (creation time only):
ifconfig wlan0 create wlandev ath0 wlanaddr <addr>

'ether' is not guaranteed to work with them (wpi(4) / iwn(4) / urtwn(4) / <most other> will write it to hardware after 'ifconfig wlan0 up', but ath(4) use it when the vap is created).
Comment 2 Teran McKinney 2016-10-04 20:07:53 UTC
Hi Andriy,

Thank you for your reply. I was unaware of the wlanaddr option in ifconfig.

However, I still have the same behavior as setting ether on wlan0 -- I can scan, but not associate.

If I run ifconfig wlan0 create wlandev ath0 wlanaddr c1:93:07:21:ce:c0 up, the device comes up, finds an open network, tries to associate, and tries over and over. If I drop the wlanaddr option, it associates just fine.

Maybe there's another bug somewhere? This used to work with 'ether' on ath0 back on FreeBSD 10, but I now understand I should have been using 'wlanaddr', instead.

Thank you!
Comment 3 Andriy Voskoboinyk freebsd_committer 2016-10-04 20:27:01 UTC
Hm, really - now it ignores MAC address change for non-AP / mesh modes.

Looks like you can set (ath(4)-specific) kernel environment variable and reload the driver:
kenv hint.ath.0.macaddr="c1:93:07:21:ce:c0"
(add it to loader.conf(5) to preserve after reboot)
kldunload if_ath && kldload if_ath
Comment 4 Andriy Voskoboinyk freebsd_committer 2016-10-04 20:35:32 UTC
(In reply to Andriy Voskoboinyk from comment #3)
> kldunload if_ath && kldload if_ath
More precisely:
ifconfig wlan0 down
ifconfig wlan0 destroy
kldunload if_ath_pci if_ath && kldload if_ath if_ath_pci
Comment 5 Teran McKinney 2016-10-05 01:15:07 UTC
Hi again,

Thanks for getting back to me so quickly.

It seems like the stock kernel may be built without if_ath just being a module, like it's a builtin? Sorry, still more familiar with Linux than FreeBSD in that regard.

# kldunload if_ath
kldunload: can't find file if_ath
# kldunload if_ath_pci
kldunload: can't find file if_ath_pci
# kenv | grep ath
# kldload if_ath
kldload: can't load if_ath: module already loaded or in kernel
# kldload if_ath_pci
kldload: an error occurred while loading the module. Please check dmesg(8) for more details.
# dmesg | tail -n 5
interface ath_pci.1 already present in the KLD 'kernel'!
linker_load_file: Unsupported file type
wlan0: link state changed to UP
interface ath_pci.1 already present in the KLD 'kernel'!
linker_load_file: Unsupported file type

I'm a bit puzzled by this. I never knew of kenv before.


Comment 6 Andriy Voskoboinyk freebsd_committer 2016-10-05 04:54:14 UTC
Yes, it's built into GENERIC; just add the variable into /boot/loader.conf and reboot.
Comment 7 Jimmy Kelley 2016-10-05 12:13:43 UTC
I have the same problem (msk and ath on a Toshiba laptop), where creating a lagg failover interface by setting the mac address on ath0 to that of msk0 worked fine on FreeBSD 10, but doesn't on FreeBSD 11.  I just tried putting that hint in /boot/loader.conf and rebooting, but that didn't fix anything.  Interesting enough, the wlan0 mac address *is* showing that it's set to the hint value after the machine is up in multi-user mode, but dmesg is showing a "kernel: wlan0: Ethernet address:  xx.xx.xx.xx.xx.xx" message with the original ath0 mac address during boot (I'm assuming that's from the 'ifconfig wlan0 create wlandev ...' that happens during startup).

To get my lagg interface working, I have to reverse the set-up, and set the mac address on msk0 to that of the ath0 device.
Comment 8 Andriy Voskoboinyk freebsd_committer 2016-10-12 18:31:39 UTC
Created attachment 175673 [details]
wlanaddr fix

Can you try the patch? It may fix MAC address change via 'wlanaddr' (but not via 'ether').
Comment 9 J.R. Oldroyd 2016-10-12 19:47:35 UTC
This affects us here, too.

In an email thread on freebsd-wireless, "Regression: ethernet + wireless/ath under lagg", I posted an alternative work-around, but both the solution here and that one require hard-coded MAC addresses in config files, which isn't a good solution.
Comment 10 J.R. Oldroyd 2016-10-12 19:54:39 UTC
Oh, to follow-up on what I said in that thread, we need either a way to determine the ath's MAC address, e.g., a sysctl dev.ath.N.macaddr or similar, so that we can use this to set the ethernet's MAC, or we need a way to set the ath's MAC address prior to wlan creation.  Or both!

As Adrian Chadd replied, "there should be a way to create a vap with a specific mac address upon creation time".
Comment 11 Adrian Chadd freebsd_committer 2016-10-12 20:32:16 UTC
So, the challenge is thus.

The device has a MAC address. There's a BSSID and a macaddress field. then, when creating say, cloned AP vaps, the isn't a list of MACs that the NIC has - the reason they're typically only a small difference is there's a BSSID /mask/ field for matching against. look at if_ath.c:assign_address() - and that only happens for hostap and mbss modes.

Now, before glebius removed the device entries from ifconfig, changing the parent device MAC would change what's effectively now ic->ic_macaddr.  When you create a new VAP, it clones ic->ic_macaddr unless you provide IEEE80211_CLONE_MACADDR as an argument and a separate MAC address. In that instance, the VAP is created with a completely different MAC address. Now that there's no parent ifnet, there's no easy (ie, same for all devices) way of modifying ic_macaddr and having that programmed into the hardware for subsequent device updates.

So here's what's going on:

* the device will read its MAC from EEPROM, etc, and feed it into ic_macaddr
* when creating VAPs, net80211 will use ic_macaddr unless given IEEE80211_CLONE_MACADDR as an argument - at which point it'll use a completely separate MAC address for that argument.
* trouble is, that won't really help with STA mode (at least on ath(4)) as there is only one MAC address, and that is what's prgorammed in via ath_hal_setmac()
* when cloning AP VAPs, if_ath.c:assign_address() will update the chipset BSSID mask, so multiple sequential MACs are accepted as "local"
* .. but that doesn't do anything useful for STA mode, so setting the VAP MAC address to anything that isn't ic_macaddr won't affect anything useful.

Ok, so what we really need is:

* fix up the hint.ath.X.macaddr thing to work right if it doesn't
* figure out a generic way to fetch a wifi device mac address, now that 'ifconfig' can't do it;
* figure out a generic way to re-program the device MAC address when the first VAP is created if it has changed, so the first VAP creation can be given an ethernet address and it will actually program the device; or
* .. document one way (eg andriy's way, where setting the wlanaddr on the first VAP will program the NIC MAC, and any subsequent creations can only vary depending upon what the hardware will provide) - and then audit /all/ drivers to make sure that method works.

I think andriy's way is fine, and we just need to document it in the manpage/docbook and then audit every wifi driver. But I'd still like some generic way to fetch ic_macaddr from a device - eg by sysctl, or if we can do it via an existing device ioctl, that.
Comment 12 J.R. Oldroyd 2016-10-14 19:42:36 UTC
I could not get Andriy's patch to work.

/etc/rc.conf was:

ether_re0="`ifconfig re0 ether`"
create_args_wlan0="wlanaddr ${ether_re0##*ether } regdomain FCC country US"
ifconfig_lagg0="laggproto failover laggport re0 laggport wlan0 DHCP"   # WAN_IF
ifconfig_lagg0_ipv6="inet6 accept_rtadv"

It does show the wlan being created with the re's MAC address (both in dmesg and in subsequent "ifconfig wlan0" output).  However, the WPA AUTH is still failing:

Oct 14 21:09:36 shibato wpa_supplicant[411]: wlan0: CTRL-EVENT-SSID-REENABLED id=39 ssid="xxx"
Oct 14 21:09:36 shibato wpa_supplicant[411]: wlan0: Trying to associate with 00:26:f2:11:22:33 (SSID='xxx' freq=2412 MHz)
Oct 14 21:09:46 shibato wpa_supplicant[411]: wlan0: Authentication with 00:26:f2:11:22:33 timed out.
Oct 14 21:09:46 shibato wpa_supplicant[411]: wlan0: CTRL-EVENT-DISCONNECTED bssid=00:26:f2:11:22:33 reason=3 locally_generated=1
Oct 14 21:09:46 shibato wpa_supplicant[411]: wlan0: CTRL-EVENT-SSID-TEMP-DISABLED id=39 ssid="xxx" auth_failures=17 duration=120 reason=CONN_FAILED
Comment 13 ml 2017-08-17 07:32:11 UTC

I've just been hit by this too, after an upgrade from 10.3 to 11.1.

With ifconfig_wlan0="ether ..., my device would not even find available WiFi networks.

With ifconfig_wlan0="wlanaddr ..., I could scan and see the networks, but not associate.

With hint.ath.0.macaddr=... everything works as expected (as it did with 10.3).
Comment 14 Account Removed 2018-04-30 10:02:23 UTC
The patch seems to work.
Comment 15 Account Removed 2018-04-30 10:11:15 UTC
No, never mind, I thought I had been running with it all this time.
Comment 16 Ian 2018-08-15 17:27:08 UTC
*** Bug 230654 has been marked as a duplicate of this bug. ***