diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md
index e3a0dc0d..fe3d51dc 100644
--- a/doc/ChangeLog.md
+++ b/doc/ChangeLog.md
@@ -3,7 +3,7 @@ Change Log
All notable changes to the project are documented in this file.
-[v26.05.0][UNRELEASED]
+[v26.05.0][] - 2026-05-29
-------------------------
### Changes
@@ -24,40 +24,44 @@ All notable changes to the project are documented in this file.
above the `ethernet` row. VLAN, GRE, VXLAN and WiFi interfaces likewise get
one row per protocol layer, with type-specific data on each (`vid:`,
`remote:`, `vni:`, `station ssid:`, etc.), issue #530
-- New `auto-negotiation/advertised-pmd-types` leaf-list replaces the
- retired `enable=false + speed + duplex` idiom for pinned link modes
- (IEEE Std 802.3.2-2025 obsoleted `eth:speed`), issue #805. Existing
- startup configurations are migrated automatically on upgrade; see
- [ethernet.md](ethernet.md#restricting-advertised-link-modes) for the
- new model, the duplex × PMD mapping, and the `enable=false` escape
- hatch for non-autoneg peers
-- New `ethernet/mdi-x` boolean leaf to force the copper MDI/MDI-X pinout
- (true = MDI-X, false = MDI, absent = Auto-MDIX). Needed on some PHYs
- where Auto-MDIX stops working once auto-negotiation is disabled; see
- [ethernet.md](ethernet.md#restricting-advertised-link-modes)
+- Add support for configurable auto-negotiation for Ethernet ports. A new
+ `advertised-pmd-types` leaf-list replaces the fixed speed idiom for pinned
+ link modes, issue #805. See the [Ethernet Interfaces][ethernet] section in
+ the User Guide for details. Existing configurations using fixed speed are
+ migrated automatically on upgrade
+- Add support for configurable MDI/MDI-X pinout on Ethernet ports. Needed on
+ some PHYs where Auto-MDIX stops working once auto-negotiation is disabled
- New operational `supported-pmd-types` leaf-list on each Ethernet interface,
- exposing the set of PMD types currently supported. Useful for SFP/SFP+
- diagnosis: an LR-only optic narrows the list to a single entry, confirming
- the transceiver without `ethtool -m`
-- New CLI command `show operational`, and XPath filtering for this and any of
- the other datastores, using `[path /path/to/subtree]`
+ exposing the set of PMD types currently supported
+- New CLI command `show operational`, and optional XPath filtering for this
+ and any of the other datastores, using `[path /path/to/subtree]`
+- CLI `show` commands now surface human-friendly error messages instead of a
+ raw Python exceptions, e.g., `Interface "w" not found`
### Fixes
-- Fix #1493: container with a physical interface not properly removed
- when switching to a configuration without containers
-- Fix #1506: add documentation on how to configure VLAN interfaces,
- including stacked (Q-in-Q) VLAN interfaces, in a dedicated `vlan.md`
-- Fix long-standing typo `auto-negotation` in `yanger`, which caused
- the operational `auto-negotiation/enable` leaf to always read as
- `unknown` regardless of the actual port setting
-- Handle unclean daemon exits better, e.g., `dbus-daemon` crashing and
- leaving a stale pidfile behind, causing it to refuse to be restarted
+- Fix #1493: container with a physical interface not properly removed when
+ switching to a configuration without containers
+- Fix #1506: add documentation on how to configure VLAN interfaces, including
+ stacked (Q-in-Q) VLAN interfaces, in a dedicated `vlan.md`
+- Handle unclean daemon exits better, e.g., `dbus-daemon` crashing and leaving
+ a stale pidfile behind, causing it to refuse to be restarted
- Fix occasional blank or garbled `[ OK ]` lines at startup
- Disallow multicast MAC addresses in custom MAC address configuration
- Fix broken Wi-Fi 6 GHz band configuration.
+- Fix operational read of `/containers` failing and thereby aborting all
+ operational get-data, including RESTCONF/NETCONF reads — for containers
+ whose command contains shell metacharacters, e.g. `sh -c "... && ..."`
+- WireGuard interfaces are now regenerated when a referenced keystore key
+ changes: the asymmetric `private-key`, and the symmetric `preshared-key` at
+ both peer-group and per-peer level
+- Fix crash in operational data when a bridge has VLAN ranges configured: the
+ kernel may report ranges (e.g. `vlan 1 vlanEnd 3`) from `bridge vlan global
+ show`, which were not expanded, so `show interface` and other operational
+ reads failed. Ranges are now expanded and listed correctly
-[BPI-R3]: https://docs.banana-pi.org/en/BPI-R3/BananaPi_BPI-R3
+[ethernet]: ethernet.md#restricting-advertised-link-modes
+[BPI-R3]: https://docs.banana-pi.org/en/BPI-R3/BananaPi_BPI-R3
[AcerConnectVero]: ../board/aarch64/acer-connect-vero-w6m/
[v26.04.0][] - 2026-04-30
@@ -2131,7 +2135,9 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
- N/A
[buildroot]: https://buildroot.org/
-[UNRELEASED]: https://github.com/kernelkit/infix/compare/v26.03.0...HEAD
+[UNRELEASED]: https://github.com/kernelkit/infix/compare/v26.05.0...HEAD
+[v26.05.0]: https://github.com/kernelkit/infix/compare/v26.04.0...v26.05.0
+[v26.04.0]: https://github.com/kernelkit/infix/compare/v26.03.0...v26.04.0
[v26.03.0]: https://github.com/kernelkit/infix/compare/v26.02.0...v26.03.0
[v26.02.0]: https://github.com/kernelkit/infix/compare/v26.01.0...v26.02.0
[v26.01.0]: https://github.com/kernelkit/infix/compare/v25.11.0...v26.01.0
diff --git a/doc/extra.css b/doc/extra.css
index 94d83360..3e9c836d 100644
--- a/doc/extra.css
+++ b/doc/extra.css
@@ -1,3 +1,90 @@
+/* Chirpy-style typography (must precede all other rules).
+ * Source Sans Pro was renamed "Source Sans 3" on Google Fonts; it is the
+ * same typeface. Lato is used for headings, matching www.kernelkit.org. */
+@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900&family=Source+Sans+3:ital,wght@0,400;0,600;0,700;1,400&display=swap');
+
+/* ---- Fonts ---------------------------------------------------------------
+ * theme.font is disabled in mkdocs.yml, so we set Material's font vars here.
+ * Body: Source Sans 3, code: system monospace (same stack Chirpy uses). */
+:root {
+ --md-text-font: "Source Sans 3";
+ --md-code-font: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New";
+}
+
+body {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+/* Lato for all headings and the masthead site title. */
+.md-typeset h1,
+.md-typeset h2,
+.md-typeset h3,
+.md-typeset h4,
+.md-typeset h5,
+.md-typeset h6,
+.md-header__title,
+.md-nav__title {
+ font-family: "Lato", "Microsoft Yahei", sans-serif;
+}
+
+/* ---- Light mode (Chirpy "default" palette) ------------------------------- */
+[data-md-color-scheme="default"] {
+ --md-typeset-color: #34343c;
+ --md-typeset-a-color: #0056b2; /* Chirpy blue links */
+ --md-accent-fg-color: #0056b2; /* link hover / active TOC */
+ --md-code-bg-color: #f6f8fa;
+ --md-code-fg-color: #3a3a3a;
+}
+
+[data-md-color-scheme="default"] .md-typeset h1,
+[data-md-color-scheme="default"] .md-typeset h2,
+[data-md-color-scheme="default"] .md-typeset h3,
+[data-md-color-scheme="default"] .md-typeset h4,
+[data-md-color-scheme="default"] .md-typeset h5,
+[data-md-color-scheme="default"] .md-typeset h6 {
+ color: #2a2a2a;
+}
+
+/* Subtle tinted sidebars (left nav + right TOC), as on the blog. */
+[data-md-color-scheme="default"] .md-sidebar {
+ background-color: #f6f8fa;
+}
+
+/* ---- Dark mode (Chirpy "dark" palette over Material's slate) ------------- */
+[data-md-color-scheme="slate"] {
+ --md-default-bg-color: rgb(27 27 30); /* neutral near-black */
+ --md-default-fg-color: rgb(207 208 209); /* UI text */
+ --md-default-fg-color--light: rgb(175 176 177);
+ --md-default-fg-color--lighter: rgb(175 176 177 / 45%);
+ --md-default-fg-color--lightest: rgb(175 176 177 / 18%);
+ --md-typeset-color: rgb(175 176 177); /* body text */
+ --md-code-bg-color: #151515;
+ --md-code-fg-color: #b0b0b0;
+ --md-typeset-a-color: rgb(138 180 248); /* Chirpy blue links */
+ --md-accent-fg-color: rgb(168 199 250); /* brighter blue on hover */
+}
+
+[data-md-color-scheme="slate"] .md-typeset h1,
+[data-md-color-scheme="slate"] .md-typeset h2,
+[data-md-color-scheme="slate"] .md-typeset h3,
+[data-md-color-scheme="slate"] .md-typeset h4,
+[data-md-color-scheme="slate"] .md-typeset h5,
+[data-md-color-scheme="slate"] .md-typeset h6 {
+ color: #cccccc;
+}
+
+/* Sidebars slightly lighter than the main background, as on the blog. */
+[data-md-color-scheme="slate"] .md-sidebar {
+ background-color: #1e1e1e;
+}
+
+/* Inline code reads as a faint highlight rather than a dark block. */
+[data-md-color-scheme="slate"] .md-typeset :not(pre) > code {
+ background-color: rgb(255 255 255 / 6%);
+}
+
+/* ---- Existing project styling -------------------------------------------- */
.md-header__title {
font-size: 1.1rem;
line-height: 2.6rem;
diff --git a/doc/img/testing-log.dot.svg b/doc/img/testing-log.svg
similarity index 100%
rename from doc/img/testing-log.dot.svg
rename to doc/img/testing-log.svg
diff --git a/doc/img/testing-phy.dot.svg b/doc/img/testing-phy.svg
similarity index 100%
rename from doc/img/testing-phy.dot.svg
rename to doc/img/testing-phy.svg
diff --git a/doc/test-arch.md b/doc/test-arch.md
index dd8437b9..04f63c5d 100644
--- a/doc/test-arch.md
+++ b/doc/test-arch.md
@@ -108,7 +108,7 @@ DHCP server, and the other two as DHCP clients - with all three having
a management connection to the host PC running the test. In other
words, the test requires a _logical_ topology like the one below.
-
+{ align=right width="360" }
```dot
graph "dhcp-client-server" {
@@ -155,7 +155,7 @@ degrees), we can deploy well-known algorithms to find such subgraphs.
Continuing our example, let's say we want to run our DHCP test on the
_physical_ topology below.
-
+{ align=right width="360" }
```dot
graph "quad-ring" {
diff --git a/mkdocs.yml b/mkdocs.yml
index 11769c7d..b372c903 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -3,7 +3,7 @@ site_description: Infix Documentation
site_url: https://kernelkit.github.io/infix/
repo_url: https://github.com/kernelkit/infix/
repo_name: kernelkit/infix
-copyright: Copyright © 2022-2025 The KernelKit Team
+copyright: Copyright © 2022-2026 The KernelKit Team
docs_dir: doc/
edit_uri: edit/master/doc/
extra_css:
@@ -79,6 +79,10 @@ nav:
theme:
logo: logo-plain.png
name: material
+ # Fonts are loaded by doc/extra.css (Lato headings + Source Sans body +
+ # system monospace, matching the Chirpy blog) instead of Material's
+ # auto-loaded Roboto. Keep this false so Material does not also fetch Roboto.
+ font: false
features:
- toc.follow
# - toc.integrate