1*9c5db199SXin Li# Codelab: Using wifi Autotests to learn 802.11 basics 2*9c5db199SXin Li 3*9c5db199SXin LiThe Autotest infrastructure provides packet capture functionality which we can 4*9c5db199SXin Liuse to intercept and view WiFi packets that are sent between the 5*9c5db199SXin LiDevice-Under-Test (DUT) and router during a test. In this codelab we will 6*9c5db199SXin Lianalyze the packet sequence during the connection process to learn the basics 7*9c5db199SXin Liof 802.11 connection protocols. 8*9c5db199SXin Li 9*9c5db199SXin Li## Setup 10*9c5db199SXin Li 11*9c5db199SXin Li### Prerequisites 12*9c5db199SXin Li 13*9c5db199SXin Li* Access to a wifi test setup (local or in test lab). Read the 14*9c5db199SXin Li [wificell documentation] for some background. 15*9c5db199SXin Li* Understanding of Autotest and the [test_that] command. 16*9c5db199SXin Li 17*9c5db199SXin Li### Configuration Considerations 18*9c5db199SXin Li 19*9c5db199SXin LiThis codelab can be completed from either a personal testing setup or a 20*9c5db199SXin Lidedicated setup in our testing lab, but there are a few special considerations 21*9c5db199SXin Liin each case. For instance, some of the commands in this lab will use the 22*9c5db199SXin Livariable `${DUT_HOSTNAME}`, and the value of this variable is dependent on the 23*9c5db199SXin Litesting setup that you use. Further considerations are included below in the 24*9c5db199SXin Liinstructions for each option. 25*9c5db199SXin Li 26*9c5db199SXin Li#### Using the wifi testing labs 27*9c5db199SXin Li 28*9c5db199SXin LiOur testing lab setups are operated through the skylab infrastructure. If you 29*9c5db199SXin Lidon't have the skylab tool installed on your machine, follow the instructions 30*9c5db199SXin Liin the [skylab tools guide]. 31*9c5db199SXin Li 32*9c5db199SXin LiOnce you have the skylab tool, you'll need to run the login command and follow 33*9c5db199SXin Liits instructions to get started. 34*9c5db199SXin Li 35*9c5db199SXin Li```bash 36*9c5db199SXin Liskylab login 37*9c5db199SXin Li``` 38*9c5db199SXin Li 39*9c5db199SXin LiFor this codelab, you will need to use a `wificell` test setup. Available DUTs 40*9c5db199SXin Lican be found on the [skylab portal]. To find a wificell test setup, visit the 41*9c5db199SXin Liportal and filter for *label-wificell = true* (the filter should already be 42*9c5db199SXin Liset when you click the link). You'll need to find a setup who's current task 43*9c5db199SXin Liis *idle* with dut_state *ready*, and then lock it while in use. To lock a DUT 44*9c5db199SXin Liin the skylab use this command to lease it for the specified number of 45*9c5db199SXin Liminutes (60 minutes should suffice for this codelab, but if your lease 46*9c5db199SXin Liexpires you can simply lease your DUT again): 47*9c5db199SXin Li 48*9c5db199SXin Li```bash 49*9c5db199SXin Liskylab lease-dut -minutes ${NUM_MINUTES} ${DUT_NAME} 50*9c5db199SXin Li``` 51*9c5db199SXin Li 52*9c5db199SXin Li*** note 53*9c5db199SXin Li**Note:** There are several similar fields on the bot page that can potentially 54*9c5db199SXin Libe confused. Bots are listed by their *id* field in the skylab search portal, 55*9c5db199SXin Liwhich usually takes a form similar to `crossk-chromeos15-row2-rack4-host6`. 56*9c5db199SXin Li*dut_name* is referred to in this document by the variable `${DUT_NAME}`, and 57*9c5db199SXin Liis typically the *id* without `crossk`, e.g. `chromeos15-row2-rack4-host6`. The 58*9c5db199SXin Lihostname for a DUT (`${DUT_HOSTNAME}` in this doc) is not shown on the skylab 59*9c5db199SXin Libot page, but it is the *dut_name* with '.cros' appended e.g. 60*9c5db199SXin Li`chromeos15-row2-rack4-host6.cros`. 61*9c5db199SXin Li*** 62*9c5db199SXin Li 63*9c5db199SXin LiAutotest requires a working build of the board type being tested on, so it is 64*9c5db199SXin Libest to pick a board for which you have already built an image on your machine. 65*9c5db199SXin Li 66*9c5db199SXin LiAutotest will automatically determine the hostnames of the router and packet 67*9c5db199SXin Licapture device but if you want to access them directly, say through ssh, 68*9c5db199SXin Liyou can use the hostnames **${DUT\_NAME}-router.cros** and 69*9c5db199SXin Li**${DUT\_NAME}-pcap.cros** respectively. You can access each with ssh 70*9c5db199SXin Lithrough the root user with password `test0000`. 71*9c5db199SXin Li 72*9c5db199SXin LiLastly, Autotest may have issues with hosts that have the `chameleon` label. 73*9c5db199SXin LiIf you are having [chameleon issues], the current workaround is to set 74*9c5db199SXin Li*enable_ssh_tunnel_for_chameleon: True* in 75*9c5db199SXin Li`src/third_party/autotest/files/global_config.ini`. 76*9c5db199SXin Li 77*9c5db199SXin Li#### Using a local testing setup 78*9c5db199SXin Li 79*9c5db199SXin LiFor a local test setup, you'll need a flashed DUT and two flashed Google-made 80*9c5db199SXin Liwifi routers that run ChromeOS, all running special test images. The 81*9c5db199SXin LiGoogle-made routers can be either of the boards `whirlwind` or `gale`, 82*9c5db199SXin Liand see [network_WiFi_UpdateRouter] for what images they should be running. 83*9c5db199SXin LiIn order for Autotest to determine the hostnames of your router and packet 84*9c5db199SXin Licapture device, you'll have to designate their IP addresses within your chroot. 85*9c5db199SXin LiAssign the IP address of your DUT to 'dut', and the IPs of your routers to 86*9c5db199SXin Li'dut-router' and 'dut-pcap' by adding lines like these to `/etc/hosts`: 87*9c5db199SXin Li 88*9c5db199SXin Li```bash 89*9c5db199SXin Lixxx.xxx.xxx.xxx dut-router 90*9c5db199SXin Lixxx.xxx.xxx.xxx dut-pcap 91*9c5db199SXin Lixxx.xxx.xxx.xxx dut 92*9c5db199SXin Li``` 93*9c5db199SXin Li 94*9c5db199SXin LiNow, you can use **${DUT\_HOSTNAME}** = '*dut*' and Autotest will use your 95*9c5db199SXin Lihosts file to find the other devices. The final consideration when using a 96*9c5db199SXin Lilocal testing setup is that the designated testbeds are contained in shielding 97*9c5db199SXin Liboxes which isolate them from other signals, while your local setup is 98*9c5db199SXin Liprobably held in open air. This means that your packet capture device will also 99*9c5db199SXin Lipick up packets from any other devices broadcasting in your area. This will make 100*9c5db199SXin Lithe packet feed noisier, but you can still find all the packets involved in the 101*9c5db199SXin Liconnection process so its not a dealbreaker for this codelab. 102*9c5db199SXin Li 103*9c5db199SXin Li### Let's get started 104*9c5db199SXin Li 105*9c5db199SXin Li[network_WiFi_SimpleConnect] is a very simple test that connects and disconnects 106*9c5db199SXin Lia DUT from a router, so it's ideal for our purposes in this codelab. The test 107*9c5db199SXin Liitself is held at `server/site_tests/network_WiFi_SimpleConnect/` in the 108*9c5db199SXin LiAutotest repository. Briefly look through this file to get a sense for what it 109*9c5db199SXin Liis doing. 110*9c5db199SXin Li 111*9c5db199SXin LiBefore you make any changes to code, be sure to start a new branch within the 112*9c5db199SXin LiAutotest repository. 113*9c5db199SXin Li 114*9c5db199SXin Li#### 1. Gather pcap data 115*9c5db199SXin Li 116*9c5db199SXin LiOur first goal is to initiate packet capture and record all of the frames that 117*9c5db199SXin Liour pcap device sees throughout the test. Conveniently, 118*9c5db199SXin Li[network_WiFi_SimpleConnect] already utilizes a pcap device, which is accessed 119*9c5db199SXin Liat `self.context.capture_host`. Before the testing starts, the test begins 120*9c5db199SXin Licapturing packets by calling `start_capture()` on the capture device, and after 121*9c5db199SXin Lithe test completes, `stop_capture()` completes the capturing process. 122*9c5db199SXin Li`stop_capture()` returns a list of filepaths that hold the captured packets, so 123*9c5db199SXin Lilet's store the results of this function in a variable: 124*9c5db199SXin Li 125*9c5db199SXin Li```python3 126*9c5db199SXin Licapture_results = self.context.capture_host.stop_capture() 127*9c5db199SXin Li``` 128*9c5db199SXin Li 129*9c5db199SXin LiThe pcap file is accessible at `capture_results[0].local_pcap_path`, so let's 130*9c5db199SXin Liprint out a dump of our captured packets. Add these lines after the call to 131*9c5db199SXin Li`stop_capture()`: 132*9c5db199SXin Li 133*9c5db199SXin Li```python3 134*9c5db199SXin Lipackets = open(capture_results[0].local_pcap_path, 'r') 135*9c5db199SXin Lilogging.info(packets.read()) 136*9c5db199SXin Lipackets.close() 137*9c5db199SXin Li``` 138*9c5db199SXin Li 139*9c5db199SXin LiNow, lets run the test and see what we can learn: 140*9c5db199SXin Li 141*9c5db199SXin Li```bash 142*9c5db199SXin Litest_that --fast -b ${BOARD} ${DUT_HOSTNAME} network_WiFi_SimpleConnect.wifi_check5HT20 143*9c5db199SXin Li``` 144*9c5db199SXin Li 145*9c5db199SXin LiThat's a lot of garbage. The packets aren't going to be much use to us in their 146*9c5db199SXin Licurrent state. In the next section, we'll use Wireshark to translate the packets 147*9c5db199SXin Liinto a readable form that we can study. 148*9c5db199SXin Li 149*9c5db199SXin Li#### 2. Use Wireshark to analyze the packets 150*9c5db199SXin Li 151*9c5db199SXin LiPyshark is a wrapper for Wireshark within Python, and we'll be using it in this 152*9c5db199SXin Licodelab to interperet our captured packets. Learn more at the 153*9c5db199SXin Li[Pyshark documentation] page. 154*9c5db199SXin Li 155*9c5db199SXin LiDelete the lines you just added and replace them with calls to Pyshark that will 156*9c5db199SXin Liparse and translate the packets, then write the packets to a file: 157*9c5db199SXin Li 158*9c5db199SXin Li```python3 159*9c5db199SXin Li 160*9c5db199SXin Liimport pyshark 161*9c5db199SXin Licapture = pyshark.FileCapture( 162*9c5db199SXin Li input_file=capture_results[0].local_pcap_path) 163*9c5db199SXin Licapture.load_packets(timeout=2) 164*9c5db199SXin Li 165*9c5db199SXin Lipacket_file = open('/tmp/pcap', 'w') 166*9c5db199SXin Lifor packet in capture: 167*9c5db199SXin Li packet_file.write(str(packet)) 168*9c5db199SXin Lipacket_file.close() 169*9c5db199SXin Li 170*9c5db199SXin Li``` 171*9c5db199SXin Li 172*9c5db199SXin LiRun the Autotest again and open `/tmp/pcap`. Look at that, tons of 173*9c5db199SXin Lihuman-readable data! Maybe even a little too much? Right now we're getting the 174*9c5db199SXin Lientirety of every packet, but we only need a few fields. As a final step, we're 175*9c5db199SXin Ligoing to parse out the needed fields from each packet so we can digest some 176*9c5db199SXin Lirelevant information about the connection process. Add the following methods to 177*9c5db199SXin Lithe global scope of [network_WiFi_SimpleConnect]: 178*9c5db199SXin Li 179*9c5db199SXin Li```python3 180*9c5db199SXin Li 181*9c5db199SXin Lidef _fetch_frame_field_value(frame, field): 182*9c5db199SXin Li layer_object = frame 183*9c5db199SXin Li for layer in field.split('.'): 184*9c5db199SXin Li try: 185*9c5db199SXin Li layer_object = getattr(layer_object, layer) 186*9c5db199SXin Li except AttributeError: 187*9c5db199SXin Li return None 188*9c5db199SXin Li return layer_object 189*9c5db199SXin Li 190*9c5db199SXin Li""" 191*9c5db199SXin LiParses input frames and stores frames of type listed in filter_types. 192*9c5db199SXin LiIf filter_types is empty, stores all parsed frames. 193*9c5db199SXin Li""" 194*9c5db199SXin Lidef parse_frames(capture_frames, filter_types): 195*9c5db199SXin Li frames = [] 196*9c5db199SXin Li for frame in capture_frames: 197*9c5db199SXin Li frame_type = _fetch_frame_field_value( 198*9c5db199SXin Li frame, 'wlan.fc_type_subtype') 199*9c5db199SXin Li if filter_types and frame_type not in filter_types: 200*9c5db199SXin Li continue 201*9c5db199SXin Li frametime = frame.sniff_time 202*9c5db199SXin Li source_addr = _fetch_frame_field_value( 203*9c5db199SXin Li frame, 'wlan.sa') 204*9c5db199SXin Li dest_addr = _fetch_frame_field_value( 205*9c5db199SXin Li frame, 'wlan.da') 206*9c5db199SXin Li frames.append([frametime, source_addr, dest_addr, frame_type]) 207*9c5db199SXin Li return frames 208*9c5db199SXin Li 209*9c5db199SXin Li``` 210*9c5db199SXin Li 211*9c5db199SXin LiUsing these functions, you can retrieve a timestamp, the source address, the 212*9c5db199SXin Lidestination address, and the frame subtype for every packet that your pcap 213*9c5db199SXin Lidevice captured over the course of the test. The keywords within 214*9c5db199SXin Li`parse_frames()` ('wlan.sa', 'wlan.da', 'wlan.fc_type_subtype'), are special 215*9c5db199SXin LiWireshark filters that correspond to the relevant data we are looking for. 216*9c5db199SXin LiThere are over 242000 such filters which you can find in the [wireshark docs]. 217*9c5db199SXin Li 218*9c5db199SXin LiNow we just need to call `parse_frames()` and upgrade our packet logging logic. 219*9c5db199SXin LiReplace the file logging logic from above with the following code which parses 220*9c5db199SXin Lithe frames into a much more readable format: 221*9c5db199SXin Li 222*9c5db199SXin Li```python3 223*9c5db199SXin Li 224*9c5db199SXin LiframeTypesToFilter = {} 225*9c5db199SXin Liframes = parse_frames(capture, frameTypesToFilter) 226*9c5db199SXin Li 227*9c5db199SXin Lipacket_file = open('/tmp/pcap', 'w') 228*9c5db199SXin Lipacket_file.write('{:^28s}|{:^19s}|{:^19s}|{:^6s}\n'.format( 229*9c5db199SXin Li 'Timestamp', 'Source Address', 'Receiver Address', 'Type')) 230*9c5db199SXin Lipacket_file.write('---------------------------------------------------------------------------\n') 231*9c5db199SXin Lifor packet in frames: 232*9c5db199SXin Li packet_file.write('{:^28s}|{:^19s}|{:^19s}|{:^6s}\n'.format( 233*9c5db199SXin Li str(packet[0]), packet[1], packet[2], packet[3])) 234*9c5db199SXin Lipacket_file.close() 235*9c5db199SXin Li 236*9c5db199SXin Li``` 237*9c5db199SXin Li 238*9c5db199SXin LiThis time when we run the test we can very concisely see every single packet 239*9c5db199SXin Lithat our pcap device captured, and we get only the data which is relevant to 240*9c5db199SXin Liour purposes. Later on we'll populate `frameTypesToFilter` to single out the 241*9c5db199SXin Liframes that are relevant to the connection/disconnection process, but first 242*9c5db199SXin Lilet's look deeper into the frames themselves. 243*9c5db199SXin Li 244*9c5db199SXin Li#### 3. Learn some 802.11 background 245*9c5db199SXin Li 246*9c5db199SXin LiBefore we start analyzing the packets, we need some background on 802.11 frames. 247*9c5db199SXin LiThe state machine below represents the 802.11 connection/disconnection protocol. 248*9c5db199SXin LiAs you can see, a connection's state is determined by the authentication and 249*9c5db199SXin Liassociation status between its devices. The types of packets that a device is 250*9c5db199SXin Liable to send and receive are dependent on the state of its connections. 251*9c5db199SXin Li 252*9c5db199SXin Li 253*9c5db199SXin Li 254*9c5db199SXin Li##### Authentication and Association 255*9c5db199SXin Li 256*9c5db199SXin LiIn order to ensure security, users must be authenticated to a network before 257*9c5db199SXin Lithey are allowed to use the network. The authentication process itself is not 258*9c5db199SXin Listrictly defined by the 802.11 protocol, but it usually consists of a robust 259*9c5db199SXin Licryptographic exchange that allows the network to trust the user. Once a user 260*9c5db199SXin Lihas been authenticated to the network, it is *trusted*, but it is still not 261*9c5db199SXin Liactually a member of the network until it has been *associated*. Association 262*9c5db199SXin Lican be thought of as the proccess of actually joining the network, and also 263*9c5db199SXin Liacts as a sort of *registration* that allows the network to determine which 264*9c5db199SXin Liaccess point to use for a given user. 265*9c5db199SXin Li 266*9c5db199SXin Li##### Class 1 frames 267*9c5db199SXin Li 268*9c5db199SXin LiClass 1 frames can be sent in any state, and they are used to support the basic 269*9c5db199SXin Lioperations of 802.11 connections. Class 1 frames are called *Management Frames* 270*9c5db199SXin Liand they allow devices to find a network and negotiate their connection status. 271*9c5db199SXin Li 272*9c5db199SXin Li**Some class 1 frames:** 273*9c5db199SXin Li 274*9c5db199SXin Li* *Beacons* are frames that access points send out on a regular interval to 275*9c5db199SXin Libroadcast their existence to the world. Devices are only aware of access points 276*9c5db199SXin Libecause they can see the beacon frames they send. 277*9c5db199SXin Li* Devices respond to beacons with *Probe Requests* which in turn let the 278*9c5db199SXin Linetwork know of their existence. The probe request also includes a list of all 279*9c5db199SXin Lidata rates the device supports, which the network can use to check for 280*9c5db199SXin Licompatibility with those supported by the access point. 281*9c5db199SXin Li* Access points respond with *Probe Responses* which either confirm or deny 282*9c5db199SXin Licompatibility. 283*9c5db199SXin Li* If the two are compatible, they can engage in the authentication/association 284*9c5db199SXin Liprocess as explained above with various *Association* and *Authentication* 285*9c5db199SXin Liframes. 286*9c5db199SXin Li 287*9c5db199SXin Li##### Class 2 frames 288*9c5db199SXin Li 289*9c5db199SXin LiClass 2 frames can only be sent from a successfully authenticated device, which 290*9c5db199SXin Limeans they can be sent in states 2 and 3. Class 2 frames are called 291*9c5db199SXin Li*Control Frames*, and their purpose is to allow authenticated devices to 292*9c5db199SXin Linegotiate the sending of data between them. Request to send (RTS), clear to send 293*9c5db199SXin Li(CTS), and acknowledge (ACK) are all examples of class 2 frames. 294*9c5db199SXin Li 295*9c5db199SXin Li##### Class 3 frames 296*9c5db199SXin Li 297*9c5db199SXin LiClass 3 frames can only be sent from an authenticated and associated device, 298*9c5db199SXin Limeaning they can only be sent while in state 3. Class 3 frames are 299*9c5db199SXin Li*Data Frames* and they make up all of the actual bulk of wireless 300*9c5db199SXin Licommunication. All frames which are used to send non-meta data between devices 301*9c5db199SXin Liare data frames. 302*9c5db199SXin Li 303*9c5db199SXin Li#### 4. Let's analyze some packets 304*9c5db199SXin Li 305*9c5db199SXin LiNow that we have a basic understanding of 802.11 frame classes, we can use our 306*9c5db199SXin Licaptured packets to study the 802.11 connection/disconnection protocol in 307*9c5db199SXin Liaction. Near the bottom of this page is a set of [lookup tables] that outline 308*9c5db199SXin Lievery type of frame in the 802.11 protocol, which you can use to determine what 309*9c5db199SXin Likind of packets we picked up. 310*9c5db199SXin Li 311*9c5db199SXin Li[Solutions and hints] to the questions below can be found after the 312*9c5db199SXin Lilookup tables at the bottom of this page, but please do your best to answer 313*9c5db199SXin Lithem yourself before referring to the solutions. 314*9c5db199SXin Li 315*9c5db199SXin LiLets see if we can answer some basic questions about your configuration based 316*9c5db199SXin Lion the context of the captured packets: 317*9c5db199SXin Li 318*9c5db199SXin Li1. What is the MAC address of your router? (you may already know this, but 319*9c5db199SXin Li try to infer from the context of the packets) 320*9c5db199SXin Li1. What is the MAC address of your DUT? 321*9c5db199SXin Li1. What is the beacon interval (time between beacons) of your router? 322*9c5db199SXin Li1. What could a receiver address of *ff:ff:ff:ff:ff:ff* indicate? 323*9c5db199SXin Li 324*9c5db199SXin LiNow, try to find the frames where the DUT and router negotiate their connection. 325*9c5db199SXin LiDepending on how noisy your setup is this could be somewhat difficult, but you 326*9c5db199SXin Lishould be able to see the authentication/association process in action by 327*9c5db199SXin Lilooking for some key frame types. (Hint: look for a class 3 frame being sent 328*9c5db199SXin Lifrom your DUT to your router, and work back to see the frames that got them 329*9c5db199SXin Lithere). Study the process and compare the flow to the frame class descriptions 330*9c5db199SXin Liabove. 331*9c5db199SXin Li 332*9c5db199SXin Li#### 5. Filter the frames and check your results 333*9c5db199SXin Li 334*9c5db199SXin LiWe can populate `framesToFilter` with frame type codes (i.e. '0x04') to show 335*9c5db199SXin Lionly the frames that are a part of the connection process. Based on what 336*9c5db199SXin Liyou know about the 802.11 state machine, begin filtering for frames 337*9c5db199SXin Lithat you know are relevant. Do not include beacon frames (type 0x08) because 338*9c5db199SXin Liwhile they are a part of the connection process, there are so many of them 339*9c5db199SXin Lithat they will clog up the output. After improving the filter, add the 340*9c5db199SXin Lifollowing code to the bottom of [network_WiFi_SimpleConnect] to produce another 341*9c5db199SXin Lioutput file which only shows the frametypes so the testing script can parse 342*9c5db199SXin Lithem. 343*9c5db199SXin Li 344*9c5db199SXin Li```python3 345*9c5db199SXin Li 346*9c5db199SXin Lioutput_file = open('/tmp/filtered_pcap', 'w') 347*9c5db199SXin Lifor packet in frames: 348*9c5db199SXin Li output_file.write(str(packet[3]) + '\n') 349*9c5db199SXin Lioutput_file.close() 350*9c5db199SXin Li 351*9c5db199SXin Li``` 352*9c5db199SXin Li 353*9c5db199SXin LiNow, test your ouput file by running the testing python script: 354*9c5db199SXin Li 355*9c5db199SXin Li```bash 356*9c5db199SXin Lipython wifi-basics-codelab-pcap-test.py 357*9c5db199SXin Li``` 358*9c5db199SXin Li 359*9c5db199SXin LiThis script will check your output to see if you've isolated the correct 360*9c5db199SXin Liframes and that the entire connection sequence can be seen. If the script 361*9c5db199SXin Lifails, keep adjusting your filter until it succeeds. After you have passed the 362*9c5db199SXin Litest, review `/tmp/pcap` again to see the entire process in action. Finally, 363*9c5db199SXin Lirefer back to the questions in [section 4] one last time to see if you've 364*9c5db199SXin Ligained any new insight into the 802.11 protocol. 365*9c5db199SXin Li 366*9c5db199SXin Li## Lookup Tables 367*9c5db199SXin Li 368*9c5db199SXin Li### Management Frames (Class 1) 369*9c5db199SXin Li 370*9c5db199SXin Li| Subtype Value | Hex Encoding | Subtype Name | 371*9c5db199SXin Li|---------------|--------------|------------------------| 372*9c5db199SXin Li| 0000 | 0x00 | Association Request | 373*9c5db199SXin Li| 0001 | 0x01 | Association Response | 374*9c5db199SXin Li| 0010 | 0x02 | Reassociation Request | 375*9c5db199SXin Li| 0011 | 0x03 | Reassociation Response | 376*9c5db199SXin Li| 0100 | 0x04 | Probe Request | 377*9c5db199SXin Li| 0101 | 0x05 | Probe Response | 378*9c5db199SXin Li| 1000 | 0x08 | Beacon | 379*9c5db199SXin Li| 1001 | 0x09 | ATIM | 380*9c5db199SXin Li| 1010 | 0x0a | Disassociation | 381*9c5db199SXin Li| 1011 | 0x0b | Authentication | 382*9c5db199SXin Li| 1100 | 0x0c | Deauthentication | 383*9c5db199SXin Li| 1101 | 0x0d | Action | 384*9c5db199SXin Li 385*9c5db199SXin Li### Control Frames (Class 2) 386*9c5db199SXin Li 387*9c5db199SXin Li| Subtype Value | Hex Encoding | Subtype Name | 388*9c5db199SXin Li|---------------|--------------|------------------------------| 389*9c5db199SXin Li| 1000 | 0x18 | Block Acknowedgement Request | 390*9c5db199SXin Li| 1001 | 0x19 | Block Acknowledgement | 391*9c5db199SXin Li| 1010 | 0x1a | Power Save (PS)-Poll | 392*9c5db199SXin Li| 1011 | 0x1b | RTS | 393*9c5db199SXin Li| 1100 | 0x1c | CTS | 394*9c5db199SXin Li| 1101 | 0x1d | Acknowledgement (ACK) | 395*9c5db199SXin Li| 1110 | 0x1e | Contention-Free (CF)-End | 396*9c5db199SXin Li| 1111 | 0x1f | CF-End+CF-ACK | 397*9c5db199SXin Li 398*9c5db199SXin Li### Data Frames (Class 3) 399*9c5db199SXin Li 400*9c5db199SXin Li| Subtype Value | Hex Encoding | Subtype Name | 401*9c5db199SXin Li|---------------|--------------|--------------------------------------------| 402*9c5db199SXin Li| 0000 | 0x20 | Data | 403*9c5db199SXin Li| 0001 | 0x21 | Data + CF-Ack | 404*9c5db199SXin Li| 0010 | 0x22 | Data + CF-Poll | 405*9c5db199SXin Li| 0011 | 0x23 | Data + CF-Ack+CF-Poll | 406*9c5db199SXin Li| 0100 | 0x24 | Null Data (no data transmitted) | 407*9c5db199SXin Li| 0101 | 0x25 | CF-Ack (no data transmitted) | 408*9c5db199SXin Li| 0110 | 0x26 | CF-Poll (no data transmitted) | 409*9c5db199SXin Li| 0111 | 0x27 | CF-Ack + CF-Poll (no data transmitted) | 410*9c5db199SXin Li| 1000 | 0x28 | QoS Data | 411*9c5db199SXin Li| 1001 | 0x29 | Qos Data + CF-Ack | 412*9c5db199SXin Li| 1010 | 0x2a | QoS Data + CF-Poll | 413*9c5db199SXin Li| 1011 | 0x2b | QoS Data + CF-Ack + CF-Poll | 414*9c5db199SXin Li| 1100 | 0x2c | QoS Null (no data transmitted) | 415*9c5db199SXin Li| 1101 | 0x2d | Qos CF-Ack (no data transmitted) | 416*9c5db199SXin Li| 1110 | 0x2e | QoS CF-Poll (no data transmitted) | 417*9c5db199SXin Li| 1111 | 0x2f | QoS CF-Ack + CF-Poll (no data transmitted) | 418*9c5db199SXin Li 419*9c5db199SXin Li## Solutions and hints 420*9c5db199SXin Li 421*9c5db199SXin Li### Configuration questions 422*9c5db199SXin Li 423*9c5db199SXin Li1. Your router should be sending many beacon packets (type 0x08 frames), so 424*9c5db199SXin Li look for the source address of the frames of type 0x08. 425*9c5db199SXin Li1. Your DUT can be recognized as the device which has a "conversation" with 426*9c5db199SXin Li your router. I.e. you should be able to see one IP which is the 427*9c5db199SXin Li sender/receiver of several different management frames (0x00, 0x01, etc.) 428*9c5db199SXin Li with your router. 429*9c5db199SXin Li1. The beacon interval is the time a device waits between sending beacon 430*9c5db199SXin Li frames. You can determine this interval for a device by finding the time 431*9c5db199SXin Li that passes between two beacons being transmitted by the 432*9c5db199SXin Li device. The beacon interval for your router is most likely 100ms. 433*9c5db199SXin Li1. A receiver address of *ff:ff:ff:ff:ff:ff* indicates that the frame is 434*9c5db199SXin Li being broadcasted to any receiver that can hear it. This is pattern is 435*9c5db199SXin Li used for beacon frames because these frames are intended as a sort of 'ping' 436*9c5db199SXin Li to all nearby devices. 437*9c5db199SXin Li 438*9c5db199SXin Li### Packet filter solution 439*9c5db199SXin Li 440*9c5db199SXin LiThe testing script is looking for a particular packet sequence that 441*9c5db199SXin Lishows the DUT and router connecting to each other. The golden connection 442*9c5db199SXin Lisequence is as follows: 443*9c5db199SXin Li 444*9c5db199SXin Li1. Probe Request: 0x04 445*9c5db199SXin Li1. Probe Response: 0x05 446*9c5db199SXin Li1. Authentication: 0x0b 447*9c5db199SXin Li1. Assoc Request: 0x00 448*9c5db199SXin Li1. Assoc Response: 0x01 449*9c5db199SXin Li1. Deauthentication: 0x0c 450*9c5db199SXin Li 451*9c5db199SXin LiIn practice, we have noticed that many of the recorded connection sequences do 452*9c5db199SXin Linot include an Assoc Request packet, so the script is tolerant of that case. 453*9c5db199SXin Li 454*9c5db199SXin LiFinally, the script also verifies that no non-relevant frames were included, 455*9c5db199SXin Liso any non class 1 frames in the output file will cause failure. (Although, 456*9c5db199SXin Lionly the frames in the sequence above are strictly required.) 457*9c5db199SXin Li 458*9c5db199SXin Li[chameleon issues]: https://crbug.com/964549 459*9c5db199SXin Li[lookup tables]: #lookup-tables 460*9c5db199SXin Li[network_WiFi_UpdateRouter]: ../server/site_tests/network_WiFi_UpdateRouter/network_WiFi_UpdateRouter.py 461*9c5db199SXin Li[network_WiFi_SimpleConnect]: ../server/site_tests/network_WiFi_SimpleConnect/network_WiFi_SimpleConnect.py 462*9c5db199SXin Li[Pyshark documentation]: https://kiminewt.github.io/pyshark/ 463*9c5db199SXin Li[section 4]: #4_let_s-analyze-some-packets 464*9c5db199SXin Li[skylab portal]: https://chromeos-swarming.appspot.com/botlist?c=id&c=task&c=dut_state&c=label-board&c=label-model&c=label-pool&c=os&c=provisionable-cros-version&c=status&d=asc&f=label-wificell%3ATrue&k=label-wificell&s=id 465*9c5db199SXin Li[skylab tools guide]: http://go/skylab-cli 466*9c5db199SXin Li[solutions and hints]: #solutions-and-hints 467*9c5db199SXin Li[test_that]: ./test-that.md 468*9c5db199SXin Li[wificell documentation]: ./wificell.md 469*9c5db199SXin Li[wireshark docs]: https://www.wireshark.org/docs/dfref/ 470