The initial modem import used a standalone infix-modem YANG module with
an integer-indexed list under /infix-modem:modems carrying a bearer
config mixed in with hardware config. Infix has adopted the ietf-hardware
model to allow for a clearer separation of concerns, this commit aims to
improve on that situation by refactoring the modem model to use the same
architectural pattern already used for WiFi radios, GPS receivers, and
USB ports:
Hardware:
/ietf-hardware:hardware/component[class=infix-hardware:modem]
/ietf-hardware:hardware/component[class=infix-hardware:sim]
Interface:
/ietf-interfaces:interfaces/interface[type=infix-if-type:modem]
Configuration split:
modem component — admin-state (enable/disable), radio access mode,
frequency bands, location services, probe-timeout
sim component — PIN, PUK, carrier profile
wwan interface — APN, IP type, roaming, route-preference, auth
This also enables the modem to appear in 'show hardware' alongside
other hardware components, and to be managed over NETCONF/RESTCONF
using the same ietf-hardware RPCs used for USB and WiFi.
YANG changes:
- infix-modem.yang removed (1089 lines, standalone module)
- infix-hardware.yang: new modem and sim containers, modem-state and
sim-state operational state, typedefs for bands/modes/location,
notification status-update; actions restart/reset/send-sms are
augmented directly on the component list entry (not inside container
modem) to work around sysrepo NP-container parent validation — when
checking a nested action's parent, sysrepo restricts its operational
data fetch to the container path, excluding the sibling 'class' leaf
needed to evaluate the container's 'when' condition, so the container
is never instantiated and the parent check fails
- infix-if-modem.yang: new submodule (same pattern as wifi/wireguard)
adds the wwan bearer container to ietf-interfaces
- infix-if-type.yang: new modem identity for wwan interface type
- confd version bumped to 1.9
confd:
- if-modem.c: new file replaces the stub modem_gen() in modem.c;
generates dagger init scripts with probe-timeout wait loop and
unconditional dummy wwan creation so downstream IP config succeeds
when a USB modem is slow to enumerate at boot
- hardware.c: start/stop/enable/disable modemd (and modem-manager)
in response to admin-state changes on the modem hardware component;
use finit_enable/disable consistently
- hardware_cand_infer_class(): auto-set class for modemN/simN names
- modem.c: stripped to RPC/notification forwarding only; the old
genconf() / enable() / disable() logic is gone — hardware.c owns
the lifecycle now
- interfaces.c: remove wwan from wait-interface timeout (the modem
interface appearance is managed by modemd, not confd's init scripts)
- migrate/1.9: script fully migrates /infix-modem:modems to the new
split model; each modem[N] becomes a modemN hardware component and
simN sim component; each bearer becomes a wwanN interface (bearers
numbered globally across modems); APN, IP type, roaming, preferred-
mode, bands, location, PIN/PUK/carrier are all carried over; plain-
text bearer credentials are moved to a named keystore symmetric-key
(base64-encoded) referenced from bearer/authentication/password;
apn-type, firewall-enabled, dns-enabled and default-route are
dropped (no equivalent in the new model)
modemd:
- load_config() replaces the infix-modem sysrepocfg call; reads from
ietf-hardware (modem/sim config), ietf-interfaces (bearer config),
and ietf-keystore (credentials) — three standard modules instead of
one proprietary one; modems absent from sysrepo config but present
in system.json are still started (physical detection wins)
- Default route written to /etc/net.d/<iface>.conf (picked up by
netd/staticd/zebra) instead of a direct 'ip route add'; routes are
now visible to FRR for redistribution and metric-based failover
- Addresses tagged with proto wwan (rt_addrprotos entry 7) for
precise flush on disconnect without touching other address sources
- _derive_gateway() handles point-to-point bearers where modem
reports gateway as "--"; derives peer from link-scope subnet route
- SimThread exits cleanly on platforms without /dev/simctrl
- sim-setup, modem-info, modem-udev, modem-rpc, modem-sms all ported
to the ietf-hardware/ietf-interfaces namespace
statd:
- infix_modem.py now emits modem-state and sim-state into ietf-hardware
component entries (modem0, sim0, ...) instead of a separate tree;
sim-state reports physical slot, lock state, and SIM operator name
- ietf_hardware.py: hardware component names deduplicated by rename
(cpu → cpu, cpu1, ...) to prevent LY_EVALID when hwmon and thermal
sysfs both normalise to the same sensor name
- show hardware: Cellular Modems and SIM Cards tables added; sensor
table width now adapts to the widest section in the output
- 00-probe: USB modem detection writes to system.json["modem"], same
source as wifi-radios, feeding gen-hardware which emits the
ietf-hardware component entries at factory config generation time
CLI:
- 'show modem [ref]': without ref shows Cellular Modems and SIM Cards
tables (same data subset as 'show hardware'); with ref shows a full
per-modem dump (hardware info, status, cellular, SIM, bearers, GPS)
- 'modem restart <ref>': disconnect and reconnect all bearers without
a full hardware reset
- 'modem reset <ref>': factory-reset the modem firmware
- 'modem sms <ref> <number> <message>': send an SMS via the modem
(uses the signalling plane; no active data bearer required)
- MODEMS PTYPE provides tab-completion reading modem names from
/run/system.json
doc:
- Add initial User Guide for modems
- Update ChangeLog with modem news
- Use absolute URLs in ChangeLog. Relative links only work for in-tree
references, not in release notes
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
In the last major refactor of confd to a stand-alone daemon, new command
line options were added, one of which -v <LEVEL>. Unfortunately opening
up for a few corner cases where the debug flag or the log_level was not
set properly.
This fixes that and also adds a CONFD_ARGS for /etc/default/confd, which
is customary for all daemons.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The M.2 LTE slot uses the USB2 bus. Add it as an unlocked component so
the modem hardware is accessible and visible to users in the config.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
When an interface has been handed off to a container it lives in
another netns, so `ip neigh/addr flush dev FOO` fails on the host.
The failure aborts dagger, and since interfaces_change() runs before
containers_change() in change_cb(), the container delete path is
never reached -- the stale container keeps the interface trapped in
its netns, breaking the next reconfiguration.
Guard both the neighbor and address flush exit scripts with
`if_nametoindex(ifname)` -- true exactly when the interface is in
the host netns, false for both "in a container" and "already gone".
This replaces the pre-existing `!cni_find(ifname) && if_nametoindex(
ifname)` guard at the addr site: cni_find() added no information
for this check and would popen(container find) for nothing when the
interface had been deleted entirely.
Also harden wrap() in /usr/sbin/container so a stale setup pidfile
doesn't short-circuit Finit's stop attempt -- kill the setup PID and
still ask podman to stop the container.
Fixes#1493
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The mt7622 soc has a built-in wmac, same driver as the mt7615, but
it lacked MODULE_DEVICE_TABLE() so udev could not autoload driver
and firmware.
This commit also adds the wmac+bluetooth specific firmware.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The U-Boot env file is generated by
mkenvimage, which prefixes the variable data with a 4-byte CRC32 by default.
ixpreboot.sh previously imported it with `env import -b` as per uboot docs(-b assume binary format (’0’ separated, “00” terminated).),
which treats the buffer as raw binary and does not strip the CRC.
As a result the first variable's name is parsed a part of CRC.
Later variables import correctly because by then the parser is past the CRC.
Switching to `env import -c` as per uboot docs (-c assume checksum protected environment format.)
makes U-Boot validate and strip the CRC before parsing, so the first variable imports under its real name.
Tested on:
- QEMU
Signed-off-by: Ejub Sabic <ejub1946@outlook.com>
On multi-chip DSA hardware (e.g., boards with multiple mv88e6xxx
chips), each switch chip has its own independent PHC device. With
boundary_clock_jbod enabled, ptp4l starts but only disciplines the
active slave port's PHC — the others drift.
Automatically start phc2sys -a alongside any BC or TC instance using
hardware timestamping. It subscribes to ptp4l's UDS socket, tracks
BMCA, and disciplines all non-active PHCs to match the active one.
On single-chip hardware it is a harmless no-op.
CLOCK_REALTIME is intentionally left untouched. Syncing the system
clock to PTP (phc2sys -rr), feeding the PHC from GPS/NTP (ts2phc,
phc2sys reverse), and full multi-source coordination (timemaster) are
planned as follow-on phases; see the issue tracker for the roadmap.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
NOTE: this is intended only for use on devboards like EspressoBin where
the onboard bootloader only understands fat and ext2 file systems.
To enable, use 'make apply-ext4'
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Inverted values for eMMC and SPI NAND. Also use ABCD instead of
Position as column name to match board markings.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Add a board README to explain how to get Infix running
- Update mkimage.sh to allow creating images without boot loader
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Also, simplify board README a bit now that we know that you don't need
to flip the boot switch to program eMMC.
[skip ci]
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add missing *.hash files for all board packages using the ix-board macro;
they declare LICENSE_FILES = LICENSE but had no hash file, producing a
warning during make legal-info.
Fix the date-cpp package where the hash file was named date.hash instead
of date-cpp.hash (package name is derived from the directory, not the mk
filename), causing Buildroot to skip the hash check entirely.
Add hash files for local-site packages confd-test-mode, netd, and
onieprom that declared LICENSE_FILES but provided no hash.
Also, rename package/date-cpp/date.mk to date-cpp.mk. Buildroot derives
the package name from the directory name, so the mk file must match. To
handle the archive name different we set DATE_CPP_SOURCE.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add board support for the BananaPi BPI-R4 router board, based on the
MediaTek MT7988A (Filogic 880) SoC with quad-core Cortex-A73 CPU.
The BPI-R4 is the successor to the BPI-R3 but uses entirely different
silicon: the internal switch runs at 2.5 GbE per port, the two SFP+
uplinks use native USXGMII at up to 10 Gbps, and WiFi is provided by
a MediaTek MT7996E PCIe module supporting tri-band WiFi 7 (2.4/5/6 GHz).
Two board variants, BPI-R4-2g5 and BPI-R4P, replace one SFP+ cage with
a 2.5 GbE RJ45 port (using the MT7988A internal 2.5G PHY); the R4P adds
an optional PoE daughterboard on that port. Both use the upstream
mt7988a-bananapi-bpi-r4-2g5 device tree.
Interfaces:
- Standard R4: eth1 (gmac1/sfp2 LAN cage) → sfp2, eth2 (gmac2/sfp1 WAN cage) → sfp1
- R4-2g5/R4P: eth1 (2.5G PHY) → wan, eth2 (gmac2/sfp1 WAN cage) → sfp1
Factory reset / WPS button (GPIO14, active-low): detected by U-Boot at
boot for factory reset; reused by Linux as KEY_WPS_BUTTON at runtime.
eMMC install note: the MT7988A eMMC (pins 38-49) and SD card (pins 32-37)
use separate physical pads so there is no electrical bus sharing, unlike
some BPi-R3 configurations. However, a single MMC controller
(mmc@11230000) handles both, so only one is active per boot session.
The eMMC install procedure therefore still requires an intermediate SPI
NAND bootloader step until a Linux-side install path is tested.
SD card build (bpi_r4_sd_boot_defconfig) now uses the new
mt7988a_bpir4_sd U-Boot defconfig with cap-sd-highspeed enabled,
giving 50 MHz SD transfers instead of the previous 25 MHz legacy mode.
Also adds MT7988/MT7996 firmware support to the buildroot linux-firmware
package, for 2.5 GbE port PHY and WiFi7 extension board, and updates the
aarch64_defconfig, aarch64_minimal_defconfig, the arch README, CI
boot/image workflows, mkimage.sh, and the ChangeLog.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add --log-level command line option to filter out log messages from
lower log levels. Then fix the annoying CzechLight warning message
and useless "NACM config validation" log. Then add audit trail as
we have in netopeer2-server, and finish off by stripping redundant
fields from log message: timestamp, identity, and log level.
Fixes#892
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Previously svc_enadis() would call 'initctl enable + touch' for every
config change event, even when the service's enabled state was unchanged.
This caused rousette to be unnecessarily restarted on every test_reset(),
racing with the active RESTCONF connection on slow hardware.
Replace svc_enadis() and svc_change() with svc_enable() which only
manages nginx symlinks and calls 'initctl enable/disable' -- never touch.
Each handler now checks the diff for the specific leaf that changed:
- If /enabled appears in diff: call svc_enable() to start or stop it
- If other config leaves changed with service already enabled: touch only
This ensures rousette, ttyd, netbrowse, avahi, sshd, and lldpd are only
restarted when their configuration actually requires it.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- Add x509-public-key-format identity to crypto-types
- Add certificate node to web services container
- Use certificate from ietf-keystore as web cert
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Neither the Raspberry Pi 2B or the Microchip SAMA7G54-EK board have WiFi
hardware by default so drop WiFi, and GPS, support to allow for smaller
builds with only the bare essentials in kernel and system.
Minimal builds in general don't need WiFi or GPS either, so let's disable
them from all. This may become a central theme going forward, keeping
the minimal builds ... minimal.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
netopeer2 and rousette were starting as soon as confd had a PID, while
confd was still loading the startup config via sr_replace_config(). This
held a write lock on the running datastore. A test calling test/reset
shortly after the NETCONF port opened would have its own sr_replace_config()
block on that lock for up to 60 s, at which point sysrepo timed out the
whole RPC with "SHM event 'rpc' processing timed out".
Fix by adding the usr/bootstrap condition to both management servers so
they don't accept connections until confd signals that bootstrap is complete.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Relocate probe of wifi radios from gen-hardware to 00-probe. This saves
one python invocation and some precious CPU cycles at boot.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Follow-up to 90f619b which first introduced the /etc/hostname.d concept.
This commit moves the setup of /etc/hostname.d to post-build.sh dropping
the initial call to the hostname activation script a bit, since it is
called anyway after bootstrap has finished. The scrip is also given a
bit of a refrehs, reducing overhead and needless log messages.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Infix technically does not need to start dbus and dnsmasq before confd
has loaded the system startup-config. So we move it in time to save
some CPU cycles for confd & C:o.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
On single-core Cortex-A7, the YANG bootstrap and config loading is the
dominant boot bottleneck. The current sequence spawns three serial
phases (bootstrap, sysrepo-plugind, load), each performing independent
sr_connect()/sr_disconnect() cycles, and every sysrepoctl/sysrepocfg
invocation is a fork+exec that rebuilds SHM from scratch.
Replace all three with a single confd binary that does one sr_connect()
and performs all datastore operations in-process:
- Wipe stale /dev/shm/sr_* for a clean slate
- sr_install_factory_config() from the generated JSON
- Smart migration: compare config version via libjansson, only
fork+exec the migrate script when versions actually differ
- Load startup-config (or test-config) via lyd_parse_data() +
sr_replace_config(), mirroring what sysrepocfg -I does internally
- On failure: revert to factory-default, load failure-config, set
login banners (Fail Secure mode)
- On first boot: copy factory-default to running, export to file
- dlopen plugins and enter event loop
The bootstrap shell script is split: config generation (gen-hostname,
gen-interfaces, etc.) stays in the new gen-config script, while all
sysrepo operations move into the C daemon. The finit boot sequence
collapses from 5 stanzas to 2 (gen-config -> confd).
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
- The biggest changes are syncing with latest BusyBox (busybox-update-config)
- Disable optimize for size
- Enable feature "SH_NOFORK" which allows /bin/sh to call applet_main()
directly without having to fork+exec busybox
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Set dhcp-authoritative so clients with unexpired leases are not NAKed
after a router crash or factory reset that clears the lease database.
Drop the untagged suppress directives for options 3 (router) and 6
(dns-server): they conflict with the global options confd writes to
dnsmasq.d/, causing spurious "Ignoring duplicate dhcp-option" warnings.
Per-subnet tagged options already suppress auto-detection, and without
an active dhcp-range there is nothing to suppress anyway.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Ensure we translate the hostname before we generate the udhcpc command
line options, otherwise we'll send '-x hostname:rpi-%m' to udhcpc.
Also update all board specific factory configs with the missing setting
'"value": "auto"' for the DHCP hostname option. This to match what we
already do when we infer options when enabling a DHCP client in the CLI.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Two races could prevent DHCP-learned default routes from being installed
at boot:
1. The signal from the DHCP client script could be lost leaving conf.d
updated but frr.conf stale.
2. Even when the signal was received, 'vtysh -b' could fail because the
FRR daemon chain (mgmtd→zebra→staticd) writes PID files before being
fully operational, causing netd to give up with no retry.
Fix both by refactoring netd to use libev:
- Use an inotify watch of CONF_DIR, so netd reacts directly to file
changes without depending on signal delivery.
- On backend_apply() failure, schedule a retry in 5s and call pidfile()
unconditionally so dependent services are not blocked waiting for the
Finit condition 'pid/netd' to be satisfied.
We also take this opportunity to rename /etc/netd/conf.d/ to /etc/net.d/
The extra /etc/netd/ directory level served no purpose — nothing else
lives there. Flatten to /etc/net.d/ which reads more naturally as the
drop-in directory for network configuration snippets.
Also, reduce logging a bit since each netd backend already logs success
or fail which is sufficient to know that a configuration change has been
applied or not.
Finally, with the new inotify processing in netd it's redundant to call
'initctl reload netd' from the udhcpc script, in fact it will only cause
unnecessary overhead, so we drop it.
Fixes#1438
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Add board support for the BananaPi BPi-R64 router board, based on the
MediaTek MT7622 SoC and MT7531 Gigabit Ethernet switch.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
The Raspberry Pi 400 shares hardware with the RPi 4B but differs in one
important way: it has an internal keyboard and mouse connected through a
VIA Labs USB hub on the VL805 xHCI controller. Break the symlink to
raspberrypi,4-model-b and maintain a dedicated product directory.
Factory config changes from the 4B default:
- USB1/USB2/USB3 all unlocked: USB2 carries the internal keyboard hub
and USB3 the superspeed companion; all are unlocked as this is a
desktop device
- DHCP vendor-class corrected to "Raspberry Pi 400"
Also add interface-quirks.json for the eth0 PHY detach behaviour and
the smsc95xx broken flow-control quirk (inherited from the 4B config
but now explicit), and remove the spurious bootable flag from the
primary and secondary rootfs partitions in genimage.cfg.in.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Remove console=map:0 from the [pi4] section which was suppressing HDMI
output and disabling the display getty. Making it really difficult to
use it as a regular console.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
Two related problems prevented devices behind an intermediate hub (e.g.
the VIA Labs hub on the RPi 400's VL805 xHCI) from being authorized
when confd unlocks a USB bus:
1. Cascade ordering: usb_authorize() ran nftw() with FTW_DEPTH, which
visits children before the root-hub entry. The hub was authorized
while authorized_default was still 2, so when the kernel probed the
hub's children it immediately denied them. Fix: write
authorized_default=1 on the bus before entering nftw.
2. Slow/async probe: hub port enumeration is asynchronous — devices
behind a hub may appear in sysfs after nftw has already finished.
Fix: add a udev rule that catches usb_device add events on buses
where authorized_default=1 is already set on any ancestor root hub
and authorizes them immediately.
The ATTRS{} matcher in udev walks the full sysfs parent chain, so
authorized_default=1 on the root hub is visible even for devices several
hubs deep. Buses still locked at authorized_default=0 are left alone.
Also expand the docstring in generic_usb_ports() to document the
design: each root hub gets its own uniquely-named entry (USB, or USB1/
USB2/... when multiple) so buses can be individually controlled, and
boards needing finer control should use DT usb-ports annotations.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>