MCS and macOS

Ā·

In my previous article on MCS and Windows, I laid some groundwork on what MCS is and why it’s useful. Check out the first few paragraphs for that background info.

This time, let’s turn our attention toward macOS. The best way to dump the Wi-Fi settings in a human-readable format, would be:

sudo /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I

which yields something like:

     agrCtlRSSI: -45
     agrExtRSSI: 0
    agrCtlNoise: -92
    agrExtNoise: 0
          state: running
        op mode: station
     lastTxRate: 1300
        maxRate: 217
lastAssocStatus: 0
    802.11 auth: open
      link auth: wpa3-sae
          BSSID: 4c:43:41:4:1c:bc
           SSID: Flowers By Irene
            MCS: 9
  guardInterval: 800
            NSS: 3
        channel: 149,80

If you run that command without ā€œsudoā€, it doesn’t list the BSSID.

You can also run the above program with the -x flag, which will dump it in XML format, if you prefer that. Honestly, I feel like even though the output above is human-readable, it’s also easier to ā€œmachine readā€ than the XML.

While this gives me more information than Windows does, it doesn’t have a separate uplink vs. downlink indicator. The ā€œmaxRateā€ is also confusing. Before digging in too much, let’s look at another example:

     agrCtlRSSI: -33
     agrExtRSSI: 0
    agrCtlNoise: -88
    agrExtNoise: 0
          state: running
        op mode: station
     lastTxRate: 1200
        maxRate: 867
lastAssocStatus: 0
    802.11 auth: open
      link auth: wpa2-psk
          BSSID:
           SSID: Anudder
            MCS: 11
  guardInterval: 800
            NSS: 2
        channel: 52,80

This helps us understand that macOS likes round numbers. Technically, MCS 11 with two spatial streams on 80 MHz OFDMA with a 0.8μs GI is 1201 Mbps.

But we have that mysterious ā€œmaxRateā€ again. Before rounding to a whole number, 867 is actually 866.7, which is MCS 9 on 2 spatial streams on an 80 MHz channel with a 4μs GI. Perhaps that means it is the uplink rate… that seems conceivable.

From the first example, we have a maxRate of 217, which, before whole-number rounding, is likely 216.7, which is MCS 7 on 3 spatial streams, but on a 20 MHz channel, but we know we’re operating on an 80 MHz channel here.

Python Fun

At any rate (pun intended), parsing the output is pretty easy. Here’s a quick program I wrote to convert macOS’s output to a JSON file.

# /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I

import json

macOS_wifi_dump = """
    agrCtlRSSI: -33
     agrExtRSSI: 0
    agrCtlNoise: -88
    agrExtNoise: 0
          state: running
        op mode: station
     lastTxRate: 1200
        maxRate: 867
lastAssocStatus: 0
    802.11 auth: open
      link auth: wpa2-psk
          BSSID:
           SSID: Anudder
            MCS: 11
  guardInterval: 800
            NSS: 2
        channel: 52,80
"""

int_fields = [
    'agrCtlRSSI', 'agrExtRSSI', 'agrCtlNoise', 'agrExtNoise',
    'lastTxRate', 'maxRate', 'lastAssocStatus', 'MCS',
    'guardInterval', 'NSS'
]

airport = {}
for line in macOS_wifi_dump.strip().splitlines():
    if ":" in line:
        left, right = line.split(":", 1)
        key = left.strip()
        value = right.strip()
        airport[key] = int(value) if key in int_fields else value

airport['channel'], airport['width'] = [int(x) for x in airport['channel'].split(',')]

my_json = json.dumps(airport, indent=4)
print(my_json)

The output would look like this:

{
    "agrCtlRSSI": -33,
    "agrExtRSSI": 0,
    "agrCtlNoise": -88,
    "agrExtNoise": 0,
    "state": "running",
    "op mode": "station",
    "lastTxRate": 1200,
    "maxRate": 867,
    "lastAssocStatus": 0,
    "802.11 auth": "open",
    "link auth": "wpa2-psk",
    "BSSID": "",
    "SSID": "Anudder",
    "MCS": 11,
    "guardInterval": 800,
    "NSS": 2,
    "channel": 52,
    "width": 80
}

My original idea behind MCS fiddling was in order to write a parser that would calculate all the MCS values in order to:

  • Output a matrix like the one found on mcsindex.com
  • Output a JSON file with the data rate being the key and an array of objects containing each of the possibilities

I may do that at some point in the future. I may also do some Linux ā€œiwā€ MCS observations. For now, at least, it’s good to know what some of the capabilities and restrictions are for reading from macOS.