---
title: "Hardening Zephyr's W5500 Driver: An Open-Source Ethernet Stress Test"
url: "https://maker.wiznet.io/viktor/projects/hardening-zephyrs-w5500-driver-an-open-source-ethernet-stress-test/"
markdown_url: "https://maker.wiznet.io/viktor/projects/hardening-zephyrs-w5500-driver-an-open-source-ethernet-stress-test/md"
type: "UCC: User Created Content"
author: "matheus-555"
author_url: "https://github.com/matheus-555/Zephyr-Ethernet-Stress-Test"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "matheus-555"
original_url: "https://github.com/matheus-555/Zephyr-Ethernet-Stress-Test"
published: "2026-10-23"
language: "en"
hardware: ["WIZnet W5500"]
likes: 0
views: 6
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# Hardening Zephyr's W5500 Driver: An Open-Source Ethernet Stress Test

> Zephyr-Ethernet-Stress-Test is a small, focused tool: it pushes the W5500 driver with realistic concurrent traffic and records exactly where it fails

Original author: matheus-555 (source: https://github.com/matheus-555/Zephyr-Ethernet-Stress-Test)

## Components

- **WIZnet W5500** x 1 ([docs](https://docs.wiznet.io/Product/Chip/Ethernet/W5500))

WIZnet parts: W5500 ([Datasheet](https://docs.wiznet.io/Product/Chip/Ethernet/W5500/datasheet?utm_source=maker&utm_medium=project&utm_campaign=w5500), [product hub](https://maker.wiznet.io/products/w5500/))

## Article

## Introduction

![](https://maker.wiznet.io/upload/ckeditor5/024a8450d88e4e2fb35d7a0b5c3c3bb6.png)
Getting an Ethernet board to fetch one web page is easy. Keeping it online for days while it opens and closes thousands of sockets is a different problem, and that is where driver bugs hide: a buffer that is not freed, an RX header the driver doesn't expect, an interrupt that is missed once in a million packets.

Zephyr-Ethernet-Stress-Test, by GitHub user **matheus-555**, is a small Zephyr application built to find exactly those bugs. It drives the network interface with concurrent real-world traffic for hours or days and records what breaks. Most of its published test logs focus on the **WIZnet W5500**, which makes it a useful contribution to anyone running a W5500 under Zephyr.

## What the Project Does

![](https://maker.wiznet.io/upload/ckeditor5/e0922900e2bb4504b14fe4668963471f.png)
After the board gets an IPv4 address over DHCP, the application starts two independent threads that share the same network stack:

| Thread | What it does | Default rate |
| --- | --- | --- |
| `http_thread` | Resolves a hostname via DNS, opens a TCP socket, sends an HTTP `GET`, closes the socket | every 500 ms |
| `mqtt_thread` | Keeps a persistent MQTT connection, subscribes to one topic, publishes to another | publish every 1 s, poll every 2 s |

Together they exercise the interface in five ways:

1. **Concurrent TCP flows** – HTTP and MQTT use separate sockets in separate threads.

2. **Constant socket churn** – every HTTP request creates and tears down a socket, putting pressure on the driver's RX/TX paths.

3. **Steady small-packet traffic** – MQTT PING, SUB, PUB and PUBACK frames.

4. **Extra UDP flows** – a DNS lookup before every request.

5. **Long run times** – designed as a soak test to expose leaks, buffer exhaustion and slow-building faults.

A companion Python script (`scripts/mqtt_client.py`) publishes a JSON payload of exactly **2,049 bytes** back to the board. That size is chosen on purpose: it is larger than a single Ethernet frame, so the board must reassemble a multi-segment TCP message, a path that often reveals RX-handling bugs.

The repository is organised so other boards can be added easily:

- `boards/` – devicetree overlays and Kconfig fragments for each host board

- `confs/` – driver-specific fragments (`eth_w5500.conf`, `eth_enc28j60.conf`) and a `debug.conf` that turns on the thread analyzer, stack sentinels, assertions and exception backtraces

- `logs/` – real test runs, including crash logs with `addr2line` backtraces

Build and flash use the standard Zephyr workflow:

bash

```plaintext
west build -p always -b <board_name> .
west flash
```

## Why the W5500 Is Used

Both reference boards attach a W5500 over SPI using Zephyr's in-tree `wiznet,w5500` binding. On the Raspberry Pi Pico W:

dts

```plaintext
&spi0 {
    cs-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
    status = "okay";

    ethernet0: w5500@0 {
        compatible = "wiznet,w5500";
        reg = <0x0>;
        spi-max-frequency = <DT_FREQ_M(10)>;
        int-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
        reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
        local-mac-address = [02 00 00 01 02 03];
        status = "okay";
    };
};
```

On the ESP32 DevKit, the same chip runs in **polling mode** (the interrupt line is left unconnected), so the project covers both of the driver's operating modes. The only W5500-specific setting is a larger RX thread stack:

```plaintext
CONFIG_ETH_WIZNET_RX_THREAD_STACK_SIZE=2048
```

Neither the ESP32 nor the RP2040 has a built-in Ethernet MAC, so an SPI Ethernet controller is the natural way to give them a wired port. The W5500 is one of the most widely used choices, and because Zephyr ships a mainline driver for it, the project can test the real upstream code instead of a custom port.

## What the Testing Found

The `logs/` folder documents an actual debugging journey on the W5500 driver:

- **RX crash under load (ESP32).** The board faulted inside the RX path of Zephyr's WIZnet driver (`wiznet_rx` in `eth_wiznet.c`). The decoded backtrace pointed at a network buffer tailroom check, a sign that a received frame's length was not being handled safely.

- **No recovery after an invalid RX header (ESP32, polling mode).** After a `header_invalid_size` condition, refreshing the link status alone did not bring the interface back.

- **Upstream fix validation.** The author ran the stress test against a proposed Zephyr pull request for the W5500 driver, on both the ESP32 and the Pico W in interrupt mode, and captured the results.

- **Stable after RX-recovery changes.** With the recovery changes applied, the ESP32 + W5500 ran for **more than 24 hours** of continuous HTTP and MQTT traffic, reaching a 100 Mb full-duplex link, receiving the 2,049-byte MQTT messages correctly, and keeping the W5500 RX thread at a steady 54% stack usage with about 1–2% CPU.

That last result is the real value of the project: it turns "it seems to work" into a reproducible, day-long test with a log that anyone can inspect.

## Advantages of Using the W5500

- **Adds Ethernet to any MCU with SPI.** The ESP32 and RP2040 have no Ethernet MAC; a W5500 gives them a wired port with four signals plus optional interrupt and reset lines.

- **MAC and PHY in one chip.** 10/100 Ethernet with an integrated PHY keeps the board design simple and the bill of materials small.

- **32 KB of internal packet buffer.** Frames are buffered on the chip, so a busy or slow host is less likely to drop traffic, which matters during exactly the kind of bursty load this project generates.

- **Mainline Zephyr support.** The `wiznet,w5500` driver is part of upstream Zephyr, configured purely through devicetree. Moving between the ESP32 and the Pico W meant changing an overlay, not the application.

- **Interrupt or polling.** The driver works with or without an interrupt pin, which helps on boards where GPIOs are scarce.

- **Hardwired TCP/IP option.** In this project Zephyr runs its own network stack and uses the W5500 as an Ethernet interface. Outside Zephyr, the same chip can also run TCP/IP entirely in hardware, so one part covers both RTOS-based and very small bare-metal designs.

## Why It Matters to the Ecosystem and Other Makers

**More reliable W5500 support for everyone.** Bugs found here were tied to specific lines of the upstream driver and to a real pull request. When the upstream driver improves, every Zephyr user with a W5500 benefits, whether or not they ever see this repository.

**A ready-made acceptance test.** Makers designing their own W5500 board, or porting it to a new MCU, can add an overlay to `boards/`, run the test overnight and see whether their hardware and configuration hold up. The 2,049-byte payload, the debug fragment and the troubleshooting table save hours of guesswork.

**A model for good bug reports.** The project asks contributors for the full serial log, the Zephyr commit, versions, the hardware setup and the devicetree. The `logs/` folder shows what that looks like in practice, with backtraces already decoded. That is the kind of report driver maintainers can act on.

**Side-by-side comparison.** Because the overlays also include a Microchip ENC28J60 node, the same test can be run against two SPI Ethernet controllers on the same board, giving makers real data when they choose hardware.

**Room to grow.** The author invites results from more boards. Adding other WIZnet chips supported by the same Zephyr driver family would extend the coverage further, and is an easy first contribution for anyone interested in Ethernet on Zephyr.

## Conclusion

Zephyr-Ethernet-Stress-Test is a small, focused tool with an outsized effect: it pushes the W5500 driver with realistic concurrent traffic, records exactly where it fails, and shows the result once it is fixed. For makers it is a practical way to validate a W5500 design before deployment; for the wider Zephyr community it is a contribution to a more robust Ethernet driver. If you are building with the W5500 on Zephyr, it is worth leaving this test running overnight.

---

Source: https://maker.wiznet.io/viktor/projects/hardening-zephyrs-w5500-driver-an-open-source-ethernet-stress-test/
