[ DOTSTAR_SYSTEMS ]

blog article

Three Ways to Fake Wi-Fi, One Merged: Zephyr's New hwsim

Linux has had mac80211_hwsim for years; Zephyr had nothing like it — you couldn't test the Wi-Fi supplicant without a radio on the bench. Three different fixes landed on the table at once; an RFC and a Wi-Fi telco sorted out which does what, and I built and merged the in-process one: N virtual radios in a single image, running real WPA2 and WPA3 handshakes with zero hardware. Here's the design call, the one problem that makes it hard on Zephyr specifically, and the war story of getting SAE green.

Three Ways to Fake Wi-Fi, One Merged: Zephyr's New hwsim

A note before this starts: this was my own initiative, not a client brief. I maintain Zephyr’s Wi-Fi stack and drivers — which includes its hostap (wpa_supplicant/hostapd) integration — and I contribute to the hostap upstream project itself. I’d wanted Linux-grade Wi-Fi testability in Zephyr — the whole supplicant exercised with no radio on the bench — for years. It landed in a commercial context: the work was done while engaged with Nordic Semiconductor, a Dotstar client, and the driver carries Nordic’s copyright. This is my own engineering account of how it was designed and landed, in a personal capacity; it isn’t a statement from Nordic. The idea, the design call, and any mistakes are mine.

The short version for a product team: this is how you test a complete Wi-Fi stack — WPA2, WPA3, the lot — in CI, in seconds, with no radios to buy or babysit. Everything after that is how it was built, and how it was led to a clean upstream merge.

The one-paragraph version

Zephyr’s Wi-Fi stack — the same wpa_supplicant/hostapd code that runs on real silicon — could not be tested without real silicon. Every scan, every 4-way handshake, every WPA3-SAE exchange in CI needed a physical radio and a physical access point sitting on a bench somewhere. Linux solved this a decade ago with mac80211_hwsim, a kernel module that fakes the radio so the entire software stack can be exercised against itself. Zephyr had no equivalent. This is the story of building one — wifi_hwsim, now merged as zephyr#111236: N virtual Wi-Fi radios inside a single Zephyr image, connected by an in-process “medium,” running the real supplicant with real crypto, so that open, WPA2-PSK, and WPA3-SAE all connect and ping — deterministically, on native_sim, with no hardware anywhere. It was one of three approaches on the table, and picking between them mattered as much as writing the code.

The idea itself wasn’t new. It had been logged as a Zephyr enhancement years earlier — zephyr#84027, “evaluate the best strategy for Wi-Fi simulation based tests” — and then sat, for want of time more than want of interest. What changed is prosaic and worth being honest about: LLM-assisted development made a job this fiddly — a driver shim, a wpa_supplicant/hostapd integration, three security paths, and walls of protocol tracing — tractable in a way it simply hadn’t been before. That’s what finally let two of these land in the same window: this in-process driver, and Jukka’s, which had been quietly coming together in the background to make a Zephyr native_sim process and the host Linux mac80211_hwsim talk to each other. Two long-idle ideas, unblocked at roughly the same moment by better tooling.

This post is two things at once, deliberately: a deep dive into the one problem that makes this genuinely hard on Zephyr (it has no network namespaces), and a walk through how the work was actually run — idea, to a public RFC comparing three designs, to a decision taken in the open at the Wi-Fi telco, to a reviewed and merged upstream contribution. The engineering and the way of working are both the point.

Why this was worth doing at all

Start with the use case, because it’s the whole justification. A Wi-Fi stack is a huge amount of protocol software — association state machines, the EAPOL 4-way handshake, WPA3’s SAE dragonfly exchange, key derivation, PMF — and almost none of it needs a radio to be logically wrong. But if the only way to run it is against hardware, then:

  • CI can’t cover it. Regression tests that need a bench don’t run on every pull request. They run rarely, by hand, if at all — which is exactly how a 10× crypto regression rides into a release unnoticed (I’ve written about one).
  • It’s not deterministic. Real RF is flaky. A test that sometimes fails because the air was noisy teaches people to ignore failures.
  • It doesn’t scale. You can’t give every developer two radios and an AP. You can give every developer a native_sim binary that runs in 2.7 seconds.

mac80211_hwsim gives Linux all of that: a virtual medium where the complete stack — including a real hostapd acting as the AP — runs against itself with only the transceiver faked. That’s the target. Nothing above the antenna should be simulated; the supplicant shouldn’t know it isn’t talking to a real radio.

Leading the design, not just shipping a patch

There’s more than one way to give Zephyr a Wi-Fi test harness, and the approaches are genuinely different in their trade-offs — not better and worse, but suited to different jobs. So rather than push my preferred patch and let the others sort themselves out in review, I opened an RFC that laid the whole design space out side by side, so the community could reason about the choice explicitly. Three approaches were live at the same time:

A — in-process hwsim (this PR)B — native_sim + host nl80211C — emulated driver
How it fakes the radioAn in-process frame-relay “medium” between virtual radiosZephyr’s native_sim talks to the host Linux kernel’s real mac80211_hwsimNo radio at all — a test API injects scan results and connect outcomes
Runs onnative_sim, QEMU, any Zephyr targetLinux host onlyAny target
Protocol fidelityFull: real EAPOL, real SAE, real supplicant/APFull: leans on the battle-tested kernel moduleScripted events only — no EAPOL, no hostapd
AP + STA in one imageYesNeeds the host to provide the APNo
The hard partZephyr has no network namespaces (see below)Needs kernel-module + elevated privilege on CI runnersN/A — it deliberately simulates nothing

The RFC’s conclusion wasn’t “mine wins.” It was that these are complementary, and saying so plainly is the useful part. Approach B (Jukka’s, zephyr#110681) leans on a kernel module that has been hardened for a decade — it’s the right tool for manual and application-protocol testing (MQTT, HTTPS over a real medium), and it was approved for exactly that. Approach C (Pieter’s, zephyr#111194) deliberately fakes nothing below the management API — perfect for unit-testing an application’s reconnection logic or scan throttling, and pointless overkill for handshake testing. Approach A — the one this post is about — is the only one that runs the complete stack, AP included, on any target with no host dependency. That portability is the reason it’s the one that can gate every CI job on every platform.

And none of that was decided unilaterally, which is the part I’d underline. The comparison lived in the RFC; the decision was made in the open, at the Zephyr Wi-Fi biweekly telco, with the people who own the surrounding code in the room — Jukka, Pieter, Maochen, Hui Bai, Satish Nallamala, Robert Lubos. As Zephyr’s Wi-Fi maintainer I was one of them, which is exactly why the job was to build consensus rather than to win an argument. The minutes are terse, and paraphrased they read:

ApproachSimulatorIts job
Ahwsim (this PR)Wi-Fi-focused testing + CI
Bnative_sim + host mac80211_hwsimManual + app-protocol testing (MQTT, HTTPS); CI deferred — needs sudo on runners
CDropped — covered by A + B

Next step: test and merge the open PRs, and find names for A and B that better convey their intent. Getting three contributors to converge on “these are complementary — here’s who does what”, instead of three overlapping PRs competing to be the Wi-Fi test harness, took as much care as any patch in the diff. The goal was never to win the merge — it was to make the merge uncontentious.

Choosing A meant signing up for its hard problem with eyes open. That’s the next section, and it’s the technical heart of the whole thing.

The architecture: N radios, one process, one medium

The shape is simple to state. Each virtual radio is a Zephyr net_if running Ethernet L2 plus the Wi-Fi offload API — from the network stack’s point of view, an ordinary Wi-Fi interface. They’re wired together by a small in-process medium (wifi_hwsim_medium.c): a mutex-protected registry of radios and a frame-relay function. Each radio has an RX thread draining a k_fifo; frames are fixed-size slab allocations (HWSIM_FRAME_MTU = 2346, an 802.11 max frame) carrying a source index, a channel, and — a detail that matters — an explicit is_mgmt flag.

The relay rules fall straight out of what each frame type is for:

  • Data frames (802.3) are delivered by destination MAC: a unicast frame goes to the single radio whose link address matches; a broadcast/multicast frame (mac[0] & 0x01) goes to every peer on the same channel. That’s a medium behaving like a medium.
  • Management frames (802.11) are broadcast to every same-channel peer and handed up to the supplicant. That’s the air.

Early code guessed a frame’s type by peeking at the 802.11 frame-control byte; that got replaced with the explicit is_mgmt flag set at the two call sites, so the medium never has to parse a frame to route it. Radios only ever hear peers on the same freq_mhz, so retuning a radio’s channel is how you connect a STA to an AP — exactly like real hardware.

How the radio is faked: each virtual radio is an ordinary net_if with its own RX thread draining a k_fifo; an in-process medium relays fixed-size slab frames between them. Data frames route by destination MAC — unicast to the one matching radio, broadcast/multicast to all peers on the same frequency; management frames broadcast to same-frequency peers and go up to the supplicant. Radios only hear peers on the same freq_mhz.

That’s the easy 80%. Now the hard part.

The one problem that makes this hard on Zephyr

Linux’s mac80211_hwsim gets a gift from the kernel that Zephyr does not: network namespaces. On Linux, each virtual radio lives in its own netns, so a frame from the STA to the AP and the AP’s reply back are isolated by the kernel — two radios, two separate network stacks, no confusion about who owns which IP.

Zephyr has no network namespaces. Every virtual radio shares one global IP stack. And that single shared stack is full of correctness guards that assume “an address that belongs to me” means “don’t put this on the wire” — which is precisely the assumption you have to defeat when both ends of the link are you.

  Linux mac80211_hwsim            Zephyr wifi_hwsim
  --------------------            -----------------
  each virtual radio in its       ALL radios share ONE IP stack
  own network namespace           (Zephyr has no netns)
        |                                 |
        v                                 v
  STA->AP and AP->STA are         the stack sees the peer's IP as
  isolated by the kernel;         "one of my own addresses" and
  replies route correctly         short-circuits the frame INTERNALLY,
                                   so it never reaches the medium
The whole difficulty in one picture: no namespaces means the shared IP stack keeps "helpfully" delivering inter-radio traffic to itself.

I flagged this in the RFC as the open question for Approach A — and, at the start, a stale note in my own project memory insisted it was unsolvable: that inter-radio data traffic in a single process fundamentally needed separate IP stacks. That turned out to be wrong, which is worth saying out loud, because the resolution is the satisfying part. The problem is real but it’s entirely solvable in the driver — no core networking changes — once you find the three guards and the lever for each.

The data path, three guards and three levers. A ping from one radio to another must survive: guard 1 in net_core.c, which loops any packet whose destination is a local address back internally without ever transmitting — defeated by CONFIG_NET_IP_ADDR_CHECK=n; guard 2 in ipv4.c, which drops any packet whose source is a local address with "DROP: src addr is mine" — defeated by marking injected RX frames with net_pkt_set_loopback(pkt, true); and the routing question of which radio an inbound frame belongs to — answered by MAC-based relay in the medium. Every fix lives in the driver or test config, with zero changes to core networking.

The debugging that surfaced these was the classic peel-one-layer-at-a-time. The first trace of a ping between two virtual radios showed the echo request from 192.168.2.1 → 192.168.1.1 being answered in the same receive queue at the same timestamp — the frame never left the stack. That’s guard one, in net_core.c: it swaps addresses and loops any packet destined for a local address straight back, and because both radios’ IPs are “mine,” every inter-radio packet qualified. CONFIG_NET_IP_ADDR_CHECK=n turns that off.

With TX finally reaching the medium, ARP worked — and the ICMP request now got dropped on the far radio instead. Grep the drop message and you land on ipv4.c: DROP: src addr is mine. Same root cause, other direction — the peer’s source IP is also local in this one-stack image. The stack makes an exception for genuinely looped-back packets, so the fix is to mark every frame the hwsim RX thread injects with net_pkt_set_loopback(pkt, true). (A separate check confirmed that flag doesn’t interfere with delivery to the raw packet socket that EAPOL rides — important for what comes next.)

Defeat all three and a full ARP + ICMP round-trip crosses the emulated medium between two radios that share one IP stack. 5 of 5 tests green. That’s the data path — but “ping works” is table stakes. The reason to build this at all is to run the secured handshakes.

The bet that made security work: relay the association, not the frame

When I first wired up open association I hardcoded the STA as authorized=1 — associated, done, no handshake. A reviewer asked the obvious question: can we actually test the 4-way handshake? The honest first answer was “no.” The much more interesting answer, after pushing on it, was “yes — and the way to do it tells you something about how FullMAC drivers really work.”

Here’s the tempting-but-wrong approach: make the STA build real 802.11 authentication and association frames, put them on the medium, and have the AP parse them back. That’s a SoftMAC design, and it means writing (and debugging) an 802.11 frame builder and parser purely to serialize data between two contexts that are already in the same process.

Looking at how the real nrf_wifi FullMAC driver behaves reframed it. When wpa_supplicant runs its connection state machine (SME) in-host, it doesn’t hand the driver a frame — it hands it a params struct (the RSN IE, the SAE auth data, and so on). A FullMAC driver packs those params off to firmware, firmware builds the actual over-the-air frame, and the result comes back up as an event. In hwsim, both “firmwares” live in the same process. Serializing to an 802.11 frame just to re-parse it on the other side is pure ceremony.

So the design is: relay the association as a firmware-style event between radio contexts, and only put real frames on the medium when they carry real crypto.

The security bet. A real FullMAC driver hands wpa_supplicant's params to firmware, which builds an 802.11 frame, sends it over the air, and the peer firmware parses it back into an event. In hwsim both firmwares live in one process, so the STA's .associate injects the association straight into the AP's supplicant context as a firmware-style EVENT_ASSOC carrying the STA's RSN IE — no frame is built or re-parsed. Only real cryptography crosses the medium as real frames: the EAPOL 4-way handshake as 0x888E data frames (113, 141, 217, 113 bytes) and WPA3-SAE commit/confirm as real 802.11 authentication frames.

Concretely, the STA’s .associate injects an EVENT_ASSOC — carrying the STA’s own wpa_ie as the association request IEs — into the peer AP radio’s supplicant context, which is exactly what a FullMAC firmware reports upward. The AP’s supplicant routes that into hostapd_notif_assoc(), builds the station, and starts the authenticator. Crucially, for a secured network the STA now reports its own association with authorized=0, so the real 4-way handshake actually runs — and EAPOL crosses the medium as ordinary 0x888E data frames, the real messages with the real MICs. When it worked, the trace showed the handshake as four frames on the wire: 113 / 141 / 217 / 113 bytes — msg1 through msg4.

Getting there flushed out a genuinely sneaky bug. WPA2-PSK connect kept failing with “no suitable network found,” and the supplicant debug (all 12 million lines of it) pinned the reason: the STA’s scan result showed wpa_ie_len=0 rsn_ie_len=0 — every hwsim AP looked open. The scan-results path was synthesizing a fake IE set (SSID, rates, DSSS param) and never surfacing the AP’s real RSN element from its beacon. The AP had computed a perfectly good RSNE; the STA just never saw it. Fix: carry the AP’s real beacon IEs into the scan result, skipping the fixed prefix. WPA2-PSK went green.

WPA3-SAE and the one capability bit

SAE — WPA3’s dragonfly handshake — was the last and best war story. Everything seemed in place: the driver relayed the SAE commit/confirm as real authentication frames over the medium, the AP path was taught to accept SAE and set the mandatory PMF (Protected Management Frames — SAE requires it), and the tests got distinct SSIDs so a stale beacon from an earlier test couldn’t win a “fast associate” race. And still the STA-side SAE connect just… hung, then timed out.

The decisive log line, once the noise was cleared:

wlan1: WPA: AP key_mgmt 0x400 network profile key_mgmt 0x400; available key_mgmt 0x0
wlan1: WPA: Failed to select authenticated key management type

Read that carefully. The AP offers SAE (key_mgmt 0x400). The station’s profile wants SAE (0x400). Their intersection is 0x400 — a match. And then “available key_mgmt” is 0x0. Something masked the one bit that both sides agreed on, after they agreed on it.

  AP offers SAE      : key_mgmt = 0x400   (WPA_KEY_MGMT_SAE = BIT(10) = 1024)
  STA profile wants  : key_mgmt = 0x400
  sel = AP & profile : 0x400              <- agreed!
                         |
     wpa_supplicant.c:1877
                         v
     if the driver did NOT advertise WPA_DRIVER_FLAGS_SAE:
         sel &= ~WPA_KEY_MGMT_SAE   ->   sel = 0x0
                         |
                         v
     "available key_mgmt 0x0"  ->  SAE never starts, connect hangs
The whole SAE saga came down to one unset capability flag, and a supplicant that quietly strips SAE unless the driver claims to support it.

The culprit is in wpa_supplicant.c: unless the driver advertises WPA_DRIVER_FLAGS_SAE (or an offload flag), the supplicant strips the SAE key-management bit from the selection — a sensible guard on real hardware, where a driver that can’t do SAE shouldn’t claim it. The hwsim get_capa advertised WPA_DRIVER_FLAGS_SME | WPA_DRIVER_FLAGS_AP but not WPA_DRIVER_FLAGS_SAE. One line — add the flag (0x02000000) and the matching key-mgmt capability — and SAE went from hanging to a clean 7 of 7, deterministic across four back-to-back runs at ~2.7 seconds each.

There’s a coda worth admitting. Blocked on SAE, I was tempted to defer it — ship open and WPA2-PSK now, file WPA3 as “future work,” and move on. I didn’t, because of a rule I don’t bend: a security feature isn’t done until it completes end to end, and “open, WPA2-PSK, and WPA3-SAE all connect and ping” was the bar I’d set at the outset. Deferring would have been the easy, defensible call — and half-finished security is exactly the kind of thing that passes review and bites someone in production. Once I stopped looking for the exit, the fix was one line.

Why the test passed but the shell didn’t

One more find is a small masterclass in “green tests can lie.” At one point the automated suite was fully green while a human typing wifi ap start at the shell got a flat rejection. Same driver, opposite results.

The reason: enabling AP mode through the network-management API — which is what the ztest calls directly — bypasses a gate the interactive shell enforces. The shell checks that the interface is registered as a software AP before it lets you start one, and the supplicant glue was registering every interface as a station only, never as both. The test never hit that gate; the human did. The fix was to let a single net_if be registered as both STA and SAP at once (one of the upstream hostap changes this PR carries), so the same interface can be a station and bring up an AP — which is exactly the multi-role setup the whole harness depends on. Lesson, same as always: a passing test proves the path the test takes, not the path the user takes.

Execution: idea → RFC → reviewed → merged

The engineering above is half the story; landing it upstream cleanly is the other half, and it’s the part clients are actually buying. A few things that turned a debugging spike into something mergeable:

  • The debugging branch was rebuilt into six logical commits — three upstream hostap glue changes (single-interface STA+SAP, hardened event lookup, WPA3-SAE for the software AP), the driver itself, the native_sim sample, and the test suite. Reviewers read intention, not archaeology.
  • CI was made fully green before asking anyone to look — the whole gauntlet of Zephyr’s compliance checks: license/SPDX headers, Kconfig prompt style, YAML lint on the devicetree binding, commit-message wrapping and sign-off/identity matching, doc build, and a test-metadata filename rule. None of it is glamorous; all of it is table stakes for a project the size of Zephyr, and getting it wrong wastes a reviewer’s goodwill.
  • Every review comment got a real answer — across two rounds and roughly a dozen comments from two maintainers, including fixing genuine races (medium configuration was being written after its lock was dropped) and hardening one-time-init flags to atomic_t. Where I disagreed with a suggestion, the reply was a reason, not a shrug.
  • The claims were checked, not asserted. When a reviewer asked whether one of the hostap commits was even necessary, rather than argue I reverted those files to mainline, re-ran the suite, and reported what actually happened (still green under the test’s direct API path — but needed for the interactive shell path). That distinction is the STA/SAP finding above; it came out of checking.

The result merged on July 17, approved by the maintainers who’d pushed hardest in review. Full hostapd AP mode is scoped as a deliberate follow-up — the current PR uses the supplicant’s software-AP path, which is enough to exercise open, WPA2-PSK, and WPA3-SAE end to end, and I said so explicitly rather than letting scope blur.

Where it goes next

The merge is a floor, not a ceiling. I scoped this PR tightly on purpose, so a few things are deliberately open rather than done:

  • Full hostapd AP mode (CONFIG_WIFI_NM_HOSTAPD_AP). The current driver runs the supplicant’s software-AP path — enough for open, WPA2-PSK, and WPA3-SAE end to end. Standing up a genuine hostapd-mode AP is the next PR.
  • Better names for A and B. A telco action item, non-blocking: “hwsim” and “native_sim” describe the mechanism, not the intent, and the two get confused.
  • One netif or two? Whether a single net_if acting as both STA and SAP is the right model, versus vendors that expose two separate interfaces, is a design thread left open in review — settled enough to merge, not enough to call final.
  • 64-bit parity. Work and CI have leaned on 32-bit native_sim; keeping the native_sim/native/64 target green is ongoing.

And then the genuinely new capability, all of it agreed at the same telco:

  • Enterprise. A hostapd-based AP with a built-in RADIUS server already runs in Zephyr; the plan is full Enterprise coverage — STA, AP, and RADIUS server — so EAP methods get the same no-hardware treatment SAE just got.
  • More modes for B. Jukka’s host-backed harness grows sideways into SoftAP and Wi-Fi Direct / P2P.
  • Real medium simulation — the piece I’m keenest on, and the one that closes the loop back to that original enhancement request. Today every radio hears every other radio perfectly; wiring in wmediumd — the userspace daemon Linux’s hwsim pairs with for per-link RSSI and packet-loss control — would let a test dial in attenuation, mobility, and loss on purpose. Its appeal is that it slots under both approaches: reimplemented in-process for A, native for B.

That last one is the whole thesis in miniature: choose the harness once, and the hard infrastructure beneath it is worth building for everyone. That’s the shared foundation the RFC set out to create.

What this unlocks

Step back from the bug-by-bug and the payoff is concrete. Zephyr now has a way to run its complete Wi-Fi stack — real supplicant, real AP, real 4-way handshake, real SAE dragonfly, real key derivation — in a single native_sim process, in a couple of seconds, on any platform, with no radio and no bench.

And this isn’t hypothetical framing — it’s already wired in. The suite ships tagged wifi (alongside hwsim, networking, drivers) and allowed on native_sim and native_sim/native/64, so it’s part of the set Zephyr’s Twister-based CI already selects: any change that touches the Wi-Fi test scope now runs open, WPA2-PSK, and WPA3-SAE connect-and-ping automatically, with no hardware to schedule and nothing to plug in. That flips the usual state of affairs from “you could gate CI on the supplicant if someone stood up a lab” to “CI already does, on every runner.” The class of bug I spend real time chasing on hardware — a crypto path that silently got an order of magnitude slower, a handshake that stopped completing inside the AP’s timeout — is exactly the class this catches before it reaches silicon, deterministically, for free.

For a product team, that arithmetic is the whole pitch. A hardware Wi-Fi CI lab is real money and real flake: radios, APs, RF isolation, someone to maintain all of it, and tests that fail because the air was noisy rather than because the code broke. This replaces the common cases of that lab with a native_sim binary that runs the real supplicant, real AP, and real handshakes in about 2.7 seconds on hardware you already own — every developer’s laptop, every CI runner. The payoff isn’t “we added a test.” It’s that a crypto regression or a handshake-timeout regression gets caught on the pull request that introduces it, instead of in a certification lab or a customer’s field return — which is exactly where catching it stops being cheap.

And it sits in a considered place in the design space, not in spite of the other two approaches but alongside them: the host-nl80211 harness for real-medium application testing, the emulated driver for management-plane unit tests, and this one for full-stack, any-target, in-CI handshake coverage. Knowing which harness answers which question is itself the deliverable.

This is the mirror image of a post I wrote about the Windows side — where the sample driver’s test harness ships no AP on purpose, and one relay hop had to be faked by hand. Same underlying discipline, opposite corner of the map: there, fake exactly the one hop you need and nothing else; here, fake only the radio and run everything above it for real. Neither is more correct. Picking the wrong one for your actual goal is where the wasted weeks come from — and picking, out loud, in an RFC the whole community can weigh in on, is the part I’d do the same way every time.


PS: This post was drafted with Claude Code from my own session transcripts and project notes, and every PR and discussion linked was checked against the public GitHub history before being cited. The design call, the debugging, the wrong turns, and the one-line SAE fix are as they happened.

Dotstar Systems is a principal-led wireless practice — run by the maintainer of Zephyr’s Wi-Fi stack and drivers (including its hostap / wpa_supplicant / hostapd integration) and the nRF70/nRF71 drivers, and a contributor to the upstream hostap project and the Linux wireless stack. We design, build, debug, and upstream wireless systems where firmware meets silicon: an in-process test harness like this one, mac80211-class drivers, WPA3 crypto paths on constrained parts — on Zephyr, Linux, or Windows. Engagements are scoped to fit the work — fixed-scope bring-up, a time-boxed hunt for a bug that won’t die, or ongoing work embedded in your firmware team — with a named principal accountable and every deliverable signed off at principal level, not handed to a team you’ll never meet. If you have a Wi-Fi stack you can’t test without a bench, or a hard driver problem you want driven from idea to merged, let’s talk.