Yes, the normal pattern is to update the driver soft state, and then do perform a backside "down / up" transition.
Stefan Sperling <s...@stsp.name> wrote: > On Sat, Feb 17, 2024 at 06:27:40PM -1000, Todd Carson wrote: > > > > On a Raspberry Pi 4 running a recent snapshot, I found that the built-in > > bwfm interface would fail to receive non-broadcast traffic after > > changing the MAC address with ifconfig (for example by having > > "lladdr random" in hostname.bwfm0). > > > > It looks like this was happening because the new MAC address was set in > > the kernel network stack but the bwfm driver wasn't doing anything > > to write the address to the device. > > > > The below diff fixes it for me. > > I don't have any other bwfm devices to test. > > An alternative approach is to memcpy the stack's MAC into ic_myaddr > whenever the interface comes up. E.g. iwx does this in iwx_preinit(): > > if (sc->attached) { > /* Update MAC in case the upper layers changed it. */ > IEEE80211_ADDR_COPY(sc->sc_ic.ic_myaddr, > ((struct arpcom *)ifp)->ac_enaddr); > return 0; > } > > This way the new value of ic_myaddr is propagated to firmware as > part of the usual startup process. > > A possible problem with your approach is that the bwfm_fwvar_set_data() > call might occur while the interface is still down and no firmware has > been loaded. It looks like you handle this case by returning EIO, which > means a hostname.bwfm0 file like the following would run into this I/O > error on the first line during boot: > > lladdr random > nwid foo wpakey bar > inet autoconf > > With the approach taken by iwx(4) such files will work without errors > and the random MAC will be set in the stack only at first, while being > passed to the device when hardware comes up. > > > diff /usr/src > > commit - 6c24eb55e021991196003dc7f0a643e806b14295 > > path + /usr/src > > blob - dfa7a1973d2ab6be7e4b2fbd869b38c441d4eae0 > > file + sys/dev/ic/bwfm.c > > --- sys/dev/ic/bwfm.c > > +++ sys/dev/ic/bwfm.c > > @@ -827,6 +827,17 @@ bwfm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data > > error = 0; > > } > > break; > > + case SIOCSIFLLADDR: > > + ifr = (struct ifreq *)data; > > + error = 0; > > + if (bwfm_fwvar_var_set_data(sc, "cur_etheraddr", > > + ifr->ifr_addr.sa_data, ETHER_ADDR_LEN)) { > > + error = EIO; > > + } else { > > + memcpy(ic->ic_myaddr, ifr->ifr_addr.sa_data, > > + sizeof(ic->ic_myaddr)); > > + } > > + break; > > case SIOCGIFMEDIA: > > case SIOCG80211NODE: > > case SIOCG80211ALLNODES: > > > > >