Search Linux Wireless

Re: [PATCH 02/12] wifi: mwifiex: fix MAC address handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Sep 06, 2024 at 04:40:36PM +0200, Francesco Dolcini wrote:
> On Mon, Aug 26, 2024 at 01:01:23PM +0200, Sascha Hauer wrote:
> > The mwifiex driver tries to derive the MAC addresses of the virtual
> > interfaces from the permanent address by adding the bss_num of the
> > particular interface used. It does so each time the virtual interface
> > is changed from AP to station or the other way round. This means that
> > the devices MAC address changes during a change_virtual_intf call which
> > is pretty unexpected by userspace.
> 
> Is this the only reason for this patch or there are other reasons?
> I'd like to understand the whole impact, to be sure the backport to
> stable is what we want.
> 
> > Furthermore the driver doesn't use the permanent address to add the
> > bss_num to, but instead the current MAC address increases each time
> > we do a change_virtual_intf.
> > 
> > Fix this by initializing the MAC address once from the permanent MAC
> > address during creation of the virtual interface and never touch it
> > again. This also means that userspace can set a different MAC address
> > which then stays like this forever and is not unexpectedly changed
> > by the driver.
> > 
> > It is not clear how many (if any) MAC addresses after the permanent MAC
> > address are reserved for a device, so set the locally admistered
> > bit for all MAC addresses modified from the permanent address.
> 
> I wonder if we should not just use the same permanent mac address whatever
> the virtual interface is. Do we have something similar in other wireless
> drivers?

Yes, there are at least four driver that generate different MAC
addresses for different vifs:

drivers/net/wireless/ath/ath6kl/cfg80211.c:3816
drivers/net/wireless/ath/wil6210/cfg80211.c:732
drivers/net/wireless/microchip/wilc1000/netdev.c:983
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:606

(line numbers match 6.11-rc6):

For the mac80211 based drivers there are also tricks played to use
unique MAC addresses in ieee80211_assign_perm_addr().

For reference in mwifiex setting different MAC addresses for different
interfaces goes down to:

| commit 864164683678e27c931b5909c72a001b1b943f36
| Author: Xinming Hu <huxm@xxxxxxxxxxx>
| Date:   Tue Feb 13 14:10:15 2018 +0800
| 
|     mwifiex: set different mac address for interfaces with same bss type
| 
|     Multiple interfaces with same bss type could affect each other if
|     they are sharing the same mac address. In this patch, different
|     mac address is assigned to new interface which have same bss type
|     with exist interfaces.
| 
|     Signed-off-by: Xinming Hu <huxm@xxxxxxxxxxx>
|     Signed-off-by: Kalle Valo <kvalo@xxxxxxxxxxxxxx>


> 
> > Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
> > Cc: stable@xxxxxxxxxxxxxxx
> > ---
> >  drivers/net/wireless/marvell/mwifiex/cfg80211.c |  4 +-
> >  drivers/net/wireless/marvell/mwifiex/init.c     |  1 -
> >  drivers/net/wireless/marvell/mwifiex/main.c     | 54 ++++++++++++-------------
> >  drivers/net/wireless/marvell/mwifiex/main.h     |  5 ++-
> >  4 files changed, 30 insertions(+), 34 deletions(-)
> > 
> ...
> 
> > diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
> > index 96d1f6039fbca..46acddd03ffd1 100644
> > --- a/drivers/net/wireless/marvell/mwifiex/main.c
> > +++ b/drivers/net/wireless/marvell/mwifiex/main.c
> > @@ -971,34 +971,16 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
> >  }
> >  
> >  int mwifiex_set_mac_address(struct mwifiex_private *priv,
> > -			    struct net_device *dev, bool external,
> > -			    u8 *new_mac)
> > +			    struct net_device *dev, u8 *new_mac)
> >  {
> >  	int ret;
> > -	u64 mac_addr, old_mac_addr;
> > +	u64 old_mac_addr;
> >  
> > -	old_mac_addr = ether_addr_to_u64(priv->curr_addr);
> > +	netdev_info(dev, "%s: old: %pM new: %pM\n", __func__, priv->curr_addr, new_mac);
> >  
> > -	if (external) {
> > -		mac_addr = ether_addr_to_u64(new_mac);
> > -	} else {
> > -		/* Internal mac address change */
> > -		if (priv->bss_type == MWIFIEX_BSS_TYPE_ANY)
> > -			return -EOPNOTSUPP;
> this was the only usage of MWIFIEX_BSS_TYPE_ANY, correct? Did it had any
> reason before?

I haven't found a path to get here with priv->bss_type ==
MWIFIEX_BSS_TYPE_ANY. This function is called from
mwifiex_init_new_priv_params() and mwifiex_add_virtual_intf(). Both
functions set priv->bss_type to something else or bail out with an error
before calling mwifiex_set_mac_address(). It's also called from the
ndo_set_mac_address method, but for a registered net device the bss_type
should also be set to something meaningful.

> 
> > -
> > -		mac_addr = old_mac_addr;
> > -
> > -		if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P) {
> > -			mac_addr |= BIT_ULL(MWIFIEX_MAC_LOCAL_ADMIN_BIT);
> > -			mac_addr += priv->bss_num;
> > -		} else if (priv->adapter->priv[0] != priv) {
> > -			/* Set mac address based on bss_type/bss_num */
> > -			mac_addr ^= BIT_ULL(priv->bss_type + 8);
> > -			mac_addr += priv->bss_num;
> > -		}
> > -	}
> > +	old_mac_addr = ether_addr_to_u64(priv->curr_addr);
> >  
> > -	u64_to_ether_addr(mac_addr, priv->curr_addr);
> > +	ether_addr_copy(priv->curr_addr, new_mac);
> >  
> >  	/* Send request to firmware */
> >  	ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
> > @@ -1015,6 +997,26 @@ int mwifiex_set_mac_address(struct mwifiex_private *priv,
> >  	return 0;
> >  }
> >  
> > +int mwifiex_set_default_mac_address(struct mwifiex_private *priv,
> > +				    struct net_device *dev)
> > +{
> > +	int priv_num;
> > +	u8 mac[ETH_ALEN];
> > +
> > +	ether_addr_copy(mac, priv->adapter->perm_addr);
> > +
> > +	for (priv_num = 0; priv_num < priv->adapter->priv_num; priv_num++)
> > +		if (priv == priv->adapter->priv[priv_num])
> > +			break;
> > +
> > +	if (priv_num) {
> > +		eth_addr_add(mac, priv_num);
> > +		mac[0] |= 0x2;
> > +	}
> 
> Please see my concern on this in the beginning of the email.
> 
> > @@ -1364,10 +1366,6 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
> >  	priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK;
> >  	priv->gen_idx = MWIFIEX_AUTO_IDX_MASK;
> >  	priv->num_tx_timeout = 0;
> > -	if (is_valid_ether_addr(dev->dev_addr))
> > -		ether_addr_copy(priv->curr_addr, dev->dev_addr);
> > -	else
> > -		ether_addr_copy(priv->curr_addr, priv->adapter->perm_addr);
> 
> With this change, when mfg_mode is true, priv->curr_addr will be not
> initialized. Wanted?

Not wanted, just me being ignorant. Let's have a look:

priv->adapter->perm_addr is initialized in the response handling of the
HostCmd_CMD_GET_HW_SPEC command. This command is only issued when
mfg_mode is false, so in mfg mode priv->adapter->perm_addr will be the
zero address.

The only documentation we have for mfg_mode is:

manufacturing mode enable:1, disable:0

I don't know what this really is about, but I could imagine that this
is for initial factory bringup when the chip is not parametrized and thus
doesn't have a permanent MAC address yet.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux