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:
> 
> 

Reply via email to