defconfig.sh used $# (find result, incl. *~ / *.bak) for the TAP total
but then 'continue'd past backups without decrementing — so a stray
bpi_r4_*_defconfig~ in the tree made TAP see "1..23" followed by only 21
results, and the harness treated the missing 2 as failures. Filter the
patterns at find instead; $# now matches what the loop iterates over
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Three bugs found while testing modem support on hardware:
ietf_system.py: "interface": null written to DNS server entries when
no interface is associated, causing LY_EVALID in the ietf-system
schema validator. Only include the key when the interface name is
non-empty.
ietf_system.py: empty list inserts (user [], server [], options [],
search []) overwrote configured data in the operational store instead
of leaving it intact. Guard each insert so operational data only
shadows configured data when there is something to report.
show system: CPU temperature reported only the first sensor named
exactly "cpu", "soc", or "core". Platforms with multiple thermal
zones (e.g. BPI-R4 exposes cpu and cpu1) always showed only one
reading. Collect all sensors whose name matches a CPU/SoC prefix
and report the maximum.
statd.c: yanger parse errors logged without model name or libyang
error string, making failures hard to diagnose. Include both.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The Ethernet packet/RMON counters at the bottom of 'show interface
<name>' were appended with a wider label column than the operational
data above them, breaking visual alignment. Group them under an
"Ethernet Statistics" section heading (Decore.title), same convention
as 'Available Networks' in the wifi scan view.
Narrow the operational-data label column from 20 to 19 chars so the
title bar exactly matches the heading text — a tighter and more
deliberately aligned look. All labels in pr_iface fit within 19
chars except 'lacp system priority' (20); rename it to 'lacp sys
priority' for consistency with the other 'lacp ...' labels (lacp
aggregate id, lacp partner mac, ...) so the new field width works
universally.
Refresh CLI snapshots and doc samples to match.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Import ieee802-ethernet-interface@2025-09-10.yang, from IEEE 802.3.2-2025,
and companion ieee802-ethernet-phy-type.yang, replacing the 2019 revision.
Operational interface speed moves to ietf-interfaces:speed, RFC 8343,
eth:speed is now obsolete. Bump infix-interfaces.yang revision to track
the upgrade.
The CLI 'show interface' command renders interfaces as bottom-up layered
protocol rows. Ethernet interfaces a new IEEE link-mode row (1000baseT,
10GbaseLR, ...) is added with 'duplex: full|half' in the DATA column.
Without link the ethernet row is the first row. Tunnels and wifi follow
the same layering: gre/vxlan rows carry remote:/vni: tokens with optional
ethernet sub-row for the L2-bearing variants; wifi rows carry 'station' or
'access-point' ssid:, signal:, stations: tokens.
admin@bpi-76-8f-c2:/> show interface
⚑ INTERFACE PROTOCOL STATE DATA
⇅ lo loopback UP
ipv4 127.0.0.1/8 (static)
ipv6 ::1/128 (static)
⇅ br0 bridge DOWN
│ ethernet 32:2e:3f:76:8f:c2
│ ipv4 192.168.0.1/24 (static)
⇅ ├ lan0 bridge LOWER-DOWN
⇅ ├ lan1 bridge LOWER-DOWN
⇅ ├ lan2 bridge LOWER-DOWN
⇅ └ lan3 bridge LOWER-DOWN
⇅ gre0 gre UP remote: 198.51.100.7
ipv4 10.255.0.1/30 (static)
⇅ sfp1 ethernet DOWN ca:59:f0:77:80:5b
⇅ wan 1000baseT UP duplex: full
ethernet 32:2e:3f:76:8f:c2
ipv4 192.168.0.235/24 (dhcp)
ipv6 fe80::302e:3fff:fe76:8fc2/64 (link-layer)
⇅ wan.10 vlan UP vid: 10
│ ipv4 10.0.10.1/24 (static)
└ wan
⇅ wan.10.20 vlan UP vid: 20
│ ipv4 10.0.10.20/28 (static)
└ wan.10
⇅ wifi0 wifi UP station ssid: corp-net signal: good
ethernet dc:a6:32:00:11:22
ipv4 192.168.7.42/24 (dhcp)
yanger populates phy-type and pmd-type from a static ETHTOOL link-mode
identity table keyed on (port, speed, duplex). Both leaves are populated
for unambiguous media (copper, DAC, copper-T); for generic fiber where
the (port, speed, duplex) tuple can map to multiple PMDs (SR vs LR vs
ER, etc.) only the phy-type family identity is emitted — guessing the
PMD would be misleading. cli_pretty prefers pmd-type (specific) and
falls back to phy-type (family) for display.
yanger also emits ietf-interfaces:speed and fixes a long-standing
'auto-negotation' typo (yanger had never matched ethtool's correctly-
spelled JSON field, so operational auto-negotiation always read
'unknown').
Filling the WG's gap on fixed-speed config
------------------------------------------
IEEE Std 802.3.2-2025 obsoleted the eth:speed leaf without providing a
config-true replacement; the standards-correct way to express what
older Infix configurations called 'fixed speed' is to restrict the set
of PMDs auto-negotiation may advertise. Augment auto-negotiation with
two leaf-lists:
auto-negotiation/advertised-pmd-types config-true, leaf-list of pmd-type
ethernet/supported-pmd-types config-false, leaf-list of pmd-type
Pinning a port to a single mode is now expressed as a single-entry
advertised-pmd-types list. The kernel-supported set is exposed as
operational state for diagnosis — SFP/SFP+ cages report the inserted
module's capabilities, narrowing the list to a single PMD when the
optic only supports one mode (as suggested by @wkz in PR review).
When the supported list collapses to a single entry, yanger uses it
to refine the operational pmd-type leaf — more accurate than the
(port, speed, duplex) lookup for fiber.
confd C apply path (src/confd/src/ieee802-ethernet-interface.c)
translates each advertised pmd-type identity to the corresponding
ETHTOOL_LINK_MODE_*_BIT_*, ORs them into a mask, and emits
'ethtool --change <if> autoneg on advertise 0x<mask>'. An empty
list keeps the historical default of advertising every supported
mode. The (legacy) 'auto-negotiation/enable = false' + speed/duplex
branch is removed — it has no model representation any more.
cli_pretty's detail view gains 'advertised' and 'supported' rows
listing the PMDs in each set. A new _pr_label_list() helper unifies
multi-row rendering across these new rows and the pre-existing
ipv4/ipv6 address rows.
The detailed interface view also gains a 'link mode' row carrying the
pmd-type / phy-type-derived label.
Migration of existing startup configurations
--------------------------------------------
Bump confd version 1.8 → 1.9 to trigger the migration on upgrade.
share/migrate/1.9/10-ethernet-advertise.sh translates old configs of
the form
ethernet { auto-negotiation { enable false; } speed S; duplex D; }
into
ethernet { auto-negotiation { advertised-pmd-types [PMD]; } duplex D; }
mapping (S, D) → PMD via a static lookup covering the copper-T speeds
the deprecated speed leaf historically supported (10/100/1000/2.5G/
5G/10G). Interfaces that don't disable auto-negotiation, or that
lack a speed leaf, are passed through untouched.
Closes#530Closes#805
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The 'command' leaf is config, with a strict pattern that doesn't allow
'&', quotes or pipes. Yanger was populating it from podman's full,
untruncated container command -- so any container whose entrypoint
uses shell metacharacters (e.g. sh -c "... && ...") failed YANG
validation.
The symptom: every operational read of /infix-containers:containers
returns SR_ERR_INTERNAL, which in turn fails the whole get-data on
the operational datastore. This breaks case/misc/operational_all and
any RESTCONF/NETCONF read that touches containers.
This was introduced in 59028c4 ("Fix #1466: 'show container' shows no
output"), which added the operational, pattern-less 'cmdline' leaf
but left the old 'command' assignment in place. Drop it -- 'cmdline'
already carries the full command line, and 'command' belongs to
running config.
Note: the failure can look intermittent across test runs because
podman storage is persistent. It only triggers once a container with
a bad-pattern command ends up in 'podman ps -a', including stale or
exited leftovers from earlier runs.
Signed-off-by: Richard Alpe <richard@bit42.se>
Add support for static ARP (IPv4) and neighbor cache (IPv6) entries per
interface. Static entries are installed as permanent kernel neighbor
table entries that are never evicted by normal ARP/NDP aging.
Fixes#819
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
A container's command line, as reported by podman, may comtain environment
variables, which the current regexp (added in ed4fe58) does not support.
Extend the regexp to allow environment variables and add an operational,
config false, 'cmdline' leaf node to allow any characters to be reported
for the full command line in the operational output.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
has_fix() only checks that fix-mode is set (2d/3d), but altitude and
other fields may not yet be populated in the operational datastore when
gpsd is still processing its first NMEA cycles after boot. Calling
verify_position() immediately after has_fix() passes can therefore race
and fail with:
KeyError: 'altitude'
This manifests reliably on the second GPS receiver (gps1) after reboot,
because it is initialized slightly later than gps0 and hits the window
where fix-mode is set but altitude has not yet appeared.
not ok 11 - Verify gps1 position is near the coordinates
# Traceback (most recent call last):
# File "test/case/hardware/gps_simple/test.py", line 29, in verify_position
# alt = float(state["altitude"])
# ~~~~~^^^^^^^^^^^^
# KeyError: 'altitude'
Add has_position() to infamy/gps.py, which gates on fix-mode AND all
position fields (latitude, longitude, altitude, satellites-used) being
present. Replace the has_fix() polls in both the pre- and post-reboot
verify steps with has_position().
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Replace fragile SSH+jq approach for reading the chassis MAC with a
NETCONF query to ietf-hardware:hardware/component[name='mainboard'],
reading phys-address directly from the YANG model.
Also add until() polling to the chassis MAC and chassis+offset MAC
verification steps, consistent with the reset-to-default steps.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
A service restart triggered by finit during sysrepo callbacks can drop
an in-flight HTTP connection, causing copy("candidate", "running") to
fail with RemoteDisconnected. Add retry logic consistent with the
existing PATCH retry pattern in put_config_dict().
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
test_reset() triggers a config reload which causes services such as
rousette to restart. Wait for the transport to become reachable again
before returning from attach(), preventing subsequent API calls from
racing with a still-restarting backend.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The setting 'stratumweight 0.0' disables stratum in Chrony source
selection (pure distance-based), making client_stratum_selection
non-deterministic on a LAN. Setting it to 1.0 gives srv1 a 1-second
effective advantage per stratum level, which no realistic distance
fluctuation can overcome.
Also correct the YANG descriptions in infix-system and infix-ntp which
had the semantics backwards — claiming 0.0 "ensures lower stratum is
always preferred" when in fact higher values do that.
Fixes#1361
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
A legacy name length limit in firewalld triggered problems with longer
policy names. This patch to firewalld lifts that limit by checking the
backend in use, no limit for nftables.
Fixes#1389
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Always emit the "1..N" plan line before exiting with error so test
harnesses don't report "test error, no plan" for failed or aborted
tests.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This patch adds support for chronyd's stratumpweight both in the NTP
client (ietf-system) and client+server (ietf-ntp) should fix the flaky
NTP stratum test.
Also, make sure to *not* 'rm -rf /etc/chrony/conf.d/*' in system.c to
prevent clobbering settings potentially made in ntp.c
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
DNS does not allow CNAME records at an apex domain (e.g. kernelkit.org),
so GitHub Pages cannot reliably redirect kernelkit.github.io to it. A
www subdomain can carry a CNAME pointing directly to kernelkit.github.io,
giving GitHub full control over the mapping and making the redirect work.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Any exception raised by fn() propagated immediately out of the retry
loop, effectively making until() a single-shot call the moment any
transient error occurred.
Fix by wrapping fn() in a try/except inside the loop and treating any
exception as a "not yet" result. The last exception is preserved and
re-raised if all attempts are exhausted, so failure output is still
meaningful. Also fix a missing newline at end of file.
Fixes#1403
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Python's urllib.request wraps OSError in URLError during the connection
phase, but NOT during response reading (getresponse()). This means a
timeout that fires after the TCP handshake completes, e.g. when a service
accepts the connection but hasn't sent a response yet, propagates as a
bare TimeoutError that bypasses the exception handler, killing the entire
until() retry loop on the first attempt.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Not all systems are equally quick, let's give it while to set before
bailing out because we test too soon.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Enable IPv6 forwarding on the left DUT's tunnel interface, matching
the IPv4 tunnel config. Without it, IPv6 packets are not forwarded
through the tunnel, causing all tunnel_basic IPv6 tests to fail.
Regression introduced when fixing issue #515 in 717c1c0.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>