openwrt / openwrt/mt76

mt76x02 hostapd unable to set multi SSID (vif)

Open
#433 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
888
Forks
436
PR merge metrics
No merged PRs in 30d

Description

I have a bananapi R2 with MT7612 wifi board (pcie), and I try to set multi AP on the same phy.
The board indicates that it supports a max of 8 AP simultaneously :

valid interface combinations:
      * #{ IBSS } <= 1, #{ managed, AP, mesh point, P2P-client, P2P-GO } <= 8,
        total <= 8, #channels <= 1, STA/AP BI must match, radar detect widths: { 20 MHz (no HT), 20 MHz, 40 MHz, 80 MHz }

When I configure a hostapd.conf file with a second bss, hostapd can't start the new vif and remove all interfaces on the phy (everything works fine with only one bss):

...
nl80211: Create interface iftype 3 (AP)
nl80211: Ignored event (cmd=7) for foreign interface (ifindex 12 wdev 0x0)
nl80211: New interface ap5G_Guest created: ifindex=12
nl80211: Add own interface ifindex 12 (ifidx_reason -1)
nl80211: if_indices[16]: 9(-1) 12(-1)
Could not set interface ap5G_Guest flags (UP): Device or resource busy
nl80211: Remove interface ifindex=12
nl80211: if_indices[16]: 9(-1)
nl80211: if_indices[16]: 9(-1)
Failed to add BSS (BSSID=00:50:56:00:00:34)
ap5G_Guest: Flushing old station entries
nl80211: flush -> DEL_STATION ap5G (all)
...

With strace on the process, we can see that hostapd received a EBUSY error when it try to set UP flag on the VIF :

socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 14
ioctl(14, SIOCGIFINDEX, {ifr_name="ap5G_Guest", }) = 0
close(14)                               = 0
write(1, "nl80211: New interface ap5G_Gues"..., 54) = 54
write(1, "nl80211: Add own interface ifind"..., 56) = 56
write(1, "nl80211: if_indices[16]: 9(-1) 1"..., 38) = 38
ioctl(6, SIOCSIFHWADDR, {ifr_name="ap5G_Guest", ifr_hwaddr={sa_family=ARPHRD_ETHER, sa_data=02:62:aa:60:02:71}}) = 0
ioctl(6, SIOCGIFFLAGS, {ifr_name="ap5G_Guest", ifr_flags=IFF_BROADCAST|IFF_MULTICAST}) = 0
ioctl(6, SIOCSIFFLAGS, {ifr_name="ap5G_Guest", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_MULTICAST}) = -1 EBUSY (Device or resource busy)
write(1, "Could not set interface ap5G_Gue"..., 71) = 71
write(1, "nl80211: Remove interface ifinde"..., 37) = 37
write(1, "nl80211: if_indices[16]: 9(-1)\n", 31) = 31
write(1, "nl80211: if_indices[16]: 9(-1)\n", 31) = 31

With some debug sessions, I fund that the EBUSY error code is retuned by mt76x02_add_interface function from 'drivers/net/wireless/mediatek/mt76/mt76x02_util.c' linux kernel driver file. I rewrote the function to add some debug:

int
mt76x02_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
    struct mt76x02_dev *dev = hw->priv;
    unsigned int idx = 0;

    /* Allow to change address in HW if we create first interface. */
    if (!dev->vif_mask &&
        (((vif->addr[0] ^ dev->mt76.macaddr[0]) & ~GENMASK(4, 1)) ||
         memcmp(vif->addr + 1, dev->mt76.macaddr + 1, ETH_ALEN - 1)))
        mt76x02_mac_setaddr(dev, vif->addr);

    if (vif->addr[0] & BIT(1))
        idx = 1 + (((dev->mt76.macaddr[0] ^ vif->addr[0]) >> 2) & 7);

    printk( KERN_ALERT "DEBUG MT76: Add interface with idx: %d\n", idx);

    /*
     * Client mode typically only has one configurable BSSID register,
     * which is used for bssidx=0. This is linked to the MAC address.
     * Since mac80211 allows changing interface types, and we cannot
     * force the use of the primary MAC address for a station mode
     * interface, we need some other way of configuring a per-interface
     * remote BSSID.
     * The hardware provides an AP-Client feature, where bssidx 0-7 are
     * used for AP mode and bssidx 8-15 for client mode.
     * We shift the station interface bss index by 8 to force the
     * hardware to recognize the BSSID.
     * The resulting bssidx mismatch for unicast frames is ignored by hw.
     */
    if (vif->type == NL80211_IFTYPE_STATION)
        idx += 8;

    /* vif is already set or idx is 8 for AP/Mesh/... */
    if (dev->vif_mask & BIT(idx) ||
        (vif->type != NL80211_IFTYPE_STATION && idx > 7)) {
        printk( KERN_ALERT "DEBUG MT76: Function %s - idx: %d\n",__FUNCTION__, idx);
        printk( KERN_ALERT "DEBUG MT76: Function %s - vif mask: %d - bit idx: %lu\n",__FUNCTION__, dev->vif_mask, BIT(idx));
        printk( KERN_ALERT "DEBUG MT76: Function %s - vif mask test: %lu\n",__FUNCTION__, (dev->vif_mask & BIT(idx)));
        return -EBUSY;
    }

    dev->vif_mask |= BIT(idx);

    mt76x02_vif_init(dev, vif, idx);
    return 0;
}
EXPORT_SYMBOL_GPL(mt76x02_add_interface);

and the log file output is below:

Aug 11 17:14:59 bpi-r2 kernel: [  108.709379] DEBUG MT76: Add interface with idx: 1
Aug 11 17:14:59 bpi-r2 kernel: [  108.709393] DEBUG MT76: Function mt76x02_vif_init 299
Aug 11 17:15:00 bpi-r2 kernel: [  110.098437] DEBUG MT76: Add interface with idx: 1
Aug 11 17:15:00 bpi-r2 kernel: [  110.098453] DEBUG MT76: Function mt76x02_add_interface - idx: 1
Aug 11 17:15:00 bpi-r2 kernel: [  110.098458] DEBUG MT76: Function mt76x02_add_interface - vif mask: 2 - bit idx: 2
Aug 11 17:15:00 bpi-r2 kernel: [  110.098462] DEBUG MT76: Function mt76x02_add_interface - vif mask test: 2

Function seems to be called twice with the same idx and return EBUSY to hostapd on the second call. I tested to comment the return EBUSY, the vif started and my phone saw all two SSID.

I don’t know if the idx is not incremented between main interface and vif or if the function is called twice on the vif by hostapd (two ioctl calls in same function without up flag and with up flag).

Full configuration and logs files:
hostapd.conf.txt
hostapd-full-log.txt
strace.txt

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in drivers/net/wireless/mediatek/mt76/mt76x02_util.c, focusing on mt76x02_add_interface and the repeated calls that produce the same index and vif mask. Reproduce with the linked hostapd.conf.txt and logs, then verify that multiple BSS interfaces start without EBUSY or removing the existing interfaces.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.