← Back to Logs

How WiFi Actually Works: The Radio Protocol Nobody Reads

Try the interactive lab for this articleTake the quiz (6 questions · ~5 min)

WiFi is a radio protocol. That sentence should be obvious, but most developers treat WiFi as a magic pipe that turns send() into delivered packets. It is not. Between your application calling write() on a socket and the data arriving at the access point, a staggering amount of radio engineering, contention resolution, and frame management happens, all defined in the IEEE 802.11 family of standards.

This post is about what actually happens in that gap. We will go from the physical radio layer up through modulation, channel access, frame formats, authentication, and modern improvements in WiFi 6/7. If you have ever wondered why your 5 GHz signal dies when you walk two rooms away, or why one slow client can tank the throughput for everyone on the network, the answers are here.

1. The Physical Layer: OFDM and Subcarrier Modulation

WiFi transmits data using OFDM: Orthogonal Frequency Division Multiplexing. This is the modulation scheme that underpins everything from 802.11a (1999) onwards, excluding the original 802.11b which used DSSS (Direct Sequence Spread Spectrum). Understanding OFDM is non-negotiable if you want to understand WiFi performance.

The Core Idea

Instead of transmitting data on a single carrier frequency, OFDM splits the available bandwidth into many narrow subcarriers and transmits data on all of them simultaneously. In 802.11a/g (20 MHz channels), there are 64 subcarriers, of which 52 are used for data and pilots. In 802.11n/ac (40/80/160 MHz), the subcarrier counts scale accordingly: a 160 MHz channel in 802.11ac uses 512 subcarriers.

Each subcarrier is modulated independently using a conventional scheme (BPSK, QPSK, 16-QAM, 64-QAM, 256-QAM, or 1024-QAM in WiFi 6). The key property that makes this work is orthogonality: the subcarriers are spaced exactly 312.5 kHz apart (for a 20 MHz channel), which means that at the centre frequency of any given subcarrier, all other subcarriers have zero amplitude. They do not interfere with each other despite overlapping in the frequency domain.

The Fourier Transform Connection

This orthogonality is not a coincidence; it is a direct consequence of the Discrete Fourier Transform. Each OFDM symbol is constructed by performing an Inverse Fast Fourier Transform (IFFT) on the data symbols assigned to each subcarrier. The receiver performs an FFT to recover them. The mathematical condition for orthogonality is:

∫₀ᵀ e^(j2πf_k t) · e^(-j2πf_m t) dt = 0  for k ≠ m

Where T is the symbol duration and f_k, f_m are the frequencies of two different subcarriers. When the subcarrier spacing Δf = 1/T, this integral is exactly zero. The symbol duration in 802.11a/g is 3.2 μs (active symbol) plus a 0.8 μs guard interval (cyclic prefix), giving 4 μs per OFDM symbol.

Why OFDM Handles Multipath

This is the real genius of OFDM for indoor wireless. When a signal bounces off walls, furniture, and the ceiling in your Athens apartment, the receiver sees multiple delayed copies of the transmitted signal. This multipath propagation causes inter-symbol interference (ISI): the tail end of one symbol bleeds into the beginning of the next.

OFDM mitigates this with the cyclic prefix (CP). The last portion of each OFDM symbol is copied and prepended to the beginning. If the maximum delay spread of the channel is less than the CP duration, all the multipath copies of the symbol arrive within the CP window, and the FFT at the receiver can cleanly demodulate the signal without ISI. For 802.11a/g with a 0.8 μs CP, this handles delay spreads up to about 240 metres of path length difference, which is more than sufficient for any indoor environment.

Compare this to single-carrier systems, where the symbol rate is high (each symbol is short), and even a modest delay spread causes devastating ISI. OFDM trades symbol rate for symbol duration: each subcarrier has a low data rate but a long symbol, making multipath a non-issue.

Modulation and Coding Schemes (MCS)

The MCS index determines both the modulation order and the forward error correction (FEC) coding rate for each subcarrier. Higher MCS values pack more bits per symbol but require a cleaner signal (higher SNR). Here is a simplified table for 802.11ac, 20 MHz, single spatial stream:

MCS Modulation Coding Rate Data Rate (Mbps)
0 BPSK 1/2 6.5
3 16-QAM 1/2 26
5 64-QAM 2/3 58.5
7 64-QAM 5/6 65
8 256-QAM 3/4 78
9 256-QAM 5/6 86.7

WiFi 6 adds MCS 10 and 11, using 1024-QAM. MCS 11 with 1024-QAM 5/6 coding pushes 143.4 Mbps on a single 20 MHz stream. The tradeoff: 1024-QAM requires approximately 35 dB of SNR, which means you need to be close to the AP in a clean RF environment.

2. The Frequency Bands: 2.4 GHz, 5 GHz, and 6 GHz

WiFi operates in unlicensed ISM (Industrial, Scientific, Medical) and U-NII frequency bands. The properties of these bands determine range, penetration, available channels, and interference characteristics.

2.4 GHz (802.11b/g/n/ax)

The 2.4 GHz band spans 2400 to 2483.5 MHz in Europe (ETSI regulation). It is divided into 13 channels (channels 1 through 13; channel 14 is Japan-only), each 22 MHz wide (for legacy 802.11b) or 20 MHz wide (for 802.11g/n/ax), with 5 MHz centre-to-centre spacing.

Here is the problem: with 20 MHz channels spaced 5 MHz apart, most channels overlap. In the European 13-channel allocation, the non-overlapping channel sets are:

  • Channels 1, 5, 9, 13 (the European four-channel plan)
  • Channels 1, 6, 11 (the traditional three-channel plan, originating from the US where only channels 1 through 11 are permitted)

In practice, most European deployments still use 1/6/11 because the firmware defaults and channel selection algorithms are designed around US regulatory assumptions. This leaves two perfectly usable non-overlapping channels (5 and 13) on the table. If you are manually configuring APs in a European office building, use the four-channel plan. You will thank yourself.

The 2.4 GHz band has excellent propagation characteristics. The signal penetrates walls and floors better than 5 GHz (more on the physics below) and propagates further in open air. The cost: the band is absurdly congested. Every WiFi network, Bluetooth device, microwave oven (which leaks broadband 2.4 GHz energy), baby monitor, and cheap IoT sensor is competing for the same 83.5 MHz of spectrum.

5 GHz (802.11a/n/ac/ax)

The 5 GHz band offers dramatically more spectrum. In Europe, it spans roughly 5150 to 5875 MHz, divided into several sub-bands (U-NII-1, U-NII-2, U-NII-2 Extended, U-NII-3). With 20 MHz channels, you get approximately 25 non-overlapping channels. With 80 MHz channels (common in 802.11ac), you get 6 non-overlapping channels. With 160 MHz channels, you get 2 or 3 depending on regulatory domain.

The catch in Europe: DFS (Dynamic Frequency Selection). The U-NII-2 and U-NII-2 Extended sub-bands (5250 to 5350 MHz and 5470 to 5725 MHz) overlap with weather radar and military radar frequencies. ETSI regulations require that any device operating on these channels must implement DFS: the radio must listen for radar pulses before transmitting, and must vacate the channel within 10 seconds if radar is detected. This means:

  1. Your AP must perform a 60-second Channel Availability Check (CAC) before it can start transmitting on a DFS channel.
  2. During operation, the AP continuously monitors for radar. If detected, it sends a Channel Switch Announcement (CSA) to all clients and moves to a non-DFS channel.
  3. Some client devices have poor DFS support, causing them to disconnect entirely when the AP switches channels.

DFS channels are worth using in uncongested environments because they offer less interference (many consumer APs avoid them). In dense urban settings, the radar detection false positives and channel switching disruptions can be a nuisance.

6 GHz (WiFi 6E, 802.11ax)

WiFi 6E opens the 5925 to 6425 MHz band in Europe (the lower 6 GHz band, 500 MHz of spectrum). The US allocation is wider, covering 5925 to 7125 MHz (1200 MHz), but ETSI has so far only approved the lower portion. This gives European WiFi 6E devices 7 additional 80 MHz channels or 3 additional 160 MHz channels.

The 6 GHz band is greenfield: no legacy 802.11a/b/g/n/ac devices are permitted. Only WiFi 6E (and later WiFi 7) devices can operate here. This means no backwards-compatibility overhead, no protection mechanisms for legacy clients, and no legacy beacon frames consuming airtime.

Signal Propagation and Path Loss

Radio signals attenuate with distance according to the free-space path loss (FSPL) formula:

FSPL (dB) = 20·log₁₀(d) + 20·log₁₀(f) + 20·log₁₀(4π/c)

Where d is the distance in metres, f is the frequency in Hz, and c is the speed of light. At 1 metre distance:

  • 2.4 GHz: FSPL = 40.0 dB
  • 5 GHz: FSPL = 46.4 dB
  • 6 GHz: FSPL = 47.9 dB

Every doubling of distance adds 6 dB of loss. Every doubling of frequency adds 6 dB of loss. This is why 5 GHz has roughly 6 dB more path loss than 2.4 GHz at the same distance, which translates to noticeably shorter range.

Material Attenuation

This is where it gets painful for apartment dwellers. Signal attenuation through common building materials, measured at typical WiFi frequencies:

Material 2.4 GHz Loss (dB) 5 GHz Loss (dB)
Drywall/plasterboard 3-4 4-6
Interior wooden door 3-4 4-6
Glass (single pane) 2-3 6-8
Glass (double/low-E) 6-8 10-15
Concrete (15cm) 10-15 15-25
Reinforced concrete 15-20 25-35
Brick (single layer) 6-8 10-12
Metal door/elevator 15-20 20-30

A typical Greek apartment with concrete walls between rooms will attenuate a 5 GHz signal by 15 to 25 dB per wall. If your AP has a transmit power of 20 dBm (100 mW, the ETSI limit for 5 GHz indoor) and your client needs at least -75 dBm for a usable connection, you can do the arithmetic:

20 dBm (TX) - 46 dB (FSPL at 5m) - 20 dB (one concrete wall) = -46 dBm  (fine)
20 dBm (TX) - 52 dB (FSPL at 10m) - 40 dB (two concrete walls) = -72 dBm  (marginal)
20 dBm (TX) - 56 dB (FSPL at 15m) - 60 dB (three concrete walls) = -96 dBm  (dead)

This is why your 5 GHz network disappears in the bedroom three walls away. At 2.4 GHz, the path loss and wall attenuation are each roughly 6 to 10 dB less, which can be the difference between a working connection and no connection at all.

3. Channel Access: CSMA/CA and the Backoff Algorithm

Ethernet uses CSMA/CD (Carrier Sense Multiple Access with Collision Detection). WiFi cannot. In a wired network, a transmitter can simultaneously send and listen on the cable, detecting if another station is also transmitting (a collision). In radio, this is physically impossible: your own transmission drowns out any received signal. A WiFi radio's transmit power might be 20 dBm, while the incoming signal is -70 dBm. That is a 90 dB difference. No practical receiver can isolate the incoming signal under those conditions (though full-duplex WiFi research is working on self-interference cancellation, it is not in any shipping standard).

So WiFi uses CSMA/CA: Carrier Sense Multiple Access with Collision Avoidance. The goal is to avoid collisions rather than detect them.

The Step-by-Step Process

Here is what happens when a station (your laptop) has a frame to transmit:

Step 1: Carrier Sense. The station listens on the channel. It checks two things: the physical carrier sense (is there actual RF energy above the CCA threshold of -82 dBm?) and the virtual carrier sense (the NAV, Network Allocation Vector, a timer set by the Duration field in recently received frames). If either indicates the channel is busy, the station waits.

Step 2: Wait for DIFS. Once the channel has been idle, the station must wait for a DCF Interframe Space (DIFS) of 34 μs (at 5 GHz with 802.11a/ac). This ensures that higher-priority traffic (which uses shorter interframe spacings) gets to go first.

Step 3: Random Backoff. After DIFS, the station picks a random backoff value between 0 and CW (the Contention Window), starting at CW_min = 15 for 802.11a/ac. The station counts down this value in slot times (9 μs each), but only while the channel is idle. If the channel becomes busy during the countdown, the station freezes its counter and resumes when the channel is idle again (after another DIFS).

Step 4: Transmit. When the backoff counter reaches zero, the station transmits the frame.

Step 5: Wait for ACK. The receiver (typically the AP) must send an ACK frame after a SIFS (Short Interframe Space) of 16 μs. SIFS is shorter than DIFS, which guarantees that the ACK gets out before any other station's backoff counter expires.

Step 6: Collision Handling. If the station does not receive an ACK within the expected time, it assumes a collision occurred. It doubles the contention window (CW = min(2·CW + 1, CW_max)) and performs the random backoff again. CW_max is 1023, so after several consecutive failures, the backoff range grows from [0,15] to [0,31] to [0,63] and so on up to [0,1023]. This exponential backoff spreads out retransmissions and reduces collision probability.

The Interframe Spacing Hierarchy

The IFS values create a priority scheme:

IFS Duration (802.11a/ac) Purpose
SIFS 16 μs ACKs, CTS, next fragment
PIFS 25 μs Point Coordination Function (PCF)
DIFS 34 μs Normal data access
AIFS Variable (per AC) QoS access categories (802.11e/WMM)
EIFS 160 μs After receiving a corrupted frame

802.11e introduced EDCA (Enhanced Distributed Channel Access) with four Access Categories: Voice (AC_VO), Video (AC_VI), Best Effort (AC_BE), and Background (AC_BK). Each has its own AIFS (Arbitration IFS) and CW_min/CW_max values. Voice traffic uses AIFS = 25 μs and CW_min = 3, giving it faster channel access than best-effort traffic with AIFS = 34 μs and CW_min = 15.

Why Collisions Still Happen

CSMA/CA reduces collisions but cannot eliminate them. Two stations can complete their backoff counters at the exact same slot boundary and transmit simultaneously. The probability increases with the number of active stations and decreases with larger contention windows. For n stations with CW_min = 15, the collision probability per transmission attempt is approximately:

P_collision ≈ 1 - (1 - 1/CW_min)^(n-1)

With 10 stations: P ≈ 1 - (14/15)^9 ≈ 0.47. Nearly half of all first transmission attempts collide. This is why WiFi throughput degrades rapidly with the number of contending stations, even before the channel is saturated in terms of raw capacity.

4. The Hidden Node Problem

Consider three devices in a Barcelona apartment: your laptop (A), the access point (B) in the hallway, and your flatmate's phone (C) in the opposite bedroom. A can hear B. C can hear B. But A cannot hear C because two concrete walls separate them.

When A performs carrier sense before transmitting to B, it does not detect C's transmission. C performs carrier sense and does not detect A. Both transmit simultaneously to B, and B receives garbage from both. This is the hidden node problem, and it is one of the fundamental unsolved pain points of WiFi in dense environments.

RTS/CTS: The Theoretical Solution

802.11 defines a handshake mechanism to mitigate hidden nodes:

  1. Station A wants to transmit. Instead of sending data, it first sends a short RTS (Request to Send) frame to AP B, specifying the expected duration of the upcoming data exchange.
  2. AP B receives the RTS and responds with a CTS (Clear to Send) frame, which includes the duration value.
  3. Station C, which cannot hear A but can hear B, receives the CTS. It reads the duration value and sets its NAV timer accordingly, deferring its own transmission for that period.
  4. Station A, having received the CTS, now transmits its data frame with reduced collision risk.

This works because the AP acts as a relay for contention information: even though A and C cannot hear each other, they can both hear the AP.

Why RTS/CTS Is Rarely Used

In practice, RTS/CTS is almost never enabled. The reasons:

Overhead. Every data exchange now requires four frames (RTS, CTS, Data, ACK) instead of two (Data, ACK). For small frames (which are the majority of WiFi traffic), the RTS/CTS overhead can exceed the data payload. If your data frame is 500 bytes and takes 50 μs to transmit, the RTS (20 bytes, ~30 μs including preamble) and CTS (14 bytes, ~28 μs) add 58 μs of overhead, more than doubling the airtime consumption.

Threshold tuning. Most implementations allow setting an RTS threshold: RTS/CTS is only used for frames above a certain size. But tuning this threshold requires knowledge of the specific environment and traffic patterns. The default on most APs is 2347 bytes (effectively disabled, since most frames are smaller).

Partial deployment. RTS/CTS only helps if all stations can hear the AP. In multi-AP environments (mesh networks, enterprise deployments), stations may be associated with different APs, and the CTS from one AP does not protect against transmissions from clients of another AP on the same channel.

The practical solution in enterprise environments is not RTS/CTS but rather careful AP placement, channel planning, and transmit power adjustment to minimize hidden node scenarios. In a studio apartment, the problem rarely arises. In a 200-room hotel with APs on every floor, it is a constant battle.

5. The 802.11 Frame Structure

Every WiFi frame follows a structure defined in clause 9 of the 802.11 standard. Understanding the frame format is essential for troubleshooting with packet captures (Wireshark, tcpdump with monitor mode).

The General Frame Format

┌──────────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────┐
│ Frame Control│ Duration │ Address 1│ Address 2│ Address 3│ Seq Ctrl │ Address 4│   Body   │   FCS    │
│   (2 bytes)  │ (2 bytes)│ (6 bytes)│ (6 bytes)│ (6 bytes)│ (2 bytes)│ (6 bytes)│ (0-2304) │ (4 bytes)│
└──────────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────┘

The Frame Control field contains the frame type, subtype, and flags (To DS, From DS, More Fragments, Retry, Power Management, More Data, Protected Frame, Order).

The Three (or Four) Address Fields

This is one of the most confusing aspects of 802.11 for people coming from Ethernet. An Ethernet frame has two addresses: source and destination. A WiFi frame has three or four, because the wireless medium introduces an intermediary (the AP) that is not present on a wire.

The meaning of each address depends on the To DS and From DS bits:

To DS From DS Addr 1 (Receiver) Addr 2 (Transmitter) Addr 3 Addr 4
0 0 Destination Source BSSID N/A
1 0 BSSID (AP) Source (Client) Destination N/A
0 1 Destination BSSID (AP) Source N/A
1 1 Receiver AP Transmitter AP Destination Source

The first case (To DS=0, From DS=0) is for IBSS (ad-hoc) mode or management frames. The second (To DS=1) is a client sending to the AP for forwarding. The third (From DS=1) is the AP sending to a client. The fourth (both set) is the WDS (Wireless Distribution System) case, used when one AP forwards frames to another AP wirelessly. This is the only case that uses all four address fields.

Frame Types

802.11 defines three main categories:

Management frames handle network discovery, authentication, and association. Key subtypes:

  • Beacon (subtype 0x8): broadcast by the AP every 100 ms (the beacon interval), containing the SSID, supported rates, channel, RSN (security) information, and capabilities.
  • Probe Request/Response (0x4/0x5): active scanning. Your device broadcasts a probe request; APs respond with their capabilities.
  • Authentication (0xB): the initial authentication exchange.
  • Association Request/Response (0x0/0x1): the formal joining of a BSS.
  • Deauthentication (0xC) and Disassociation (0xA): the frames that kick you off the network. Notoriously, these were unauthenticated in WPA2, enabling trivial deauth attacks.

Control frames manage channel access and acknowledgements:

  • ACK (0xD): acknowledges received frames.
  • RTS/CTS (0xB/0xC): the contention handshake described above.
  • Block ACK (0x9): acknowledges multiple frames at once (introduced in 802.11n).

Data frames carry the actual payload. In modern networks, these are almost always QoS Data frames (subtype 0x8), which include a QoS Control field for WMM priority tagging.

What a Beacon Frame Contains

The beacon is the heartbeat of a WiFi network. A typical beacon frame includes:

  • Timestamp (8 bytes): the AP's TSF (Timing Synchronization Function) timer, used to synchronize clocks across the BSS.
  • Beacon Interval (2 bytes): typically 100 TU (Time Units, where 1 TU = 1024 μs), so roughly every 102.4 ms.
  • Capability Information (2 bytes): flags indicating ESS/IBSS, CF-Pollable, privacy (encryption required), short preamble, etc.
  • SSID (variable): the network name. Can be zero-length for hidden networks (which are not actually hidden from anyone with a packet sniffer).
  • Supported Rates (variable): the PHY rates the AP supports.
  • DS Parameter Set: the channel number.
  • TIM (Traffic Indication Map): indicates which power-saving clients have buffered frames waiting at the AP.
  • RSN Information Element: the security parameters (WPA2/WPA3, cipher suites, AKM suites).
  • HT/VHT/HE Capabilities: the 802.11n/ac/ax capability advertisements.

A single beacon frame is typically 200 to 400 bytes. At the mandatory minimum rate of 6 Mbps (802.11a/g) or 1 Mbps (802.11b), a beacon takes 267 to 533 μs or 1.6 to 3.2 ms to transmit, respectively. With multiple SSIDs on one AP (common in enterprise), each SSID gets its own beacon, and the airtime consumed by beacons alone becomes significant.

6. Authentication and the WPA2/WPA3 Handshakes

Connecting to a WPA2 network involves two phases: an 802.11 open authentication exchange (a vestigial formality) followed by the real security handshake using EAPOL (Extensible Authentication Protocol over LAN).

The WPA2 Four-Way Handshake

Assume WPA2-Personal (PSK mode). Before the handshake begins, both the client and the AP derive the PMK (Pairwise Master Key) from the pre-shared passphrase using PBKDF2:

PMK = PBKDF2(SHA1, passphrase, SSID, 4096, 256)

The 4096 is the iteration count, and 256 is the output length in bits. This computation is intentionally slow (to resist brute-force attacks on captured handshakes), taking roughly 50 to 100 ms on modern hardware.

The four-way handshake then derives session-specific keys:

Message 1 (AP to Client): The AP sends a random nonce, ANonce.

Message 2 (Client to AP): The client generates its own random nonce, SNonce. Using PMK, ANonce, SNonce, and both MAC addresses, it derives the PTK (Pairwise Transient Key) using the PRF (Pseudo-Random Function):

PTK = PRF-384(PMK, "Pairwise key expansion",
              min(AA, SPA) || max(AA, SPA) ||
              min(ANonce, SNonce) || max(ANonce, SNonce))

Where AA is the AP's MAC address and SPA is the client's MAC address. The PTK is split into:

  • KCK (Key Confirmation Key, 128 bits): used to generate MICs for EAPOL frames
  • KEK (Key Encryption Key, 128 bits): used to encrypt the GTK in message 3
  • TK (Temporal Key, 128 bits): the actual data encryption key

The client sends SNonce and a MIC (Message Integrity Code) computed with KCK. The AP can now independently derive the same PTK (it has all the inputs) and verify the MIC. If the MIC is valid, the client has proven knowledge of the PMK without transmitting it.

Message 3 (AP to Client): The AP sends the GTK (Group Temporal Key, used for broadcast/multicast traffic), encrypted with KEK, along with a MIC.

Message 4 (Client to AP): The client confirms receipt. Both sides install the PTK. Encrypted data transmission can begin.

Why This Matters for Security

The four-way handshake is vulnerable to offline dictionary attacks. An attacker who captures messages 1 and 2 has both nonces and both MAC addresses. They can compute the PTK for any candidate passphrase and check if the MIC matches. Tools like hashcat and aircrack-ng can test millions of passphrases per second. A weak passphrase (dictionary word, short length) will fall in minutes.

This is the core weakness of WPA2-PSK: it authenticates with a shared secret that both sides already know, and the handshake leaks enough information to enable offline brute-force.

WPA3 and SAE (Simultaneous Authentication of Equals)

WPA3 replaces the PSK handshake with SAE, based on the Dragonfly key exchange protocol (RFC 7664). SAE is a password-authenticated key exchange (PAKE) that provides:

Forward secrecy. Each session derives fresh keys. Capturing the handshake does not allow decryption of past sessions, even if the passphrase is later compromised.

Offline attack resistance. SAE is a zero-knowledge proof: the handshake does not reveal enough information to mount an offline dictionary attack. An attacker must interact with the AP (an online attack) for every passphrase guess, and the AP can rate-limit these attempts.

The Dragonfly exchange works as follows:

  1. Both sides derive a shared point on an elliptic curve from the password and their MAC addresses using a hash-to-curve operation.
  2. Each side generates a random scalar, computes an element (point multiplication on the curve), and exchanges a Commit message containing the scalar and element.
  3. Each side verifies the other's Commit and computes a shared secret (PMK).
  4. Both sides exchange Confirm messages (HMACs of the transcript) to verify consistency.

SAE operates before 802.11 Association, replacing the open authentication phase. It is also used in 802.11s (mesh networking) where there is no distinction between AP and client.

The transition mode (WPA3-Transition) allows both WPA2 and WPA3 clients on the same network, but this necessarily re-enables the WPA2 handshake for legacy clients, partially negating the security improvement. For a clean deployment, WPA3-only mode is strongly preferred.

7. Airtime Fairness and the Performance Anomaly

This is one of the least understood and most impactful problems in WiFi networking. It affects every multi-client network and explains why a single slow device can destroy performance for everyone.

The Problem

Consider an AP in a Berlin coworking space with two clients: Client A is 2 metres away with a strong signal, using MCS 9 (256-QAM, 86.7 Mbps on a 20 MHz channel). Client B is 15 metres away behind a wall, struggling with MCS 0 (BPSK, 6.5 Mbps).

CSMA/CA is "fair" in the sense that it gives each station an equal probability of winning channel access. Over time, each client gets roughly the same number of transmission opportunities. But a transmission opportunity for Client A sends data at 86.7 Mbps, while a transmission opportunity for Client B sends at 6.5 Mbps. Client B occupies the channel for 13 times longer to transmit the same amount of data.

The result: Client A achieves approximately 5 Mbps of throughput instead of the 40+ Mbps it could achieve alone. Client B also gets roughly 5 Mbps. The total network throughput drops from ~86 Mbps (if only Client A were present) to ~10 Mbps. This is the performance anomaly, first described by Heusse et al. in 2003.

Why It Happens

The mechanism is straightforward. When Client B transmits a 1500-byte frame at MCS 0, it occupies the channel for approximately 1.85 ms. During that time, no other station can transmit. Client A could have sent the same frame in 0.14 ms at MCS 9. The slow client effectively taxes every other client by consuming disproportionate airtime.

This is not a bug in CSMA/CA. CSMA/CA provides equal access probability, not equal throughput or equal airtime. The standard makes no distinction between a fast client and a slow one.

The Legacy Client Problem

The situation is even worse with 802.11b clients. An 802.11b device operates at 1 Mbps, 2 Mbps, 5.5 Mbps, or 11 Mbps, using DSSS modulation. When an 802.11b client is associated to an AP that also serves 802.11n/ac clients, the AP must:

  1. Transmit beacons at the lowest supported rate (1 Mbps for b/g compatibility) so all clients can decode them.
  2. Use the 802.11b preamble and header format (longer than the OFDM preamble).
  3. Apply CTS-to-self or RTS/CTS protection mechanisms before every OFDM transmission, to ensure legacy clients defer appropriately.

Each of these adds overhead. The protection mechanism alone (a CTS-to-self frame at 1 Mbps before every data frame) adds approximately 200 μs per frame. In a busy network, this can reduce aggregate throughput by 30 to 50 percent.

The engineering recommendation is clear: disable 802.11b support on every AP you control. There is no legitimate reason for a device manufactured after 2010 to require 802.11b.

Airtime Fairness Mechanisms

Some enterprise AP vendors (Cisco, Aruba, Ruckus) implement proprietary airtime fairness algorithms that give each client equal airtime rather than equal transmission opportunities. This means the AP schedules more transmission opportunities for fast clients and fewer for slow clients, ensuring that a slow client does not monopolise the medium.

WiFi 6 addresses this at the protocol level with OFDMA, which we will cover in the next section.

8. WiFi 6 (802.11ax), WiFi 6E, and WiFi 7 (802.11be)

WiFi 6: The Dense Deployment Standard

802.11ax was designed explicitly for high-density environments. Its key innovations operate at the MAC and PHY layers:

OFDMA (Orthogonal Frequency Division Multiple Access). This is the single most important change. In previous WiFi generations, a station owned the entire channel for the duration of its transmission. OFDMA allows the AP to subdivide the channel into Resource Units (RUs) and assign different RUs to different clients simultaneously. A 20 MHz channel can be divided into up to 9 RUs of 26 subcarriers each. A 160 MHz channel can serve up to 74 clients simultaneously.

This directly solves the airtime fairness problem for small packets (VoIP, IoT telemetry, web browsing). Instead of each client contending for the full channel, the AP coordinates small allocations to many clients in the same OFDM symbol time. Uplink OFDMA (trigger-based access) lets the AP poll multiple clients to transmit simultaneously on different RUs, replacing contention-based access with scheduled access for uplink traffic.

BSS Coloring. In dense environments, overlapping BSSs (Basic Service Sets) on the same channel cause the CCA mechanism to defer unnecessarily. If your AP and the neighbour's AP both use channel 36, your client detects the neighbour's transmissions as "busy" and defers. BSS Coloring adds a 6-bit BSS Color field to the PHY preamble. Each BSS is assigned a colour (0 to 63). A receiver can check the colour in the first few microseconds of a received frame and determine if it belongs to the same BSS. If not, it can apply a higher CCA threshold (OBSS/PD, Overlapping BSS Preamble Detection), effectively ignoring weaker signals from neighbouring BSSs and transmitting over them. This significantly improves spatial reuse.

TWT (Target Wake Time). An AP and client negotiate specific times for the client to wake up and exchange data. Between those times, the client can sleep deeply. This is critical for battery-powered IoT devices and also reduces contention: if 50 IoT sensors are scheduled to wake at staggered intervals, they never contend with each other.

1024-QAM. MCS 10 and 11 use 1024-QAM, packing 10 bits per symbol per subcarrier (up from 8 with 256-QAM). This is a 25% throughput improvement at close range, but it requires very high SNR (approximately 35 dB), limiting it to devices within a few metres of the AP with minimal interference.

Longer OFDM Symbol Duration. 802.11ax quadruples the OFDM symbol duration to 12.8 μs (from 3.2 μs in ac), with a correspondingly longer cyclic prefix (0.8, 1.6, or 3.2 μs). The subcarrier spacing narrows to 78.125 kHz (from 312.5 kHz). This improves performance in environments with long delay spreads and increases the FFT size to 256 (for 20 MHz), enabling finer-grained OFDMA resource allocation.

WiFi 6E: Same Protocol, More Spectrum

WiFi 6E is 802.11ax operating in the 6 GHz band. The protocol is identical. The benefit is purely from the additional spectrum: less congestion, no legacy devices, and the ability to use 160 MHz channels without fighting over the limited 5 GHz allocation.

In a dense European urban environment, WiFi 6E can provide consistent multi-gigabit throughput precisely because the 6 GHz band is (currently) uncrowded. This will change as adoption increases, but for the next few years, 6 GHz is the closest thing to a clean radio environment you will find indoors.

WiFi 7 (802.11be): Multi-Link Operation

WiFi 7, expected to be fully ratified in late 2026, introduces several significant changes:

MLO (Multi-Link Operation). A WiFi 7 device can simultaneously connect to an AP across multiple bands (2.4 + 5 + 6 GHz) or multiple channels within the same band. The device appears as a single logical entity at the MAC layer but can transmit and receive on multiple links concurrently. This provides:

  • Aggregated throughput across links
  • Seamless failover if one link becomes congested or degraded
  • Lower latency by selecting the least-busy link for each frame

4096-QAM. WiFi 7 pushes to 4096-QAM (12 bits per symbol), offering another 20% throughput improvement over 1024-QAM at extremely short range. The required SNR is approximately 40 dB, which limits practical use to devices within 2 to 3 metres of the AP.

320 MHz Channels. In the 6 GHz band (where sufficient spectrum exists), WiFi 7 supports 320 MHz channel widths, doubling the maximum bandwidth compared to WiFi 6. Combined with 4096-QAM and 16 spatial streams, the theoretical maximum PHY rate reaches 46 Gbps. Practical throughput will be a fraction of this, but single-link rates exceeding 5 Gbps are achievable in controlled conditions.

Preamble Puncturing. If a portion of a wide channel (say, a 20 MHz sub-channel within a 160 MHz channel) is occupied by another BSS or a radar signal, WiFi 7 can "puncture" that sub-channel and still use the rest. Previous standards required falling back to a narrower channel entirely.

9. Practical Wireless Analysis

Theory is good. Measurement is better. Here are the tools and commands for analysing WiFi in practice on Linux.

Scanning with iw

The iw command is the modern replacement for the deprecated iwconfig and iwlist:

# List wireless interfaces
iw dev
 
# Show interface details (associated BSSID, channel, signal strength)
iw dev wlan0 info
 
# Scan for networks (requires root or CAP_NET_ADMIN)
sudo iw dev wlan0 scan
 
# Show detailed scan results: SSID, BSSID, signal, channel, capabilities
sudo iw dev wlan0 scan | grep -E "SSID|signal|freq|BSS "
 
# Show current link quality and signal
iw dev wlan0 link
 
# Show station statistics (TX/RX bytes, bitrate, signal, retries)
iw dev wlan0 station dump

The station dump output is particularly valuable. Look for:

  • signal: the RSSI in dBm. Above -50 is excellent. -50 to -60 is good. -60 to -70 is fair. Below -70 is poor.
  • tx bitrate: the actual MCS and rate being used. If this is much lower than your device's maximum, you have a signal or interference problem.
  • tx retries: high retry counts indicate collisions or interference.
  • tx failed: frames that were retried the maximum number of times and dropped.

Monitor Mode and Packet Capture

For deeper analysis, put your wireless card into monitor mode:

# Take interface down
sudo ip link set wlan0 down
 
# Set monitor mode
sudo iw dev wlan0 set type monitor
 
# Bring it back up
sudo ip link set wlan0 up
 
# Set to a specific channel
sudo iw dev wlan0 set channel 36
 
# Capture with tcpdump
sudo tcpdump -i wlan0 -w capture.pcap
 
# Or use tshark for live filtering
sudo tshark -i wlan0 -Y "wlan.fc.type_subtype == 0x08" -T fields -e wlan.ssid -e wlan.bssid -e radiotap.dbm_antsignal

The tshark command above filters for beacon frames (type 0, subtype 8) and extracts the SSID, BSSID, and signal strength. This is the fastest way to survey the RF environment.

Channel Utilisation with wavemon

wavemon is a ncurses-based tool that provides real-time signal monitoring:

sudo apt install wavemon
wavemon

It shows signal level, noise level, SNR, link quality, and a histogram of signal strength over time. The "Scan" tab (press F3) shows nearby networks with their channels and signal levels.

Python: Parsing Beacon Frames with Scapy

For programmatic analysis, Scapy is the standard tool. This script scans for beacon frames and extracts network information:

#!/usr/bin/env python3
"""
WiFi beacon scanner using Scapy.
Requires: pip install scapy
Must run as root. Interface must be in monitor mode.
"""
 
from scapy.all import sniff, Dot11, Dot11Beacon, Dot11Elt, RadioTap
from collections import defaultdict
import time
import sys
 
networks = defaultdict(dict)
 
 
def parse_beacon(pkt):
    if not pkt.haslayer(Dot11Beacon):
        return
 
    bssid = pkt[Dot11].addr2
    stats = pkt[Dot11Beacon].network_stats()
    ssid = stats.get("ssid", "")
    channel = stats.get("channel", 0)
 
    # Extract signal strength from RadioTap header
    signal = None
    if pkt.haslayer(RadioTap):
        signal = pkt[RadioTap].dBm_AntSignal
 
    # Parse capability information
    cap = pkt[Dot11Beacon].cap
    crypto = set()
    if cap.privacy:
        crypto.add("WEP/WPA")  # Further inspection needed
 
    # Walk through information elements for RSN (WPA2/WPA3)
    elt = pkt[Dot11Beacon].payload
    while isinstance(elt, Dot11Elt):
        if elt.ID == 48:  # RSN Information Element
            crypto.discard("WEP/WPA")
            # Parse RSN IE for AKM suites
            rsn_data = bytes(elt.info)
            if len(rsn_data) >= 8:
                # Simplified: check for SAE (WPA3) AKM
                # AKM suite type 8 = SAE
                if b'\x00\x0f\xac\x08' in rsn_data:
                    crypto.add("WPA3-SAE")
                elif b'\x00\x0f\xac\x02' in rsn_data:
                    crypto.add("WPA2-PSK")
                elif b'\x00\x0f\xac\x01' in rsn_data:
                    crypto.add("WPA2-Enterprise")
                else:
                    crypto.add("WPA2")
        elt = elt.payload
 
    networks[bssid] = {
        "ssid": ssid,
        "channel": channel,
        "signal": signal,
        "crypto": crypto,
        "last_seen": time.time(),
    }
 
 
def print_results():
    print(f"\n{'BSSID':<20} {'SSID':<25} {'Ch':>3} {'Signal':>7} {'Security'}")
    print("-" * 80)
    for bssid, info in sorted(
        networks.items(), key=lambda x: x[1].get("signal") or -100, reverse=True
    ):
        sig = f"{info['signal']} dBm" if info["signal"] else "N/A"
        crypto = ", ".join(info["crypto"]) if info["crypto"] else "Open"
        print(f"{bssid:<20} {info['ssid']:<25} {info['channel']:>3} {sig:>7} {crypto}")
 
 
if __name__ == "__main__":
    iface = sys.argv[1] if len(sys.argv) > 1 else "wlan0"
    print(f"Scanning on {iface} (monitor mode required)...")
    print("Press Ctrl+C to stop and show results.\n")
 
    try:
        sniff(iface=iface, prn=parse_beacon, store=0)
    except KeyboardInterrupt:
        print_results()
        print(f"\nTotal networks found: {len(networks)}")

Run it with:

sudo python3 beacon_scanner.py wlan0

Channel Overlap Analyser

This script analyses which channels are congested in your environment:

#!/usr/bin/env python3
"""
Analyses channel congestion from beacon scan data.
Accounts for 2.4 GHz channel overlap (each channel is 20 MHz wide,
channels are spaced 5 MHz apart).
"""
 
from collections import defaultdict
 
# Example scan data: list of (channel, signal_dbm) tuples
# In practice, populate this from iw scan or scapy capture
scan_results = [
    (1, -45), (1, -62), (1, -78),
    (3, -55),
    (6, -40), (6, -51), (6, -68), (6, -72),
    (9, -60),
    (11, -42), (11, -59), (11, -65),
    (36, -50), (36, -71),
    (40, -48),
    (44, -55), (44, -67),
]
 
 
def channel_to_freq_mhz(ch):
    """Convert WiFi channel number to centre frequency in MHz."""
    if 1 <= ch <= 13:
        return 2407 + ch * 5
    elif ch == 14:
        return 2484
    elif 36 <= ch <= 165:
        return 5000 + ch * 5
    return 0
 
 
def compute_interference(scan_results):
    """
    Compute per-channel interference score.
    For 2.4 GHz, accounts for overlapping channels
    (20 MHz channel width, 5 MHz spacing).
    For 5 GHz, only co-channel interference is considered.
    """
    interference = defaultdict(float)
 
    for target_ch in range(1, 14):  # 2.4 GHz channels (EU: 1-13)
        target_freq = channel_to_freq_mhz(target_ch)
        for net_ch, signal in scan_results:
            if net_ch > 14:
                continue
            net_freq = channel_to_freq_mhz(net_ch)
            freq_diff = abs(target_freq - net_freq)
            # 20 MHz channel: overlap exists if centres are < 20 MHz apart
            if freq_diff < 20:
                # Overlap fraction: 1.0 for co-channel, decreasing linearly
                overlap = 1.0 - (freq_diff / 20.0)
                # Convert dBm to linear power for summation
                power_mw = 10 ** (signal / 10.0)
                interference[target_ch] += overlap * power_mw
 
    for target_ch in [36, 40, 44, 48, 52, 56, 60, 64, 100, 104,
                      108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
                      149, 153, 157, 161, 165]:
        for net_ch, signal in scan_results:
            if net_ch == target_ch:
                power_mw = 10 ** (signal / 10.0)
                interference[target_ch] += power_mw
 
    return interference
 
 
scores = compute_interference(scan_results)
print(f"{'Channel':>8} {'Band':>6} {'Interference Score':>20} {'Rating'}")
print("-" * 55)
for ch in sorted(scores.keys()):
    score = scores[ch]
    if score == 0:
        rating = "Clear"
    elif score < 1e-6:
        rating = "Low"
    elif score < 1e-4:
        rating = "Moderate"
    else:
        rating = "High"
    band = "2.4G" if ch <= 14 else "5G"
    print(f"{ch:>8} {band:>6} {score:>20.2e} {rating}")

10. CSMA/CA Backoff Simulation

To build intuition for how the backoff algorithm behaves under load, here is a C implementation that simulates contention among multiple stations:

/*
 * CSMA/CA Backoff Simulator
 * Simulates n stations contending for a shared channel using
 * the 802.11 DCF exponential backoff algorithm.
 *
 * Compile: gcc -O2 -o csma_sim csma_sim.c -lm
 * Run:     ./csma_sim <num_stations> <num_rounds>
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#define CW_MIN      15
#define CW_MAX      1023
#define SLOT_TIME   9       /* microseconds (802.11a/ac) */
#define SIFS        16      /* microseconds */
#define DIFS        34      /* microseconds */
 
typedef struct {
    int id;
    int backoff;
    int cw;
    int tx_success;
    int tx_collision;
    int total_backoff_slots;
} Station;
 
static int random_backoff(int cw) {
    return rand() % (cw + 1);
}
 
int main(int argc, char *argv[]) {
    if (argc < 3) {
        fprintf(stderr, "Usage: %s <num_stations> <num_rounds>\n", argv[0]);
        return 1;
    }
 
    int n = atoi(argv[1]);
    int rounds = atoi(argv[2]);
 
    srand((unsigned)time(NULL));
 
    Station *stations = calloc(n, sizeof(Station));
    for (int i = 0; i < n; i++) {
        stations[i].id = i;
        stations[i].cw = CW_MIN;
        stations[i].backoff = random_backoff(CW_MIN);
        stations[i].total_backoff_slots = stations[i].backoff;
    }
 
    long total_idle_slots = 0;
    long total_collisions = 0;
    long total_successes = 0;
 
    for (int round = 0; round < rounds; round++) {
        /* Find the minimum backoff among all stations */
        int min_backoff = stations[0].backoff;
        for (int i = 1; i < n; i++) {
            if (stations[i].backoff < min_backoff)
                min_backoff = stations[i].backoff;
        }
 
        /* Advance all counters by min_backoff slots */
        total_idle_slots += min_backoff;
        for (int i = 0; i < n; i++)
            stations[i].backoff -= min_backoff;
 
        /* Count how many stations reached zero */
        int tx_count = 0;
        int tx_ids[n];
        for (int i = 0; i < n; i++) {
            if (stations[i].backoff == 0) {
                tx_ids[tx_count++] = i;
            }
        }
 
        if (tx_count == 1) {
            /* Successful transmission */
            int sid = tx_ids[0];
            stations[sid].tx_success++;
            stations[sid].cw = CW_MIN;
            stations[sid].backoff = random_backoff(CW_MIN);
            stations[sid].total_backoff_slots += stations[sid].backoff;
            total_successes++;
        } else {
            /* Collision: all transmitting stations double their CW */
            for (int j = 0; j < tx_count; j++) {
                int sid = tx_ids[j];
                stations[sid].tx_collision++;
                stations[sid].cw = (stations[sid].cw * 2 + 1);
                if (stations[sid].cw > CW_MAX)
                    stations[sid].cw = CW_MAX;
                stations[sid].backoff = random_backoff(stations[sid].cw);
                stations[sid].total_backoff_slots += stations[sid].backoff;
            }
            total_collisions++;
        }
    }
 
    printf("Stations: %d, Rounds: %d\n", n, rounds);
    printf("Total successes:  %ld\n", total_successes);
    printf("Total collisions: %ld\n", total_collisions);
    printf("Collision rate:   %.2f%%\n",
           100.0 * total_collisions / (total_successes + total_collisions));
    printf("Avg idle slots:   %.1f\n",
           (double)total_idle_slots / (total_successes + total_collisions));
    printf("\nPer-station stats:\n");
    printf("%5s %10s %10s %12s\n", "ID", "Success", "Collision", "Avg Backoff");
    for (int i = 0; i < n; i++) {
        int total_tx = stations[i].tx_success + stations[i].tx_collision;
        double avg_bo = total_tx > 0
            ? (double)stations[i].total_backoff_slots / total_tx
            : 0;
        printf("%5d %10d %10d %12.1f\n",
               stations[i].id, stations[i].tx_success,
               stations[i].tx_collision, avg_bo);
    }
 
    free(stations);
    return 0;
}

Running this with different station counts illustrates the scaling problem:

$ ./csma_sim 2 10000
Collision rate:   6.12%
Avg idle slots:   7.4
 
$ ./csma_sim 10 10000
Collision rate:   32.87%
Avg idle slots:   5.2
 
$ ./csma_sim 50 10000
Collision rate:   71.43%
Avg idle slots:   2.1

With 50 contending stations, over 70% of transmission attempts result in collisions. The average idle time decreases (because someone always has a low backoff), but the collision waste is enormous. This is why WiFi 6's OFDMA, which replaces contention with scheduled access, is such a fundamental improvement for dense environments.

11. The Apartment Building Problem

Take a typical European apartment building. In Athens, Barcelona, or Paris, you might have 30 to 60 apartments in a single building, each with its own access point. Add the shops on the ground floor with their own networks, the building's CCTV system on WiFi, and assorted IoT devices, and you easily have 50 to 100 BSSs within radio range of any given apartment.

Co-Channel vs. Adjacent Channel Interference

There are two types of interference, and they are not the same.

Co-channel interference (CCI) occurs when two BSSs operate on the exact same channel. Paradoxically, this is the better type. Because both APs and their clients are on the same channel, they can decode each other's frames (or at least the preambles), set their NAV timers, and defer correctly. The CSMA/CA mechanism works as designed: the networks time-share the channel. Throughput is reduced, but the protocol functions correctly.

Adjacent channel interference (ACI) occurs when two BSSs operate on overlapping but not identical channels (for instance, channels 1 and 3 in the 2.4 GHz band). The signals overlap in frequency, but neither network can decode the other's frames. The energy from the adjacent channel appears as noise, raising the noise floor and degrading SNR. The CCA mechanism may or may not trigger (depending on the energy level), leading to inconsistent deferral behaviour. Some frames are corrupted, but the corruptions are not "clean" collisions that the protocol can handle, they are noise-induced errors that look like random bit flips.

This is why the universal advice is: use non-overlapping channels only. In 2.4 GHz, that means 1/6/11 (or 1/5/9/13 in Europe). Never set your AP to channel 3, 4, 7, 8, or any other overlapping channel. Many consumer routers default to "auto" channel selection, which often picks overlapping channels in a misguided attempt to find a "quiet" one.

Why Auto-Channel Selection Fails

Most consumer AP auto-channel algorithms work as follows:

  1. Scan the environment and count the number of BSSs on each channel.
  2. Measure the noise floor on each channel.
  3. Pick the channel with the fewest BSSs and/or lowest noise.

This sounds reasonable but fails in dense environments for several reasons:

Static snapshot. The scan happens at boot time (or periodically). WiFi traffic is bursty; a channel that looks quiet during a 200 ms scan window might be heavily loaded when actual traffic flows. The algorithm optimises for a moment in time.

Ignoring adjacent channel effects. Many auto-channel algorithms count BSSs per channel without accounting for ACI. If channels 1 and 11 each have 10 networks but channel 3 has zero, the algorithm picks channel 3. This creates adjacent channel interference with all 10 networks on channel 1, which is worse than sharing channel 1 with them.

No coordination. Every AP in the building runs its own auto-channel algorithm independently. When AP A switches to channel 6, AP B detects the change in its next scan and might switch away from channel 6, causing AP C to see channel 6 as empty and switch to it. This creates a musical-chairs situation where APs keep shuffling channels, each time disrupting clients with a brief connectivity loss.

Channel width greed. Many 5 GHz APs default to 80 MHz channel width. In the 5 GHz U-NII-1 band (channels 36 to 48), there is exactly one 80 MHz channel. If your AP uses it, it is occupying the entire sub-band, and so is every other AP in the building that made the same choice. Dropping to 40 MHz or even 20 MHz channels and having a clean, uncontested channel often delivers higher real-world throughput than an 80 MHz channel shared with five neighbours.

Practical Mitigation

For an apartment in a dense building, the best approach:

  1. Survey first. Use iw dev wlan0 scan or the Python scanner above to identify which channels are most congested in your specific location. Do this at peak hours (evenings), not 3 AM.

  2. Use 5 GHz or 6 GHz as primary. The higher bands have more channels and shorter range, meaning fewer neighbours interfere. If your apartment is small enough (most European apartments are), a single 5 GHz AP covers the entire space.

  3. Fix your channel. Disable auto-channel selection. Pick a non-overlapping channel manually based on your survey data.

  4. Use the narrowest channel width that meets your needs. If your internet connection is 200 Mbps, you do not need an 80 MHz channel that provides a 400 Mbps PHY rate but is shared with three neighbours. A 40 MHz channel with less contention will give you better sustained throughput.

  5. Reduce transmit power. Counter-intuitive, but lowering your AP's transmit power reduces the radius in which it causes interference to neighbours and the radius in which it receives interference from them. If your AP is covering a 60 square metre apartment, you do not need the transmit power to cover 200 metres of open field.

  6. Disable 2.4 GHz if possible. If all your devices support 5 GHz or 6 GHz, turning off the 2.4 GHz radio eliminates one source of interference for everyone in the building. If you need 2.4 GHz for IoT devices, set it to a fixed non-overlapping channel with minimum transmit power.

12. Putting It All Together

WiFi is a shared, half-duplex, contention-based radio network running in unlicensed spectrum. Every aspect of its design is a compromise: OFDM trades bandwidth efficiency for multipath resilience, CSMA/CA trades throughput for collision avoidance, wider channels trade interference resistance for raw speed. Understanding these tradeoffs lets you make informed decisions rather than blindly trusting default configurations.

The protocol has evolved remarkably from the original 1997 standard (2 Mbps, frequency hopping) to WiFi 7 (46 Gbps theoretical, multi-link, OFDMA). But the fundamental constraints remain: radio is a shared medium, unlicensed spectrum is crowded, and physics does not care about your throughput needs. Concrete absorbs 5 GHz signals. Hidden nodes cause collisions that no amount of firmware updates can fix. One slow client can tank performance for fifty fast ones.

The practical takeaway for anyone running a WiFi network: measure your RF environment, pick your channels deliberately, disable legacy protocols, and match your configuration to the physics of your space. A €50 access point with correct settings will outperform a €300 access point on auto-everything in a congested European apartment building.

If you want to go deeper, the IEEE 802.11 standard itself (IEEE Std 802.11-2020, plus amendments for ax and be) is freely available from the IEEE GET programme. It is over 7,000 pages. But now you have enough context to navigate the parts that matter.