morrownr / 8814au

Linux Driver for USB WiFi Adapters that are based on the RTL8814AU Chipset
Other
478 stars 88 forks source link

Implementation of Beamforming in the driver is dummy #44

Closed Vito-Swift closed 2 years ago

Vito-Swift commented 2 years ago

Hi everyone, I'm working on a project that needs to read the channel estimation matrix out from the NDP procedure. To do so, I used an EDUP-1622 wireless card (with up to 3 spatial stream supported) and planed to do some minor modifications on rtl8814au driver for my project.

In the first step, I setuped 2 devices in AP/STA scheme, and confirmed the connection is using 802.11AC standard.

$ sudo lshw -C network
... ...
  *-network:2
       description: Wireless interface
       physical id: 3
       bus info: usb@2:1
       logical name: wlan1
       serial: e8:4e:06:95:28:cd
       capabilities: ethernet physical wireless
       configuration: broadcast=yes driver=rtl8814au driverversion=5.10.63-v7l+ ip=169.254.138.77 multicast=yes wireless=IEEE 802.11AC

To better describe the protocol-related parameters of my setup, I pasted my hostapd.conf as below:

interface=wlan1
driver=nl80211
ssid=Beamformer
macaddr_acl=0
auth_algs=1
ignore_broadcast_sisd=0
beacon_int=100
dtim_period=1
wpa=2
wpa_passphrase=xxxxxxxx
wpa_key_mgmt=WPA-PSK WPA-PSK-SHA256
wpa_pairwise=CCMP
rsn_pairwise=CCMP

hw_mode=a
ieee80211n=1
ieee80211ac=1
channel=36
wmm_enabled=1
wme_enabled=1
country_code=US

ht_capab=[LDPC][HT40-][HT40+][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]
vht_capab=[RXLDPC][MAX-MPDU-11454][SHORT-GI-80][SU-BEAMFORMER][SU-BEAMFORMEE][BF-ANTENNA-2][SOUNDING-DIMENSION-2][HTC-VHT]

vht_oper_chwidth=1
vht_oper_centr_freq_seg0_idx=42

Next, I checked dmesg -wH report which shows that each time the TX initiates an NDP procedure the driver will put a line in the kernel log.

$ sudo dmesg -wH
... ...
[  +4.080076] RTW: [C2H], C2H_TXBF!!
[  +4.080137] RTW: [C2H], C2H_TXBF!!
[  +4.080012] RTW: [C2H], C2H_TXBF!!
[  +4.080075] RTW: [C2H], C2H_TXBF!!
[  +4.080042] RTW: [C2H], C2H_TXBF!!
[  +4.079979] RTW: [C2H], C2H_TXBF!!
[  +4.080090] RTW: [C2H], C2H_TXBF!!
[  +4.080073] RTW: [C2H], C2H_TXBF!!
[Oct23 21:14] RTW: [C2H], C2H_TXBF!!
[  +4.080024] RTW: [C2H], C2H_TXBF!!
[  +4.079886] RTW: [C2H], C2H_TXBF!!
[  +4.080050] RTW: [C2H], C2H_TXBF!!
[  +4.080142] RTW: [C2H], C2H_TXBF!!
[  +4.079968] RTW: [C2H], C2H_TXBF!!
[  +4.080043] RTW: [C2H], C2H_TXBF!!
[  +4.080037] RTW: [C2H], C2H_TXBF!!
[  +4.080112] RTW: [C2H], C2H_TXBF!!
[  +4.080107] RTW: [C2H], C2H_TXBF!

However, when I look into the source code to investigate where the channel estimation matrix is stored and how it is being modified by the NDP procedure, I found the implementation seems dummy. The related source code is pasted below

source code here:

#elif (DM_ODM_SUPPORT_TYPE == ODM_CE)

u32 beamforming_get_report_frame(
    void *dm_void,
    union recv_frame *precv_frame)
{
    struct dm_struct *dm = (struct dm_struct *)dm_void;
    u32 ret = _SUCCESS;
    struct _RT_BEAMFORMEE_ENTRY *beamform_entry = NULL;
    u8 *pframe = precv_frame->u.hdr.rx_data;
    u32 frame_len = precv_frame->u.hdr.len;
    u8 *TA;
    u8 idx, offset;

    /*@Memory comparison to see if CSI report is the same with previous one*/
    TA = get_addr2_ptr(pframe);
    beamform_entry = phydm_beamforming_get_bfee_entry_by_addr(dm, TA, &idx);
    if (beamform_entry->beamform_entry_cap & BEAMFORMER_CAP_VHT_SU)
        offset = 31; /*@24+(1+1+3)+2  MAC header+(Category+ActionCode+MIMOControlField)+SNR(nc=2)*/
    else if (beamform_entry->beamform_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)
        offset = 34; /*@24+(1+1+6)+2  MAC header+(Category+ActionCode+MIMOControlField)+SNR(nc=2)*/
    else
        return ret;

    return ret;
}

To my understanding of the 802.11ac vht standard and this driver, when each time beamformer initials a NDP procedure and the beamformee responds with a compressed channel matrix, the beamformer shall enter this beamforming_get-report_frame() function to collect the compressed channel matrix and store it in the beamforming_entry->csi_matrix. But in the implementation, I did not see the csi_matrix being modified.

Also, I print the values of the csi_matrix in the kernel long after the connection is established, but it seems to me the csi_matrix stays unchanged (the value of all the elements in csi_matrix[] are zeros and will never changed).

Is that mean this driver has not implemented beamforming functionality yet?

morrownr commented 2 years ago

@Vito-Swift

Good day sir! Very interesting project you are working on. It certainly is of interest. My initial comments:

-- Realtek out-of-kernel drivers are based on the wrong technology. Realtek should be producing mac80211 drivers per Linux Wireless guidance.

-- Realtek should be upstreaming mac80211 technology drivers to include and maintain them in the Linux kernel. This is how it should be done. Out-of-kernel drivers are problematic.

A good place to start is:

https://wireless.wiki.kernel.org/welcome

You can get information about the core mac80211 type of driver and look at the current in-kernel mac80211 usb drivers:

https://wireless.wiki.kernel.org/en/users/drivers/mediatek

You can subscribe to the Linux Wireless mailing list:

https://wireless.wiki.kernel.org/en/developers/mailinglists

You can even submit changes that will become part of the Linux kernel and benefit users around the world. The Mediatek MT76 drivers for the mt7612u and mt7610u might be a good place to take a look and adapters that use those drivers are readily available:

https://github.com/morrownr/USB-WiFi

I would be interested to know what you decide.

Regards,

Nick

Vito-Swift commented 2 years ago

@morrownr Dear Nick,

Thanks for your quick response. I must say I extremely appreciate you for your strong enthusiasm in maintaining this open-source wireless card driver.

Indeed, the Realtek driver is poorly implemented, and as my investigation, they implemented 2 or more versions of beamforming inside this driver, and functions of different versions are cross-calling each other (i.e. you can find many places in this driver where beamforming_func_ver1() is calling beamforming_func_ver2()), which is a really bad practice to maintain a driver in quick iterations.

The reason I choose this driver is that there are honestly not many open-source 802.11ac+beamforming wifi drivers operating on off-the-shelf devices. This rtl8814au device is one of very few drivers which have complete beamforming implementation and show sufficient modification possibilities for my project. Recent Mediatek and Atheros mac layer capabilities are no longer implemented in the driver. There are also many testbeds like WARP and OpenWIFI which have implemented a full-stack WiFi protocol+RF modulation using FPGA and Software Defined Radio, but the price to purchase the hardware+software is really expensive even for research purposes. Hence, here I am. Thank you again for your maintenance.

Back to the issue I raised, after a few days of research, I found I was wrong in thinking that the beamforming functions are fully implemented in the driver. It's not true when I look into the source code. From the source code, I could find some clue that the beamforming functionality is implemented in the hardware instead of the software, because most beamforming related commands are called through the hardware abstract layer (rtw_bf_hal). After printing out the content of memory, I suspect the beamforming capabilities are correctly implemented in the firmware, so maybe I could close this issue at this time. I will keep investigating this driver (or maybe other drivers) and share what I have found with the community. Thank you and wish you have a good day.

Best Regards, Chenhao

libc0607 commented 3 months ago

Hi @Vito-Swift ,

I'm currently looking into the beamforming implementation in Realtek's driver and Google brought me here. My goal is to use its beamforming feature in FPV (bi-directional injecting & monitoring, without establishing AP/STA connection).

From the source code, I could find some clue that the beamforming functionality is implemented in the hardware instead of the software, because most beamforming related commands are called through the hardware abstract layer (rtw_bf_hal). After printing out the content of memory, I suspect the beamforming capabilities are correctly implemented in the firmware, so maybe I could close this issue at this time.

I did notice the _send_*ht_ndpa_packet() in rtw_beamforming.c triggered by some rtw_bf_cmd, but I haven't noticed any code related to receiving NDPA/NDP packet or sending the matrix (maybe when acting as a SU beamformee?). Does that mean -- to start a beamforming process, only need to config some regs, send an NDPA packet (in the driver), then the rest is automatically done by hardware or firmware?

Vito-Swift commented 3 months ago

Hi @Vito-Swift ,

I'm currently looking into the beamforming implementation in Realtek's driver and Google brought me here. My goal is to use its beamforming feature in FPV (bi-directional injecting & monitoring, without establishing AP/STA connection).

From the source code, I could find some clue that the beamforming functionality is implemented in the hardware instead of the software, because most beamforming related commands are called through the hardware abstract layer (rtw_bf_hal). After printing out the content of memory, I suspect the beamforming capabilities are correctly implemented in the firmware, so maybe I could close this issue at this time.

I did notice the _send_*ht_ndpa_packet() in rtw_beamforming.c triggered by some rtw_bf_cmd, but I haven't noticed any code related to receiving NDPA/NDP packet or sending the matrix (maybe when acting as a SU beamformee?). Does that mean -- to start a beamforming process, only need to config some regs, send an NDPA packet (in the driver), then the rest is automatically done by hardware or firmware?

I guess the whole channel sounding process is done in the hardware/firmware so there is no clear implementation in the code of this driver. One reason I guess is that the time interval between NDPA and NDP is really short according to the 802.11 standard and putting an extra control logic at the software level does not make sense. Another one is that realtek just decided not to disclose this part.

I have no idea whether injecting NDPA/NDP can be done with some firmware commands instead of using monitor interfaces. Others are welcome to comment on this part.

libc0607 commented 2 months ago

@Vito-Swift Thank you for your reply.

One reason I guess is that the time interval between NDPA and NDP is really short according to the 802.11 standard and putting an extra control logic at the software level does not make sense.

It does make sense. I forgot this part.

I've been reading the rtw88's beamformee implementation in mainline Linux (because the Realtek driver is a mess) and I recognized that the beamforming is most likely implemented in hardware. There are register-level configurations, such as MAC address and NDP RX timer.

Gonna explore more on Realtek's driver, and will update if something new discovered.

I have no idea whether injecting NDPA/NDP can be done with some firmware commands instead of using monitor interfaces.

I think the NDPA packet is assembled and sent at here -- it's similar to monitor injection. The MU report poll is similar, at here.

It seems that the hardware do send the NDP packet. Maybe triggered by recognizing a TX packet with an "NDPA" type set on the Frame Control field?

Others are welcome to comment on this part.

Me too.