Skip to content

Yangerd - #1536

Draft
mattiaswal wants to merge 19 commits into
mainfrom
yangerd
Draft

Yangerd#1536
mattiaswal wants to merge 19 commits into
mainfrom
yangerd

Conversation

@mattiaswal

Copy link
Copy Markdown
Contributor

Description

Checklist

Tick relevant boxes, this PR is-a or has-a:

  • Bugfix
    • Regression tests
    • ChangeLog updates (for next release)
  • Feature
    • YANG model change => revision updated?
    • Regression tests added?
    • ChangeLog updates (for next release)
    • Documentation added?
  • Test changes
    • Checked in changed Readme.adoc (make test-spec)
    • Added new test to group Readme.adoc and yaml file
  • Code style update (formatting, renaming)
  • Refactoring (please detail in commit messages)
  • Build related changes
  • Documentation content changes
    • ChangeLog updated (for major changes)
  • Other (please describe):

@mattiaswal mattiaswal added the ci:main Build default defconfig, not minimal label Jun 12, 2026
@mattiaswal
mattiaswal force-pushed the yangerd branch 3 times, most recently from 3ec2747 to 71d50ea Compare June 19, 2026 09:38
@mattiaswal
mattiaswal force-pushed the yangerd branch 3 times, most recently from 7537929 to 8e6b2a1 Compare August 17, 2026 11:52
@mattiaswal
mattiaswal force-pushed the yangerd branch 4 times, most recently from 01b4d8f to ba1a1b3 Compare October 5, 2026 11:22
@mattiaswal
mattiaswal force-pushed the yangerd branch 5 times, most recently from 431f3e7 to 1609c19 Compare October 12, 2026 04:24
A Go daemon replacing the Python yanger scripts that statd forked on
every GET.  It keeps operational state in memory, driven by netlink,
nl80211, D-Bus, ZAPI, inotify and the FRR vty sockets, polls only what
has no events, and serves it to statd over a Unix socket as JSON.
Covers interfaces, routing, system, hardware, NTP, LLDP, containers,
firewall, DHCP, TFTP, PTP and WiFi.  The RIB comes from zebra when
built with FRR and from the kernel table otherwise.

Interface queries go through a long-lived 'ip -batch' process.  A
failing command prints nothing, [] or [{}] before its "Command failed"
line depending on the iproute2 version, and stdout and stderr race on
separate pipes, so the pipes are merged and every command is followed
by one that always fails, whose failure line delimits the answer.

inotify and the wireguard device dump are thin layers over x/sys/unix
and the mdlayher/genetlink stack already used for ethtool and nl80211,
rather than fsnotify and wgctrl, which brought their BSD, Darwin and
Windows backends and x/crypto into vendor.  The inotify watcher must
not leave a goroutine blocked in poll(2) per event: each pinned an OS
thread, 1300 of them after an hour of tests on a DUT.

A route change is the one event FRR gives for a neighbor loss, so the
ZAPI watcher pokes the routing collector instead of waiting for the
10 s poll, and the rauc software object is re-read once rauc appears
on the bus, since on the styx boards yangerd came up before it.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Buildroot builds with -mod=vendor and no network access.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Finit service with readiness notification.  Build-time feature flags
in /etc/default/yangerd mirror the packages selected, so yangerd only
runs the monitors that have something to monitor.

GOMEMLIMIT caps the Go heap at 64 MiB.  The live tree is under 1 MiB
but RSS drifted past 100 MiB, enough for the OOM killer to pick
yangerd while rauc held a bundle in tmpfs on a 512 MiB box.
Dependabot tracks the Go dependencies on the same weekly schedule as
webui and netbrowse, and re-vendors on every bump.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Replaces forking the Python yanger scripts with a query over yangerd's
Unix socket.  Nested subscriptions graft only the requested node into
the parent sysrepo passes, control-plane-protocols is one merged
subscription so config-only instances stay, and an empty answer from a
yangerd still starting is no data rather than an error.  Entries
libyang rejects are dropped instead of failing the whole GET.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Nudges yangerd to re-read its polled sources after a configuration
change.  Best effort, the commit must not fail when yangerd is not
installed or not yet running.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Mattias Walström <lazzer@gmail.com>
Room for yangerd on the virtual DUTs.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Operational data now comes from yangerd.  Interfaces, routes and
containers are reactive, the rest is polled, so checks that read a
value once right after a change now poll with until().  Also dumps AP
and client state when a WiFi check gives up, and updates the generated
test specifications.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Loading all modules took ~0.7 s per DUT before a test could even ask
has_feature() and skip.  The module list is enough for that.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
PPPoE is the only PPP transport, the kernel cannot tell.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Interfaces without carrier handling, AP_VLAN ports and tunnels, stay in
UNKNOWN; the UP and LOWER_UP flags tell the real state.  Loopback is now
up rather than unknown.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A wds-link port is an AP_VLAN interface without a control socket of its
own, its state is the one station the kernel has bound to it.  hostapd
binds the station without an nl80211 event for the port, so the station
events on the access point refresh the ports too.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
wpa_supplicant labels every RSN network WPA2, the key management tells
them apart: SAE only is WPA3, SAE next to PSK is a transition network.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
Survey data is collected on request by the channel-survey action since
infix-hardware@2026-10-06, the container is gone from the model.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
confd sets force_forwarding for IPv6, the aggregator reads it, but only
the plain forwarding file was watched.  An IPv6-only change was picked
up solely because the IPv4 sysctl is written at the same time.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
The bridge/vlans container and the bridge-port pvid leaf were never
produced, so any view of VLAN membership came up empty.  Read `bridge
vlan show` and the per-bridge global table, follow RTNLGRP_BRVLAN when
the kernel has it and bridge link events otherwise.  A VLAN filtering
bridge carries its multicast state per VLAN, a plain bridge at the
bridge level, as the YANG choice says.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
A refresh started before a disconnect could publish over it, leaving a
gone association in the operational data.  Hold a per-interface lock
from read to publish.

Signed-off-by: Mattias Walström <lazzer@gmail.com>
hostapd announces its shutdown with CTRL-EVENT-TERMINATING, but the
attach kept waiting for the keepalive to time out, ten seconds in which
the restarted hostapd bound its stations again unseen.  End the attach
on the event, and re-read the wds-link ports whenever a control socket
is gained or lost, since their state is the kernel's and the station
events that would have refreshed them never arrived.

Signed-off-by: Mattias Walström <lazzer@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:main Build default defconfig, not minimal

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant