Roaming Analysis using only a Mac and Wireshark

There are many ways to examine the roaming performance of a Wi-Fi client. Perhaps the gold standard is to follow the client with a laptop running Omnipeek and several Wi-Fi adapters all capturing frames on different channels. I’m also impressed with 7signal’s recent update to Mobile Eye which now logs roaming data as well. But what if you don’t have that, or want to do something quickly with a Mac without switching to Windows and hooking up your Wi-Fi adapter array?

Using a Mac laptop to capture frames on a single channel with Airtool, you can still get valuable information about the roaming performance of a Wi-Fi client with a few Wireshark display filters and some I/O Graphs magic.

The process is simple. Discover the channel the test client is using, and start an over-the-air capture on that channel. Take you Mac and the test client and move out of the current AP’s cell so the client roams away, then come back so that the client roams back. Repeat as necessary until you have captured both a roam-away and a roam-back.

roam_capture
Let’s roam

Now it’s time to look at the captured frames. First, let’s build a display filter to only show the frames to/from the test client, as well as all of the AP’s beacon frames. We’re including the AP’s beacon frames so that we can see the changes in RSSI as the client moved away from then back towards the AP.

wlan.addr == aa:bb:cc:dd:ee:ff || ( wlan.ta contains 11:22:33:44:55 && wlan.fc.type_subtype == 8)

aa:bb:cc:dd:ee:ff is the MAC of the test client. 11:22:33:44:55 is the first five octects of the AP’s BSSID. By matching on the first five octets of the AP’s BSSID rather than the exact BSSID, we preserve the beacon frames from all of the AP’s BSSID’s, which will gives us more data to calculate the RSSI of the AP.

Once applied, export the displayed packets only to a new file that we’ll generate the graphs from. Open the new file and now we can configure the I/O Graphs. These are some of the display filters I use:

7925_roam_graph.png
The roam-away is on the left, and the roam-back is on the right.

AVG Tx Data Rate needs to be set with the test client MAC address, and AP RSSI needs to have the first five octets of the AP’s BSSID.

By zooming into the beginning of the graph, we can observe the client’s data frames, retries, Tx data rate, and the RSSI at which it roamed away. A benefit of dBm being measured in values less than zero is that it is separated from the rest of the data on the graph, so we have layer 1 data below 0, and layer 2 data above.

7925_roam_follow_roam

This Cisco 7925G phone roams away before the AP’s RSSI drops to 70 dBm, and before retries start to increase. We see similar good behavior when it roams back below.

7925_roam_follow_back

Let’s take a look at a Wi-Fi client that roams poorly. Here’s a client-that-shall-remain-nameless roaming away from an AP. You can see retries spiking and its data rate plummeting well before it roams away. The AP’s RSSI drops into the -80’s for most of a minute before it decides to roam!

bad_roam-filtered
This graph includes the test client’s average Tx data rate.

Of course, this approach has some limitations. You must know that a client like the one above was in range of a louder AP operating on a channel it supports when it started having trouble before you decide it’s a sticky client, otherwise it’s doing exactly what it should be doing–trying to maintain the only association it can.

You know when the client decided to roam, but you don’t know how long it took.

As you move away from the AP, you might see the AP’s RSSI spike to 0. That happens when your laptop’s adapter is unable to demodulate beacon frames from the AP due to poor SNR.

Also, the AP RSSI is measured by a Mac laptop that is following the test client. Unless the test client is the same model of Mac laptop, it will probably hear the AP differently, most likely with less sensitivity. My MacBook Pro is a 3×3:3 client, and the two test clients I looked at for this blog are both 1×1, so it’s reasonable to assume the Mac benefits from a significant increase in RSSI from MRC. Taking that into consideration, the poor roaming from the client-that-shall-remain-nameless is probably even worse than it looks.

Advertisements

Beware of mDNS Floods from Buggy Android Clients

android_sickRecently, I discovered a large increase in multicast traffic on an enterprise Cisco WLAN. This increase was large enough to cause packet loss in several areas where bandwidth is limited, usually at the WAN edge. While throughput remained within the acceptable range for a circuit, an extremely high packet rate was overwhelming the edge device’s capacity to process packets. So despite bandwidth utilization being normal, packet loss was still occuring.

The primary symptom of this problem was poor voice call quality on calls across the WAN, at seemingly random times, including periods where bandwidth utilization was very low.

A close inspection of one particular site uncovered abnormally high packet rates, measured in pps (packets per second). We used a span port to run a packet capture of the traffic, with the hope of isolating a source of the packet flood. Here’s what we found:

mdns-flood-protocols
Wireshark’s Protocol Hierarchy Window

37% of the packets on this busy WAN circuit were mDNS queries! More specifically, the sources were smartphones on the guest WLAN that were sending mDNS queries for Chromecasts, Apple TV’s, and other services advertised with mDNS. In a centrally-switched WLAN, all of that traffic is backhauled across the WAN to the WLC which services it. These queries were leaving remote sites in a CAPWAP tunnel, traversing the WAN to the WLC, which then forwarded them on to all of it’s AP’s at all other sites, once again traversing the WAN.

Once we had this data, it became any easy problem to fix. There was no business requirement for multicast on the guest WLAN, so we blocked it at the WLC using a layer 3 ACL. This ACL blocks all multicast, but we added a separate line for mDNS to get an idea of the volume of mDNS packets compared to other multicast traffic on the WLAN.

mdns-flood-acl
ACL to block all multicast on the WLAN

You can see from the hit counters that this guest WLAN is seeing a lot of mDNS traffic, which dwarfs any other multicast traffic. With this ACL in place, the problem was resolved. mDNS uses multicast address 224.0.0.251 and UDP port 5353, if you want to block it more precisely.

Looking back at our pre-ACL pcap, I observed several clients on the guest WLAN flooding the network with mDNS queries, which the WLC then forwarded back across the WAN to its AP’s. The top five worst offenders in the pcap were all Android phones, with OUI’s from Samsung, HTC, and LG, and they were each responsible dumping thousands of mDNS packets on the network in a matter of seconds.

mdns-flood-client-pcap
An unfiltered pcap from the WAN edge should not look like this!

In a network with several thousand guest devices, most of which are smartphones, if enough of these buggy Android phones are dumping mDNS queries like this, it could result in serious problems if it is not controlled. The packet rate at the WAN edge may cause issues with other traffic if it results in output drops (such as voice which we observed), and the increase in multicast traffic on the RF may be an issue as well if the WLAN handles multicast traffic normally, which means transmitting it at the lowest mandatory data rate. That will increase airtime utilization substantially, leaving less airtime for other clients to transmit and receive data.

Until recently, I did not understand what triggered this problem to occur. Now I do. There appears to be a bug in recent versions of Android that results in these mDNS floods when the phones leave sleep mode, resulting in thousands of frames being transmitted in the seconds after the client wakes up. TP-Link discovered the same behavior we observed and traced it to “recent releases of Android OS and Google Apps.”

For WLAN administrators, I suggest taking a few minutes to think through the implications of this issue for your network. As I discovered in my troubleshooting, it is very likely to affect more than just the guest WLAN.

PS: For those of you reading this that aren’t network engineers and think your wireless router is junk, it isn’t. And please stop jumping to the conclusion that the infrastructure is to blame for Wi-Fi problems! 80% of Wi-Fi problems are client device issues, not infrastructure issues.

Update: Google has acknowledged this issue and is releasing a patch via Google Play on January 18th.

Splunking Wi-Fi DFS Events

splunk-logo

One aspect of wireless networking that I’ve always struggled with is visibility into DFS events. Usually I catch them by chance by noticing two nearby AP’s on a site map using the same non-DFS channel, or maybe by casually looking through logs, but I’ve never felt like I had the reporting and alerting that should be in place for DFS events, because they can be very disruptive. An AP will abruptly change the channel it is operating on, and if it switches back, it may observe a “quiet period” of 60 seconds in which is does not transmit any data. Not good.

Enter Splunk.

Splunk is a powerful log analysis tool that you can think of as “Google for the data center.” It takes log data from almost any source and makes it as searchable as Google has made the web. For wireless network engineers, you can quickly and easily search syslog and SNMP data, build reports, and create alerts. Splunk Light is free and will process up to 5 GB of data a day, which should be plenty for most WLAN’s. It also runs easily on macOS if you just want to demo it locally.

Using Splunk I very quickly created this dashboard of real DFS data from SNMP traps coming from a Cisco WLC. It’s a little rough around the edges still (I need to figure out how to clean-up those AP names and channels), but it still shows me a lot of the valuable data.

splunk-dfs-report
Yes, DFS is a problem at this site.

I can easily create email alerts too, so that if a DFS event occurs an email is triggered, or if say 10 DFS events occur within 30 minutes an email is triggered.

How To

I installed Splunk on a Mac then setup the built-in snmptrapd to listen for incoming traps and log them to a file. For snmptrapd to interpret the SNMP traps from a Cisco WLC, download the Cisco MIB’s and copy them to /usr/share/snmp/mibs/. Then you can start snmptrapd.

Here’s the CLI one-liner to do that:

sudo snmptrapd -Lf /var/log/snmp-traps --disableAuthorization=yes -m +ALL

Next configure the WLC to send SNMP traps to the Splunk box by adding its IP address under Management -> SNMP -> Trap Receivers. While you’re there go to Trap Controls and turn everything on you want to analyze.

wlc-snmp

Even though DFS events only generate SNMP traps, it’s still a good idea to send syslog messages to Splunk too, so do that under Management -> Logs -> Config. Set the Syslog Level to “Informational” to get a lot of good data. “Debugging” is probably way too much. The Syslog Facility isn’t important.

wlc-syslog

Monitor the file snmptrapd is writing traps to to make sure it is working. Run this command on the Mac and you should see traps streaming in. If not you have some troubleshooting to do.

tail -f /var/log/snmp-traps

Now add the file to Splunk under Data -> Data inputs -> Files & directories, and you should be able to see the traps in searches.

Have a look at Splunk’s documentation on SNMP data for more setup help. Setting up syslog is easier. Under Data -> Data inputs -> UDP add UDP port 514 with the Source type “syslog.”

Once the data is coming into Splunk you can start searching it and creating fields. Search “RADIO_RC_DFS” (with quotes) to see all the DFS traps. From that search click “Extract new fields” and select the tab delimiter to parse the data. Give the AP name field a label, and then you can create visualizations of DFS events by AP name. Any search can also be used to trigger an alert, such as an email.

Cisco has published a WLC SNMP Trap Guide as well as a WLC syslog Guide that is helpful when working with this data. Find the messages you are looking for in those guides, then search for them in Splunk.

From there it’s all up to your own creativity. DFS events is just scratching the surface of Splunk’s potential. You can look at authentication events, monitor RRM, and there might be some interesting roaming analysis that can be done with this data as well. I’m sure there are some bright engineers out there that have taken this a lot farther. Please share your work!

802.11ac Encryption Upgrade

encryption

The security features provided by the IEEE 802.11 standard haven’t changed much since the 802.11i amendment was ratified in 2004, which is more commonly known by its Wi-Fi Alliance certification name WPA2. 802.11w protected management frames were introduced in 2009, but it is only recently that Wi-Fi chipsets for client devices have included support for it. WPA2 introduced the robust CCMP encryption protocol as a replacement for the compromised WEP-based encryption schemes of the past. CCMP utilizes stronger 128 bit AES encryption keys. As a general rule of thumb, if you aren’t using CCMP on a Wi-Fi network designed for security, you’re doing it wrong. It’s been out for a long time and older protocols have well-established weaknesses.

11acHowever, there are some new encryption changes in the 802.11ac amendment which have mostly flown under the radar. Besides 256 QAM, wider channels, and MU-MIMO, 802.11ac now includes support for 256 bit AES keys and the GCMP encryption protocol. Galois Counter Mode Protocol is a more efficient and performance-friendly encryption protocol than CCMP.

A few interesting nuggets from section 11.4 of the 802.11ac amendment:

The AES algorithm is defined in FIPS PUB 197-2001. All AES processing used within CCMP uses AES with either a 128-bit key (CCMP-128) or a 256-bit key (CCMP-256).

And…

CCMP-128 processing expands the original MPDU size by 16 octets, 8 octets for the CCMP Header field and 8 octets for the MIC field. CCMP-256 processing expands the original MPDU size by 24 octets, 8 octets for the CCMP Header field, and 16 octets for the MIC field.

By the way, you can download the 802.11ac amendment or the entire 802.11-2012 standard from the IEEE here for free. For more on these security changes read sections 8.4.2.27 and 11.4 of the 802.11ac amendment.

It seems odd that these changes were included in the 802.11ac amendment, and not in a separate security-focussed amendment like 802.11w and 802.11i. Nothing wrong with it, just unexpected. I’m curious to see if the 802.11ax amendment includes security changes as well.

Why the addition of 256 bit AES keys? It could have something to do with a few chinks in the armor of 128 bit AES keys. The current attacks appear to be impractical, but future attacks that take advantage of quantum computing may put 128 bit AES keys at risk. NIST thinks that larger key sizes are needed to defend symmetric AES keys like those used in WPA2 against quantum computer attacks, which they say will be operational within the next 20 years. I’ll take their word for it.

Because the amendment only specifies CCMP-128 as mandatory for RSN compliance, it’s very unlikely that we’ll see CCMP-256/GCMP-256 in use anytime soon. Further, enabling 256 bit cipher suites effectively disables support for all non-802.11ac clients as well as 802.11ac clients that only support the mandatory cipher suites (most of them?). That’s because CCMP-256 and GCMP-256 pairwise keys are only compatible with 256 bit group keys, breaking backwards compatibility with legacy clients. There are also a lot of 802.11n clients out there that aren’t going away anytime soon, so actually deploying CCMP-256/GCMP-256 will require a separate CCMP-256/GCMP-256-only SSID. Excited yet?

Further, I can’t find any documentation that suggests that infrastructure vendors have implemented CCMP-256/GCMP-256 at all, just a few slide decks here and there with an overview of the changes. These cipher suites appear to be optional, so I wonder if any VHT clients or AP’s actually support them today, and when they will in the future. The Linux Wi-Fi configuration API cfg80211 and driver framework mac80211 have added software support for it. That’s about all the implementation I have found. Perhaps PCS compliance or Wi-Fi Alliance certification will eventually force the issue, or perhaps it will go the way of 802.11n Tx beamforming and never be implemented. There are a lot obstacles to overcome before 256 bit keys become practical.

However, a VHT client can negotiate a GCMP-128 RSNA within a BSS that uses a backwards-compatible CCMP-128 group key, and the 802.11 standard does support multiple pairwise cipher suites within a BSS (remember TSN’s?). That allows the GCMP-128 pairwise cipher suite to be used alongside everyday CCMP-128 pairwise and group keys on real, production networks.

To tell if a BSS is using one of the new cipher suites in a packet capture, look at a beacon frame’s RSN information element. The cipher suite selector is always 00-0F-AC for the CCMP/GCMP encryption protocols, it’s the cipher suite type that distinguishes between the specific cipher suites. For example, 00-0F-AC:4 is the default CCMP-128, 00-0F-AC:9 indicates GCMP-256 and 00-0F-AC:10 indicates CCMP-256. Group keys for a BSS with protected management frames have their own suite type numbers. Look for multiple pairwise cipher suites to find support for the new stuff. Here’s the table of the new cipher suites. I’m on the lookout for 00-0F-AC:8 (GCMP-128), but I’ve yet to find a beacon frame with it advertised.

Table 8-99—Cipher suite selectors

OUI

Suite type  Meaning
00-0F-AC  4 CCMP-128 – default pairwise cipher suite and default group cipher suite for data frames in an RSNA
 00-0F-AC  6  BIP-CMAC-128—default group management cipher suite in an RSNA with management frame protection enabled
 00-0F-AC  8  GCMP-128 – default for a DMG STA
 00-0F-AC  9  GCMP-256
 00-0F-AC  10  CCMP-256
 00-0F-AC  11  BIP-GMAC-128
 00-0F-AC  12  BIP-GMAC-256
 00-0F-AC  13  BIP-CMAC-256

Interesting note that GCMP-128 is the default for a DMG STA, which is a directional multi-gigabit station defined in the 802.11ad amendment for operation in the 60 GHz band.

The standard limits the mixing of cipher suites so that the key sizes of the pairwise and group keys must match, and GCMP group keys can only be used with GCMP pairwise keys.

 

 

Chrome OS Wi-Fi Diagnostics

chromebook-logo

In the K-12 market Chromebooks are the most common devices used in 1:1 programs. If you are designing high density Wi-Fi networks for Chromebook 1:1 programs, it helps to know how to access their Wi-Fi statistics, logs, and networking tools. This knowledge is valuable for troubleshooting day-to-day Chromebook Wi-Fi issues as well.

The Basics

Despite its simplicity, Chrome OS, the Linux variant that Chromebooks run, does have some useful diagnostics tools that can help troubleshoot Wi-Fi problems. Most of these tools are included in the crosh shell, which you can open by typing Control-Alt-T. Here are some of my go-to crosh networking commands that don’t require an explanation.

ping
route
tracepath

 

This command provides some good Wi-Fi stats like retries, MCS index, and also RoamThreshold, which is the SNR at which this Chromebook will attempt to roam to a new BSS. Hopefully, one day we’ll be able to modify this value on enterprise-managed Chromebooks through the Google Apps admin console.

crosh> connectivity show devices

/device/wlan0
  Address: 485ab6######
  BgscanMethod: simple
  BgscanShortInterval: 30
  BgscanSignalThreshold: -50
  ForceWakeToScanTimer: false
  IPConfigs/0: /ipconfig/wlan0_0_dhcp
  Interface: wlan0
  LinkMonitorResponseTime: 3
  LinkStatistics/0/AverageReceiveSignalDbm: -61
  LinkStatistics/1/InactiveTimeMilliseconds: 8002
  LinkStatistics/2/LastReceiveSignalDbm: -62
  LinkStatistics/3/PacketReceiveSuccesses: 63919
  LinkStatistics/4/PacketTransmitFailures: 25
  LinkStatistics/5/PacketTrasmitSuccesses: 34432
  LinkStatistics/6/TransmitBitrate: 52.0 MBit/s MCS 11
  LinkStatistics/7/TransmitRetries: 60969
  Name: wlan0
  NetDetectScanPeriodSeconds: 120
  Powered: true
  ReceiveByteCount: 1610461765
  RoamThreshold: 18
  ScanInterval: 60
  Scanning: false
  SelectedService: /service/5
  TransmitByteCount: 133127986
  Type: wifi
  WakeOnWiFiFeaturesEnabled: not_supported
  WakeToScanPeriodSeconds: 900

 

This command is very useful in troubleshooting 802.1X issues. It shows more layer 2 details on all the BSS’s that have been discovered. In this case, /service/12 is an 802.1X network that the Chromebook is associated with, and /service/15 an open network also in range.

crosh> connectivity show services

/service/12
  AutoConnect: true
  CheckPortal: auto
  Connectable: true
  ConnectionId: 2069398120
  Country: US
  DNSAutoFallback: false
  Device: /device/wlan0
  EAP.AnonymousIdentity: anonymous
  EAP.CACert: 
  EAP.CACertID: 
  EAP.CACertNSS: 
  EAP.CertID: 
  EAP.ClientCert: 
  EAP.EAP: PEAP
  EAP.Identity: <username>
  EAP.InnerEAP: auth=MSCHAPV2
  EAP.KeyID: 
  EAP.KeyMgmt: WPA-EAP
  EAP.PIN: 
  EAP.PrivateKey: 
  EAP.RemoteCertification/0: /OU=Domain Control Validated/CN=<cn>
  EAP.RemoteCertification/1: /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
  EAP.RemoteCertification/2: /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
  EAP.RemoteCertification/3: /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
  EAP.SubjectMatch: 
  EAP.UseProactiveKeyCaching: false
  EAP.UseSystemCAs: true
  Error: Unknown
  ErrorDetails: 
  GUID: 5137BA48-0424-41B0-B5DE-29A427084925
  HTTPProxyPort: 34599
  IPConfig: /ipconfig/wlan0_1_dhcp
  IsActive: true
  LinkMonitorDisable: false
  ManagedCredentials: false
  Mode: managed
  Name: <SSID name>
  PassphraseRequired: false
  PortalDetectionFailedPhase: 
  PortalDetectionFailedStatus: 
  PreviousError: 
  PreviousErrorSerialNumber: 0
  Priority: 0
  PriorityWithinTechnology: 0
  Profile: /profile/chronos/shill
  ProxyConfig: 
  SaveCredentials: true
  SavedIP.Address: 192.168.1.20
  SavedIP.Gateway: 192.168.1.1
  SavedIP.Mtu: 0
  SavedIP.NameServers: 192.168.1.1
  SavedIP.PeerAddress: 
  SavedIP.Prefixlen: 26
  SavedIPConfig/0/Address: 192.168.1.20
  SavedIPConfig/1/Gateway: 192.168.1.1
  SavedIPConfig/2/Mtu: 0
  SavedIPConfig/3/NameServers/0: 192.168.1.1
  SavedIPConfig/4/PeerAddress: 
  SavedIPConfig/5/Prefixlen: 26
  Security: 802_1x
  SecurityClass: 802_1x
  State: online
  Strength: 35
  Tethering: NotDetected
  Type: wifi
  UIData: 
  Visible: true
  WiFi.AuthMode: 
  WiFi.BSSID: 00:11:74:##:##:##
  WiFi.Frequency: 5240
  WiFi.FrequencyList/0: 2412
  WiFi.FrequencyList/1: 2462
  WiFi.FrequencyList/2: 5240
  WiFi.FrequencyList/3: 5320
  WiFi.HexSSID: ########
  WiFi.HiddenSSID: false
  WiFi.PhyMode: 7
  WiFi.PreferredDevice: 
  WiFi.ProtectedManagementFrameRequired: false
  WiFi.RoamThreshold: 0
  WiFi.VendorInformation/0/OUIList: 00-03-7f

/service/15
  AutoConnect: false
  CheckPortal: auto
  Connectable: true
  ConnectionId: 0
  Country: US
  DNSAutoFallback: false
  Device: /device/wlan0
  EAP.AnonymousIdentity: 
  EAP.CACert: 
  EAP.CACertID: 
  EAP.CACertNSS: 
  EAP.CertID: 
  EAP.ClientCert: 
  EAP.EAP: 
  EAP.Identity: 
  EAP.InnerEAP: 
  EAP.KeyID: 
  EAP.KeyMgmt: NONE
  EAP.PIN: 
  EAP.PrivateKey: 
  EAP.SubjectMatch: 
  EAP.UseProactiveKeyCaching: false
  EAP.UseSystemCAs: true
  Error: Unknown
  ErrorDetails: 
  GUID: 
  HTTPProxyPort: 0
  IsActive: false
  LinkMonitorDisable: false
  ManagedCredentials: false
  Mode: managed
  Name: <SSID name>
  PassphraseRequired: false
  PortalDetectionFailedPhase: 
  PortalDetectionFailedStatus: 
  PreviousError: 
  PreviousErrorSerialNumber: 0
  Priority: 0
  PriorityWithinTechnology: 0
  Profile: 
  ProxyConfig: 
  SaveCredentials: true
  Security: none
  SecurityClass: none
  State: idle
  Strength: 44
  Tethering: NotDetected
  Type: wifi
  UIData: 
  Visible: true
  WiFi.AuthMode: 
  WiFi.BSSID: 7c:69:f6:##:##:##
  WiFi.Frequency: 5320
  WiFi.FrequencyList/0: 5240
  WiFi.FrequencyList/1: 5320
  WiFi.HexSSID: ##########
  WiFi.HiddenSSID: false
  WiFi.PhyMode: 7
  WiFi.PreferredDevice: 
  WiFi.ProtectedManagementFrameRequired: false
  WiFi.RoamThreshold: 0
  WiFi.VendorInformation/0/OUIList: 00-10-18

 

This command brings up a lot of valuable information including a dump of the latest full channel scan and the Wi-Fi chipset’s capabilities, among other useful data.

crosh> network_diag --wifi

iw dev wlan0 survey dump:
Survey data from wlan0
 frequency: 2412 MHz
 noise: -92 dBm
 channel active time: 63 ms
 channel busy time: 49 ms
 channel receive time: 45 ms
 channel transmit time: 0 ms
Survey data from wlan0
 frequency: 2417 MHz
 noise: -93 dBm
 channel active time: 62 ms
 channel busy time: 47 ms
 channel receive time: 41 ms
 channel transmit time: 0 ms
Survey data from wlan0
 frequency: 2422 MHz
 noise: -92 dBm
 channel active time: 63 ms
 channel busy time: 4 ms
 channel receive time: 0 ms
 channel transmit time: 0 ms

[truncated]

Survey data from wlan0
 frequency: 5220 MHz
 noise: -94 dBm
 channel active time: 124 ms
 channel busy time: 0 ms
 channel receive time: 0 ms
 channel transmit time: 0 ms
Survey data from wlan0
 frequency: 5240 MHz [in use]
 noise: -94 dBm
 channel active time: 15723 ms
 channel busy time: 513 ms
 channel receive time: 185 ms
 channel transmit time: 3 ms
Survey data from wlan0
 frequency: 5260 MHz
 noise: -94 dBm
 channel active time: 85031 ms
 channel busy time: 84907 ms
 channel receive time: 84907 ms
 channel transmit time: 84907 ms

[truncated]

iw dev wlan0 station dump:
Station 00:11:74:##:##:## (on wlan0)
 inactive time: 5444 ms
 rx bytes: 11797197
 rx packets: 38419
 tx bytes: 1703260
 tx packets: 9779
 tx retries: 14295
 tx failed: 43
 signal: -58 dBm
 signal avg: -60 dBm
 tx bitrate: 24.0 MBit/s
 rx bitrate: 300.0 MBit/s MCS 15 40MHz short GI
 authorized: yes
 authenticated: yes
 preamble: long
 WMM/WME: yes
 MFP: no
 TDLS peer: no
iw dev wlan0 scan dump:
BSS 00:11:74:##:##:##(on wlan0) -- associated
 TSF: 61418055#### usec (7d, 02:36:20)
 freq: 5240
 beacon interval: 100 TUs
 capability: ESS Privacy SpectrumMgmt ShortSlotTime (0x0511)
 signal: -60.00 dBm
 last seen: 847370 ms ago
 Information elements from Probe Response frame:
 Supported rates: 24.0* 36.0 48.0 54.0 
 DS Parameter set: channel 48
 Country: US Environment: Indoor/Outdoor
 Channels [36 - 36] @ 24 dBm
 Channels [40 - 40] @ 24 dBm
 Channels [44 - 44] @ 24 dBm
 Channels [48 - 48] @ 24 dBm
 Channels [52 - 52] @ 23 dBm
 Channels [56 - 56] @ 23 dBm
 Channels [60 - 60] @ 23 dBm
 Channels [64 - 64] @ 23 dBm
 Channels [100 - 100] @ 24 dBm
 Channels [104 - 104] @ 24 dBm
 Channels [108 - 108] @ 24 dBm
 Channels [112 - 112] @ 24 dBm
 Channels [116 - 116] @ 24 dBm
 Channels [120 - 120] @ 24 dBm
 Channels [124 - 124] @ 24 dBm
 Channels [128 - 128] @ 24 dBm
 Channels [132 - 132] @ 24 dBm
 Channels [136 - 136] @ 24 dBm
 Channels [140 - 140] @ 24 dBm
 Channels [144 - 144] @ 24 dBm
 Channels [149 - 149] @ 30 dBm
 Channels [153 - 153] @ 30 dBm
 Channels [157 - 157] @ 30 dBm
 Channels [161 - 161] @ 30 dBm
 Channels [165 - 165] @ 30 dBm
 Power constraint: 3 dB
 BSS Load:
 * station count: 2
 * channel utilisation: 4/255
 * available admission capacity: 31250 [*32us]
 HT capabilities:
 Capabilities: 0x9ef
 RX LDPC
 HT20/HT40
 SM Power Save disabled
 RX HT20 SGI
 RX HT40 SGI
 TX STBC
 RX STBC 1-stream
 Max AMSDU length: 7935 bytes
 No DSSS/CCK HT40
 Maximum RX AMPDU length 65535 bytes (exponent: 0x003)
 Minimum RX AMPDU time spacing: 8 usec (0x06)
 HT TX/RX MCS rate indexes supported: 0-15
 HT operation:
 * primary channel: 48
 * secondary channel offset: below
 * STA channel width: any
 * RIFS: 1
 * HT protection: no
 * non-GF present: 1
 * OBSS non-GF present: 0
 * dual beacon: 0
 * dual CTS protection: 0
 * STBC beacon: 0
 * L-SIG TXOP Prot: 0
 * PCO active: 0
 * PCO phase: 0
 VHT capabilities:
 VHT Capabilities (0x338001b2):
 Max MPDU length: 11454
 Supported Channel Width: neither 160 nor 80+80
 RX LDPC
 short GI (80 MHz)
 TX STBC
 RX antenna pattern consistency
 TX antenna pattern consistency
 VHT RX MCS set:
 1 streams: MCS 0-9
 2 streams: MCS 0-9
 3 streams: not supported
 4 streams: not supported
 5 streams: not supported
 6 streams: not supported
 7 streams: not supported
 8 streams: not supported
 VHT RX highest supported: 0 Mbps
 VHT TX MCS set:
 1 streams: MCS 0-9
 2 streams: MCS 0-9
 3 streams: not supported
 4 streams: not supported
 5 streams: not supported
 6 streams: not supported
 7 streams: not supported
 8 streams: not supported
 VHT TX highest supported: 0 Mbps
 VHT operation:
 * channel width: 1 (80 MHz)
 * center freq segment 1: 42
 * center freq segment 2: 0
 * VHT basic MCS set: 0xfffc
 WMM: * Parameter version 1
 * u-APSD
 * BE: CW 15-1023, AIFSN 3
 * BK: CW 15-1023, AIFSN 7
 * VI: CW 7-15, AIFSN 2, TXOP 3008 usec
 * VO: CW 3-7, AIFSN 2, TXOP 1504 usec
 RSN: * Version: 1
 * Group cipher: CCMP
 * Pairwise ciphers: CCMP
 * Authentication suites: IEEE 802.1X FT/IEEE 802.1X
 * Capabilities: PreAuth 1-PTKSA-RC 1-GTKSA-RC MFP-capable (0x0081)
 * 0 PMKIDs
 * Group mgmt cipher suite: AES-128-CMAC
iw dev wlan0 link:
Connected to 00:11:74:##:##:## (on wlan0)
 freq: 5240
 RX: 11797197 bytes (38419 packets)
 TX: 1703260 bytes (9779 packets)
 signal: -58 dBm
 tx bitrate: 24.0 MBit/s

 bss flags: short-slot-time
 dtim period: 1
 beacon int: 100

That’s a lot more Wi-Fi data than most other platforms make natively accessible.

Additionally, to view most of this data without crosh, use this internal Chrome URL. Just enter it into the address bar and hit enter.

chrome://system/

Areas of interest for Wi-Fi data:

  • network-devices – same output as the “connectivity show devices” crosh command
  • network-services – same output as the “connectivity show services” crosh command
  • wifi_status – same output as the “network_diag –wifi” crosh command
  • lspci – you can see the Wi-Fi chipset hardware here (more on that later)
  • network_event_log
  • netlog

Viewing Logs

You can start logging Wi-Fi events using this crosh command.

crosh> network_logging wifi

Old flimflam tags: []
Current flimflam tags: [device+inet+manager+service+wifi]

method return sender=:1.1 -> dest=:1.146 reply_serial=2
Old wpa level: info
Current wpa level: msgdump

View the resulting device event logs at this internal Chrome URL: chrome://device-log/

Run this command to view the kernel log, which includes a lot of Wi-Fi events. I wish there was a –follow option, but currently there is not.

crosh> dmesg

A restart will return the Chromebook to normal logging levels.

And if you really want to bury yourself in logs, go to chrome://net-internals/#chromeos, click Wi-Fi to enable debugging on that interface, let the “capturing events” count creep up while you perform a task, then click “Store debug logs” to save a debug-logs_<date>.tgz archive in your Downloads folder. Be warned, the signal to noise ratio is very low with this approach. Google provides a log analyzer that you can upload these files to, but I’ve never had the need to go that far down the road. This is best used if you need to submit logs to the Google Apps Enterprise Support Team or a hardware manufacturer.

Advanced Wi-Fi Analysis with Developer Mode

But wait, there’s more! If you can put a Chromebook into Developer Mode, you can run packet captures and break into the Linux bash shell. Most enterprise-managed Chromebooks will have this mode disabled for obvious reasons, but it’s easy enough to move your test Chromebook into a test OU and disable this and other restrictions for testing purposes. (That’s IT testing, not high-stakes student testing! Make sure your OU’s clearly differentiate the two.)

Packet Capture

First, determine which channel’s frequency you’d like to run the capture, and also if channel bonding is in use. The internal URL from above will work for this as well as the “network_diag –wifi” crosh command. The frequency of the currently associated BSS is displayed at the end of that output here.

…
iw dev wlan0 link:
Connected to 00:11:74:##:##:## (on wlan0)
 freq: 5240
 RX: 11797197 bytes (38419 packets)
 TX: 1703260 bytes (9779 packets)
 signal: -58 dBm
 tx bitrate: 24.0 MBit/s

 bss flags: short-slot-time
 dtim period: 1
 beacon int: 100
Screenshot 2016-05-09 at 2.37.00 PM
Disable the Wi-Fi NIC here.

Now turn off the Wi-Fi NIC in the GUI so it can be put into monitor mode.

You can now run the packet capture using the crosh command below.

Optionally, specify a secondary channel above or below the primary if you are doing a 40 MHz 802.11n capture by appending the “–ht-location <above|below>” flag.

 

crosh> packet_capture --frequency <frequency in MHz>

Capturing from phy0_mon.  Press Ctrl-C to stop.
^CCapture stored in /home/chronos/user/Downloads/packet_capture_7K08.pcap

You’ll get a pcap file complete with Radiotap headers if the hardware supports it saved in the Downloads folder which you can send to another machine to do analysis. If the Chromebook is all you have available, you can upload the pcap to CloudShark for analysis.

Wi-Fi Troubleshooting in Bash

Once you’ve got Developer Mode enabled, you can use the bash shell and follow the network log (or any other log) as things happen. This is my preferred way to troubleshoot Chromebook Wi-Fi issues in real time.

crosh> shell
chronos@localhost / $ tail -f /var/log/net.log

Now go do something to the Wi-Fi connection and watch the log scroll by.

A few Linux networking commands you may already know are available here as well like ifconfig, arp, and netstat.

Wi-Fi Chipset and Driver Information

While you’re in the bash shell, you can also determine the Wi-Fi chipset hardware in use. The output of this lspci command will only show the Wi-Fi adapter and the driver it is using. The basic output of lspci is included in chrome://system, but this method allows you to get more data. Add a -v flag or two to see even more.

crosh> shell
chronos@localhost /sys $ sudo lspci -nnk | grep -A2 0280

01:00.0 Network controller [0280]: Qualcomm Atheros AR9462 Wireless Network Adapter [168c:0034] (rev 01)
        Subsystem: Foxconn International, Inc. Device [105b:e058]
        Kernel driver in use: ath9k

This Acer C720 Chromebook has a Qualcomm Atheros AR9462 and uses the ath9k driver.

Run this command to discover the Wi-Fi chipset driver version. This is helpful if you want to know if the Wi-Fi chipset drivers were updated during a system update.

crosh> shell
chronos@localhost / $ sudo ethtool -i wlan0

driver: ath9k
version: 
firmware-version: 
bus-info: 0000:01:00.0
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

In this case no version number is reported, perhaps because the OS is using a generic Atheros driver that is packaged with the Linux kernel.

Below is the output of the same commands on an HP Chromebook 11 G4 running Chrome OS 41. This machine has an Intel Wireless-AC 7260 chipset and the driver and firmware-version are listed.

crosh> shell
chronos@localhost / $ sudo lspci -nnk | grep -A2 0280

01:00.0 Network controller [0280]: Intel Corporation Wireless 7260 [8086:08b1] (rev c3)
        Subsystem: Intel Corporation Dual Band Wireless-AC 7260 [8086:c070]
        Kernel driver in use: iwlwifi
crosh> shell
chronos@localhost / $ sudo ethtool -i wlan0

driver: iwlwifi
version: 3.10.18
firmware-version: 23.14.10.0
bus-info: 0000:01:00.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

The driver version appears to just be the Linux kernel version. The firmware-version is the chipset driver version.

Interestingly, after updating this HP Chromebook to Chrome OS 50, the Wi-Fi chipset firmware-version changed… but went down.

crosh> shell
chronos@localhost / $ sudo ethtool -i wlan0

driver: iwlwifi
version: 3.10.18
firmware-version: 16.229726.0
bus-info: 0000:01:00.0
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

An inspection of the iwlwifi version history shows that this driver is actually newer than the previous version. Before version 16 it was the third number in the version that indicated what major branch it came from, so version 23.14.10.0 was actually from the version 10 branch. Thankfully, that’s cleared up in newer versions of the driver so that the first number is the version branch.

It’s good to see that Google includes Wi-Fi chipset driver updates with Chrome OS updates. This is especially nice as system updates are downloaded and installed automatically to Chromebooks. Personally, I’ve seen system updates resolve odd Chromebook Wi-Fi problems and it’s possible the newer drivers are the solution.