[BPI R2] Hostapd multiple SSID on MT7612

Hi,

I bought a MT7612 for my BPI R2 board. Acces point configuration works perfectly with one SSID.

If I understand wifi board specifications, it seems to support multiple AP (for a total of 8):

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 try to add new SSID with bss option on hostapd configuration file I have the following error :

...
nl80211: Create interface iftype 3 (AP)
nl80211: Ignored event (cmd=7) for foreign interface (ifindex 12 wdev 0x0)
nl80211: New interface wlp1s0_1 created: ifindex=12
nl80211: Add own interface ifindex 12 (ifidx_reason -1)
nl80211: if_indices[16]: 9(-1) 12(-1)
Could not set interface wlp1s0_1 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)
wlp1s0_1: Flushing old station entries
nl80211: flush -> DEL_STATION wlp1s0 (all)
...

Interface alias seems to not be started by kernel.

Anyone have test multiple SSID on this wifi board ? Is kernel drivers MT76x2e support it ?

FYI: I put interface alias on /etc/network/interfaces with allow-hotplug directive with ip address and netmask. I tried different MAC address for bssid option.

hostapd.conf (1,3 Ko) hostapd-full-log.txt (16,4 Ko)

afair you cannot open multiple APs with mt7612…there are not much cards available which have multiple AP support. afair some compex and maybe mt7615, but i don’t know if driver support is ready for this

Hi Frank,

Compared to MT7623 internal wifi board, which not permits interface combinations:

 interface combinations are not supported

I can’t create manually new virtual interface with AP (because, I think, the firmware split wifi card into 2 physicals device : 1 AP and 1 managed) :

root@bpi-r2:~# iw dev
phy#2
   Interface ap2G
           ifindex 11
           wdev 0x200000001
           addr 02:08:22:78:e6:fb
           ssid Test-AP
           type AP
phy#1
   Interface wlan0
           ifindex 10
           wdev 0x100000001
           addr 00:08:22:78:e6:fb
           type managed
root@bpi-r2:~# iw dev ap2G interface add ap2G_Guest type __ap
command failed: Operation not supported (-95)

Like many examples found on the internet (https://www.reddit.com/r/linuxquestions/comments/52r2nh/is_is_possible_to_split_a_single_wireless_nic/) interface combinaisons indicates that we can use a maximum of 8 AP on the same card.

Effectively, with the MT7612 card, I can create multi acces point on the same physical card manually with iw command (iw dev wlp1s0 interface add wlp1s0_2 type __ap):

phy#0
   Interface wlp1s0_2
           ifindex 30
           wdev 0x12
           addr fa:62:aa:60:02:79
           type AP
           txpower 21.00 dBm
           multicast TXQ:
                   qsz-byt qsz-pkt flows   drops   marks   overlmt hashcol tx-bytes        tx-packets
                   0       0       0       0       0       0       0       0               0
   Interface wlp1s0_1
           ifindex 29
           wdev 0x11
           addr f8:62:aa:60:02:79
           type AP
           txpower 21.00 dBm
           multicast TXQ:
                   qsz-byt qsz-pkt flows   drops   marks   overlmt hashcol tx-bytes        tx-packets
                   0       0       0       0       0       0       0       0               0
   Interface wlp1s0
           ifindex 9
           wdev 0x1
           addr 02:62:aa:60:02:70
           type AP
           txpower 21.00 dBm
           multicast TXQ:
                   qsz-byt qsz-pkt flows   drops   marks   overlmt hashcol tx-bytes        tx-packets
                   0       0       0       0       0       0       0       0               0

It sems that the kernel can’t start the new virtual interface created by hostapd (I can’t start the interface manually, ip link set wlp1s0_1 up has no effect, interface still down despite of /etc/network/interfaces configuration exist).

Any ideas ?

1 Like

I have not do anything with multiple virtual interfaces. Maybe driver of mt76x2 does not support it. If i find some time i can test a bit around. Currently have my mt7612 not in slot to test sata enumeration in uboot if i get the Patch from mtk. Maybe i can test on r64,as slot is more eccessable due to not case around the board :slight_smile:

Till then i would post link to documentation wiki i found while reading sites behind your link

https://wireless.wiki.kernel.org/en/users/documentation/iw/vif

I made a strace on hostapd process when I ran my configuration :

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

Error was triggered when hostapd program try to set UP flag to the network device socket by IOCTL sysinternal call.

I checked on hostapd source code to get the following (simplified) call trace :

ap/hostapd.c
     hostapd_setup_bss --> hostapd_if_add
ap/ap_drv_ops.c
     hapd->driver->if_add = wpa_driver_nl80211_if_add
 drivers/driver_nl80211.c
     nl80211_create_iface
     ...
     linux_set_iface_flags
drivers/linux_ioctl.c
     ioctl(sock, SIOCSIFFLAGS, &ifr) --> EBUSY

If i check C files from mediatek mt76 wireless drivers, I found only 3 code lines with EBUSY return code :

BPI-R2/drivers/net/wireless/mediatek/mt76$ find . -type f -iname "*.c" -exec egrep -Hn "EBUSY" {} \;
./tx.c:451:                     return -EBUSY;
./tx.c:507:                     ret = -EBUSY;
./mt76x02_util.c:335:           return -EBUSY;

I’ve tried GDB and KGDB to get line code or indication when the EBUSY error was triggered (and by who) but I’m not familiar with C developping and debugging (too far away)… KGDB seems to not working with USB keyboard (keyboard doen’t response once in debug mode) and I don’t have (yet) the equipment to make debug with serial console.

If anyone knows a way to debug the kernel without tools other than the card itself, i’m interested.

@frank-w : I think that the MT76 drivers are the same between R2 and R64 board. I don’t see any reason for not getting the same error on the R64.

My strace file: strace (236,1 Ko)

does you hostapd use the vif in its config (instead of the main interface)?

maybe mt76x2 driver does not support vif (and mt7622/7615 does)?

the mt76 core driver is same, but it uses different abstraction layers for mt76x[02] and mt7615/22

i’m not that deep in such things

if you have only 3 occurences, then you can add a printk-line before to show which one it is…thats the way i debug such drivers :wink:

printk(KERN_ALERT "DEBUG: Passed %s %d val:0x%0x\n",__FUNCTION__,__LINE__,(u32)val);

(you can drop “val…” and “(,u32)val”) if you don’t want to show any value (or set val to 0).

The issue is located on “mt76x02_add_interface” function in “drivers/net/wireless/mediatek/mt76/mt76x02_util.c” kernel driver file.

I changed the function to set debug printk :

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);

I got the following debug logs:

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).

Sorry but my programming on C language is very limited… I can’t display device interface name on debug log due to struct of struct or struct of pointer of struct… I can’t continue to debug and especially correct the issue without a big help…

I don’t known which wifi board(s) uses this part of driver, but I think the 7612 is not the only one board impacted by the issue. Is used by 7615 or other ? (anyone can try ?)

Thanks in advance ^^

mt76x02_add_interface is used only for mt76x0 and 76x2 (except mt7622 which is handled by 7615 part). I guess not much users try to create vif on mt7612

You could try send issue on mt76 repo.

https://github.com/openwrt/mt76/issues

For name you can try this:

https://elixir.bootlin.com/linux/latest/source/drivers/net/wireless/mediatek/mt76/mt76x02.h#L75

https://elixir.bootlin.com/linux/latest/source/drivers/net/wireless/mediatek/mt76/mt76.h#L519

https://elixir.bootlin.com/linux/latest/source/include/linux/device.h#L542

Alternatively

https://elixir.bootlin.com/linux/latest/source/drivers/net/wireless/mediatek/mt76/mt76.h#L523

https://elixir.bootlin.com/linux/latest/source/include/linux/netdevice.h#L1844

so something like this:

printk(KERN_ALERT "DEBUG MT76: dev.init_name: %s napi_dev.name: %s",
       dev->mt76.dev->init_name,
       dev->mt76.napi_dev.name);

I tried with your output without success…

I added the following printk command on the function:

  printk( KERN_ALERT "DEBUG MT76: Add interface - dev.init_name '%s' / napi_dev.name: '%s' with idx: %d\n", dev->mt76.dev->init_name, dev->mt76.napi_dev.name, idx);

I got the following debug log ^^ :

  Aug 12 09:32:11 bpi-r2 kernel: [  810.258468] DEBUG MT76: Add interface - dev.init_name '(null)' / napi_dev.name: '' with idx: 1

I opened a case on openwrt/mt76 github : https://github.com/openwrt/mt76/issues/433. I will see if anyone give me a valid solution to see device name for troubleshooting on it ^^

Thanks for your help and for all your work on R2/R64 boards (or others).