doc and app notes update
283
doc/README.md
@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
# Openwifi document
|
||||
<img src="./openwifi-detail.jpg" width="1100">
|
||||
|
||||
Above figure shows software and hardware/FPGA modules that compose the openwifi design. The module name is equal/similar to the source code file name. Driver module source codes are in openwifi/driver/. FPGA module source codes are in openwifi-hw repository. The user space tool sdrctl source code are in openwifi/user_space/sdrctl_src/.
|
||||
Above figure shows software and hardware/FPGA modules that compose the openwifi design. The module name is equal/similar to the source code file name. Driver module source codes are in openwifi/driver/. FPGA module source codes are in openwifi-hw repository. The user space tool sdrctl source code are in openwifi/user_space/sdrctl_src/. [Sysfs](https://man7.org/linux/man-pages/man5/sysfs.5.html) is another channel that is offered to do userspace-driver communication by mapping driver variables to virtual files. Check [this app note](app_notes/driver_stat.md#Sysfs-explanation) for further explanation.
|
||||
|
||||
- [Driver and software overall principle](#Driver-and-software-overall-principle)
|
||||
- [sdrctl command](#sdrctl-command)
|
||||
@ -17,11 +17,12 @@ Above figure shows software and hardware/FPGA modules that compose the openwifi
|
||||
- [Regulation and channel config](#Regulation-and-channel-config)
|
||||
- [Analog and digital frequency design](#Analog-and-digital-frequency-design)
|
||||
- [Debug methods](#Debug-methods)
|
||||
- [Test mode driver](#Test-mode-driver)
|
||||
- [Application notes](app_notes/README.md)
|
||||
|
||||
## Driver and software overall principle
|
||||
|
||||
[Linux mac80211 subsystem](https://www.kernel.org/doc/html/v4.16/driver-api/80211/mac80211.html), as a part of [Linux wireless](https://wireless.wiki.kernel.org/en/developers/documentation/mac80211), defines a set of APIs ([ieee80211_ops](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#c.ieee80211_ops)) to rule the Wi-Fi chip driver behavior. SoftMAC Wi-Fi chip driver implements (subset of) those APIs. That is why Linux can support so many Wi-Fi chips of different chip vendors.
|
||||
[Linux mac80211 subsystem](https://www.kernel.org/doc/html/v4.16/driver-api/80211/mac80211.html), as a part of [Linux wireless](https://wireless.wiki.kernel.org/en/developers/documentation/mac80211), defines a set of APIs ([ieee80211_ops](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#c.ieee80211_ops)) to rule the Wi-Fi chip driver behavior. SoftMAC Wi-Fi chip driver implements (subset of) those APIs. That is why Linux can support so many Wi-Fi chips of different chip vendors. Different mode (AP/Client/ad-hoc/mesh) might need different set of APIs
|
||||
|
||||
openwifi driver (sdr.c) implements following APIs of ieee80211_ops:
|
||||
- **tx**. It is called when upper layer has a packet to send
|
||||
@ -30,6 +31,8 @@ openwifi driver (sdr.c) implements following APIs of ieee80211_ops:
|
||||
- **add_interface**. It is called when NIC is created
|
||||
- **remove_interface**. It is called when NIC is deleted
|
||||
- **config**. It is called when upper layer wants to change channel/frequency (like the scan operation)
|
||||
- **set_antenna**. Set/select the tx/rx antenna
|
||||
- **get_antenna**. Read the current tx/rx antenna idx/combination
|
||||
- **bss_info_changed**. It is called when upper layer believe some BSS parameters need to be changed (BSSID, TX power, beacon interval, etc)
|
||||
- **conf_tx**. It is called when upper layer needs to config/change some tx parameters (AIFS, CW_MIN, CW_MAX, TXOP, etc)
|
||||
- **prepare_multicast**. It is called when upper layer needs to prepare multicast, currently only a empty function hook is present.
|
||||
@ -39,19 +42,20 @@ openwifi driver (sdr.c) implements following APIs of ieee80211_ops:
|
||||
- **set_tsf**. It is called when upper layer wants to set 64bit FPGA timer value
|
||||
- **reset_tsf**. It is called when upper layer wants to reset 64bit FPGA timer value
|
||||
- **set_rts_threshold**. It is called when upper layer wants to change the threshold (packet length) for turning on RTS mechanism
|
||||
- **ampdu_action**. AMPDU (Aggregated Mac PDU) related operations
|
||||
- **testmode_cmd**. It is called when upper layer has test command for us. [sdrctl command](#sdrctl-command) message is handled by this function.
|
||||
|
||||
Above APIs are called by upper layer (Linux mac80211 subsystem). When they are called, the driver (sdr.c) will do necessary job over SDR platform. If necessary, the driver will call other component drivers, like tx_intf_api/rx_intf_api/openofdm_tx_api/openofdm_rx_api/xpu_api, for help.
|
||||
Above APIs are called by upper layer (Linux mac80211 subsystem). When they are called, the driver (sdr.c) will do necessary job via openwifi FPGA implementation. If necessary, the driver will call other component drivers, like tx_intf_api/rx_intf_api/openofdm_tx_api/openofdm_rx_api/xpu_api, for help.
|
||||
|
||||
After receiving a packet from the air, FPGA will raise interrupt (if the frame filtering rule allows) to Linux, then the function openwifi_rx_interrupt() of openwifi driver (sdr.c) will be triggered. In that function, ieee80211_rx_irqsafe() API is used to give the packet and related information (timestamp, rssi, etc) to upper layer.
|
||||
|
||||
The packet sending is initiated by upper layer. After the packet is sent by the driver over FPGA to the air, the upper layer will expect a sending report from the driver. Each time FPGA sends a packet, an interrupt will be raised to Linux and trigger openwifi_tx_interrupt(). This function will report the sending result (failed? succeeded? number of retransmissions, etc.) to upper layer via ieee80211_tx_status_irqsafe() API.
|
||||
The packet sending is initiated by upper layer towards openwifi driver. After the packet is sent by the driver over FPGA to the air, the upper layer will expect a sending report from the driver. Each time FPGA sends a packet, an interrupt will be raised to Linux and trigger openwifi_tx_interrupt(). This function will report the sending result (failed? succeeded? number of retransmissions, etc.) to upper layer via ieee80211_tx_status_irqsafe() API.
|
||||
|
||||
## sdrctl command
|
||||
|
||||
Besides the Linux native Wi-Fi control programs, such as ifconfig/iw/iwconfig/iwlist/wpa_supplicant/hostapd/etc, openwifi offers a user space tool sdrctl to access openwifi specific functionalities, such as time sharing of the interface between two network slices, you may find more details of the slicing mechanism [here](https://doc.ilabt.imec.be/ilabt/wilab/tutorials/openwifi.html#sdr-tx-time-slicing).
|
||||
Besides the Linux native Wi-Fi control programs, such as ifconfig/iw/iwconfig/iwlist/wpa_supplicant/hostapd/etc, openwifi offers a user space tool sdrctl to access openwifi specific functionalities, such as time sharing of the interface between two network slices, arbitrary Tx/Rx frequency, Tx attenuation, etc. you may find more details of the slicing mechanism [here](https://doc.ilabt.imec.be/ilabt/wilab/tutorials/openwifi.html#sdr-tx-time-slicing).
|
||||
|
||||
sdrctl is implemented as nl80211 testmode command and communicates with openwifi driver (function openwifi_testmode_cmd() in sdr.c) via Linux nl80211--cfg80211--mac80211 path
|
||||
sdrctl is implemented as nl80211 testmode command and communicates with openwifi driver (function openwifi_testmode_cmd() in sdrctl_intf.c) via Linux nl80211--cfg80211--mac80211 path
|
||||
|
||||
### Get and set a parameter
|
||||
```
|
||||
@ -72,18 +76,21 @@ tsf| sets TSF value| it requires two values "high_TSF low_TSF". Decimal
|
||||
sdrctl dev sdr0 get reg module_name reg_idx
|
||||
sdrctl dev sdr0 set reg module_name reg_idx reg_value
|
||||
```
|
||||
module_name drv_rx/drv_tx/drv_xpu refers to the corresponding driver functionality. Related registers are defined in sdr.h. Search drv_rx_reg_val/drv_tx_reg_val/drv_xpu_reg_val in sdr.c to see their functionalities.
|
||||
module_name **drv_rx**/**drv_tx**/**drv_xpu**/**rf** refers to the corresponding driver functionality. Related registers are defined in sdr.h. Search drv_rx_reg_val/drv_tx_reg_val/drv_xpu_reg_val/rf_reg_val to see their functionalities.
|
||||
|
||||
module_name rf/rx_intf/tx_intf/rx/tx/xpu refer to RF (ad9xxx front-end) and FPGA modules (rx_intf/tx_intf/openofdm_rx/openofdm_tx/xpu). Related register addresses are defined in hw_def.h and mapped to slv_regX in .v file (X is the register index). Check rx_intf/tx_intf/openofdm_rx/openofdm_tx/xpu.c and .v files to see their functionalities.
|
||||
module_name **rx_intf**/**tx_intf**/**rx**/**tx**/**xpu** FPGA modules (rx_intf/tx_intf/openofdm_rx/openofdm_tx/xpu). Related register addresses are defined in hw_def.h and mapped to slv_regX in .v file (X is the register index). Check rx_intf/tx_intf/openofdm_rx/openofdm_tx/xpu.c and .v files to see their functionalities.
|
||||
|
||||
Please be aware that some registers are set by sdr.c in real-time (instructed by Linux mac80211), so be careful when set them manually.
|
||||
module name **rf** refers to RF (ad9xxx front-end). The agent register rf_reg_val is defined in sdr.h.
|
||||
|
||||
Please be aware that some registers are set by driver in real-time (instructed by Linux mac80211), so be careful when set them manually.
|
||||
|
||||
module_name: **drv_rx** (for full list, search drv_rx_reg_val in sdr.c)
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
1|rx antenna selection|0:rx1, 1:rx2. After this command, you should down and up sdr0 by ifconfig, but not reload sdr0 driver via ./wgd.sh
|
||||
7|dmesg print control|bit0:error msg (0:OFF, 1:ON); bit1:regular msg (0:OFF, 1:ON)
|
||||
0|receiver action threshold|receiver will not react (short preamble search and further) if the signal strength is less than this threshold. N means -NdBm
|
||||
4|rx antenna selection|0:rx1, 1:rx2
|
||||
7|dmesg print control|please check Debug methods section in this page
|
||||
|
||||
(In the **comment** column, you may get a list of **decimalvalue(0xhexvalue):explanation** for a register, only use the **decimalvalue** in the sdrctl command)
|
||||
|
||||
@ -91,91 +98,132 @@ module_name: **drv_tx** (for full list, search drv_tx_reg_val in sdr.c)
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
0|override Linux rate control of tx unicast data packet|4:6M, 5:9M, 6:12M, 7:18M, 8:24M, 9:36M, 10:48M, 11:54M
|
||||
1|tx antenna selection|0:tx1, 1:tx2. After this command, you should down and up sdr0 by ifconfig, but not reload sdr0 driver via ./wgd.sh
|
||||
7|dmesg print control|bit0:error msg (0:OFF, 1:ON); bit1:regular msg (0:OFF, 1:ON)
|
||||
0|override Linux rate control of non-ht TX unicast data packet|0:auto by Linux, 4:6M, 5:9M, 6:12M, 7:18M, 8:24M, 9:36M, 10:48M, 11:54M
|
||||
1|override Linux rate control of ht TX unicast data packet|0:auto by Linux, 4:6.5M, 5:13M, 6:19.5M,7:26M, 8:39M, 9:52M, 10:58.5M, 11:65M (add 16 to these values for short GI rate)
|
||||
2|override Linux rate control of vht (11ac)|not implemented yet
|
||||
3|override Linux rate control of he (11ax)|not implemented yet
|
||||
4|tx antenna selection|0:tx1, 1:tx2
|
||||
7|dmesg print control|please check Debug methods section in this page
|
||||
|
||||
module_name: **drv_xpu** (for full list, search drv_xpu_reg_val in sdr.c)
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
7|git revision when build the driver|example: return value 0071bc74 means git revision is 071bc74 (the 1st 0 is always 0!)
|
||||
0|LBT/CCA threshold|0: automatic threshold by ad9361_rf_set_channel(). others -- N means -NdBm fixed threshold
|
||||
7|git revision when build the driver|return the git revision in hex format
|
||||
|
||||
module_name: **rf**
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
x|x|to be defined
|
||||
0|TX attenuation in dB\*1000|example: set to 3000 for 3dB attenuation
|
||||
1|TX frequency in MHz|example: set to 5000 for 5GHz -- override Linux channenl tuning/control
|
||||
5|RX frequency in MHz|example: set to 4000 for 4GHz -- override Linux channenl tuning/control
|
||||
|
||||
module_name: **rx_intf** (for full list, check rx_intf.c and **slv_reg** in rx_intf.v)
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
0|reset|each bit is connected to rx_intf.v internal sub-module. 1 -- reset; 0 -- normal
|
||||
1|trigger for ILA debug|bit4 and bit0. Please check slv_reg1 in rx_intf.v
|
||||
2|enable/disable rx interrupt|256(0x100):disable, 0:enable
|
||||
3|get loopback I/Q from tx_intf|256(0x100):from tx_intf, 0:from ad9361 ADC
|
||||
4|baseband clock and IQ fifo in/out control|no use anymore -- for old bb rf independent mode
|
||||
5|control/config dma to cpu|check rx_intf.v slv_reg5
|
||||
6|abnormal packet length threshold|bit31-16 to store the threshold. if the packet length is not in the range of 14 to threshold, terminate the dma to cpu
|
||||
7|source selection of rx dma to cpu|check rx_intf.v slv_reg7
|
||||
8|reserved|reserved
|
||||
9|number of dma symbol to cpu|only valid in manual mode (slv_reg5[5]==1). normally the dma is set automatically by the received packet length
|
||||
10|rx adc fifo reading control|check rx_intf.v slv_reg10
|
||||
11|rx digital I/Q gain|number of bit shift to left. default 4 in rx_intf.c: rx_intf_api->RX_INTF_REG_BB_GAIN_write(4)
|
||||
13|delay from RX DMA complete to RX packet interrupt|unit 0.1us
|
||||
16|rx antenna selection|0:ant0, 1:ant1. default 0 in rx_intf.c: rx_intf_api->RX_INTF_REG_ANT_SEL_write(ant_sel)
|
||||
12|timeout/reset control of dma to cpu|check rx_intf.v slv_reg12
|
||||
13|delay from RX DMA complete to RX packet interrupt to cpu|unit 0.1us
|
||||
16|rx antenna selection|0:ant0, 1:ant1. default 0
|
||||
|
||||
module_name: **tx_intf** (for full list, check tx_intf.c and **slv_reg** in tx_intf.v)
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
1|DUC config|tx_intf_api->TX_INTF_REG_MIXER_CFG_write(mixer_cfg) in tx_intf.c and openwifi-hw/ip/mixer_duc/src/mixer_duc.cpp
|
||||
4|CTS to Self config|auto set by cts_reg in openwifi_tx of sdr.c. bit31: enable/disable, bit30: rate selection: 1: use traffic rate, 0: manual rate in bit7-4, bit23-8: duration
|
||||
0|reset|each bit is connected to tx_intf.v internal sub-module. 1 -- reset; 0 -- normal
|
||||
1|DUC config or tx arbitrary IQ write port|DUC is removed already. Now it is used to write arbitrary IQ to tx_intf for test purpose
|
||||
2|phy tx auto start config|check tx_intf.v slv_reg2
|
||||
4|CTS to Self config|auto set by cts_reg in openwifi_tx of sdr.c. bit31: enable/disable, bit30: rate selection: 1: use traffic rate, 0: manual rate in bit7-4, bit23-8: duration field
|
||||
5|csi fuzzer config|check CSI fuzzer app note
|
||||
6|CTS to Self sending delay (for SIFS)|unit 0.1us. bit13-0 for 2.4GHz, bit29-16 for 5GHz
|
||||
7|tx arbitrary IQ config|check tx_intf.v slv_reg7
|
||||
8|tx config per packet|automatically set per packet in openwifi_tx() via tx_intf_api->TX_INTF_REG_TX_CONFIG_write(tx_config)
|
||||
9|reserved|reserved
|
||||
10|dac input and dma control|check tx_intf.v slv_reg10
|
||||
11|threshold for FPGA fifo almost full|driver(sdr.c) read 1bit flag in slv_reg21 (4bit in total for 4 queue) to know the FPGA fifo/queue is almost full.
|
||||
12|threshold to pause openofdm_tx|back pressure flow control for I/Q generation speed of openofdm_tx
|
||||
13|tx I/Q digital gain before DUC|current optimal value: 100
|
||||
14|enable/disable tx interrupt|196612(0x30004):disable, 4:enable
|
||||
16|tx antenna selection|1:ant0, 2:ant1. default 1 in tx_intf.c: tx_intf_api->TX_INTF_REG_ANT_SEL_write(ant_sel)
|
||||
12|threshold to pause openofdm_tx|unit: number of sample. back pressure flow control for I/Q generation speed of openofdm_tx
|
||||
13|tx I/Q digital gain before dac|find the optimal value (and test record) in tx_intf.c: tx_intf_api->TX_INTF_REG_BB_GAIN_write
|
||||
14|tx interrupt config|196612(0x30004):disable, 4:enable. check tx_intv.v slv_reg14
|
||||
15|ampdu action config|set automatically in driver (sdr.c) by openwifi_ampdu_action()
|
||||
16|tx antenna selection and cdd control|bit1: 0 or 1 to select ant0 or 1. bit4: 1 to enable simple cdd (two antennas have 1 sample tx delay)
|
||||
17|phy config per packet|aggregation/rate/GI/ht/non-ht/etc. automatically set by driver tx_intf_api->TX_INTF_REG_PHY_HDR_CONFIG_write(phy_hdr_config)
|
||||
21|queue almost full flag|4bit for 4 queue. criteria is the threshold in slv_reg11. check by tx_intf_api->TX_INTF_REG_S_AXIS_FIFO_NO_ROOM_read() in sdr.c
|
||||
22|tx status0 per pkt sent|cw,num_slot_random,linux_prio,tx_queue_idx,bd_wr_idx,num_retrans -- per pkt info read by tx interrupt after the pkt sent
|
||||
23|tx status1 per pkt sent|blk_ack_resp_ssn, pkt_cnt -- per pkt info read by tx interrupt after the pkt sent
|
||||
24|tx status2 per pkt sent|blk_ack_bitmap_low -- per pkt info read by tx interrupt after the pkt sent
|
||||
25|tx status3 per pkt sent|blk_ack_bitmap_high -- per pkt info read by tx interrupt after the pkt sent
|
||||
26|FPGA tx queue runtime length|bit6-0: queue0; bit14-8: queue1; bit22-16: queue2; bit30-24: queue3
|
||||
|
||||
module_name: **rx** (for full list, check openofdm_rx.c and **slv_reg** in openofdm_rx.v)
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
2|power trigger threshold|default 0. openofdm_rx.c: openofdm_rx_api->OPENOFDM_RX_REG_POWER_THRES_write(0)
|
||||
3|minimum plateau used for short preamble detection|default 100. openofdm_rx.c: openofdm_rx_api->OPENOFDM_RX_REG_MIN_PLATEAU_write(100)
|
||||
4|soft or hard decision for viterbi decoder|0:hard, 1:soft. default 1. openofdm_rx.c: openofdm_rx_api->OPENOFDM_RX_REG_SOFT_DECODING_write(1)
|
||||
0|reset|each bit is connected to openofdm_rx.v internal sub-module. 1 -- reset; 0 -- normal
|
||||
1|channel estimation subcarrier smoothing control|bit0: 1--force smoothing; 0--auto by ht header. bit4: 1--disable all smoothing; 0--let bit0 decide
|
||||
2|power trigger and dc detection threshold|bit10-0: signal level below this threshold won't trigger demodulation. the unit is rssi_half_db, check rssi_half_db_to_rssi_dbm()/rssi_dbm_to_rssi_half_db() in sdr.c to see the relation to rssi dBm. bit23-16: threshold to prevent dc (or low frequency interference) triggered demodulation
|
||||
3|minimum plateau used for short preamble detection|initialized by openofdm_rx.c: openofdm_rx_api->OPENOFDM_RX_REG_MIN_PLATEAU_write
|
||||
4|soft decoding flag and abnormal packet length threshold|bit0 for soft decoding: 0 -- hard, 1 -- soft. bit31-16: if the packet length is not in the range of 14 to this threshold, terminate demodulation.
|
||||
20|history of PHY rx state|read only. If the last digit readback is always 3, it means the Viterbi decoder stops working
|
||||
31|git revision when build the receiver|returned register value means git revision in hex format
|
||||
|
||||
module_name: **tx** (for full list, check openofdm_tx.c and **slv_reg** in openofdm_tx.v)
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
1|pilot scrambler initial state|lowest 7 bits are used. 0x7E by default in openofdm_tx.c
|
||||
2|data scrambler initial state|lowest 7 bits are used. 0x7F by default in openofdm_tx.c
|
||||
0|reset|each bit is connected to openofdm_tx.v internal sub-module. 1 -- reset; 0 -- normal
|
||||
1|pilot scrambler initial state|lowest 7 bits are used. 127(0x7F) by default in openofdm_tx.c
|
||||
2|data scrambler initial state|lowest 7 bits are used. 127(0x7F) by default in openofdm_tx.c
|
||||
20|reserved|reserved
|
||||
|
||||
module_name: **xpu** (for full list, check xpu.c and **slv_reg** in xpu.v)
|
||||
|
||||
reg_idx|meaning|comment
|
||||
-------|-------|----
|
||||
1|mute rx I/Q when tx|0:mute when tx, 1:unmute, which means rx baseband will receive tx signal from its own. Rx packet and tx packet (such as ACK) can be monitored in FPGA for timing analysis
|
||||
0|reset|each bit is connected to xpu.v internal sub-module. 1 -- reset; 0 -- normal
|
||||
1|rx packet and I/Q config when tx|bit0 0: auto control (auto self-rx-IQ-mute when tx), 1:manual control by bit31 (1 self-IQ-mute; 0 unmute). bit2 0: rx packet filtering is configured by Linux, 1: no rx packet filtering, send all to Linux
|
||||
2|TSF timer low 32bit write|only write this register won't trigger the TSF timer reload. should use together with register for high 31bit
|
||||
3|TSF timer high 31bit write|falling edge of MSB will trigger the TSF timer reload, which means write '1' then '0' to MSB
|
||||
4|band, channel and ERP short slot setting|see enum/define in hw_def.h. set automatically by Linux. manual set will be overrided unless you change sdr.c
|
||||
5|DIFS and backoff advance (us)|advance (us) for tx preparation before the end of DIFS/backoff. bit7-0:DIFS advance, bit15-8: backoff advance
|
||||
6|forced idle, CSMA settings|bit7-0: forced channel idle (us) after decoding done to avoid false alarm caused by strong "AGC tail" signal. bit31: NAV enable, bit30: DIFS enable, bit29: EIFS enable, bit28: dynamic CW enable (when disable, CW is taken from bit3-0 of register 19)
|
||||
7|some RSSI and delay setting|please check xpu.v (search slv_reg7)
|
||||
8|RSSI threshold for channel idle/busy|set by ad9361_rf_set_channel --> xpu_api->XPU_REG_LBT_TH_write
|
||||
9|some time setting|bit31 0:auto, 1:manual. When manual, bit6-0: PHY rx delay, bit13-7: SIFS, bit18-14: slot time, bit23-19: ofdm symbol time, bit30-24: preamble+SIG time. unit us. check xpu.v (search slv_reg9)
|
||||
10|BB RF delay setting|bit7-0: BB RF delay (0.1us), bit11-8: RF end extended time (0.1us). check xpu.v (search slv_reg10)
|
||||
11|ACK control and max num retransmission|bit4: 0:normal ACK, 1:disable auto ACK reply in FPGA. bit3-0: 0: the number of retransmission is decided by Linux, non-zero: Linux auto setting about num of retransmission will be replaced by this value
|
||||
16|setting when wait for ACK in 2.4GHz|unit 0.1us. bit14-0: OFDM decoding timeout (after detect PHY header), bit30-16: timeout for PHY header detection, bit31: 0: FCS valid is not needed for ACK packet, 1: FCS valid is needed for ACK packet
|
||||
17|setting when wait for ACK in 5GHz|unit 0.1us. bit14-0: OFDM decoding timeout (after detect PHY header), bit30-16: timeout for PHY header detection, bit31: 0: FCS valid is not needed for ACK packet, 1: FCS valid is needed for ACK packet
|
||||
3|TSF timer high 31bit write|falling edge of register MSB will trigger the TSF timer reload, which means write '1' then '0' to bit31 (bit30-0 for TSF)
|
||||
4|band, channel and ERP short slot setting|for CSMA engine config. set automatically by Linux. manual set could be overrided unless you change sdr.c
|
||||
5|DIFS and backoff advance (us), abnormal pkt length threshold|advance (us) for tx preparation before the end of DIFS/backoff. bit7-0:DIFS advance, bit15-8: backoff advance. bit31-16: if the packet length is not in the range of 14 to this threshold, terminate pkt filtering procedure
|
||||
6|multi purpose CSMA settings|bit7-0: forced channel idle (us) after decoding done to avoid false alarm caused by strong "AGC tail" signal. bit31: NAV disable, bit30: DIFS disable, bit29: EIFS disable, bit28: dynamic CW disable (when disable, CW is taken from bit19-16). (value 1 -- forced disable; 0 -- normal/enable)
|
||||
7|RSSI and ad9361 gpio/gain delay setting (sync with IQ rssi)|bit26-16: offset for rssi report to Linux; bit6-0 delay (number of sample) of ad9361 gpio/gain to sync with IQ sample rssi/amplitude
|
||||
8|RSSI threshold for CCA (channel idle/busy)|set by ad9361_rf_set_channel automatically. the unit is rssi_half_db, check rssi_half_db_to_rssi_dbm()/rssi_dbm_to_rssi_half_db() in sdr.c to see the relation to rssi dBm
|
||||
9|some low MAC time setting|bit31 0:auto, 1:manual. When manual, bit6-0: PHY rx delay, bit13-7: SIFS, bit18-14: slot time, bit23-19: ofdm symbol time, bit30-24: preamble+SIG time. unit us. check xpu.v (search slv_reg9)
|
||||
10|BB RF delay setting|unit 0.1us. bit7-0: BB RF delay, bit14-8: RF end extended time on top of the delay. bit22-16: delay between bb tx start to RF tx on (lo or port control via spi). bit30-24: delay between bb tx end to RF tx off. check xpu.v (search slv_reg10)
|
||||
11|ACK control and max num retransmission|bit4: 0:normal ACK, 1:disable auto ACK reply in FPGA. bit3-0: if bit3==0, the number of retransmission is decided by Linux. if bit3==1, the max num retransmission is taken from bit2-0
|
||||
12|AMPDU control|bit0: indicate low MAC start to receive AMPDU. bit4-1: tid. bit31: tid enable (by default, tid is not enabled and we decode AMPDU of all tid)
|
||||
13|spi controller config|1: disable spi control and Tx RF is always on; 0: enable spi control and Tx RF only on (lo/port) when pkt sending
|
||||
16|setting when wait for ACK in 2.4GHz|unit 0.1us. bit14-0: OFDM decoding timeout (after detect PHY header), bit30-16: timeout for PHY header detection, bit31: 0: FCS valid is not needed for ACK packet, 1: FCS valid is needed for ACK packet
|
||||
17|setting when wait for ACK in 5GHz|unit 0.1us. bit14-0: OFDM decoding timeout (after detect PHY header), bit30-16: timeout for PHY header detection, bit31: 0: FCS valid is not needed for ACK packet, 1: FCS valid is needed for ACK packet
|
||||
18|setting for sending ACK|unit 0.1us. bit14-0: ACK sending delay in 2.4GHz, bit30-16: ACK sending delay in 5GHz
|
||||
19|CW min and max setting for 4 FPGA queues|bit3-0: CW min for queue 0, bit7-4: CW max for queue 0, bit11-8: CW min for queue 1, bit15-12: CW max for queue 1, bit19-16: CW min for queue 2, bit23-20: CW max for queue 2, bit27-24: CW min for queue 3, bit31-28: CW max for queue 3. automatically set by openwifi_conf_tx of sdr.c
|
||||
19|CW min and max setting for 4 FPGA queues|bit3-0: CW min for queue 0, bit7-4: CW max for queue 0, bit11-8: CW min for queue 1, bit15-12: CW max for queue 1, bit19-16: CW min for queue 2, bit23-20: CW max for queue 2, bit27-24: CW min for queue 3, bit31-28: CW max for queue 3. automatically decided by Linux via openwifi_conf_tx of sdr.c
|
||||
20|slice/queue-tx-gate total cycle length|bit21-20: queue selection. bit19-0: total cycle length in us
|
||||
21|slice/queue-tx-gate start time in the cycle|bit21-20: queue selection. bit19-0: start time in us
|
||||
22|slice/queue-tx-gate end time in the cycle|bit21-20: queue selection. bit19-0: end time in us
|
||||
26|CTS to RTS setting|bit15-0: extra duration, bit20-16: rate/MCS, bit31: 0:enable CTStoRTS 1:disable CTStoRTS
|
||||
27|FPGA packet filter config|check openwifi_configure_filter in sdr.c. also [mac80211 frame filtering](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#frame-filtering)
|
||||
27|FPGA packet filter config|bit13-0 passing/filter config. bit24-16 dropping config. check openwifi_configure_filter in sdr.c. also [mac80211 frame filtering](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#frame-filtering)
|
||||
28|BSSID address low 32bit for BSSID filtering|auto set by xpu_api->XPU_REG_BSSID_FILTER_LOW_write in openwifi_bss_info_changed of sdr.c
|
||||
29|BSSID address high 32bit for BSSID filtering|auto set by xpu_api->XPU_REG_BSSID_FILTER_HIGH_write in openwifi_bss_info_changed of sdr.c
|
||||
29|BSSID address high 16bit for BSSID filtering|auto set by xpu_api->XPU_REG_BSSID_FILTER_HIGH_write in openwifi_bss_info_changed of sdr.c
|
||||
30|MAC address low 32bit|auto set by XPU_REG_MAC_ADDR_write in sdr.c
|
||||
31|MAC address high 32bit|auto set by XPU_REG_MAC_ADDR_write in sdr.c
|
||||
31|MAC address high 16bit|auto set by XPU_REG_MAC_ADDR_write in sdr.c
|
||||
37|addr2 of rx packet read back|bit31-0 are from bit47-16 of addr2 field in the received packet
|
||||
58|TSF runtime value low 32bit|read only
|
||||
59|TSF runtime value high 32bit|read only
|
||||
63|git revision when build the FPGA|example: return value 065272ac means git revision is 65272ac (the 1st 0 is always 0)
|
||||
63|git revision when build the FPGA|returned register value means git revision in hex format
|
||||
|
||||
## Rx packet flow and filtering config
|
||||
|
||||
@ -183,7 +231,7 @@ After FPGA receives a packet, no matter the FCS/CRC is correct or not it will ra
|
||||
|
||||
- frame filtering
|
||||
|
||||
The FPGA frame filtering configuration is done in real-time by function openwifi_configure_filter() in sdr.c. The filter_flag together with **HIGH_PRIORITY_DISCARD_FLAG** finally go to pkt_filter_ctl.v of xpu module in FPGA, and control how FPGA does frame filtering. Openwifi has the capability to capture all received packets even if the CRC is bad. You just need to set the NIC to monitor mode by iwconfig command (check monitor_ch.sh in user_space directory). In monitor mode, all received packets (including ACK) will be given to Linux mac80211.
|
||||
The FPGA frame filtering configuration is done by function openwifi_configure_filter() in sdr.c. The filter_flag together with **HIGH_PRIORITY_DISCARD_FLAG** finally go to pkt_filter_ctl.v of xpu module in FPGA, and control how FPGA does frame filtering. Openwifi has the capability to capture all received packets even if the CRC is wrong. You just need to set the NIC to monitor mode by iwconfig command (check monitor_ch.sh in user_space directory). In monitor mode, all received packets (including control packet, like ACK) will be given to Linux mac80211.
|
||||
|
||||
- main rx interrupt operations in openwifi_rx_interrupt()
|
||||
- get raw content from DMA buffer. When Linux receives interrupt from FPGA rx_intf module, the content has been ready in Linux DMA buffer
|
||||
@ -192,7 +240,7 @@ The FPGA frame filtering configuration is done in real-time by function openwifi
|
||||
- raw RSSI value that will be converted to actual RSSI in dBm by different correction in different bands/channels
|
||||
- packet length and MCS
|
||||
- FCS is valid or not
|
||||
- send packet content and necessary extra information to upper layer via ieee80211_rx_irqsafe()
|
||||
- send packet pointer (skb) and necessary extra information to upper layer via ieee80211_rx_irqsafe()
|
||||
|
||||
## Tx packet flow and config
|
||||
|
||||
@ -202,28 +250,27 @@ Linux mac80211 subsystem calls openwifi_tx() to initiate a packet sending.
|
||||
- get necessary information from the packet header (struct ieee80211_hdr) for future FPGA configuration
|
||||
- packet length and MCS
|
||||
- unicast or broadcast? does it need ACK? how many retransmissions at most are allowed to be tried by FPGA in case ACK is not received in time?
|
||||
- which queue (time slice) in FPGA the packet should go?
|
||||
- which driver-ring/queue (time slice) in FPGA the packet should go?
|
||||
- should RTS-CTS be used? (Send RTS and wait for CTS before actually send the data packet)
|
||||
- should CTS-to-self be used? (Send CTS-to-self packet before sending the data packet. You can force this on by force_use_cts_protect = true;)
|
||||
- should a sequence number be inserted?
|
||||
- generate SIGNAL field according to length and MCS information. Insert it before the packet for the future openofdm_tx FPGA module use
|
||||
- maintain sequence number (ring->bd_wr_idx) for internal use (cross check between Linux and FPGA)
|
||||
- config FPGA register according to the above information to help FPGA do correct actions according to the packet specific requirement.
|
||||
- fire DMA transmission from Linux to one of FPGA tx queues. The packet may not be sent immediately if there are still some packets in FPGA tx queue (FPGA does the queue packet transmission according to channel and low MAC state)
|
||||
- should a sequence number be inserted to the packet at the driver/chip level?
|
||||
- maintain sequence number (ring->bd_wr_idx) for internal use (cross check between FPGA, openwifi_tx and openwifi_tx_interrupt)
|
||||
- config FPGA register according to the above information to help FPGA do correct actions (generate PHY header, etc) according to the packet specific requirement.
|
||||
- fire DMA transmission from Linux to one of FPGA tx queues. The packet may not be sent immediately if there are still some packets in FPGA tx queue (FPGA does the queue packet transmission according to channel and low MAC CSMA state)
|
||||
|
||||
Each time when FPGA sends a packet, an interrupt will be raised to Linux reporting the packet sending result. This interrupt handler is openwifi_tx_interrupt().
|
||||
|
||||
- main operations in openwifi_tx_interrupt()
|
||||
- get necessary information/status of the packet just sent by FPGA
|
||||
- packet length and sequence number to capture abnormal situation (cross checking between Linux and FPGA)
|
||||
- packet length and sequence number to capture abnormal situation (cross checking between FPGA, openwifi_tx and openwifi_tx_interrupt)
|
||||
- packet sending result: packet is sent successfully (FPGA receives ACK for this packet) or not. How many retransmissions have been done (in case FPGA doesn't receive ACK in time, FPGA will do retransmission according to CSMA/CA low MAC state)
|
||||
- send above information to upper layer (Linux mac80211 subsystem) via ieee80211_tx_status_irqsafe()
|
||||
|
||||
## Regulation and channel config
|
||||
|
||||
SDR is a powerful tool for research. It is the user's responsibility to align with local spectrum regulation.
|
||||
SDR is a powerful tool for research. It is the user's responsibility to align with local spectrum regulation when doing OTA (Over The Air) test, or do the test via cable (conducted test), or in a chamber to avoid any potential interference.
|
||||
|
||||
This section explains how openwifi config the frequency/channel range and change it in real-time. After knowing the mechanism, you can try to extend frequency/channel by yourself.
|
||||
This section explains how openwifi config the frequency/channel range and change it driven by Linux. The frequency overriding method is also offered by openwifi to allow the system working in any frequency in 70MHz-6GHz.
|
||||
|
||||
### Frequency range
|
||||
|
||||
@ -233,14 +280,13 @@ dev->wiphy->regulatory_flags = xxx
|
||||
wiphy_apply_custom_regulatory(dev->wiphy, &sdr_regd);
|
||||
```
|
||||
sdr_regd is the predefined variable in sdr.h. You can search the definition/meaning of its type: struct ieee80211_regdomain.
|
||||
Then it is not difficult to find out how to change the frequency range in SDR_2GHZ_CH01_14 and SDR_5GHZ_CH36_64.
|
||||
|
||||
### Supported channel
|
||||
|
||||
The supported channel list is defined in openwifi_2GHz_channels and openwifi_5GHz_channels in sdr.h. If you change the number of supported channels, make sure you also change the frequency range in sdr_regd accordingly and also array size of the following two fields in the struct openwifi_priv:
|
||||
```
|
||||
struct ieee80211_channel channels_2GHz[14];
|
||||
struct ieee80211_channel channels_5GHz[11];
|
||||
struct ieee80211_channel channels_5GHz[53];
|
||||
```
|
||||
Finally, the supported channel list is transferred to Linux mac80211 when openwifi driver is loaded by following two lines in openwifi_dev_probe():
|
||||
```
|
||||
@ -248,27 +294,48 @@ dev->wiphy->bands[NL80211_BAND_2GHZ] = &(priv->band_2GHz);
|
||||
dev->wiphy->bands[NL80211_BAND_5GHZ] = &(priv->band_5GHz);
|
||||
```
|
||||
|
||||
### Real-time channel setting
|
||||
### Real-time channel setting and restrict the channel
|
||||
|
||||
Linux mac80211 (struct ieee80211_ops openwifi_ops in sdr.c) uses the "config" API to configure channel frequency and some other parameters in real-time (such as during scanning or channel setting by iwconfig). It is hooked to openwifi_config() in sdr.c, and supports only frequency setting currently. The real execution of frequency setting falls to ad9361_rf_set_channel() via the "set_chan" field of struct openwifi_rf_ops ad9361_rf_ops in sdr.c. Besides tuning RF front-end (AD9361), the ad9361_rf_set_channel() also handles RSSI compensation for different frequencies and FPGA configurations (SIFS, etc) for different bands.
|
||||
Linux mac80211 (struct ieee80211_ops openwifi_ops in sdr.c) uses the "config" API to configure channel frequency and some other parameters in real-time (such as during scanning or channel setting by iwconfig). It is hooked to openwifi_config() in sdr.c, and supports only frequency setting currently. The real execution of frequency setting falls to ad9361_rf_set_channel() via the "set_chan" field of struct openwifi_rf_ops ad9361_rf_ops in sdr.c. Besides tuning RF front-end (AD9361), the ad9361_rf_set_channel() also handles AD9361 calibration (if the tuning step size >= 100MHz), RSSI compensation for different frequencies and FPGA configurations (SIFS, etc) for different bands.
|
||||
|
||||
If you don't want openwifi node to change the channel anymore (even the Linux asks to do so), use the script user_space/set_restrict_freq.sh to limit the frequency.
|
||||
```
|
||||
./set_restrict_freq abcd
|
||||
```
|
||||
Above will limit the frequency to abcdMHz. For instance, after you setup the working system in channel 44 and you don't want the node to tune to other channel (occasionally driven by Linux scanning for example), input 5220 as argument to the script.
|
||||
```
|
||||
./set_restrict_freq 0
|
||||
```
|
||||
Above will remove the limitation. Linux driven channel tuning will be recovered.
|
||||
|
||||
### Let openwifi work at arbitrary frequency
|
||||
|
||||
Before setting a non-WiFi frequency to the system, a normal working system should be setup in normal WiFi frequency. After this, you can set it to any frequency in 70MHz-6GHz.
|
||||
```
|
||||
./sdrctl dev sdr0 set reg rf 1 3500
|
||||
```
|
||||
Above will set the Tx frequency to 3.5GHz.
|
||||
|
||||
```
|
||||
./sdrctl dev sdr0 set reg rf 5 3500
|
||||
```
|
||||
Above will set the Rx frequency to 3.5GHz.
|
||||
|
||||
## Analog and digital frequency design
|
||||
|
||||
Following figure shows the current openwifi analog and digital frequency design strategy. The Tx RF center frequency is tuned with 10MHz offset deliberately to ease Tx Lo leakage suppressed by Rx filter. This RF offset is pre-compensated by Tx DUC (Digital Up Converter) in FPGA (duc_bank_core.bd used by tx_intf.v). It combines AD9361's bandwidth, frequency, sampling rate and FPGA's digital up converter (duc_bank_core.bd) setting to achieve this example spectrum arrangement. Values in the figure are configurable in the openwifi design.
|
||||
![](./rf-digital-if-chain-spectrum.jpg)
|
||||
|
||||
Above spectrum setting has two benefits:
|
||||
- The Tx Lo leakage is suppressed by Rx filter
|
||||
- The centered Rx Lo leads to more easy/accurate RSSI estimation in FPGA (together with real-time AD9361 AGC gain value accessed via FPGA GPIO)
|
||||
Openwifi has adopted a new RF/baseband frequency and sampling design instead of the original "offset tuning" to achieve better EVM, spectrum mask conformance, sensitivity and RSSI measurement accuracy. The AD9361 is set to FDD working mode with the same Tx and Rx frequency. Realtime AD9361 Tx chain control is done via FPGA SPI interface (openwifi-hw/ip/xpu/src/spi.v) to achieve self-interference free (when Rx) and fast Tx/Rx turn around time (0.6us). The AD9361 Tx lo (local oscillator) or RF switch is turned on before the Tx packet and turned off after the Tx packet. so that there isn't any Tx lo noise leakage during Rx period. The IQ sampling rate between AD9361 and FPGA is 40Msps. It is converted to 20Msps via decimation/interpolation inside FPGA to WiFi baseband transceiver.
|
||||
|
||||
Following figure shows the detailed configuration point in AD9361, driver (.c file) and related FPGA modules (.v file).
|
||||
![](./rf-digital-if-chain-config.jpg)
|
||||
|
||||
The openwifi FPGA baseband clock is driven by AD9361 clock, so there won't be any clock drifting/slight-mismatching between RF and baseband as shown in the following picture.
|
||||
![](./bb-clk.jpg)
|
||||
|
||||
## Debug methods
|
||||
|
||||
### dmesg
|
||||
|
||||
To debug/see the basic driver behaviour, you could turn on **dmesg** message printing by
|
||||
To debug/see the basic driver behaviour via printk in the sdr.c, you could turn on **dmesg** message printing by
|
||||
```
|
||||
./sdrctl dev sdr0 set reg drv_tx 7 X
|
||||
./sdrctl dev sdr0 set reg drv_rx 7 X
|
||||
@ -277,6 +344,7 @@ The bit in value X controls what type of information will be printed to the dmes
|
||||
bit0: error message
|
||||
bit1: regular message for unicast packet (openwifi_tx/openwifi_tx_interrupt/openwifi_rx_interrupt)
|
||||
bit2: regular message for broadcast packet
|
||||
bit3: regular queue stop/wake-up message due to too much traffic
|
||||
|
||||
For example, regular message for unicast packet and error message
|
||||
./sdrctl dev sdr0 set reg drv_tx 7 3
|
||||
@ -290,53 +358,70 @@ and use **dmesg** command in Linux to see those messages. Regular printing inclu
|
||||
|
||||
### tx printing example
|
||||
```
|
||||
sdr,sdr openwifi_tx: 1410bytes ht0 540M FC0208 DI002c addr1/2/3:2ec08902fdb2/6655443322ad/6655443322ad SC2100 flag40000012 retr6 ack1 prio2 q2 wr44 rd31
|
||||
sdr,sdr openwifi_tx: 70B RC0 10M FC0040 DI0000 ADDRffffffffffff/6655443322aa/ffffffffffff flag4001201e QoS00 SC20_1 retr1 ack0 prio0 q0 wr19 rd18
|
||||
```
|
||||
- printing from sdr driver, openwifi_tx function
|
||||
- 1410bytes: packet size (length field in SIGNAL)
|
||||
- ht0: non-ht means 11a/g; ht1 means 11n
|
||||
- 54M: MCS (rate field in SIGNAL)
|
||||
- FC0208: Frame Control field, which means type data, subtype data, to DS 0, from DS 1 (a packet from AP to client)
|
||||
- DI002c: Duration/ID field 0x002c. How many us this packet will occupy the channel (including waiting for ACK)
|
||||
- addr1/2/3: address fields. Target MAC address 2ec08902fdb2, source MAC address 6655443322ad (openwifi)
|
||||
- SC2100: Sequence Control, which means that the driver inserts sequence number 0x2100 to the packet under request of Linux mac80211
|
||||
- flag40000012: flags field from Linux mac80211 struct ieee80211_tx_info (first fragment? need ACK? need sequence number insertion? etc.)
|
||||
- retry6: Linux mac80211 tells driver the maximum number of transmissions for this packet is 6
|
||||
- ack1: Linux mac80211 tells driver this packet needs ACK
|
||||
- prio2: Linux select priority queue 2 for this packet (0:VO voice, 1:VI video, 2:BE best effort and 3:BK background)
|
||||
- q2: the packet goes to FPGA queue 2. (You can change the mapping between Linux priority and FPGA queue in sdr.c)
|
||||
- wr44 rd31: the write/read index of buffer (shared buffer between the active openwifi_tx and background openwifi_tx_interrupt/FPGA)
|
||||
- 70B: packet size (length field in SIGNAL)
|
||||
- RC0: rate of the packet. enum mac80211_rate_control_flags in Linux kernel mac80211.h
|
||||
- 10M: rate 1Mbps. This 802.11b rate will be converted to 6Mbps, because openwifi supports only OFDM rate.
|
||||
- FC0040: Frame Control field. Example: FC0208 means type data, subtype data, to DS 0, from DS 1 (a packet from AP to client)
|
||||
- DI0000: Duration/ID field
|
||||
- ADDR: address fields addr1/2/3. Target MAC address ffffffffffff (broadcast), source MAC address 6655443322aa (openwifi)
|
||||
- flag4001201e: flags field from Linux mac80211 struct ieee80211_tx_info (first fragment? need ACK? need sequence number insertion? etc.)
|
||||
- QoS00: QoS control byte related to the packet (from Linux mac80211)
|
||||
- SC20_1: sequence number 20 is set to the header of the packet. 1 means that it is set by driver (under request of Linux mac80211)
|
||||
- retr1: retr1 means no retransmission is needed. retr6 means the maximum number of transmissions for this packet is 6 (set by Linux mac80211)
|
||||
- ack0: ack0 means the packet doesn't need ACK; ack1 means the packet needs ACK. (set by Linux mac80211)
|
||||
- prio0: priority queue 0 for this packet (0:VO voice, 1:VI video, 2:BE best effort and 3:BK background). check prio in openwifi_tx() of sdr.c (set by Linux mac80211)
|
||||
- q0: the packet goes to FPGA queue 0. (You can change the mapping between Linux priority and FPGA queue in sdr.c)
|
||||
- wr19 rd18: the write/read index of buffer (shared buffer between the active openwifi_tx and background openwifi_tx_interrupt/FPGA)
|
||||
|
||||
### tx interrupt printing example
|
||||
```
|
||||
sdr,sdr openwifi_tx_interrupt: tx_result 02 prio2 wr28 rd25 num_rand_slot 21 cw 6
|
||||
sdr,sdr openwifi_tx_interrupt: tx_result [nof_retx 1 pass 1] SC20 prio0 q0 wr20 rd19 num_slot0 cw0 hwq len00000000 no_room_flag0
|
||||
```
|
||||
- printing from sdr driver, openwifi_tx_interrupt function
|
||||
- tx_result: 5bit, bit3~0 tells how many tx attempts are made on this packet, and bit4 indicates NO ACK (1) or an ACK (0) is received
|
||||
- prio, wr, rd: these fields can be interpreted the same way as the print in openwifi_tx function
|
||||
- num_rand_slot: tells how many slots the CSMA/CA state machine waited until the packet is sent in the last tx attempt
|
||||
- tx_result [nof_retx 1 pass 1]: nof_retx 1 means the total number of transmission is 1. pass 1 indicates ACK is received. (0 means not)
|
||||
- SC20: sequence number 20
|
||||
- prio, q, wr, rd: these fields can be interpreted the same way as the print in openwifi_tx function
|
||||
- num_slot: tells how many slots the CSMA/CA state machine waited until the packet is sent in the last tx attempt
|
||||
- cw: the exponent of the Contention Window for this packet. 6 means the CW size 64. If the contention phase is never entered, CW is 0
|
||||
|
||||
- hwq len: the current FPGA queue length (number of pkt left in the queue).8bit per queue. see tx_intf register 26 (https://github.com/open-sdr/openwifi/blob/master/doc/README.md)
|
||||
- no_room_flag: the DMA room of FPGA queue is almost run out. 1bit per queue. see tx_intf register 21 (https://github.com/open-sdr/openwifi/blob/master/doc/README.md)
|
||||
|
||||
### rx printing example
|
||||
```
|
||||
sdr,sdr openwifi_rx_interrupt: 796bytes ht0 120M FC0108 DI0030 addr1/2/3:6655443322f4/2ec08902fdb2/6655443322f4 SC4760 fcs1 buf_idx13 -50dBm
|
||||
sdr,sdr openwifi_rx: 270B ht0aggr0/0 sgi0 240M FC0080 DI0000 ADDRffffffffffff/00c88b113f5f/00c88b113f5f SC2133 fcs1 buf_idx10 -78dBm
|
||||
```
|
||||
- printing from sdr driver, openwifi_rx_interrupt function
|
||||
- 796bytes: packet size (length field in SIGNAL)
|
||||
- ht0: non-ht means 11a/g; ht1 means 11n
|
||||
- 12M: MCS (rate field in SIGNAL)
|
||||
- FC0108: Frame Control field 0x0108, which means type data, subtype data, to DS 1, from DS 0 (a packet client to openwifi AP)
|
||||
- DI0030: Duration/ID field 0x0030. How many us this packet will occupy the channel (including waiting for ACK)
|
||||
- addr1/2/3: address fields. Target MAC address 6655443322f4 (openwifi), source MAC address 2ec08902fdb2
|
||||
- SC4760: Sequence Control, which means that the packet includes sequence number 0x4760 (under request of upper layer of the peer)
|
||||
- 270B: packet size (length field in SIGNAL)
|
||||
- ht0: ht0 means 11a/g (legacy); ht1 means 11n (ht)
|
||||
- aggr0/0: the 1st digit means the packet is from a AMPDU packet (1) or not (0). the 2nd digit means the packet is the last packet of a AMPDU packet (1) or not (0)
|
||||
- sgi0: 0 means normal GI (Guard Interval); 1 means short GI
|
||||
- 240M: rate 24Mbps
|
||||
- FC0080: Frame Control field. Example: FC0108 means type data, subtype data, to DS 1, from DS 0 (a packet client to openwifi AP)
|
||||
- DI0000: Duration/ID field
|
||||
- ADDR: address fields addr1/2/3. Target MAC address ffffffffffff (broadcast), source MAC address 00c88b113f5f
|
||||
- SC2133: sequence number 2133 from the header of the packet
|
||||
- fcs1: FCS/CRC is OK. (fcs0 means bad CRC)
|
||||
- buf_idx13: current rx packet DMA buffer index 13
|
||||
- -50dBm: signal strength of this received packet (after calibration)
|
||||
- buf_idx10: the rx packet is from DMA buffer with index 10
|
||||
- -78dBm: signal strength of this received packet (after calibration)
|
||||
|
||||
### Native Linux tools
|
||||
|
||||
For analysis/debug, many native Linux tools you still could rely on. Such as tcpdump, tshark, etc.
|
||||
|
||||
### FPGA
|
||||
### Debug FPGA
|
||||
|
||||
For FPGA itself, FPGA developer could use Xilinx ILA tools to analyze FPGA signals. Spying on those state machines in xpu/tx_intf/rx_intf would be very helpful for understanding/debugging Wi-Fi low level functionalities.
|
||||
For FPGA itself, FPGA developer could use Xilinx ILA tools to analyze FPGA signals (https://github.com/open-sdr/openwifi-hw/issues/39). Spying on those state machines in xpu/tx_intf/rx_intf would be very helpful for understanding/debugging Wi-Fi low level functionalities.
|
||||
|
||||
## Test mode driver
|
||||
|
||||
While loading the openwifi driver by "insmod sdr.ko", a test_mode argument can be specified (You can also specify the test_mode value to wgd.sh or fosdem.sh). It will enable some experimental feataures (such as AMPDU aggregation):
|
||||
```
|
||||
insmod sdr.ko test_mode=value
|
||||
```
|
||||
It is implemented by the global static variable test_mode in sdr.c.
|
||||
|
||||
Supported test_mode value definitions:
|
||||
- bit0: AMPDU/aggregation is ON (1) or OFF (0 -- default OFF)
|
||||
|
@ -19,5 +19,5 @@ Application notes collect many small topics about using openwifi in different sc
|
||||
- [CSI fuzzer](csi_fuzzer.md)
|
||||
- [Access counter/statistics in FPGA](perf_counter.md)
|
||||
- [Access counter/statistics in driver](driver_stat.md)
|
||||
- [Frequent trick on controlling Gain/Att/Frequency/CCA/LBT/CSMA/CW/etc](frequent_trick.md)
|
||||
- [Frequent/usual trick on controlling Gain/Att/Frequency/CCA/LBT/CSMA/CW/Sensitivity/etc](frequent_trick.md)
|
||||
- [owfuzz: a WiFi protocol fuzzing tool using openwifi.](https://github.com/alipay/WiFi-Protocol-Fuzzing-Tool) [[**Vulnerabilities**]](https://github.com/E7mer/Owfuzz)
|
||||
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 576 KiB After Width: | Height: | Size: 406 KiB |
@ -20,33 +20,9 @@ CSI fuzzer implementation principle.
|
||||
|
||||
## Demo instructions
|
||||
|
||||
Thanks to the full-duplex capability and CSI extraction feature of openwifi, you can monitor the artificial channel response via [side channel](./csi.md) by Tx-Rx over the air coupling without affecting the normal operation/traffic of openwifi. Before the self-monitoring, the auto-mute during Tx needs to be disabled.
|
||||
Thanks to the full-duplex capability and CSI extraction feature of openwifi, you can monitor the artificial channel response via [side channel](./csi.md) by Tx-Rx over the air coupling without affecting the normal operation/traffic of openwifi. Before fuzzing the CSI, please follow [WiFi CSI radar via self CSI capturing](radar-self-csi.md) app note to setup normal self CSI monitoring.
|
||||
|
||||
The full demo steps are:
|
||||
|
||||
```
|
||||
ssh root@192.168.10.122
|
||||
(password: openwifi)
|
||||
|
||||
cd openwifi
|
||||
|
||||
./fosdem-11ag.sh
|
||||
(setup openwifi AP)
|
||||
|
||||
./sdrctl dev sdr0 set reg xpu 1 1
|
||||
(Disable auto-muting to listen self-TX)
|
||||
|
||||
insmod side_ch.ko num_eq_init=0
|
||||
|
||||
./side_ch_ctl wh1h2001
|
||||
./side_ch_ctl wh6hffffffff
|
||||
(Let's only monitor self-beacon-TX CSI over-the-air loopback)
|
||||
|
||||
./side_ch_ctl g1
|
||||
```
|
||||
Go to openwifi/user_space/side_ch_ctl_src, and run `python3 side_info_display.py 0`. You should see the over-the-air loopback CSI when CSI fuzzer is not enabled. Then stop the python3 side_info_display.py script to ease the next step.
|
||||
|
||||
Start another ssh session to the openwifi board:
|
||||
Then, start another ssh session to the openwifi board:
|
||||
```
|
||||
ssh root@192.168.10.122
|
||||
(password: openwifi)
|
||||
@ -58,7 +34,7 @@ cd openwifi
|
||||
(csi_fuzzer.sh is called. Please read both scripts to understand these commands)
|
||||
```
|
||||
|
||||
Go to openwifi/user_space/side_ch_ctl_src, and run `python3 side_info_display.py 0`. Now you should see that CSI keeps changing like in this [video](https://youtu.be/aOPYwT77Qdw).
|
||||
Now you should see that CSI keeps changing like in this [video](https://youtu.be/aOPYwT77Qdw).
|
||||
|
||||
# Further explanation on parameters
|
||||
|
||||
@ -72,7 +48,7 @@ CSI self-monitoring before fuzzing.
|
||||
|
||||
![](./csi-fuzzer-beacon-ant-back-0.jpg)
|
||||
|
||||
CSI self-monitoring after fuzzing command: `csi_fuzzer.sh 1 45 0 13`
|
||||
CSI self-monitoring after fuzzing command: `./csi_fuzzer.sh 1 45 0 13`
|
||||
|
||||
![](./csi-fuzzer-beacon-ant-back-1-45-0-13.jpg)
|
||||
|
||||
|
@ -10,9 +10,10 @@ Some usual/frequent control trick over the openwifi FPGA. You need to do these c
|
||||
[[Tx Lo and port config](#Tx-Lo-and-port-config)]
|
||||
[[Antenna selection](#Antenna-selection)]
|
||||
[[Restrict the frequency](#Restrict-the-frequency)]
|
||||
[[Receiver sensitivity control](#Receiver-sensitivity-control)]
|
||||
|
||||
[[Tx rate config](#Tx-rate-config)]
|
||||
[[Arbiturary Tx IQ sample](#Arbiturary-Tx-IQ-sample)]
|
||||
[[Arbitrary Tx IQ sample](#Arbitrary-Tx-IQ-sample)]
|
||||
|
||||
## CCA LBT threshold and disable
|
||||
|
||||
@ -20,11 +21,11 @@ In normal operation, different threshold is set to FPGA according to the differe
|
||||
```
|
||||
./set_lbt_th.sh
|
||||
```
|
||||
"reg val: 00000086" means the current threshold is 134 (86 in Hex).
|
||||
"reg val: 00000086" means the current threshold is 134 (86 in Hex). Its unit is rssi_half_db. Check rssi_half_db_to_rssi_dbm()/rssi_dbm_to_rssi_half_db() in sdr.c to see the relation to rssi dBm.
|
||||
|
||||
Override a new threshold to FPGA, for example 4dB higher than 134, the new value should be 134 + 4*2 = 142 (1 means 0.5dB, so 4dB higher needs adding 8)
|
||||
Override a new threshold -NNdBm to FPGA, for example -70dBm:
|
||||
```
|
||||
./set_lbt_th.sh 142
|
||||
./set_lbt_th.sh 70
|
||||
```
|
||||
Above will disable the automatic CCA threshold setting from the openwifi driver.
|
||||
|
||||
@ -32,11 +33,11 @@ Recover the driver automatic control on the threshold:
|
||||
```
|
||||
./set_lbt_th.sh 0
|
||||
```
|
||||
Disable the CCA by setting a maximum threshold 2047:
|
||||
Disable the CCA by setting a very strong level as threshold, for example -1dBm:
|
||||
```
|
||||
./set_lbt_th.sh 2047
|
||||
./set_lbt_th.sh 1
|
||||
```
|
||||
After above command, the CCA engine will always believe the channel is idle.
|
||||
After above command, the CCA engine will always believe the channel is idle, because the rx signal strength not likely could exceed -1dBm.
|
||||
|
||||
## Retransmission and ACK tx control
|
||||
|
||||
@ -50,7 +51,7 @@ The FPGA also has a register to override the re-transmission and ACK behavior. C
|
||||
```
|
||||
./sdrctl dev sdr0 get reg xpu 11
|
||||
```
|
||||
When operate this register, make sure you only change the relevant bits and leave other bits untouched, because other bits have other purposes.
|
||||
When operate this register, make sure you only change the relevant bits and leave other bits untouched, because other bits have other purposes. Also check the xpu register 11 in the document: https://github.com/open-sdr/openwifi/blob/master/doc/README.md
|
||||
|
||||
To override the maximum number of re-transmission, set bit3 to 1, and set the value (0 ~ 7) to bit2 ~ 0. Example, override the maximum number of re-transmission to 1
|
||||
```
|
||||
@ -197,6 +198,15 @@ Above command will fix the AD9361 in 5220MHz and let driver ignore frequency tun
|
||||
```
|
||||
./set_restrict_freq.sh 0
|
||||
```
|
||||
To let openwifi work at arbitrary frequency, please check "Let openwifi work at arbitrary frequency" in https://github.com/open-sdr/openwifi/blob/master/doc/README.md#Regulation-and-channel-config
|
||||
|
||||
## Receiver sensitivity control
|
||||
|
||||
Sometimes too good sensitivity could be a bad thing. WiFi receiver could be "attracted" by many weak signal/packet in the background, and has less "attention" to its real communication target (client/AP). Openwifi has offered a way to make the receiver less sensitive by setting a threshold. When the received signal is lower than this threshold, the receiver will not try to search the WiFi short preamble, i.e. ignore it. For example, if you want to set -70dBm as the threshold, use:
|
||||
```
|
||||
./sdrctl dev sdr0 set reg drv_rx 0 70
|
||||
```
|
||||
|
||||
## Tx rate config
|
||||
|
||||
By default, the Linux rate adaptation algorithm **minstrel_ht** set the packet rate/MCS automatically via openwifi_tx() function.
|
||||
@ -215,6 +225,6 @@ To override the Linux automatic control for ht packet
|
||||
```
|
||||
Value N: 0 for Linux auto control; 4 ~ 11 for 6.5M, 13M, 19.5M, 26M, 39M, 52M, 58.5M, 65M. By default, the normal GI is used. To use the short GI, you need to add 16 to the target value N.
|
||||
|
||||
## Arbiturary Tx IQ sample
|
||||
## Arbitrary Tx IQ sample
|
||||
|
||||
To be written.
|
||||
Arbitrary IQ sample (maximum 512 samples) can be written to tx_intf and sent for test purpose.
|
||||
|
@ -26,13 +26,35 @@ make
|
||||
To customize the packet, following piece of the inject_80211.c needs to be changed:
|
||||
```
|
||||
/* IEEE80211 header */
|
||||
static const u8 ieee_hdr[] =
|
||||
static u8 ieee_hdr_data[] =
|
||||
{
|
||||
0x08, 0x01, 0x00, 0x00, // FC 0x0801. 0--subtype; 8--type&version; 01--toDS1 fromDS0 (data packet to DS)
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // BSSID/MAC of AP
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // Source address (STA)
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x33, // Destination address (another STA under the same AP)
|
||||
0x10, 0x86, // 0--fragment number; 0x861=2145--sequence number
|
||||
0x08, 0x02, 0x00, 0x00,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x22,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x33,
|
||||
0x10, 0x86,
|
||||
};
|
||||
|
||||
static u8 ieee_hdr_mgmt[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x22,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x33,
|
||||
0x10, 0x86,
|
||||
};
|
||||
|
||||
static u8 ieee_hdr_ack_cts[] =
|
||||
{
|
||||
0xd4, 0x00, 0x00, 0x00,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
|
||||
};
|
||||
|
||||
static u8 ieee_hdr_rts[] =
|
||||
{
|
||||
0xb4, 0x00, 0x00, 0x00,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
|
||||
0x66, 0x55, 0x44, 0x33, 0x22, 0x22,
|
||||
};
|
||||
```
|
||||
Note: The byte/bit order might not be intuitive when comparing with the standard.
|
||||
@ -57,6 +79,13 @@ sdrctl dev sdr0 set reg xpu 11 16
|
||||
```
|
||||
-m/--hw_mode <hardware operation mode> (a,g,n)
|
||||
-r/--rate_index <rate/MCS index> (0,1,2,3,4,5,6,7)
|
||||
-t/--packet_type (m/c/d/r for management/control/data/reserved)
|
||||
-e/--sub_type (hex value. example:
|
||||
8/A/B/C for Beacon/Disassociation/Authentication/Deauth, when packet_type m
|
||||
A/B/C/D for PS-Poll/RTS/CTS/ACK, when packet_type c
|
||||
0/1/2/8 for Data/Data+CF-Ack/Data+CF-Poll/QoS-Data, when packet_type d)
|
||||
-a/--addr1 <the last byte of addr1 in hex>
|
||||
-b/--addr2 <the last byte of addr2 in hex>
|
||||
-i/--sgi_flag (0,1)
|
||||
-n/--num_packets <number of packets>
|
||||
-s/--payload_size <payload size in bytes>
|
||||
|
@ -46,6 +46,9 @@ One super power of the openwifi platform is "**Full Duplex**" which means that o
|
||||
While running, all CSI data is also stored into a file **side_info.txt**. A matlab script **test_side_info_file_display.m** is offered to help you do CSI analysis offline. In this case, run **test_side_info_file_display(0)** in Matlab.
|
||||
![](./csi-screen-shot-radar-matlab.jpg)
|
||||
|
||||
The following picture is generated by data processing on the captured openwifi CSI while people move in front of two directional antennas (Tx/Rx antenna).
|
||||
![](./sensing.png)
|
||||
|
||||
Please learn the python and Matlab script for CSI data structure per packet according to your requirement.
|
||||
|
||||
Do read the [normal CSI app note](csi.md) to understand the basic implementation architecture.
|
||||
|
Before Width: | Height: | Size: 375 KiB After Width: | Height: | Size: 343 KiB |
Before Width: | Height: | Size: 288 KiB After Width: | Height: | Size: 253 KiB |