Chasing Trigger Frames

Lately, I have been on the hunt for as many trigger frames as possible to accomplish two main goals:

  • Learn more about the conditions that produce different trigger frames.
  • Prove when OFDMA vs MU-MIMO operation is happening (or happened).

Maybe it isn’t 100% correct to pit these two against each other, but many Wifi6 AP’s are switching between OFDMA and MU-MIMO when confronted with certain RF and traffic conditions from 11ax capable stations.

In my testing for this write-up, I stuck with one particular AP where I could monitor the AP for its participation in OFDMA or MU-MIMO which was a big help in looking for patterns in the pcaps. I did run into trouble with uplinks (STA-to-AP) because the AP only shows what it is doing for downlinks (AP-to-STA). So it was a bit more difficult to tell what happened in upload captures, but I found some interesting IO Graphs and what follows are snapshots of my journey down this particular rabbit hole…enjoy!

For reference, here are two wireshark filters for trigger frame hunters:

wlan.trigger.he.trigger_type <= 15

One question is, between the above two filters, if wlan.fc==0x2400 is all trigger frames, why is it showing 166 less frames than wlan.trigger.he.trigger_type<=15 which is also all trigger frames?

If I setup a wireshark filter for those 166 frames, there is no clear pattern that explains the difference…so please feel free to let me know if you can explain!

wlan.trigger.he.trigger_type<=15 and !wlan.fc==0x2400

To clearly define the exact trigger frames I am chasing, here are the possible values for the wlan.trigger.he.trigger_type filter:

  • 0 – Basic
  • 1 – Beamforming Report Poll (BRP)
  • 2 – Multi-User Block ACK Request (MU-BAR)
  • 3 – Multi-User Request To Send (MU-RTS)
  • 4 – Buffer Status Report Poll (BSRP)
  • 5 – Group Cast Retries (GCR MU-BAR)
  • 6 – Bandwidth Query Report Poll (BQRP)
  • 7 – NDP Feedback Report Poll (NFRP)
  • 8-15 – Reserved

However, as is the case with wifi, this isn’t the whole story…there is another important frame named the HE TB PPDU (High Efficiency Trigger Based PPDU) which is the 802.11ax frame sent by stations when they have uplink data to send. It is labeled in wireshark as HE_TRIG and found with the filter:


How I Tested

The test setup is a ASUS AXE11000 Wifi6e AP with a LANforge traffic generator with 4 11ax stations, a Jetson Nano, and a Samsung S10. Although the ASUS is a 6E AP, I am only chasing trigger frames on 5GHz during this round of testing and will plan to go trigger frame hunting on 6GHz next.

Using the ASUS AP built in monitoring commands, I can observe when OFDMA or MU-MIMO is happening from the AP’s perspective…so my reasoning is: if the AP thinks it is doing fancy things…let’s go capture it!

Setting up the AP status monitoring:

  • Enable SSH service from the AP’s Administration menu
  • SSH in as the admin user
  • while true; do wl -i eth7 bs_data; sleep 1; done

Setting up the monitor interface:

  • Setup at least one 11ax interface as described in Gjermund’s blog.
  • Verify that you have the correct AID for the station you want to monitor for OFDMA.
    This is an important step because it allows the monitor interface to decode the HE frames for that particular station and the AID can change if the station reassociates.

Useful tshark command to grab the AID when the station associates or reassociates…basically filter for wlan subtype 1, the Association Response, and display the station’s MAC and AID in hexadecimal:

tshark -i <monitor interface> -Y "wlan.fc.type_subtype==0x0001" -T fields -e wlan.addr -e wlan.fixed.aid

Traffic Tests to stimulate OFDMA or MU-MIMO

In general, smaller payload sizes will stimulate OFDMA and larger payload sizes will stimulate MU-MIMO. However, it seems that different AP’s will toggle between OFDMA and MU-MIMO at different payload sizes. For the Asus AP, the sizes that worked for me were 300B for OFDMA and 1472B for MU-MIMO. Using these payload sizes, I performed the following tests:

  • UDP Download
  • UDP Upload

Iperf3 Server is running on all station devices as:

iperf3 -s -i <interface>

Each iperf3 client connection was run from the LANforge device on the wired interface connected to the AP, but this could also have been any iperf3 capable device with a wired connection to the AP. I used LANforge mainly to orchestrate the different tests for all iperf clients as well as run the background traffic from the additional 11ax stations.

The IO Graphs are generated from the Wireshark Statistics menu. Some tests only needed a single graph to see what was happening, but for other tests it was better to generate multiple graphs to observe what was happening.

  • Jetson Nano – DL OFDMA – UDP – Link to pcap: nano-ofdma-udp-down.pcapng
    iperf3 -c -t 10 –length 300 -u –tos 0 -b 200000K –bind_dev eth1 -i 1
    This graph clearly shows HE_MU DL OFDMA.

  • Jetson Nano – UL OFDMA – UDP – Link to pcap: nano-ofdma-udp-up.pcapng
    iperf3 -c -t 10 –length 300 -u -R –tos 0 -b 200000K –bind_dev eth1 -i 1
    Graph of HE_TRIG and UL OFDMA.

    What I think this next graph shows is that the Basic Trigger frames broadcast from the AP also indicate UL OFDMA is happening.

  • Jetson Nano – MU-MIMO – UDP
    I could not get the Nano to participate in MU-MIMO. I tried to limit the number of spatial streams in use, but the iw command would not allow the set antenna option.
  • Samsung S10 – DL OFDMA- UDP – Link to pcap: s10-ofdma-udp-down.pcapng
    iperf3 -c -t 10 –length 300 -u –tos 0 -b 100000K –bind_dev eth1 -i 1
    Another example of HE_MU DL OFDMA.

  • Samsung S10 – UL OFDMA – UDP – Link to pcap: s10-ofdma-udp-up.pcapng
    iperf3 -c -t 10 –length 300 -u -R –tos 0 -b 100000K –bind_dev eth1 -i 1
    It appears that the HE_TRIG here indicates an uplink OFDMA.

    Graph of Basic Trigger frames and Multi-STA Block ACKs broadcast from the AP indicating UL OFDMA.

  • Samsung S10 – DL MU-MIMO – UDP – Link to pcap: s10-mumimo-udp-down.pcapng
    iperf3 -c -t 10 –length 1472 -u –tos 0 -b 100000K –bind_dev eth1 -i 1
    Here, the S10 iperf starts at 11s into the capture, where HE_SU increases which is one indication that the traffic is no longer OFDMA, but how to prove that it is MU-MIMO?

    There are also a large number of Beamforming Report Poll type trigger frames.

    If I filter the BRP frames by Upload Length, then it appears to show when the BRP frames include multiple users and this seems to agree with what the AP shows as participation in downlink MU-MIMO.


OFDMA can be identified, but has to be further classified as Uplink or Downlink.

  • The PPDU formats tell the story pretty well for UDP traffic.
  • HE_MU indicates DL-OFDMA
  • HE_TRIG indicates UL-OFDMA
  • Originally, I was going to test UDP and TCP, but this post was getting long…so I decided to just try and analyze the UDP tests and save TCP testing for another time. I did run one combined UDP and TCP test that was very interesting. TCP traffic is different because the protocol has TCP ACKs that have to be uplinked when the station is downlinking and downlinked when the station is uplinking so there is a mixture of HE_MU and HE_TRIG as seen in this IO Graph.
    10-20 secs is a UDP download
    25-35 secs is a UDP upload
    45-55 secs is a TCP download
    60-70 secs is a TCP upload

    Link to pcap: he-udp-down-up_tcp-down-up.pcapng
  • Don’t be discouraged if the payload size is not working at first…keep trying because the AP is in charge and its behavior varies.
  • MU-MIMO is more difficult to identify in wireshark, I’ll need to spend some time doing further testing to explore upload MU-MIMO.
  • Despite using similar traffic settings, I could not get the Jetson Nano to participate in MU-MIMO traffic.

In conclusion, here is my estimate of difficulty level with capturing trigger frames:

Link to pcap for the following: nano-ofdma-udp-down.pcapng

Basic Trigger Frame – difficulty level EASY – downloading or uploading tests.

BRP – difficulty level EASY – downloading or uploading tests.

MU-BAR – difficulty level MEDIUM – found one during the Jetson Nano OFDMA download test from AP to Nano.

MU-RTS – difficulty level EASY – found many during the Jetson Nano OFDMA download test.

BSRP – difficulty level MEDIUM – found a few during the Jetson Nano OFDMA download test.

GCR MU-BAR – difficulty level UNKNOWN

BQRP – difficulty level HARD – found one, but could not repeat the capture.

NFRP – difficulty level UNKNOWN

Thanks for reading, please let me know if you have any comments or suggestions.

And a big thank you to all the Wifi Pros out there who blog/vlog/present and tweet!

Wlanpi a la Mode

Have you had a chance to check out the wlanpi project yet? Wlanpi is a tiny odroid linux box that packs a punch with several free test tools pre-installed on its default image. Go to for more info including where to source parts and software. Fortunately, there has been a lot written on how to use the existing wlanpi tools and how to turn it into a remote packet sniffer/wlan sensor. Here I’ll show you how to add another cool tool to your wlanpi kit for throughput testing and graphical analysis.

This tool is named Flent – FLExible Network Tester developed by Toke Høiland-Jørgensen. Flent is a set of python scripts that wrap and run netperf, netserver and other tools which allow you to take your throughput testing to another level…with graphs…lots and lots of data-driven, presentation-ready sharp looking graphs.  The graphing capability is IMHO what sets this tool apart, specifically because it allows you the ability to easily compare data sets from previous tests and see differences between test runs.

NOTE: You may want to experiment on a freshly etched wlanpi image on a separate memory card so you do not fubar anything you have already setup on your existing install. I am using two usb-to-wifi adapters and have unmasked the wpa_supplicant.service so I can use wlan1 as a traffic source/sink with the following command:
wlanpi@wlanpi:~$ sudo systemctl unmask wpa_supplicant.service

Once unmasked, you can use the nmtui to configure wlan1.
wlanpi@wlanpi:~$ sudo nmtui

Here is the method of installation I recommend based on my testing on the 1.5.0 wlanpi image running on my wlanpi with an internet connection!

Flent – install from github.
wlanpi@wlanpi:~$ git clone
wlanpi@wlanpi:~$ cd flent
wlanpi@wlanpi:~/flent$ sudo python install

Netperf/Netserver – install from github and be sure to use “–enable-demo=yes” and compile netperf to enable netperf to emit “interim results” at semi-regular intervals…as stated in the user guide for this feature.
wlanpi@wlanpi:~$ git clone
wlanpi@wlanpi:~$ cd netperf
wlanpi@wlanpi:~/netperf$ sudo ./
wlanpi@wlanpi:~/netperf$ sudo ./configure --enable-demo=yes
wlanpi@wlanpi:~/netperf$ sudo make
wlanpi@wlanpi:~/netperf$ sudo make install

Fping – version 3.15 is already on the wlanpi image, but Flent would like a higher version. Install from github.
wlanpi@wlanpi:~$ git clone
wlanpi@wlanpi:~$ cd fping
wlanpi@wlanpi:~/fping$ sudo ./
wlanpi@wlanpi:~/fping$ sudo ./configure
wlanpi@wlanpi:~/fping$ sudo make
wlanpi@wlanpi:~/fping$ sudo make install

You can install flent and netperf/netserver using apt on the wlanpi, but you will be using older versions than what is available from github.

Flent works similarly to iperf in that there is a server and a client required to run tests. The server runs on one system and the client runs on another. It is up to you to decide how you want to run tests, but there are command-line options to swap upload and download direction for example if you need it. I recommend running the flent tests on the wlanpi which means a netserver process will need to run on a separate system such as a laptop that is also connected to the same network under test. For a more detailed explanation…head over to Flent intro page:

For your laptop or other system that will be acting as a netserver, you will need to install the flent-gui as well as flent, netserver and fping so you can run tests and then scp results files from your wlanpi and view graphical results. You will have to install additional packages to get the flent-gui to display correctly. The flent-gui does have the capability to run tests directly from its interface, but I am not covering that feature in this post. Here is what I installed on a Ubuntu 18.04 laptop and then I was able to install flent, netserver and fping and then run flent-gui.

sudo apt install python-setuptools-git autotools-dev automake python-qt4 python-matplotlib

After the installs are completed, you can now run tests. Start netserver on your laptop or other server system by simply typing “netserver” and then ssh to the wired interface on the wlanpi and run one or more of the flent tests on the wireless interface.

To see what tests are available, type “flent –list-tests” (it takes a couple of minutes for this command to complete…not sure why). I have not tried all of the available tests and you may need other software installed to run some of the other tests, but the main ones I have used are tcp_download, tcp_upload, rrul and udp_flood. I have experimented a bit with the multi stream tcp and the different rrul tests, but you can try the ones that look interesting to you and see what happens!

wlanpi@wlanpi:~$ flent –list-tests
Available tests:
bursts : Latency measurements under intermittent UDP bursts
bursts_11e : 802.11e Latency measurements under intermittent UDP bursts
cisco_5tcpup : RTT Fair Realtime Response Under Load
cisco_5tcpup_2udpflood : Cisco 5TCP up + 2 6Mbit UDP
cubic_bbr : Cubic VS BBR smackdown
cubic_cdg : Cubic VS CDG smackdown
cubic_dctcp : Cubic VS DCTCP smackdown
cubic_ledbat : Cubic VS Ledbat smackdown
cubic_ledbat_1 : Cubic vs LEDBAT upload streams w/ping
cubic_reno : Cubic VS Reno smackdown
cubic_westwood : Cubic VS Westwood
dslreports_8dn : 8 down – dslreports dsl test equivalent
http : HTTP latency test
http-1down : HTTP get latency with competing TCP download stream
http-1up : HTTP get latency with competing TCP upload stream
http-rrul : HTTP get latency with competing RRUL test
iterated_bidirectional : Iterated TCP bidirectional transfers example
ledbat_cubic_1 : Cubic vs LEDBAT upload streams w/ping
ping : Ping test (ICMP and UDP)
qdisc-stats : Capture qdisc stats
reno_cubic_westwood_cdg : Realtime Response Under Load
(with different congestion control algs)
reno_cubic_westwood_ledbat : Realtime Response Under Load
(with different congestion control algs)
reno_cubic_westwood_lp : Realtime Response Under Load
(with different congestion control algs)
rrul : Realtime Response Under Load
rrul46 : Realtime Response Under Load – Mixed IPv4/6
rrul46compete : Realtime Response Under Load – Mixed v4/v6 compete
rrul_100_up : 100 up vs 1 down – exclusively Best Effort
rrul_50_down : 50 down vs 1 up – exclusively Best Effort
rrul_50_up : 50 up vs 1 down – exclusively Best Effort
rrul_be : Realtime Response Under Load – exclusively Best Effort
rrul_be_iperf : Realtime Response Under Load – exclusively Best Effort (Iperf TCP)
rrul_be_nflows : Realtime Response Under Load – Best Effort, configurable no of flows
rrul_cs8 : Realtime Response Under Load CS8, one flow per CS/precedence level
rrul_icmp : Realtime Response Under Load – Best Effort, only ICMP ping
rrul_noclassification : Realtime Response Under Load – no classification on data flows
rrul_prio : Realtime Response Under Load – Test Prio Queue
rrul_torrent : Torrent-like competition
rrul_up : Realtime Response Under Load – upload only
rtt_fair : RTT Fair Realtime Response Under Load
rtt_fair4be : RTT Fair Realtime Response Under Load
rtt_fair6be : RTT Fair Realtime Response Under Load
rtt_fair_up : RTT Fair upstream only
rtt_fair_var : RTT Fair – variable number of hosts
rtt_fair_var_down : RTT Fair – variable number of hosts (download only)
rtt_fair_var_mixed : RTT Fair – variable number of hosts (mixed up and down)
rtt_fair_var_up : RTT Fair – variable number of hosts (upload only)
sctp_vs_tcp : SCTP vs TCP
tcp_12down : TCP download – 12 streams w/ping
tcp_12up : TCP upload – 12 streams w/ping
tcp_1down : Single TCP download stream w/ping
tcp_1up : Single TCP upload stream w/ping
tcp_1up_noping : Single TCP upload stream
tcp_2down : TCP download – 2 streams w/ping
tcp_2up : TCP upload – 2 streams w/ping
tcp_2up_delay : Two TCP upload streams; 2nd stream started delayed
tcp_2up_square : Two TCP upload streams; 2nd stream started delayed
tcp_2up_square_westwood : Two TCP upload streams; 2nd stream started delayed
tcp_4down : TCP download – 4 streams w/ping
tcp_4up : TCP upload – 4 streams w/ping
tcp_4up_squarewave : Four TCP upload streams; 2nd streams started delayed, cubic vs BBR
tcp_6down : TCP download – 6 streams w/ping
tcp_6up : TCP upload – 6 streams w/ping
tcp_8down : TCP download – 8 streams w/ping
tcp_8up : TCP upload – 8 streams w/ping
tcp_bidirectional : Bidirectional TCP streams w/ping
tcp_download : TCP download stream w/ping
tcp_ndown : TCP download – N streams w/ping
tcp_nup : TCP upload – N streams w/ping
tcp_upload : TCP upload stream w/ping
tcp_upload_1000 : 1000 up – exclusively Best Effort
tcp_upload_prio : TCP upload stream w/ToS prio bits
udp_flood : UDP flood w/ping
udp_flood_var_up : UDP flood w/ping – variable number of hosts
udp_flood_var_up_stagger : UDP flood w/ping – variable number of hosts, staggered start
voip : VoIP one-way stream test
voip-1up : VoIP one-way stream test with competing TCP stream
voip-rrul : VoIP one-way stream test with competing RRUL test

A word about RRUL – the Realtime Response Under Load test attempts to saturate the traffic link with four TCP upload streams and four TCP download streams each of which are marked to correspond to different QoS traffic classes. The point of this test is to identify potential bufferbloat in the network under test. Bufferbloat is the effect of having too many network buffers causing unwanted and excessive delay in a network. The advantage of running the RRUL test on a wireless network is that it can show how a highly contentious RF environment can behave as badly or worse than a bufferbloated wired network. By running RRUL and its variants, you can measure how the existing or modified queuing mechanisms implemented by vendors of your networking equipment stand up to a traffic load as well as collect the data to visually inspect what happens when someone complains that “the wifi is slow.” ™
For additional info on this topic, see the following:
The Blind Men and the Elephant
Make Wifi Fast Project
Battle Mesh write-up

To view the results, scp the *.flent.gz results files to your flent-gui system, then run the flent-gui to view the data. Add additional data sets by going to the Data menu. As you can see there are plenty of graphs to choose from.


Below is an example comparison of a TCP upload test on a wifi network with 25 other transmitting stations and again without other stations using the network. You can see the difference in latency results between the tests when many stations vs one station are contending for airtime.

You can use IP addresses for the -H and –local-bind options, or you can edit your /etc/hosts file on the wlanpi to use human readable names. The -x collects metadata about your test, –socket-stats collects TCP stats but only for the upload test and -t allows you to give your test run a title. There are many other options of course to control how flent behaves. Type “flent –help” to see them or visit

wlanpi@wlanpi:~$ sudo flent -x -H laptop --local-bind wlan1 tcp_upload --socket-stats -t tcp-up-25stas-tx
wlanpi@wlanpi:~$ sudo flent -x -H laptop --local-bind wlan1 tcp_upload -t tcp-up-no-stas

The above two commands each ran a 70 second TCP upload test which resulted in two *.flent.gz files which I scp’d to the laptop and then opened with flent-gui to obtain the following graphs of the two data series. The box plot shows better upload results and the Ping CDF plot shows better ping times when comparing no stations to many transmitting stations.


Next up is a rrul test where a comparison of the same test network once with 25 transmitting stations and again without other stations using the network.

wlanpi@wlanpi:~$ sudo flent -x -H laptop --local-bind wlan1 rrul --socket-stats -t rrul-25stas-tx
wlanpi@wlanpi:~$ sudo flent -x -H laptop --local-bind wlan1 rrul --socket-stats -t rrul-no-stas

The box plot shows better TCP download results and the ICMP CDF plot shows better ping times when comparing no stations to many transmitting stations.


You can also build flent batch files to run different tests or the same test over and over again instead of running the tests one at a time. The batch capability is also quite useful because you can kick off other scripts or initiate a wireshark capture when a particular test runs.

The batch file below named flent-batch.txt names three tests and repeats each of the three tests five times.

wlanpi@wlanpi:~$ cat flent-batch.txt
test_name = tcp_download
hosts = laptop
title = wlanpi-tcp-down rep:${repetition}
filename_extra = wlanpi-tcp-down-${repetition}
repetitions = 5
test_name = tcp_upload
hosts = laptop
title = wlanpi-tcp-up rep:${repetition}
filename_extra = wlanpi-tcp-up-${repetition}
repetitions = 5
test_name = rrul
hosts = laptop
title = wlanpi-rrul rep:${repetition}
filename_extra = wlanpi-rrul-${repetition}
repetitions = 5

Then to run the entire batch file, you use the following command:

wlanpi@wlanpi:~$ sudo flent -x --local-bind wlan1 -b tcp-down -b tcp-up -b rrul -B flent-batch.txt

This lengthy post only scratches the surface of what Flent can do, but I wanted to demonstrate that this tool can be very useful for collecting data on how your networks are behaving. The fact that it runs on linux and the wlanpi is a sweet bonus! With the many test options, batch operations and graphing capabilities of Flent, you can turn your wlanpi into a significant little test system for your wifi networks. A big thanks to @jolla @wlanpi and others for their work on this project. Keep Testing!

Additional Articles on using WlanPi

Here is the main user guide found at

Here are a handful of links to articles written about using the wlanpi:

Fun with iperf

For a quick throughput tester, iperf can come in very handy. Here are some basics with setting up iperf and running tests. Note that iperf refers to version iperf2.

Install on Linux or Windows – Just download the binary you need from and go!

   Keys to remember: iperf serveR Receives traffic, iperf clienT Transmits traffic. There are options and methods to change this behavior, but in general this is the default. How do I know this? Well, the answer is experience! and sniffing traffic!

   After installation, the next step is to start an iperf server on the system you want to receive traffic…how do you decide? Well, it depends on the type of environment you are testing. If you’re testing a wired setup on a local LAN it doesn’t much matter. If you’re testing a wifi network you may want an upload or download test…the bottom line is for most cases, the iperf server will be receiving the traffic flow from the client.

Start an iperf server on any interface:
iperf -s
iperf3 -s

Start an iperf server on a specific interface:
iperf -s -B
iperf3 -s -B

⇒   After starting your iperf server, move along to the next system and start the client.

Start an iperf client with TCP traffic to run for 30s and report every 1s:
iperf -c -t30 -i1

Start an iperf client with UDP traffic to run for 30s, report every 1s and try to achieve 1Gbps throughput:
iperf -c -t30 -i1 -u -b1G

Start an iperf client with TCP traffic for 30s reporting every 1s and use a specific interface for the connection.
iperf -c -t30 -i1 -B

Run the client in reverse mode (-R) where the client receives and the server transmits. Although the man page for iperf2 does not show this option, it worked for me on both iperf2 and iperf3.
iperf -c -B -t30 -i1 -R

Run the client in dualtest mode which is a simultaneous bidirectional test where the client and the server transmit and receive at the same time! This option requires the use of -L for a listen port to receive bidirectional tests on and importantly only works with iperf2 and not with iperf3.
iperf -c -B -t30 -i1 -d -L 5002

Run the client in tradeoff mode which is an individual bidirectional test. Tradeoff (-r) first sets the client to transmit for 30s in this example, then sets the server to transmit and run for 30s. This option also requires the use of -L for a listen port to receive bidirectional tests on and importantly only works with iperf2 and not with iperf3.
iperf -c -B -t30 -i1 -r -L 5002

Run the client with multiple parallel streams for multiple connections to the server. Although this option is available for iperf2, I was only able to reliably get it to work with iperf3.
iperf3 -c -B -t30 -i1 -P 5

Iperf has many other options that you can experiment with to find the right mix for your testing. One of the cool things about iperf is that there are a few different Android and IOS apps that also allow you to use your mobile device as an iperf endpoint. Here is an example of  the app described at

An iperf3 client to connects to another iperf3 server:

Because iperf can be run on many different platforms with many different options, it is a great tool to learn how to use for your throughput testing toolbox. Enjoy!

802.11r Fast BSS Transition

This is not an in-depth post on 802.11r. Instead, it is just about one piece of the 802.11r puzzle that will hopefully remain in my brain long enough for certification and beyond!

For a detailed review of 802.11r, I suggest Devin Akin’s excellent white paper:

And, Rasika Nayanajith’s excellent blog posts:
802.11r FT over the DS and 802.11r FT over the air

I was having trouble understanding the difference between two of the wpa_cli commands ft_ds and roam. The wpa_cli is the WPA command line interface for interacting with wpa_supplicant (as a station in client mode).

The wpa_cli command help gave me a clue, but wasn’t giving me the full story:
ft_ds = request over-the-DS FT with
roam = roam to the specified BSS

So I setup a Cisco testbed with a WLC2504 and two 1602 APs. Then setup a LANforge-WiFIRE test system with a client to roam between the two APs and with a separate monitor interface for packet captures.

With the wpa_cli ft_ds command I obtained the following capture:

With the wpa_cli roam command I obtained the following capture:

Staring at the packet captures and re-reading the following helped me see the difference:
• STA communication to the target AP via current AP using FT Action frames.
• STA communicates directly with the target AP using FT Authentication frames.

The command wpa_cli ft_ds dc:a5:f4:ff:4f:af initiates a FT Request (Action Frame) from the station 00:0e:8e:43:3a:71 to the target AP dc:a5:f4:ff:4f:af via the current AP dc:a5:f4:f3:ce:9f that the station is connected to.

The command wpa_cli roam dc:a5:f4:ff:4f:af initiates a FT Authentication from the station 00:0e:8e:43:3a:71 over the air directly to the target AP dc:a5:f4:ff:4f:af.

Both commands initiate an 802.11r Fast BSS Transition, but the distinction between the two is important to understanding how clients will transition. Using this command is a helpful way to test 802.11r wireless network setups and verifying that when it comes time for real clients to roam, you will have some confidence that it will work as expected.

Comparing USB-to-Wifi Adapters

After purchasing a handful of the Eye P.A. supported USB-to-Wifi adapters to see how well they could capture wifi traffic when compared to a dedicated PCI-E wifi NIC, I found that some of the adapters were better than others but none as good as the dedicated NIC.

Test Setup: Using a LANforge CT523b wifi traffic generator and an Aruba 315 AP setup on channel 100, I setup a single wifi client for a 10 second over-the-air UDP download at 500Mbps with a 1472B payload size. A second wifi NIC in monitor mode was used on the LANforge system to perform a 15 second wifi capture to compare against each USB adapter capture using the Eye P.A. capture tool.

The first 3 rounds were control tests to see how well the dedicated NIC would capture wifi traffic:

Round 1
    wiphy2 RX Pkts 217788
    wlan2 RX Pkts 424631
        captured 109306
        dropped 106672
Round 2
    wiphy2 RX Pkts 214776
    wlan2 RX Pkts 424618
        captured 109218
        dropped 106119
Round 3
    wiphy2 RX Pkts 215087
    wlan2 RX Pkts 424568
        captured 108803
        dropped 107875

The next 5 rounds compared different USB adapters to the dedicated NIC wifi capture:

Round 4 – adding capture device Edimax 7833
Eye P.A. captured 8730 pkts with 4240 data frames
    wiphy2 RX Pkts 213697
    wlan2 RX Pkts 424569
        captured 114925
        dropped 102400
Round 5 – capture device Linksys 6300
Eye P.A. captured 4970 pkts with 9 data frames
    wiphy2 RX Pkts 213462
    wlan2 RX Pkts 416002
        captured 109170
        dropped 106777
Round 6 – capture device Asus AC68
Eye P.A. captured 7240 pkts with 3276 data frames
    wiphy2 RX Pkts 138598
    wlan2 RX Pkts 241384
        captured 91625
        dropped 65146
Round 7 – capture device Asus AC68
Eye P.A. captured 7957 pkts with 4269 data frames
    wiphy2 RX Pkts 213985
    wlan2 RX Pkts 424611
        captured 108988
        dropped 109630
Round 8 – capture device Comfast Realtek 8812
Eye P.A. captured 6560 pkts with no data frames captured
    wiphy2 RX Pkts 226968
    wlan2 RX Pkts 424522
        captured 111036
        dropped 58637

Next steps are to try this test again under Linux or modify some of the other test setup to see if there is any benefit. Also I’d like to try the test against other APs and wifi modes, but the overall result appears to be that the USB-to-wifi adapters are not a good as a dedicated wifi NIC…but you probably already knew that!

Hidden SSIDs

How hidden are hidden SSIDs? Hidden SSIDs are only “hidden” because the AP doesn’t put the SSID (wlan_mgt.ssid) in the Beacon (wlan.fc.type_subtype==0x0008) and that’s it.



However, if any device that already has the SSID configured, sends an
Association Request (wlan.fc.type_subtype==0x0000) or a
Probe Request (wlan.fc.type_subtype==0x0004), then the SSID is not hidden anymore.


Association Request


Probe Request

As demonstrated here, if you’re running a wifi capture and happen to sniff these two requests or you happen to get the Probe Response (wlan.fc.type_subtype==0x0005), then you get the SSID!!!


Probe Response

It’s kinda like telling your toddler “Don’t tell Mommy we got her a surprise birthday cake!” If anyone asks how her day was, it only takes about 5 seconds for her to blurt out “We got cake!”

The takeaway here is…don’t bother hiding your SSID…there are better ways to secure your wlan network as well as surprise your loved ones with cake!!!

Measuring Beacon Interval

Here is my attempt to take a wifi capture file and use the IO Graph feature in Wireshark to measure the beacon interval as well as see how beacons behave with wifi traffic.

The wifi beacon from the AP is configurable and the default is usually around 100ms. But, this is more accurately described in the CWNP article:

In the Wireshark capture, I can filter on beacons by using wlan.fc.type_subtype==0x0008 and see the time delta from the previous displayed frame as 0.1025 seconds then 0.1023 seconds then 0.1024 seconds and so on which makes sense…but a graph would be much better to visualize what is happening.

Starting with the how-to I found here,
I started building a graph for beacon intervals. Going to Wireshark – Statistics – IO Graphs brings up the IO Graphs window. The default graph is for All Packets, but you modify this with a display filter and then add Y-axis filters if needed. After adding the entries for time deltas for Min/Max/Avg beacons, I also added a display filter for QoS Data to show when traffic was being transmitted.
Wireshark · IO Graphs · wifi-capture_045
The default time scale is too big to see what is going on, so next I set the Interval to 100ms.

Wireshark · IO Graphs · wifi-capture_040
Here the time scale to too compact, so next I zoom in.

Wireshark · IO Graphs · wifi-capture_041
Now you can see that the Max Beacon Interval before traffic starts and after traffic stops is measurable at 100000 microseconds or 100ms. There is a big gap at 10.24 seconds where the beacon was delayed for some reason, but I haven’t figured that out yet. When traffic starts, the beacon intervals are scattered among the traffic carrying frames because now there is more contention for air time.

Wireshark · IO Graphs · wifi-capture_043
Zooming in further shows how closely yet separate the beacons are from the data traffic.

Wireshark · IO Graphs · wifi-capture_044

Now with the original goal accomplished, measuring the beacon interval, this post also reveals that beacon intervals can change as air time becomes limited. Another cool trick is that you can also measure the beacon interval with this tshark command:

tshark -r wifi-capture.pcap -q -Y wlan.fc.type_subtype==0x0008 \
-z io,stat,0.01,”AVG(frame.time_delta_displayed)frame.time_delta_displayed” \
|grep -v “0.000000”

Partial output of this is:

| IO Statistics                                                    |
|                                                                  |
| Duration: 29.39 secs                                             |
| Interval:  0.01 secs                                             |
|                                                                  |
| Col 1: AVG(frame.time_delta_displayed)frame.time_delta_displayed |
|                |1         |                                      |
| Interval       |    AVG   |                                      |
|---------------------------|                                      |
|  0.10 <>  0.11 | 0.102500 |                                      |
|  0.20 <>  0.21 | 0.102273 |                                      |
|  0.30 <>  0.31 | 0.102406 |                                      |
|  0.40 <>  0.41 | 0.102391 |                                      |
|  0.51 <>  0.52 | 0.102361 |                                      |
|  0.61 <>  0.62 | 0.102445 |                                      |
|  0.71 <>  0.72 | 0.102400 |                                      |
|  0.81 <>  0.82 | 0.102398 |                                      |
|  0.92 <>  0.93 | 0.102402 |                                      |
|  1.02 <>  1.03 | 0.102402 |                                      |
|  1.12 <>  1.13 | 0.102409 |                                      |
|  1.22 <>  1.23 | 0.102393 |                                      |
|  1.33 <>  1.34 | 0.102381 |                                      |

Thanks for taking a look at this post!


Capture The Frames

When MetaGeek announced that they would support wifi capture from within Eye P.A., I quickly scanned the list and purchased the Edimax EW-7833UAC AC1750 Dual-Band Wi-Fi USB 3.0 Adapter, Supports Windows 7/8/8.1/10, Mac and Linux, because it was only $33.70 on Amazon and Eye P.A. is a fantastic visualization tool for analyzing wifi events. My company had previously purchased the software-only license for Eye P.A., but this adapter also supports Linux which is great for using horst and wireshark among the many free tools available.

Here is MetaGeek’s list as of July 2018:
Windows: 802.11ac adapters

Here is the full list of compatible adapters for 802.11a/b/g/n/ac packet capture built into Eye P.A.:

Linksys WUSB6300 (recommended)
ALFA Network AWUS1900
EnGenius EUB1200AC
D-Link DWA-182 rev C1
D-Link DWA-192
TP-LINK Archer T4U v2
TP-LINK Archer T4UH v2
Edimax EW-7822UAC
Edimax EW-7833UAC
Windows: 802.11n adapters

Linksys AE2500
Linksys AE1200
Netgear A6200 WiFi Adapters
RiverBed AirPcap Nx

Installing and capturing wifi with the EW-7833UAC via Eye P.A. in Windows was easy enough.

My Windows setup…

I did have a bit of trouble getting the EW-7833UAC adapter to work in Ubuntu 16.04, but I was eventually able to enable monitor mode and get horst and wireshark to start scanning and sniffing. At first I went to the Edimax site to download the driver version because Ubuntu is running kernel 4.13, but the make errored out. I also tried the 4.3.21 driver just to see, but make also errored out.

Then I found a post on the Ubuntu forums that sorted the driver out:

sudo apt-get update && sudo apt-get install git dkms
git clone
cd rtl8814au
gedit dkms.conf

Replace line 1 MAKE=”‘make'” with
MAKE="'make' all KVER=${kernelver}"
save and exit gedit, then
sudo dkms add ./rtl8814au
sudo dkms install rtl8814au/4.3.21

However, I was not able to put the device into monitor mode with:
sudo iw dev wlx123 set monitor

and had to use
sudo iwconfig wlx123 mode monitor

Now I can sniff, capture and analyze wifi with my dual boot laptop and be ready to study wifi wherever and whenever necessary.

My Linux setup…

By the way…if you haven’t already done so, go get some wifi coloring rules from these guys or make your own!


Begin Wifi Certification

Wifi Certification is something that I’ve been thinking about pursuing for a while now. There are many facets to wireless networking that I think I know, but I would like to know more and actually study the concepts. After listening to WLAN Pros podcast #153, I too asked myself, “Why haven’t you done it yet?”

The last certification I obtained was the CCNA almost 9 years ago to the day of this writing. There must be something about July that inspires me to get more done before the end of the year! Anyway, the CCNA cert was useful in the sense that I was able to configure new test scenarios and be more confident using Cisco gear, however after 3 years I decided not to renew because my overall job did not require the certification and higher level certifications were not tempting me.

The CWNE certification however appears to me to be a potentially great investment of time given the heavy focus on wireless test gear that my company is now providing. Furthermore, I would like to better understand the concepts behind the wireless specifications and features. I have first hand experience with many wireless networking features and would like to find out more. The amount of time I have to devote to study is limited, but my day job involves using wireless and testing wireless and I believe that in the next 6 months I should be able to make significant progress toward the CWNA as a starting point. So, here we go…