Compare commits

...
Author SHA1 Message Date
Mattias Walström 68d98f6e78 WiP: Example on howto use restconf notifications
Start script with ./subscribe_ietf_system.py --url "https://10.10.10.100" --user admin --password admin --no-verify-ssl --no-filter
2025-12-18 12:31:54 +01:00
Tobias WaldekranzandGitHub 45ff5d232e Merge pull request #1322 from kernelkit/upgrade-sysrepo
Upgrade sysrepo
2025-12-17 08:37:21 +01:00
Mattias Walström 773aab6ec1 factory-config.cfg: Update all static factory-config.cfg to the new syntax in ietf-netconf 2025-12-16 18:30:03 +01:00
Mattias Walström 542fd4006a Bump sysrepo,lignetconf2, libyang and netopeer2
This update got pretty messy, since libyang had some
breaking changes. And unfortunatly rousette, libyang-cpp
and sysrepo-cpp has not made any new release yet.
2025-12-16 18:30:03 +01:00
Mattias Walström e69d53a7b5 confd: Add migrate script to migrate configuration to new YANG syntax 2025-12-16 18:30:02 +01:00
Mattias Walström b0643430ec confd: factory-config: Change syntax to follow new yang model 2025-12-16 18:30:02 +01:00
Mattias Walström e49b3c9206 confd: Adapt YANG models after libyang/netopeer2 upgrade
We previously run a draft version of a lot of YANG models,
netconf-server,ssh-server and mode. Now they are released
with minor changes.

infix-meta is an exception, here we had to remove the obsolete
marker of the node and value, since this is no longer allowed in
libyang.
2025-12-16 18:30:01 +01:00
Tobias WaldekranzandGitHub 86eaea6237 Merge pull request #1323 from kernelkit/cn913x-ecc-stat
CN913x ECC Statistics Collection
2025-12-16 16:11:02 +01:00
Mattias Walström 2dba50db76 confd: Step up version of confd
Incompatible changes in YANG models for netconf.
2025-12-16 14:28:25 +01:00
Mattias Walström 0fe9cfad46 confd: Use correct YANG modules after upgrading libnetconf2 and sysrepo 2025-12-16 14:28:25 +01:00
Mattias Walström 0c60649c62 confd: Let rousette install its own yang models in rootfs
Previously rousette did not install the yang models so we kept a copy
of them in confd. Now it is implemented in rousette, let them install
their models.
2025-12-16 14:28:24 +01:00
Mattias Walström 9224bcc819 copy: Adapt to libyang4 API 2025-12-16 14:28:24 +01:00
Mattias Walström 0c7651705b confd, statd, libsrx: Adapt to libyang4 api 2025-12-16 14:28:24 +01:00
Tobias Waldekranz 8ae018baae support: cn913x: Collect DRAM ECC status
On platforms based on CN913{0,1,2}, collect all ECC related counters
so that we know if any correctable errors have been encountered since
the most recent boot.
2025-12-16 14:26:47 +01:00
Tobias Waldekranz 15aa98b7e3 support: Exec hardware specific scripts from /etc/support.d
Allow particular boards or platforms install hardware specific scripts
in /etc/support.d, via the usual /usr/share/product logic, which are
then run by /sbin/support and included in the resulting bundle.

This lets us collect hardware specific information, e.g., SoC-specific
error counters, without /sbin/support needing to know about all the
nitty gritty details.
2025-12-16 14:26:46 +01:00
Tobias WaldekranzandGitHub 2aeeadb045 Merge pull request #1321 from kernelkit/cn9130-wdg
CN9130 Watchdog
2025-12-16 11:17:05 +01:00
Tobias Waldekranz 553d659eac test/case/hardware/watchdog: Add test
Verify that if the system encounters a hard lockup, i.e., interrupts
are no longer being serviced, then the system's watchdog will
correctly reboot it.
2025-12-16 09:34:00 +01:00
Tobias Waldekranz 3460169bc5 aarch64/styx-dcp-sc-28p-a: Fix warm reset on old rev. a boards
Rev. A has a FLASH that Linux reconfigures to 4B-addressing, but must
be in 3B-addressing when accessed by the BootROM. Since it has no
reset input, this would not work on warm resets. Linux has a
workaround for this issue for the common case of a controlled reboot,
which this change enables on those boards (which are admittedly few
and far between, but still useful as testing vehicles).

(This won't take effect until Finit is updated to at least 4.15, which
switches over from watchdog- to reboot(2)- based reboot, by default)
2025-12-16 09:33:59 +01:00
Tobias Waldekranz d720323b50 kernel: Enable test_lockup module
This will be us the ability to test a hardware watchdog's ability to
trigger on different kinds of lockups.
2025-12-16 09:33:58 +01:00
Tobias Waldekranz 8eb706b564 aarch64: kernel: Enable SBSA watchdog
Usable by all Server Base System Architecture (SBSA) compliant SoCs,
e.g., CN9130.
2025-12-16 09:33:57 +01:00
Tobias Waldekranz 0298dc3c1a test: ssh: Wait for target SSH server to launch, by default
By default, ensure that the target device accepts TCP connections on
the specified port before returning the device object. This aligns the
SSH implementation with {NET,REST}CONF.

This solves the issue where tests that use SSH commands early in their
execution would sometimes fail as the remote server had not started up
yet.
2025-12-16 09:33:51 +01:00
Mattias Walström 0ea3380349 Upgrade python-libyang to support libyang4 2025-12-16 08:06:38 +01:00
Richard AlpeandGitHub 7fcbc88105 Merge pull request #1316 from kernelkit/statd-journaling
Add operational data journal with retention policy
2025-12-15 16:55:20 +01:00
Richard Alpe cb9aeea351 statd: compress journal snapshots with gzip
Store historical snapshots as compressed .json.gz files to reduce disk
usage. The operational.json file remains uncompressed for easy access.

Signed-off-by: Richard Alpe <richard@bit42.se>
2025-12-15 11:07:45 +01:00
Joachim WibergandGitHub 8d5e9c7ea0 Merge pull request #1320 from kernelkit/kernel-upgrade-c0ebffc2-d335-4b53-be81-f87050bba030
Upgrade to kernel 6.12.62
2025-12-13 07:13:35 +01:00
ael-bot 9fb9ac41d6 Upgrade Linux kernel to 6.12.62 2025-12-13 03:59:40 +00:00
Joachim WibergandGitHub 231bf1ed96 Merge pull request #1318 from kernelkit/rusage
Kernel config changes and resource usage monitoring
2025-12-12 11:55:11 +01:00
Tobias WaldekranzandGitHub 17d99aec41 Merge pull request #1312 from kernelkit/run-vs-qemu
Update documentation: qemu.sh -> run.sh
2025-12-11 00:05:55 +01:00
Richard Alpe c767a6f9a0 statd: add operational data journal with retention policy
Dump operational datastore to timestamped JSON snapshots every 5 minutes
(in /var/lib/statd/). The operational.json symlink always points to the
latest snapshot.

Implement hierarchical retention policy that keeps the first snapshot of
each time period (hour/day/week/month/year), providing fine-grained recent
history while preventing unbounded disk usage.

This will allow us to plot / track how the system state evolves as
well as give us somewhat fine-grained info in the case of an event,
such as a crash.

Add unit test simulating months of snapshots to verify retention
behavior using a statd stub that only runs the retention code locally
(unit test)

Signed-off-by: Richard Alpe <richard@bit42.se>
2025-12-09 16:16:53 +01:00
Joachim Wiberg c2a9ee4fbc board/*/linux_defconfig: panic on lockups and hung tasks
Turn on OOPS-to-panic, soft/hard lockup panic, hung-task panic, and
extra workqueue watchdog reporting. This makes latent stalls visible
instead of silently freezing, improving diagnosis of issues like the
recent resource-pressure lockup.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-08 17:01:54 +01:00
Joachim Wiberg d155f33b7c board/common: log disk/mem/filenr resource usage every hour
Dec  8 15:22:44 ix-00-00-00 watchdogd[2599]: Memory usage: 195036 kB, cached: 69740 kB, total: 423628 kB
Dec  8 15:22:44 ix-00-00-00 watchdogd[2599]: File system /var usage: blocks 4710/52564 inodes 80/65456
Dec  8 15:22:44 ix-00-00-00 watchdogd[2599]: File descriptor usage: 640/34603

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-08 17:01:54 +01:00
Joachim Wiberg f374bc12c5 Follow-up to ec0ed82b, update documentation
[skip ci]

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-07 09:15:47 +01:00
Joachim WibergandGitHub d9af63c2be Merge pull request #1311 from kernelkit/kernel-upgrade-077cf354-823d-43ad-b980-6022549c60dc
Upgrade to kernel 6.12.61
2025-12-07 08:39:19 +01:00
ael-bot 9044aef9d3 Upgrade Linux kernel to 6.12.61 2025-12-06 22:35:33 +00:00
Mattias WalströmandGitHub 6fafafc828 Merge pull request #1310 from kernelkit/remove-python-statd 2025-12-06 23:18:40 +01:00
Mattias Walström dc6abfaaae statd: Remove python-statd package
Now statd handling the rebuilding of the python libraries by using
the same script as buildroot uses for building python-packages.
2025-12-06 22:03:55 +01:00
Joachim WibergandGitHub 2d35f15242 Merge pull request #1306 from kernelkit/rip 2025-12-06 20:44:58 +01:00
Mattias WalströmandGitHub 167184ddd9 Merge pull request #1309 from kernelkit/rpi-fw
buildroot: bump rpi-firmware version to 95be71b
2025-12-06 15:39:56 +01:00
Joachim Wiberg 19471dd95e buildroot: bump rpi-firmware version to 95be71b
Newer board revisions of RPi4 and CM4, as well as older boards with
upgraded EEPROM, require newer firmware.

This is a backport of the latest rpi-firmware on Buildroot master.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-06 14:05:51 +01:00
Joachim WibergandGitHub 5e353a8470 Merge pull request #1307 from kernelkit/flaky 2025-12-06 14:03:35 +01:00
Joachim WibergandGitHub c35342baec Merge pull request #1308 from kernelkit/misc
Fix factory-config, duplicate IPv6 address entry
2025-12-06 13:08:01 +01:00
Mattias Walström 0a0e03a504 Add .claude to gitignore 2025-12-06 11:48:11 +01:00
Mattias Walström dd9ebf2d3f factory-config: Remove duplicate "ietf-ip:ipv6" node
Signed-off-by: Mattias Walström <lazzer@gmail.com>
2025-12-06 10:51:12 +01:00
Joachim Wiberg e596ffc7c4 doc: relocate support data collection to separate section
Does not really fit under "System Configuration".

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 17:46:05 +01:00
Joachim Wiberg 69bbf6fafc support: use $0 in usage text and error messages
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 16:33:06 +01:00
Joachim Wiberg c89c1f689b support: diagnostic debug for flaky test
This patch adds diagnostic data and additional logging to catch the root
cause for issue #1303:

  - Exactly when and why cleanup is called
  - Whether the cd /tmp command succeeds
  - The actual tar exit code (not just 255 from SSH)
  - Whether cleanup happens before tar completes (race condition)
  - The full collection.log showing the sequence of events

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 14:40:02 +01:00
Joachim Wiberg a6966dff88 doc: update ChangeLog, RIP support
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 11:15:35 +01:00
Joachim Wiberg ab54b4cf47 doc: add RIP documentation
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 11:12:04 +01:00
Joachim Wiberg 8c52ffc4ca test: update unit test data for new ip forwarding
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 11:12:04 +01:00
Joachim Wiberg 0a491ffff5 test: add new tests for RIP
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 11:12:03 +01:00
Joachim Wiberg 024b51cc6a statd: add support for ip forwarding operational state
This patch unlocks "routing interfaces" support in the ietf-routing yang
model.  An array of interface with IP forwarding enabled.

Note, because of #515 we skip IPv6 forwarding for now.  This will in the
near future be handled by a per-interface force_forwarding sysctl flag.

The 'show interface [ifname]' admin-exec command has been extended with
a Flags field for a quick overview of which interfaces have forwarding
currently enabled.

Fixes #647

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 11:12:03 +01:00
Joachim Wiberg 1cbc9a49a2 confd: initial support for rip
Fixes #582

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-05 10:58:35 +01:00
Tobias WaldekranzandGitHub dc6e82759a Merge pull request #1304 from kernelkit/post-post-post-image
Move to a post `post-post-image` world
2025-12-04 10:25:51 +01:00
Tobias Waldekranz db5309cb40 defconfig: Fix boot defconfigs post post-post-image
After merging post-post-image, TRUSTED_KEYS must be set in order for
the keys to be injected into the U-Boot DTB, so we need to explicitly
enable it for all boards that use the generic secure boot scripts.
2025-12-04 09:35:59 +01:00
Tobias Waldekranz c7bde09aa6 aarch64_qemu_boot: Don't repack a new QCOW image
This was a stray config fragment used during development that was
accedentally included in the referenced commit.

Fixes: 0fe5964909 ("aarch64_qemu_boot: Restore build after removing post-image.sh")
2025-12-04 09:35:53 +01:00
Joachim WibergandGitHub ec0ed82b71 Merge pull request #1267 from kernelkit/post-post-image
Move to a post post-image world

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-03 20:32:36 +01:00
Tobias Waldekranz bac11dad0f defconfig: Update all architectures to use new image types 2025-12-03 16:46:16 +01:00
Tobias Waldekranz 0fe5964909 aarch64_qemu_boot: Restore build after removing post-image.sh
Use the new image-itb-dl-release to compose a QCOW with Infix and
U-Boot, in the same way that we previously did in post-image.sh.
2025-12-03 16:46:15 +01:00
Tobias Waldekranz cf6e211b91 board/common/qemu: Downgrade CPU to Cortex-A53 on aarch64
This CPU has less emulation overhead than `max`, which is what we
mostly care about.
2025-12-03 16:46:14 +01:00
Tobias Waldekranz 87b3f9c304 board/common: Restore capability to create QEMU image from tarball
Previously, post-image.sh was able to create QEMU images from an
existing release tarball. This was useful when you wanted to test a
new bootloader build without having to wait for a full Infix build.

Restore this capability by adding a separate image target for it, and
then allow image-itb-qcow to source its input images from that instead
of a locally build squash+aux.
2025-12-03 16:46:13 +01:00
Tobias Waldekranz 04e33c0f15 board/common: Remove post-image.sh
Now that all components are generated from their own fragments, we
have no need for post-image.sh anymore.
2025-12-03 16:46:12 +01:00
Tobias Waldekranz 696d41d263 board/common: Move README.md installation to separate make target 2025-12-03 16:46:11 +01:00
Tobias Waldekranz 94f5463504 onieprom: Create proper package 2025-12-03 16:46:10 +01:00
Tobias Waldekranz ceb9c0bb6f board/common: Remove unused MMC image creation script
Remnants from the olde country.
2025-12-03 16:46:09 +01:00
Tobias Waldekranz 6e485ccb53 board/common: Skip unused infix-branded symlink to rootfs.squashfs
This is an internal artifact, so there is no need to give it a branded
name.
2025-12-03 16:46:08 +01:00
Tobias Waldekranz 516313b489 board/common: Move QEMU script generation to separate make target 2025-12-03 16:46:07 +01:00
Tobias Waldekranz 065c131285 board/common: Move GNS3 appliance creation to separate make target
Limit support to x86, like we do on the "official" appliances on the
marketplace. Aarch64 has never really been used AFAIK.

Avoid the os-release import, since all that info is not important now
that these appliance files are only for development scenarios. In all
other cases, the official one, based on a proper release, should be
used.
2025-12-03 16:46:06 +01:00
Tobias Waldekranz 046a736dc9 board/common: Remove broken "Traditional FIT image"
We have not installed .dtb:s to $O/images/ for quite some time, and
nobody cared. That goes to show that this is not really used.

The image is still useful at times, so if it needed in the future,
then we can resurrect it from the logs and refactor it to an image
package.
2025-12-03 16:46:05 +01:00
Tobias Waldekranz aee053c94b board/common: Move QEMU disk creation to separate make target 2025-12-03 16:46:04 +01:00
Tobias Waldekranz 290bdfcedb board/common: Consolidate aux.ext4 generation
Add a generic image target to build aux.ext4, which can be used both
when creating target-specific SD-card images, and when creating
regular disk images.

While we're here, make sure that we don't need a RAUC bundle in order
to generate aux.ext4 (which mkrauc-status.sh did). This saves us time
on _every_ incremental build.
2025-12-03 16:46:03 +01:00
Tobias Waldekranz dd98c57bc7 board/common: Move RAUC bundle creation to separate make target 2025-12-03 16:46:02 +01:00
Tobias Waldekranz bf1a431692 board/common: Move rootfs.itb/itbh creation to separate make target 2025-12-03 16:46:01 +01:00
Tobias Waldekranz 7cebc36ab2 board/common: Add common macro for image generation
Add scaffolding for breaking out image generation to separate make
targets.
2025-12-03 16:46:00 +01:00
Tobias Waldekranz f0d56691c7 board/common: Fix trusted key installation logic
Rather than using the creation of a signed image as a proxy for
whether the trusted keys should be installed RAUC/U-Boot's trust
stores, use the dedicated option.
2025-12-03 16:45:59 +01:00
Tobias Waldekranz 218cf5ccdb board: Defer Makefile fragment inclusion to each architecture
The board/*/*/*.mk is very broad, intended to hit all board specific
definitions, but may also cause duplicate inclusions, e.g., in
board/common.

Let each architecture do the inclusion instead.
2025-12-03 16:45:58 +01:00
Tobias Waldekranz 3053662468 infix.mk: Define artifact name in one place
A bunch of different artifacts should follow the same naming scheme,
depending on a bunch of config settings + whether we're building a
release or not.

Therefore, provide a single definition of this that we can reuse to
name disk images, upgrade packages, etc.
2025-12-03 16:45:52 +01:00
Joachim WibergandGitHub 9def1e6873 Merge pull request #1297 from kernelkit/ospf-debug
Configurable support for OSPF debug
2025-12-03 11:20:09 +01:00
Joachim Wiberg 39ffad6b08 doc: update ChangeLog, new ospf debug settings
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-02 17:06:49 +01:00
Joachim Wiberg 989197e2c3 doc: add information on ospf debug settings
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-02 17:06:14 +01:00
Joachim Wiberg c0646d1a66 test: new test to verify ospf debug logging
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-02 17:06:13 +01:00
Joachim Wiberg 7edc3c19f7 confd: add support for toggling OSPF debug logs
Fixes #1281

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2025-12-02 17:06:10 +01:00
323 changed files with 17198 additions and 3863 deletions
+1
View File
@@ -1,4 +1,5 @@
*~
.claude
.gdb_history
/.backup
/.ccache
+8 -1
View File
@@ -387,7 +387,14 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=20
CONFIG_DETECT_HUNG_TASK=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
CONFIG_WQ_WATCHDOG=y
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
CONFIG_TEST_LOCKUP=m
# CONFIG_SCHED_DEBUG is not set
# CONFIG_RCU_TRACE is not set
CONFIG_FUNCTION_TRACER=y
@@ -41,14 +41,31 @@
"ietf-ip:ipv4": {
"infix-dhcp-client:dhcp": {
"option": [
{"id": "netmask"},
{"id": "broadcast"},
{"id": "router"},
{"id": "domain"},
{"id": "hostname"},
{"id": "dns-server"},
{"id": "ntp-server"},
{"id": "vendor-class", "value": "Raspberry Pi 2 Model B"}
{
"id": "netmask"
},
{
"id": "broadcast"
},
{
"id": "router"
},
{
"id": "domain"
},
{
"id": "hostname"
},
{
"id": "dns-server"
},
{
"id": "ntp-server"
},
{
"id": "vendor-class",
"value": "Raspberry Pi 2 Model B"
}
]
}
}
@@ -122,7 +139,11 @@
"name": "default-ssh",
"ssh": {
"tcp-server-parameters": {
"local-address": "::"
"local-bind": [
{
"local-address": "::"
}
]
},
"ssh-server-parameters": {
"server-identity": {
@@ -168,7 +189,7 @@
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
},
"infix-meta:meta": {
"version": "1.6"
"version": "1.7"
},
"infix-services:mdns": {
"enabled": true
@@ -99,28 +99,52 @@
{
"name": "wan",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"ietf-ip:ipv4": {
"infix-dhcp-client:dhcp": {
"option": [
{"id": "ntp-server"},
{"id": "broadcast"},
{"id": "domain"},
{"id": "hostname"},
{"id": "dns-server"},
{"id": "router"},
{"id": "netmask"},
{"id": "vendor-class", "value": "Banana Pi BPI-R3"}
{
"id": "ntp-server"
},
{
"id": "broadcast"
},
{
"id": "domain"
},
{
"id": "hostname"
},
{
"id": "dns-server"
},
{
"id": "router"
},
{
"id": "netmask"
},
{
"id": "vendor-class",
"value": "Banana Pi BPI-R3"
}
]
}
},
"ietf-ip:ipv6": {
"infix-dhcpv6-client:dhcp": {
"option": [
{"id": "ntp-server"},
{"id": "client-fqdn"},
{"id": "domain-search"},
{"id": "dns-server"}
{
"id": "ntp-server"
},
{
"id": "client-fqdn"
},
{
"id": "domain-search"
},
{
"id": "dns-server"
}
]
}
}
@@ -136,18 +160,18 @@
]
},
"ietf-keystore:keystore": {
"asymmetric-keys": {
"asymmetric-key": [
{
"name": "genkey",
"public-key-format": "infix-crypto-types:ssh-public-key-format",
"public-key": "",
"private-key-format": "infix-crypto-types:rsa-private-key-format",
"cleartext-private-key": "",
"certificates": {}
}
]
"asymmetric-keys": {
"asymmetric-key": [
{
"name": "genkey",
"public-key-format": "infix-crypto-types:ssh-public-key-format",
"public-key": "",
"private-key-format": "infix-crypto-types:rsa-private-key-format",
"cleartext-private-key": "",
"certificates": {}
}
]
}
},
"ietf-netconf-acm:nacm": {
"enable-nacm": true,
@@ -202,7 +226,11 @@
"name": "default-ssh",
"ssh": {
"tcp-server-parameters": {
"local-address": "::"
"local-bind": [
{
"local-address": "::"
}
]
},
"ssh-server-parameters": {
"server-identity": {
@@ -294,7 +322,7 @@
"policy": [
{
"name": "lan-to-wan",
"action": "accept",
"action": "accept",
"ingress": [
"lan"
],
@@ -306,7 +334,7 @@
]
},
"infix-meta:meta": {
"version": "1.6"
"version": "1.7"
},
"infix-services:mdns": {
"enabled": true
@@ -342,4 +370,3 @@
}
}
}
+1 -7
View File
@@ -1,3 +1,4 @@
include $(sort $(wildcard $(BR2_EXTERNAL_INFIX_PATH)/board/aarch64/*/*.mk))
.PHONY: board-enable-qemu-uboot
board-enable-qemu-uboot:
@@ -19,13 +20,6 @@ board-enable-qemu-uboot:
'$$(BR2_EXTERNAL_INFIX_PATH)/board/common/uboot/extras.config' \
--enable TARGET_UBOOT_FORMAT_DTB
.PHONY: board-enable-sparx-fit
board-enable-sparx-fit:
@$(call IXMSG,"Enabling SparX-5i compatible FIT options")
@BR2_PREFIX= ./utils/config --file $(BR2_CONFIG) \
--enable FIT_IMAGE \
--set-str FIT_KERNEL_LOAD_ADDR "0x7 0x00000000"
.PHONY: board-sparx-flash-uboot
board-sparx-flash-uboot: $(BINARIES_DIR)/u-boot.bin
@grep -q 'BR2_TARGET_UBOOT_BOARD_DEFCONFIG="mscc_fireant_pcb135_emmc"' $(BR2_CONFIG) || \
@@ -58,28 +58,52 @@
{
"name": "wan",
"type": "infix-if-type:ethernet",
"ietf-ip:ipv6": {},
"ietf-ip:ipv4": {
"infix-dhcp-client:dhcp": {
"option": [
{"id": "ntp-server"},
{"id": "broadcast"},
{"id": "domain"},
{"id": "hostname"},
{"id": "dns-server"},
{"id": "router"},
{"id": "netmask"},
{"id": "vendor-class", "value": "NanoPi R2S"}
{
"id": "ntp-server"
},
{
"id": "broadcast"
},
{
"id": "domain"
},
{
"id": "hostname"
},
{
"id": "dns-server"
},
{
"id": "router"
},
{
"id": "netmask"
},
{
"id": "vendor-class",
"value": "NanoPi R2S"
}
]
}
},
"ietf-ip:ipv6": {
"infix-dhcpv6-client:dhcp": {
"option": [
{"id": "ntp-server"},
{"id": "client-fqdn"},
{"id": "domain-search"},
{"id": "dns-server"}
{
"id": "ntp-server"
},
{
"id": "client-fqdn"
},
{
"id": "domain-search"
},
{
"id": "dns-server"
}
]
}
}
@@ -87,18 +111,18 @@
]
},
"ietf-keystore:keystore": {
"asymmetric-keys": {
"asymmetric-key": [
{
"name": "genkey",
"public-key-format": "infix-crypto-types:ssh-public-key-format",
"public-key": "",
"private-key-format": "infix-crypto-types:rsa-private-key-format",
"cleartext-private-key": "",
"certificates": {}
}
]
"asymmetric-keys": {
"asymmetric-key": [
{
"name": "genkey",
"public-key-format": "infix-crypto-types:ssh-public-key-format",
"public-key": "",
"private-key-format": "infix-crypto-types:rsa-private-key-format",
"cleartext-private-key": "",
"certificates": {}
}
]
}
},
"ietf-netconf-acm:nacm": {
"enable-nacm": true,
@@ -153,7 +177,11 @@
"name": "default-ssh",
"ssh": {
"tcp-server-parameters": {
"local-address": "::"
"local-bind": [
{
"local-address": "::"
}
]
},
"ssh-server-parameters": {
"server-identity": {
@@ -245,7 +273,7 @@
"policy": [
{
"name": "lan-to-wan",
"action": "accept",
"action": "accept",
"ingress": [
"lan"
],
@@ -257,7 +285,7 @@
]
},
"infix-meta:meta": {
"version": "1.6"
"version": "1.7"
},
"infix-services:mdns": {
"enabled": true
+9 -1
View File
@@ -407,6 +407,7 @@ CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_SYSFS=y
CONFIG_SOFT_WATCHDOG=y
CONFIG_GPIO_WATCHDOG=y
CONFIG_ARM_SBSA_WATCHDOG=y
CONFIG_ARMADA_37XX_WATCHDOG=y
CONFIG_I6300ESB_WDT=y
CONFIG_MFD_MAX77620=y
@@ -557,7 +558,14 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=20
CONFIG_DETECT_HUNG_TASK=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
CONFIG_WQ_WATCHDOG=y
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
CONFIG_TEST_LOCKUP=m
# CONFIG_SCHED_DEBUG is not set
# CONFIG_RCU_TRACE is not set
CONFIG_FUNCTION_TRACER=y
+1 -1
View File
@@ -108,7 +108,7 @@ To configure WiFi as a client, first store your WiFi password in the keystore:
admin@infix:/> configure
admin@infix:/config/> edit keystore symmetric-key mywifi
admin@infix:/config/keystore/…/mywifi/> set key-format wifi-preshared-key-format
admin@infix:/config/keystore/…/mywifi/> set cleartext-key YourWiFiPassword
admin@infix:/config/keystore/…/mywifi/> set cleartext-symmetric-key YourWiFiPassword
admin@infix:/config/keystore/…/mywifi/> leave
```
@@ -41,14 +41,31 @@
"ietf-ip:ipv4": {
"infix-dhcp-client:dhcp": {
"option": [
{"id": "netmask"},
{"id": "broadcast"},
{"id": "router"},
{"id": "domain"},
{"id": "hostname"},
{"id": "dns-server"},
{"id": "ntp-server"},
{"id": "vendor-class", "value": "Raspberry Pi 4 Model B"}
{
"id": "netmask"
},
{
"id": "broadcast"
},
{
"id": "router"
},
{
"id": "domain"
},
{
"id": "hostname"
},
{
"id": "dns-server"
},
{
"id": "ntp-server"
},
{
"id": "vendor-class",
"value": "Raspberry Pi 4 Model B"
}
]
}
}
@@ -126,7 +143,11 @@
"name": "default-ssh",
"ssh": {
"tcp-server-parameters": {
"local-address": "::"
"local-bind": [
{
"local-address": "::"
}
]
},
"ssh-server-parameters": {
"server-identity": {
@@ -172,7 +193,7 @@
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
},
"infix-meta:meta": {
"version": "1.6"
"version": "1.7"
},
"infix-services:mdns": {
"enabled": true
@@ -0,0 +1,26 @@
#!/bin/sh
set -e
ecc_stat()
{
local chan=
local base=
for chan in 0 1; do
base=$((0xf0020360 + 0x200 * chan))
echo "DRAM Channel $chan ECC Status"
echo -n " Log config: "; devmem $((base + 0x0)) 32
echo -n " 1b errors: "; devmem $((base + 0x4)) 32
echo -n " Info 0: "; devmem $((base + 0x8)) 32
echo -n " Info 1: "; devmem $((base + 0xc)) 32
echo
done
}
[ -n "$1" ] || { echo "usage: $0 OUT-DIR"; exit 1; }
work="$1"/marvell-cn913x
mkdir -p "${work}"
ecc_stat >"${work}"/ecc-stat
@@ -59,3 +59,9 @@
XSWP(a, "e13", 13, &sfp0);
};
};
&cp0_spi1 {
spi-flash@0 {
broken-flash-reset;
};
};
+2 -1
View File
@@ -1,2 +1,3 @@
include $(BR2_EXTERNAL_INFIX_PATH)/board/common/common.mk
include $(BR2_EXTERNAL_INFIX_PATH)/board/ix-board.mk
include $(sort $(wildcard $(BR2_EXTERNAL_INFIX_PATH)/board/*/*/*.mk))
-include $(BR2_EXTERNAL_INFIX_PATH)/board/$(patsubst "%",%,$(BR2_ARCH))/board.mk
+18 -149
View File
@@ -1,32 +1,28 @@
menuconfig SIGN_ENABLED
bool "Image Signing"
menu "Images"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-rootfs/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-aux/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-qcow/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-gns3a/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-rauc/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-itb-dl-release/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/board/common/image/image-readme/Config.in"
endmenu
config QEMU_SCRIPTS
bool "QEMU scripts"
default y
choice
prompt "Signing key source"
depends on SIGN_ENABLED
default SIGN_SRC_DIR
config SIGN_SRC_DIR
bool "Directory"
config SIGN_SRC_PKCS11
bool "PKCS#11 URL"
endchoice
config SIGN_KEY
string "Signing key"
depends on SIGN_ENABLED
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/signing-keys/development" if SIGN_SRC_DIR
help
Install QEMU scripts and related files in the images
directory, which can be used to launch virtual Infix
instances.
menuconfig TRUSTED_KEYS
bool "Trusted keys for image"
depends on SIGN_ENABLED
help
Keys that will be accepted for this image
config TRUSTED_KEYS_DEVELOPMENT
bool "Development key"
depends on TRUSTED_KEYS
@@ -39,130 +35,3 @@ config TRUSTED_KEYS_DEVELOPMENT_PATH
config TRUSTED_KEYS_EXTRA_PATH
string "Path to extra keys to include in image"
depends on TRUSTED_KEYS
menuconfig DISK_IMAGE
bool "Disk image"
help
Compose a full disk image with redundant Linux OS partitions,
configuration partition, etc.
This is useful when:
- Bringing up a blank system during manufacturing
- Creating a GNS3 appliance
- Developing/debugging issues in the boot process in QEMU
menuconfig DISK_IMAGE_SIZE
string "Image size"
depends on DISK_IMAGE
default "512M"
help
Create a disk image of this size. A K/M/G suffix may be used
to multiply by powers of 1024. Suffixes like KB/MB/GB may be
used to multiply by powers of 1000. The image will be split
proportionally to fit the two rootfs, a kernel, a writable
/cfg and /var partiotions.
Minimum supported size is 512M.
choice
prompt "Bootloader"
depends on DISK_IMAGE
default DISK_IMAGE_BOOT_EFI if BR2_x86_64
default DISK_IMAGE_BOOT_NONE
config DISK_IMAGE_BOOT_NONE
bool "None"
help
Do not create any bootloader partition in the disk image.
config DISK_IMAGE_BOOT_EFI
bool "EFI"
help
Create a boot partition from a directory containing an EFI
boot application, e.g. GRUB.
config DISK_IMAGE_BOOT_BIN
bool "Binary"
help
Create a boot partition from a raw image containing the boot
application, e.g. U-Boot.
endchoice
config DISK_IMAGE_BOOT_DATA
string "Bootloader data"
depends on DISK_IMAGE
depends on DISK_IMAGE_BOOT_EFI || DISK_IMAGE_BOOT_BIN
default "${BINARIES_DIR}/efi-part/EFI" if BR2_x86_64
help
Path to the directory or file holding the bootloader data.
config DISK_IMAGE_BOOT_OFFSET
hex "Bootloader offset"
depends on DISK_IMAGE
depends on DISK_IMAGE_BOOT_EFI || DISK_IMAGE_BOOT_BIN
default 0x8000
help
Offset at which the bootloader partition is placed. Remember
to make sure that the GPT still fits at the start of the
image.
config DISK_IMAGE_RELEASE_URL
string "Infix URL"
depends on DISK_IMAGE
depends on !BR2_TARGET_ROOTFS_SQUASHFS
default "https://github.com/kernelkit/infix/releases/download/latest/infix-${BR2_ARCH}.tar.gz"
help
In situations where Infix itself is not being built, but a
disk image is, i.e. when building a bootloader: place this
Infix release in the primary and secondary partitions.
menuconfig GNS3_APPLIANCE
bool "GNS3 Appliance"
select DISK_IMAGE
default y
help
Create a GNS3 appliance description that, together with the
disk image, can be imported into GNS3.
config GNS3_APPLIANCE_RAM
int "Reserved RAM (MiB)"
depends on GNS3_APPLIANCE
default "192"
help
Amount of host RAM reserved for an appliance instance.
Minimum supported size is 192M.
config GNS3_APPLIANCE_IFNUM
int "Number of interfaces"
depends on GNS3_APPLIANCE
default "1"
help
Number of Ethernet interfaces to create for an appliance instance.
menuconfig FIT_IMAGE
bool "Traditional FIT image"
help
Create a "regular" FIT image where the kernel and DTBs are
stored in the FIT rather than inside the rootfs (like it
normally is in Infix).
This is useful when trying out Infix on targets whose
bootloader might not be capable of booting a raw Squash, but
is able to handle an FIT.
config FIT_ARCH
string
depends on FIT_IMAGE
default "arm64" if BR2_aarch64
config FIT_KERNEL_LOAD_ADDR
string "Kernel load address"
depends on FIT_IMAGE
config SDCARD_AUX
bool "Create SD-card aux partition"
help
Create and populate aux.ext4 with rootfs.itbh and rauc.status
For use with a static genimage.cfg for, e.g., SD-cards.
+4 -1
View File
@@ -1,4 +1,7 @@
ifeq ($(SIGN_ENABLED),y)
include $(BR2_EXTERNAL_INFIX_PATH)/board/common/image/image.mk
include $(BR2_EXTERNAL_INFIX_PATH)/board/common/qemu/qemu.mk
ifeq ($(TRUSTED_KEYS),y)
include $(BR2_EXTERNAL_INFIX_PATH)/board/common/uboot/uboot.mk
TRUSTED_KEYS=$(TRUSTED_KEYS_DEVELOPMENT_PATH) $(TRUSTED_KEYS_EXTRA_PATH)
@@ -0,0 +1,10 @@
config IMAGE_ITB_AUX
bool "aux partition"
depends on IMAGE_ITB_ROOTFS
select BR2_PACKAGE_HOST_UBOOT_TOOLS
select BR2_PACKAGE_HOST_GENIMAGE
help
Create and populate auxiliary partition, aux.ext4, with
metadata needed by U-Boot and RAUC to operate properly on
systems using ITB images. This may then be included as a
partition in a larger disk image.
+85
View File
@@ -0,0 +1,85 @@
#!/bin/sh
set -e
boot="${1}"
squash="${BINARIES_DIR}"/rootfs.squashfs
itbh="${BINARIES_DIR}"/rootfs.itbh
aux="${BINARIES_DIR}"/aux.ext4
mkdir -p "${WORKDIR}"/aux
rm -rf "${WORKDIR}"/tmp
mkdir -p "${WORKDIR}"/tmp
cp -f "${itbh}" "${WORKDIR}"/aux/primary.itbh
cp -f "${itbh}" "${WORKDIR}"/aux/secondary.itbh
tstamp=$(date -u +%FT%TZ)
rootsha=$(sha256sum "${squash}" | cut -d" " -f1)
rootsize=$(stat -c %s "${squash}")
cat <<EOF >"${WORKDIR}"/aux/rauc.status
[slot.rootfs.0]
bundle.compatible=${COMPATIBLE}
bundle.version=${VERSION}
status=ok
sha256=${rootsha}
size=${rootsize}
installed.timestamp=$tstamp
installed.count=1
activated.timestamp=$tstamp
activated.count=1
[slot.rootfs.1]
bundle.compatible=${COMPATIBLE}
bundle.version=${VERSION}
status=ok
sha256=${rootsha}
size=${rootsize}
installed.timestamp=$tstamp
installed.count=1
activated.timestamp=$tstamp
activated.count=1
EOF
case "${boot}" in
uboot)
cat <<EOF | mkenvimage -s 0x4000 -o "${WORKDIR}"/aux/uboot.env -
BOOT_ORDER=primary secondary net
BOOT_primary_LEFT=1
BOOT_secondary_LEFT=1
BOOT_net_LEFT=1
EOF
;;
grub)
mkdir -p "${WORKDIR}"/aux/grub
cp -f "${PKGDIR}"/grub.cfg "${PKGDIR}"/grubenv "${WORKDIR}"/aux/grub
;;
*)
echo "UNSUPPORTED BOOTLOADER ${boot}" >&2
exit 1
esac
cat <<EOF >"${WORKDIR}"/genimage.cfg
image $(basename ${aux}) {
mountpoint = "/"
size = 8M
ext4 {
label = "aux"
use-mke2fs = true
features = "^metadata_csum,^metadata_csum_seed,uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
# Silence genimage warnings
config {}
EOF
genimage \
--loglevel 1 \
--tmppath "${WORKDIR}"/tmp \
--rootpath "${WORKDIR}"/aux \
--inputpath "${WORKDIR}" \
--outputpath "$(dirname ${aux})" \
--config "${WORKDIR}"/genimage.cfg
+80
View File
@@ -0,0 +1,80 @@
set timeout="1"
load_env ORDER DEBUG
if [ -z "$ORDER" ]; then
set ORDER="primary secondary"
fi
set ORDER="$ORDER reboot"
for slot in $ORDER; do
if [ -z "$default" ]; then
set default="$slot"
else
# Contrary to what the documentation says, GRUB (2.06) does
# not support using titles or IDs in the fallback variable, so
# we translate to indices.
if [ "$slot" = "primary" ]; then
set fallback="$fallback 0"
elif [ "$slot" = "secondary" ]; then
set fallback="$fallback 1"
elif [ "$slot" = "net" ]; then
set fallback="$fallback 2"
elif [ "$slot" = "reboot" ]; then
set fallback="$fallback 3"
fi
fi
done
if [ "$DEBUG" ]; then
set log="debug"
else
set log="loglevel=4"
fi
# From board/common/rootfs/etc/partition-uuid
search -p 107ae911-a97b-4380-975c-7ce1a2dde1e0 --set primary
search -p 352bd9b2-2ca9-44e2-bdc7-edbc87ba1e02 --set secondary
export primary
export secondary
submenu "primary" "$log" {
set slot="$1"
set append="console=ttyS0 console=hvc0 usbcore.authorized_default=2 root=PARTLABEL=$slot $2"
set root="($primary)"
source /boot/grub/grub.cfg
}
submenu "secondary" "$log" {
set slot="$1"
set append="console=ttyS0 console=hvc0 usbcore.authorized_default=2 root=PARTLABEL=$slot $2"
set root="($secondary)"
source /boot/grub/grub.cfg
}
submenu "net" "$log" {
net_dhcp
if [ "$net_efinet0_dhcp_next_server" -a "$net_efinet0_dhcp_boot_file" ]; then
set initrd=(tftp,$net_efinet0_dhcp_next_server)/$net_efinet0_dhcp_boot_file
loopback initrd $initrd
set root=(initrd)
set slot="$1"
set append="console=ttyS0 console=hvc0 usbcore.authorized_default=2 qroot=/dev/ram0 ramdisk_size=65536 $2"
source /boot/grub/grub.cfg
else
if [ -z "$net_efinet0_dhcp_next_server" ]; then
echo "No TFTP server supplied in DHCP response"
fi
if [ -z "$net_efinet0_dhcp_boot_file" ]; then
echo "No bootfile supplied in DHCP response"
fi
fi
}
submenu "reboot" {
reboot
}
+10
View File
@@ -0,0 +1,10 @@
# GRUB Environment Block
# WARNING: Do not edit this file by tools other than grub-editenv!!!
ORDER=primary secondary net
primary_OK=1
secondary_OK=1
net_OK=1
primary_TRY=0
secondary_TRY=0
net_TRY=0
#########################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
@@ -0,0 +1,10 @@
################################################################################
#
# image-itb-aux
#
################################################################################
IMAGE_ITB_AUX_DEPENDENCIES := host-uboot-tools host-genimage image-itb-rootfs
IMAGE_ITB_AUX_OPTS := $(if $(BR2_TARGET_GRUB2),grub,uboot)
$(eval $(ix-image))
@@ -0,0 +1,15 @@
menuconfig IMAGE_ITB_DL_RELEASE
bool "Download existing release"
depends on !BR2_TARGET_ROOTFS_SQUASHFS
help
This is primarily used by target specific builds, where the
bootloader artifact needs to be combined with an existing
Infix image, to create a full disk image that can be
provisioned to an SD-card or eMMC.
config IMAGE_ITB_DL_RELEASE_URL
string "URL"
depends on IMAGE_ITB_DL_RELEASE
default "https://github.com/kernelkit/infix/releases/download/latest/infix-${BR2_ARCH}.tar.gz"
help
URL to release tarball.
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
set -e
squash="${BINARIES_DIR}"/rootfs.squashfs
aux="${BINARIES_DIR}"/aux.ext4
[ -f "${squash}" ] && [ -f "${aux}" ] && exit 0
archive="${WORKDIR}/$(basename ${URL})"
[ -f "${archive}" ] || wget -O"${archive}" "${URL}"
echo "Unpacking..."
tar -xa --strip-components=1 -C "${BINARIES_DIR}" -f "${archive}"
auxsize=$(stat -c %s "${aux}")
if [ "${auxsize}" -gt $((8 << 20)) ]; then
# In older releases, 16M aux.ext4 images were generated. In order
# to keep the image-itb-qcow logic simpler, trim it 8M, which we
# always generate nowadays.
echo "WARNING: Auxiliary partition is unexpectedly large. Resizing..."
resize2fs "${aux}" 8M
truncate -s 8M "${aux}"
tune2fs -l "${aux}"
fi
@@ -0,0 +1,9 @@
################################################################################
#
# image-itb-dl-release
#
################################################################################
IMAGE_ITB_DL_RELEASE_CONFIG_VARS := URL
$(eval $(ix-image))
@@ -0,0 +1,23 @@
menuconfig IMAGE_ITB_GNS3A
bool "GNS3 Appliance (ITB)"
depends on BR2_x86_64
select IMAGE_ITB_QCOW
help
Create a GNS3 appliance description that, together with the
disk image, can be imported into GNS3.
config IMAGE_ITB_GNS3A_RAM
int "Reserved RAM (MiB)"
depends on IMAGE_ITB_GNS3A
default "192"
help
Amount of host RAM reserved for an appliance instance.
Minimum supported size is 192M.
config IMAGE_ITB_GNS3A_IFNUM
int "Number of interfaces"
depends on IMAGE_ITB_GNS3A
default "1"
help
Number of Ethernet interfaces to create for an appliance instance.
+59
View File
@@ -0,0 +1,59 @@
#!/bin/sh
set -e
bios="${BINARIES_DIR}"/OVMF.fd
qcow="${BINARIES_DIR}"/"${ARTIFACT}".qcow2
gns3a="${BINARIES_DIR}"/"${ARTIFACT}".gns3a
cat <<EOF >"${gns3a}"
{
"name": "${ARTIFACT} devel",
"category": "router",
"description": "${ARTIFACT} development appliance",
"vendor_name": "Kernelkit",
"vendor_url": "https://kernelkit.org",
"product_name": "${ARTIFACT} devel",
"registry_version": 6,
"status": "experimental",
"maintainer": "Kernelkit",
"maintainer_email": "null@kernelkit.org",
"usage": "Default login, user/pass: admin/admin\n\nType 'cli' (and Enter) followed by 'help' for an overview of commands and relevant configuration files.",
"port_name_format": "eth{0}",
"linked_clone": true,
"qemu": {
"adapter_type": "virtio-net-pci",
"adapters": ${IFNUM},
"ram": ${RAM},
"cpus": 1,
"hda_disk_interface": "virtio",
"arch": "x86_64",
"console_type": "telnet",
"bios_image": "$(basename ${bios})",
"kvm": "allow"
},
"images": [
{
"filename": "$(basename "${bios}")",
"filesize": $(stat --printf='%s' "${bios}"),
"md5sum": "$(md5sum "${bios}" | awk '{print $1}')",
"version": "0.0"
},
{
"filename": "$(basename "${qcow}")",
"filesize": $(stat --printf='%s' "${qcow}"),
"md5sum": "$(md5sum "${qcow}" | awk '{print $1}')",
"version": "${VERSION}"
}
],
"versions": [
{
"name": "${VERSION}",
"images": {
"bios_image": "$(basename ${bios})",
"hda_disk_image": "$(basename ${qcow})"
}
}
]
}
EOF
@@ -0,0 +1,10 @@
################################################################################
#
# image-itb-gns3a
#
################################################################################
IMAGE_ITB_GNS3A_DEPENDENCIES := image-itb-qcow
IMAGE_ITB_GNS3A_CONFIG_VARS := IFNUM RAM
$(eval $(ix-image))
@@ -0,0 +1,68 @@
menuconfig IMAGE_ITB_QCOW
bool "QEMU disk image (ITB)"
depends on (IMAGE_ITB_ROOTFS && IMAGE_ITB_AUX) || IMAGE_ITB_DL_RELEASE
select BR2_PACKAGE_HOST_GENIMAGE
help
Compose a full disk image with redundant Linux OS partitions,
configuration partition, etc., for systems using ITB images.
This is useful when:
- Bringing up a blank system during manufacturing
- Creating a GNS3 appliance
- Developing/debugging issues in the boot process in QEMU
menuconfig IMAGE_ITB_QCOW_SIZE
string "Image size"
depends on IMAGE_ITB_QCOW
default "512M"
help
Create a disk image of this size. A K/M/G suffix may be used
to multiply by powers of 1024. Suffixes like KB/MB/GB may be
used to multiply by powers of 1000. The image will be split
proportionally to fit the two rootfs, a kernel, a writable
/cfg and /var partiotions.
Minimum supported size is 512M.
choice
prompt "Bootloader"
depends on IMAGE_ITB_QCOW
default IMAGE_ITB_QCOW_BOOT_EFI if BR2_x86_64
default IMAGE_ITB_QCOW_BOOT_NONE
config IMAGE_ITB_QCOW_BOOT_NONE
bool "None"
help
Do not create any bootloader partition in the disk image.
config IMAGE_ITB_QCOW_BOOT_EFI
bool "EFI"
help
Create a boot partition from a directory containing an EFI
boot application, e.g. GRUB.
config IMAGE_ITB_QCOW_BOOT_BIN
bool "Binary"
help
Create a boot partition from a raw image containing the boot
application, e.g. U-Boot.
endchoice
config IMAGE_ITB_QCOW_BOOT_DATA
string "Bootloader data"
depends on IMAGE_ITB_QCOW
depends on IMAGE_ITB_QCOW_BOOT_EFI || IMAGE_ITB_QCOW_BOOT_BIN
default "${BINARIES_DIR}/efi-part/EFI" if BR2_x86_64
help
Path to the directory or file holding the bootloader data.
config IMAGE_ITB_QCOW_BOOT_OFFSET
hex "Bootloader offset"
depends on IMAGE_ITB_QCOW
depends on IMAGE_ITB_QCOW_BOOT_EFI || IMAGE_ITB_QCOW_BOOT_BIN
default 0x8000
help
Offset at which the bootloader partition is placed. Remember
to make sure that the GPT still fits at the start of the
image.
@@ -1,8 +1,6 @@
#!/bin/sh
set -e
. $BR2_EXTERNAL_INFIX_PATH/board/common/rootfs/etc/partition-uuid
K=10
M=20
G=30
@@ -47,43 +45,32 @@ dimension()
exit 1
fi
# Size var to fit whatever is left over. Also reserve another 32K
# at the end to make room for the backup GPT.
varsize=$(($total - $auxsize - 2 * $imgsize - $cfgsize))
if [ "$bootoffs" ]; then
varsize=$(($varsize - $bootsize))
fi
varsize=$(($varsize - (32 << K)))
# Place aux right after the GPT...
auxoffs=$((32 << K))
if [ "$bootoffs" ]; then
# Align the end of the boot partition to an even MiB. E.g. if
# boot was dimensioned to 4M, and bootoffs is 32K, then the
# final bootsize becomes 4M - 32K, meaning aux will start on
# exactly 4M.
auxoffs=$bootsize
bootsize=$(($bootsize - $bootoffs))
else
# No bootloader, place aux after GPT, resize it to end on an
# even MiB (as is done for boot above).
auxoffs=$((32 << K))
auxsize=$(($auxsize - $auxoffs))
fi
}
if [ $((bootoffs)) -lt $((32 << K)) ]; then
echo "Boot partition collides with GPT"
exit 1
fi
probeboot()
{
# If we have built an EFI app, typically grub, make sure to
# include it.
if [ -d $BINARIES_DIR/efi-part/EFI ]; then
bootoffs=$((32 << K))
# ...unless we have a boot partition, in which case we place
# it after that.
auxoffs=$((auxoffs + bootsize))
fi
# Finally, size var to fit whatever is left over by subtracting
# all other images, plus another 32K at the end for the backup
# GPT.
varsize=$((total - auxoffs - auxsize - 2 * imgsize - cfgsize - (32 << K)))
}
genboot()
{
if [ -d "$bootdata" ]; then
bootimg=$(cat <<EOF
image $BINARIES_DIR/efi-part.vfat {
image efi-part.vfat {
temporary = true
size = $bootsize
vfat {
file EFI {
@@ -98,7 +85,7 @@ EOF
offset = $bootoffs
partition-type-uuid = U
bootable = true
image = $BINARIES_DIR/efi-part.vfat
image = efi-part.vfat
}
EOF
)
@@ -117,44 +104,29 @@ EOF
fi
}
common=$(dirname $(readlink -f "$0"))
root=$BUILD_DIR/genimage.root
tmp=$BUILD_DIR/genimage.tmp
mkdir -p "${WORKDIR}"/root
rm -rf "${WORKDIR}"/tmp
mkdir -p "${WORKDIR}"/tmp
total=$((512 << M))
bootoffs=$((32 << K))
bootdata=
diskimg=disk.img
qcowimg="${ARTIFACT}.qcow2"
total=$(size2int $SIZE)
bootoffs=
bootdata=$BOOT_DATA
bootimg=
bootpart=
tmpimage=$(mktemp)
while getopts "a:b:B:n:s:" opt; do
case ${opt} in
a)
arch=$OPTARG
;;
b)
bootdata=$OPTARG
;;
B)
bootoffs=$(($OPTARG))
;;
n)
diskimg=${OPTARG}
;;
s)
total=$(size2int $OPTARG)
;;
esac
done
shift $((OPTIND - 1))
mkdir -p $root
if [ -n "${BOOT_OFFSET}" ]; then
bootoffs=$(($BOOT_OFFSET))
fi
probeboot
dimension
genboot
. $BR2_EXTERNAL_INFIX_PATH/board/common/rootfs/etc/partition-uuid
[ -n "${AUX_UUID}" ]
[ -n "${PRIMARY_UUID}" ]
[ -n "${SECONDARY_UUID}" ]
# Use awk over sed because replacement text may contain newlines,
# which sed does not approve of.
awk \
@@ -166,7 +138,7 @@ awk \
-vimgsize=$imgsize \
-vcfgsize=$cfgsize \
-vvarsize=$varsize \
-vdiskimg=$tmpimage \
-vqcowimg=$qcowimg \
-vbootimg="$bootimg" -vbootpart="$bootpart" \
'{
sub(/@TOTALSIZE@/, total);
@@ -175,7 +147,7 @@ awk \
sub(/@IMGSIZE@/, imgsize);
sub(/@CFGSIZE@/, cfgsize);
sub(/@VARSIZE@/, varsize);
sub(/@DISKIMG@/, diskimg);
sub(/@QCOWIMG@/, qcowimg);
sub(/@BOOTIMG@/, bootimg);
sub(/@BOOTPART@/, bootpart);
sub(/@AUXUUID@/, auxuuid);
@@ -183,35 +155,11 @@ awk \
sub(/@SECONDARYUUID@/, secondaryuuid);
}1' \
< $common/genimage.cfg.in >$root/genimage.cfg
mkdir -p $root/aux
cp -f $BINARIES_DIR/rootfs.itbh $root/aux/primary.itbh
cp -f $BINARIES_DIR/rootfs.itbh $root/aux/secondary.itbh
cp -f $BINARIES_DIR/rauc.status $root/aux/rauc.status
case "$arch" in
aarch64)
mkenvimage -s 0x4000 -o "$root/aux/uboot.env" \
"$BR2_EXTERNAL_INFIX_PATH/board/common/uboot/aux-env.txt"
;;
x86_64)
mkdir -p "$root/aux/grub"
cp -f "$BR2_EXTERNAL_INFIX_PATH/board/$arch/grub.cfg" \
"$BR2_EXTERNAL_INFIX_PATH/board/$arch/grubenv" \
"$root/aux/grub/"
;;
*)
;;
esac
rm -rf "$tmp"
< $PKGDIR/genimage.cfg.in >$WORKDIR/genimage.cfg
genimage \
--rootpath "$root" \
--tmppath "$tmp" \
--inputpath "$BINARIES_DIR" \
--config "$root/genimage.cfg"
qemu-img convert -c -O qcow2 "$tmpimage" "$BINARIES_DIR/$diskimg"
rm "$tmpimage"
--tmppath "${WORKDIR}"/tmp \
--rootpath "${WORKDIR}"/root \
--inputpath "$BINARIES_DIR" \
--outputpath "$BINARIES_DIR" \
--config "${WORKDIR}"/genimage.cfg
@@ -1,16 +1,5 @@
@BOOTIMG@
image aux.ext4 {
mountpoint = "/aux"
temporary = true
size = @AUXSIZE@
ext4 {
label = "aux"
use-mke2fs = true
}
}
image cfg.ext4 {
empty = true
temporary = true
@@ -33,7 +22,8 @@ image var.ext4 {
}
}
image @DISKIMG@ {
image disk.img {
temporary = true
size = @TOTALSIZE@
hdimage {
partition-table-type = "gpt"
@@ -68,5 +58,15 @@ image @DISKIMG@ {
}
}
image @QCOWIMG@ {
qemu {
format = "qcow2"
}
partition disk {
image = "disk.img"
}
}
# Silence genimage warnings
config {}
@@ -0,0 +1,15 @@
################################################################################
#
# image-itb-qcow
#
################################################################################
# We can source the rootfs+aux from a local build, or from a
# downloaded release; so adjust our dependencies accordingly.
IMAGE_ITB_QCOW_SRC-$(IMAGE_ITB_ROOTFS) := image-itb-rootfs image-itb-aux
IMAGE_ITB_QCOW_SRC-$(IMAGE_ITB_DL_RELEASE) := image-itb-dl-release
IMAGE_ITB_QCOW_DEPENDENCIES := host-genimage $(IMAGE_ITB_QCOW_SRC-y)
IMAGE_ITB_QCOW_CONFIG_VARS := BOOT_DATA BOOT_OFFSET SIZE
$(eval $(ix-image))
@@ -0,0 +1,27 @@
menuconfig IMAGE_ITB_RAUC
bool "RAUC upgrade bundle (ITB)"
select IMAGE_ITB_ROOTFS
select BR2_PACKAGE_HOST_RAUC
help
Create RAUC upgrade bundle, for targets using ITB images,
that can be used to upgrade a running system to this version
of Infix.
config IMAGE_ITB_RAUC_KEY
string "signing key"
depends on IMAGE_ITB_RAUC
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/signing-keys/development/infix.key"
help
Path to the private key, in PKCS#8 format, used to sign
the RAUC bundle; or a PKCS#11 URI.
config IMAGE_ITB_RAUC_CERT
string "signing certificate"
depends on IMAGE_ITB_RAUC
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/signing-keys/development/infix.crt"
help
Path to the X509 certificate which will be associated with
the bundle signature.
NOTE: This cert MUST be included in the trust store of the
system on which this bundle is to be installed.
+35
View File
@@ -0,0 +1,35 @@
#!/bin/sh
set -e
squash="${BINARIES_DIR}"/rootfs.squashfs
itbh="${BINARIES_DIR}"/rootfs.itbh
pkg="${BINARIES_DIR}"/"${ARTIFACT}.pkg"
cp -f "${PKGDIR}"/hooks.sh "${WORKDIR}"/hooks.sh
# RAUC internally uses the file extension to find a suitable install
# handler, hence the name must be .img
cp -f "${squash}" "${WORKDIR}"/rootfs.img
cp -f "${itbh}" "${WORKDIR}"/rootfs.itbh
cat >"${WORKDIR}"/manifest.raucm <<EOF
[update]
compatible=${COMPATIBLE}
version=${VERSION}
[bundle]
format=verity
[hooks]
filename=hooks.sh
[image.rootfs]
filename=rootfs.img
hooks=post-install
EOF
rauc --cert="${CERT}" --key="${KEY}" \
bundle "${WORKDIR}" "${pkg}.next"
mv "${pkg}.next" "${pkg}"
@@ -0,0 +1,10 @@
################################################################################
#
# image-itb-rauc
#
################################################################################
IMAGE_ITB_RAUC_DEPENDENCIES := host-rauc image-itb-rootfs
IMAGE_ITB_RAUC_CONFIG_VARS := KEY CERT
$(eval $(ix-image))
@@ -0,0 +1,20 @@
menuconfig IMAGE_ITB_ROOTFS
bool "rootfs.itb+.itbh"
select BR2_TARGET_ROOTFS_SQUASHFS
select BR2_PACKAGE_HOST_UBOOT_TOOLS
help
Create a signed ITB image containing a SquashFS of rootfs
and extract detached header (.itbh) for U-Boot based
targets.
config IMAGE_ITB_ROOTFS_KEY
string "signing key"
depends on IMAGE_ITB_ROOTFS
default "${BR2_EXTERNAL_INFIX_PATH}/board/common/signing-keys/development/infix.key"
help
Path to the private RSA key, in PKCS#8 format, used to sign
the root filesystem.
If the path is prefixed with "<hint>:", then that used as
the "key-name-hint" in the resulting ITB, otherwise the
basename of the path, with any extension removed, is used.
+71
View File
@@ -0,0 +1,71 @@
#!/bin/sh
set -e
squash="${BINARIES_DIR}"/rootfs.squashfs
itb="${BINARIES_DIR}"/rootfs.itb
itbh_size=0x1000
IFS=:
set ${KEY}
case $# in
1)
keyfile="$1"
hint=$(basename ${keyfile%.*})
;;
2)
keyfile="$2"
hint="$1"
;;
*)
echo "INVALID KEY" >&2
exit 1
;;
esac
rsanibbles=$(openssl rsa -in "${KEY}" -noout -modulus | \
sed -e 's/^Modulus=//' | tr -d '\n' | wc -c)
if [ "${rsanibbles}" -le 0 ]; then
echo "ONLY RSA KEYS ARE SUPPORTED" >&2
exit 1
fi
cat >"${WORKDIR}"/rootfs.its <<EOF
/dts-v1/;
/ {
description = "${ARTIFACT}";
creator = "infix";
#address-cells = <0x1>;
images {
rootfs {
description = "rootfs";
type = "ramdisk";
os = "linux";
compression = "none";
data = /incbin/("${squash}");
signature-1 {
algo = "sha256,rsa$((rsanibbles << 2))";
key-name-hint = "${hint}";
};
};
};
configurations {
default = "verity";
verity {
ramdisk = "rootfs";
};
};
};
EOF
mkimage -E -p $itbh_size -B $itbh_size \
-f "${WORKDIR}"/rootfs.its \
-g "${hint}" -G "${keyfile}" \
"${itb}"
dd if="${itb}" bs=$((itbh_size)) count=1 of="${itb}h" status=none
@@ -0,0 +1,10 @@
################################################################################
#
# image-itb-rootfs
#
################################################################################
IMAGE_ITB_ROOTFS_DEPENDENCIES := rootfs-squashfs
IMAGE_ITB_ROOTFS_CONFIG_VARS := KEY
$(eval $(ix-image))
@@ -0,0 +1,6 @@
config IMAGE_README
bool "Install README.md in images"
help
Install a README.md with useful information about getting
started with Infix in the images directory (thereby also
including it in the resulting release tarball).
@@ -34,7 +34,7 @@ Depending on how your Linux installation is set up, the following may
require being run with superuser privileges, i.e., you may need to
repend the command with 'sudo'.
$ ./qemu.sh
$ ./qemu/run.sh
You should now see the Infix init system booting up. When the final
"Please press Enter to activate this console." is shown, press Enter
@@ -75,13 +75,13 @@ interface, which requires the following extra package:
We can now enter the configuration:
$ ./qemu.sh -c
$ ./qemu/run.sh -c
Go down to *Networking*, select *TAP*, now you can change the *Number of
TAPs*, e.g. to 10. Exit and save the configuration, then you can start
Qemu again:
./qemu.sh
$ ./qemu/run.sh
> Make sure to do a factory reset from the CLI, otherwise you will be
> stuck with that single interface from before.
@@ -0,0 +1,18 @@
################################################################################
#
# image-readme
#
################################################################################
IMAGE_README_DIR := $(pkgdir)
image-readme: $(BINARIES_DIR)/README.md
$(BINARIES_DIR)/README.md: $(IMAGE_README_DIR)/README.md
@$(call IXMSG,"Installing README.md")
@mkdir -p $(BINARIES_DIR)
@cp $< $@
ifeq ($(IMAGE_README),y)
TARGETS_ROOTFS += image-readme
endif
+2
View File
@@ -0,0 +1,2 @@
include $(BR2_EXTERNAL_INFIX_PATH)/board/common/image/ix-image.mk
include $(sort $(wildcard $(BR2_EXTERNAL_INFIX_PATH)/board/common/image/*/*.mk))
+26
View File
@@ -0,0 +1,26 @@
define inner-ix-image
$(2)_DIR := $$(pkgdir)
$(1): $$($(2)_DEPENDENCIES)
@$$(call IXMSG,"$$(if $$($(2)_MESSAGE),$$($(2)_MESSAGE),Creating $(1))")
@mkdir -p $$(BUILD_DIR)/$(1)
@ \
PATH=$$(BR_PATH) \
PKGDIR=$$($(2)_DIR) \
WORKDIR=$$(BUILD_DIR)/$(1) \
BINARIES_DIR=$$(BINARIES_DIR) \
BR2_EXTERNAL_INFIX_PATH=$$(BR2_EXTERNAL_INFIX_PATH) \
ARTIFACT=$$(INFIX_ARTIFACT) \
COMPATIBLE=$$(INFIX_COMPATIBLE) \
VERSION=$$(INFIX_VERSION) \
$$(foreach var,$$($(2)_CONFIG_VARS),$$(var)=$$($(2)_$$(var)) ) \
$$($(2)_DIR)/generate.sh $$($(2)_OPTS)
ifeq ($$($(2)),y)
TARGETS_ROOTFS += $(1)
endif
endef
ix-image = $(call inner-ix-image,$(pkgname),$(call UPPERCASE,$(pkgname)))
-40
View File
@@ -1,40 +0,0 @@
#!/bin/sh
rootdir=$BUILD_DIR/genimage.root
tempdir=$BUILD_DIR/genimage.tmp
cat <<EOF > /tmp/mkaux.cfg
image aux.ext4 {
mountpoint = "/aux"
size = 16M
ext4 {
label = "aux"
use-mke2fs = true
features = "^metadata_csum,^metadata_csum_seed,uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
# Silence genimage warnings
config {}
EOF
rm -rf "$rootdir/aux"
mkdir -p "$rootdir/aux"
cp -f "$BINARIES_DIR/rootfs.itbh" "$rootdir/aux/primary.itbh"
cp -f "$BINARIES_DIR/rootfs.itbh" "$rootdir/aux/secondary.itbh"
cp -f "$BINARIES_DIR/rauc.status" "$rootdir/aux/rauc.status"
mkenvimage -s 0x4000 -o "$rootdir/aux/uboot.env" \
"$BR2_EXTERNAL_INFIX_PATH/board/common/uboot/aux-env.txt"
rm -rf "$BINARIES_DIR/aux.ext4"
rm -rf "$tempdir"
genimage \
--rootpath "$rootdir" \
--tmppath "$tempdir" \
--inputpath "$BINARIES_DIR" \
--outputpath "$BINARIES_DIR" \
--config "/tmp/mkaux.cfg"
-118
View File
@@ -1,118 +0,0 @@
#!/bin/sh
die()
{
echo "$@" >&2
exit 1
}
load_cfg()
{
local tmp=$(mktemp -p /tmp)
grep ^FIT_ $BR2_CONFIG >$tmp
. $tmp
rm $tmp
}
load_cfg
[ "$FIT_IMAGE" = "y" ] || exit 0
work=$BUILD_DIR/fit-image-local
dtbs=$(find $BINARIES_DIR -name '*.dtb')
kernel=$(find $BINARIES_DIR -name '*Image' | head -n1)
squash=$BINARIES_DIR/rootfs.squashfs
mkdir -p $work
gzip <$kernel >$work/Image.gz
kernel=$work/Image.gz
rm -rf $work/rootfs
unsquashfs -f -d $work/rootfs $squash
rm -f $work/rootfs/boot/*Image
squash=$work/rootfs-no-kernel.squashfs
rm -f $squash
mksquashfs $work/rootfs $squash
# mkimage will only align images to 4 bytes, but U-Boot will leave
# both DTB and ramdisk in place when starting the kernel. So we pad
# all components up to a 4k boundary.
truncate -s %4k $kernel $dtbs
: >$work/dtbs.itsi
: >$work/cfgs.itsi
for dtb in $dtbs; do
name=$(basename $dtb .dtb)
cat <<EOF >>$work/dtbs.itsi
$name-dtb {
description = "$name";
type = "flat_dt";
arch = "$FIT_ARCH";
compression = "none";
data = /incbin/("$dtb");
};
EOF
cat <<EOF >>$work/cfgs.itsi
$name {
description = "$name";
kernel = "kernel";
ramdisk = "ramdisk";
fdt = "$name-dtb";
};
EOF
done
: >$work/kernel-load.itsi
if [ "$FIT_KERNEL_LOAD_ADDR" ]; then
cat <<EOF >$work/kernel-load.itsi
load = <$FIT_KERNEL_LOAD_ADDR>;
entry = <$FIT_KERNEL_LOAD_ADDR>;
EOF
fi
cat <<EOF >$work/infix.its
/dts-v1/;
/ {
timestamp = <$(date +%s)>;
description = "Infix ($FIT_ARCH)";
creator = "infix";
#address-cells = <0x1>;
images {
kernel {
description = "Linux";
type = "kernel";
arch = "$FIT_ARCH";
os = "linux";
$(cat $work/kernel-load.itsi)
compression = "gzip";
data = /incbin/("$kernel");
};
ramdisk {
description = "Infix";
type = "ramdisk";
os = "linux";
arch = "$FIT_ARCH";
compression = "none";
data = /incbin/("$squash");
};
$(cat $work/dtbs.itsi)
};
configurations {
$(cat $work/cfgs.itsi)
};
};
EOF
mkimage \
-E -p 0x1000 \
-f $work/infix.its $BINARIES_DIR/infix.itb \
|| die "Unable to create FIT image"
-103
View File
@@ -1,103 +0,0 @@
#!/bin/sh
# shellcheck disable=SC1091
. "$TARGET_DIR/etc/os-release"
if [ -n "$INFIX_RELEASE" ]; then
rel="-${INFIX_RELEASE}"
fi
ARCH=$1
NM="${2:-custom}${rel}"
DISK=$3
RAM=${4:-512}
IFNUM=${5:-1}
# The aarch64 build currently has no "loader" but instead starts Linux
# directly, so we need to add a basic cmdline.
loader_args()
{
if [ "$ARCH" = "aarch64" ]; then
cat <<EOF
"kernel_command_line": "console=ttyAMA0 root=PARTLABEL=primary quiet",
EOF
fi
}
loader_img()
{
if [ "$ARCH" = "x86_64" ]; then
cat <<EOF
"bios_image": "$loader",
EOF
else
cat <<EOF
"kernel_image": "$loader",
EOF
fi
}
if [ "$ARCH" = "x86_64" ]; then
loader=OVMF.fd
accel=allow
opts=
else
loader=Image
accel=disable
opts="-M virt -cpu cortex-a72"
fi
echo ">> Disk image MD5: $(md5sum "$BINARIES_DIR/$DISK" | awk '{print $1}')"
cat <<EOF >"$BINARIES_DIR/${NM}.gns3a"
{
"name": "$NM",
"category": "router",
"description": "$INFIX_DESC",
"vendor_name": "$VENDOR_NAME",
"vendor_url": "$VENDOR_HOME",
"product_name": "$NAME",
"registry_version": 6,
"status": "stable",
"maintainer": "$VENDOR_NAME",
"maintainer_email": "${SUPPORT_URL#mailto:}",
"usage": "Default login, user/pass: admin/admin\n\nType 'cli' (and Enter) followed by 'help' for an overview of commands and relevant configuration files.",
"port_name_format": "eth{0}",
"linked_clone": true,
"qemu": {
"adapter_type": "virtio-net-pci",
"adapters": ${IFNUM},
"ram": ${RAM},
"cpus": 1,
"hda_disk_interface": "virtio",
"arch": "$ARCH",
"console_type": "telnet",
$(loader_img)
$(loader_args)
"kvm": "$accel",
"options": "$opts"
},
"images": [
{
"filename": "$loader",
"filesize": $(stat --printf='%s' "$BINARIES_DIR/$loader"),
"md5sum": "$(md5sum "$BINARIES_DIR/$loader" | awk '{print $1}')",
"version": "0.0"
},
{
"filename": "$DISK",
"filesize": $(stat --printf='%s' "$BINARIES_DIR/$DISK"),
"md5sum": "$(md5sum "$BINARIES_DIR/$DISK" | awk '{print $1}')",
"version": "0.0"
}
],
"versions": [
{
"name": "0.0",
"images": {
$(loader_img)
"hda_disk_image": "$DISK"
}
}
]
}
EOF
-22
View File
@@ -1,22 +0,0 @@
#!/bin/sh
set -e
common=$(dirname $(readlink -f "$0"))
root=$BUILD_DIR/genimage.root
tmp=$BUILD_DIR/genimage.tmp
mkdir -p $root/aux
cp -f $BINARIES_DIR/uboot-env.bin $root/aux/uboot.env
cp -f $BINARIES_DIR/rootfs.itbh $root/aux/primary.itbh
cp -f $BINARIES_DIR/rootfs.itbh $root/aux/secondary.itbh
rm -rf $tmp
genimage \
--rootpath $root \
--tmppath $tmp \
--inputpath $BINARIES_DIR \
--outputpath $BINARIES_DIR \
--config $common/genimage.cfg
-35
View File
@@ -1,35 +0,0 @@
#!/bin/sh
set -e
# Bootstrap a RAUC status file showing the newly created image
# installed to both the primary and secondary slots. This then bundled
# in the aux partition in mkdisk.sh, so that RAUC (on the target) can
# always report the installed versions.
rauc info --no-verify --output-format=shell $1 >/tmp/rauc-$$.info
. /tmp/rauc-$$.info
rm /tmp/rauc-$$.info
tstamp=$(date -u +%FT%TZ)
cat <<EOF
[slot.rootfs.0]
bundle.compatible=$RAUC_MF_COMPATIBLE
bundle.version=$RAUC_MF_VERSION
status=ok
sha256=$RAUC_IMAGE_DIGEST_0
size=$RAUC_IMAGE_SIZE_0
installed.timestamp=$tstamp
installed.count=1
activated.timestamp=$tstamp
activated.count=1
[slot.rootfs.1]
bundle.compatible=$RAUC_MF_COMPATIBLE
bundle.version=$RAUC_MF_VERSION
status=ok
sha256=$RAUC_IMAGE_DIGEST_0
size=$RAUC_IMAGE_SIZE_0
installed.timestamp=$tstamp
installed.count=1
activated.timestamp=$tstamp
activated.count=1
EOF
-43
View File
@@ -1,43 +0,0 @@
#!/bin/sh
set -e
name=$1
compat=$2
sign=$3
crt=$(ls $sign/*.crt)
key=$(ls $sign/*.key)
common=$(dirname "$(readlink -f "$0")")
work=$BUILD_DIR/mkrauc
mkdir -p "$work"
cp -f "$common/rauc-hooks.sh" "$work/hooks.sh"
# RAUC internally uses the file extension to find a suitable install
# handler, hence the name must be .img
cp -f "$BINARIES_DIR/rootfs.squashfs" "$work/rootfs.img"
cp -f "$BINARIES_DIR/rootfs.itbh" "$work/rootfs.itbh"
cat >"$work/manifest.raucm" <<EOF
[update]
compatible=${compat}
version=${INFIX_VERSION}
[bundle]
format=verity
[hooks]
filename=hooks.sh
[image.rootfs]
filename=rootfs.img
hooks=post-install
EOF
rm -f "$BINARIES_DIR/$name.pkg"
rauc --cert="$crt" --key="$key" \
bundle "$work" "$BINARIES_DIR/$name.pkg"
-112
View File
@@ -1,112 +0,0 @@
#!/bin/sh
# shellcheck disable=SC2086
common=$(dirname "$(readlink -f "$0")")
. "$common/lib.sh"
# shellcheck disable=SC1091
. "$TARGET_DIR/etc/os-release"
# The INFIX_* variables may be composed from BR2_* variables,
# so we source them last.
load_cfg BR2_ARCH
load_cfg BR2_DEFCONFIG
load_cfg BR2_EXTERNAL_INFIX_PATH
load_cfg BR2_TARGET_ROOTFS
load_cfg INFIX_ID
load_cfg INFIX_COMPATIBLE
# The default IMAGE_ID is infix-$BR2_ARCH but can be overridden
# for imaage names, and compat strings, like infix-r2s
if [ -n "$IMAGE_ID" ]; then
NAME="$IMAGE_ID"
else
NAME="$INFIX_ID"-$(echo "$BR2_ARCH" | tr _ - | sed 's/x86-64/x86_64/')
fi
diskimg=disk.qcow2
ver()
{
if [ -n "$INFIX_RELEASE" ]; then
printf -- "-%s" "${INFIX_RELEASE#v}"
return
fi
}
load_cfg SIGN_ENABLED
if [ "$SIGN_ENABLED" = "y" ]; then
load_cfg BR2_ARCH
load_cfg SIGN_KEY
ixmsg "Signing SquashFS Image"
$common/sign.sh $BR2_ARCH $SIGN_KEY
ixmsg "Creating RAUC Update Bundle"
$common/mkrauc.sh "$NAME$(ver)" $INFIX_COMPATIBLE $SIGN_KEY
fi
load_cfg DISK_IMAGE
if [ "$DISK_IMAGE" = "y" ]; then
ixmsg "Creating Disk Image"
diskimg="${NAME}-disk$(ver).qcow2"
bootcfg=
if [ "$DISK_IMAGE_BOOT_DATA" ]; then
bootcfg="-b $DISK_IMAGE_BOOT_DATA -B $DISK_IMAGE_BOOT_OFFSET"
fi
if [ "$BR2_TARGET_ROOTFS_SQUASHFS" != "y" ] && \
[ ! -f "$BINARIES_DIR/rootfs.squashfs" ]; then
ixmsg " Injecting $DISK_IMAGE_RELEASE_URL"
archive="$BINARIES_DIR/$(basename $DISK_IMAGE_RELEASE_URL)"
[ -f "$archive" ] || wget -O"$archive" "$DISK_IMAGE_RELEASE_URL"
tar -xa --strip-components=1 -C "$BINARIES_DIR" -f "$archive"
fi
$common/mkrauc-status.sh "$BINARIES_DIR/${NAME}.pkg" >"$BINARIES_DIR/rauc.status"
$common/mkdisk.sh -a $BR2_ARCH -n $diskimg -s $DISK_IMAGE_SIZE $bootcfg
fi
load_cfg SDCARD_AUX
if [ "$SDCARD_AUX" = "y" ]; then
ixmsg "Creating initial rauc.status"
$common/mkrauc-status.sh "$BINARIES_DIR/${NAME}.pkg" >"$BINARIES_DIR/rauc.status"
ixmsg "Creating aux.ext4 for sdcard.img"
$common/mkaux.sh
fi
load_cfg GNS3_APPLIANCE
if [ "$GNS3_APPLIANCE" = "y" ]; then
ixmsg "Creating GNS3 Appliance, $GNS3_APPLIANCE_RAM MiB with $GNS3_APPLIANCE_IFNUM ports"
$common/mkgns3a.sh $BR2_ARCH $NAME $diskimg $GNS3_APPLIANCE_RAM $GNS3_APPLIANCE_IFNUM
fi
load_cfg FIT_IMAGE
if [ "$FIT_IMAGE" = "y" ]; then
ixmsg "Creating Traditional FIT Image"
$common/mkfit.sh
fi
# Only for regular builds, not bootloader-only builds
if [ "$BR2_TARGET_ROOTFS_SQUASHFS" = "y" ]; then
rel=$(ver)
ln -sf rootfs.squashfs "$BINARIES_DIR/${NAME}${rel}.img"
if [ -n "$rel" ]; then
ln -sf "${NAME}${rel}.img" "$BINARIES_DIR/${NAME}.img"
fi
cp "$BR2_EXTERNAL_INFIX_PATH/board/common/rootfs/usr/bin/onieprom" "$BINARIES_DIR/"
# Menuconfig support for modifying Qemu args in release tarballs
cp "$BR2_EXTERNAL_INFIX_PATH/board/common/qemu/qemu.sh" "$BINARIES_DIR/"
sed -e "s/@ARCH@/QEMU_$BR2_ARCH/" \
-e "s/@DISK_IMG@/$diskimg/" \
< "$BR2_EXTERNAL_INFIX_PATH/board/common/qemu/Config.in.in" \
> "$BINARIES_DIR/Config.in"
rm -f "$BINARIES_DIR/qemu.cfg"
CONFIG_="CONFIG_" BR2_CONFIG="$BINARIES_DIR/qemu.cfg" \
"$O/build/buildroot-config/conf" --olddefconfig "$BINARIES_DIR/Config.in"
rm -f "$BINARIES_DIR/qemu.cfg.old" "$BINARIES_DIR/.config.old"
# Quick intro for beginners, with links to more information
cp "$BR2_EXTERNAL_INFIX_PATH/board/common/README.txt" "$BINARIES_DIR/"
fi
+7 -7
View File
@@ -78,7 +78,7 @@ endchoice
config QEMU_MACHINE
string "Select emulated machine"
default "qemu-system-arm -M virt,accel=kvm:tcg -cpu max" if QEMU_arm
default "qemu-system-aarch64 -M virt,accel=kvm:tcg -cpu max,pauth-impdef=on" if QEMU_aarch64
default "qemu-system-aarch64 -M virt,accel=kvm:tcg -cpu cortex-a53" if QEMU_aarch64
default "qemu-system-x86_64 -M pc,accel=kvm:tcg -cpu max" if QEMU_x86_64
help
You should not have to change this setting, although you may
@@ -99,20 +99,20 @@ config QEMU_MACHINE_RAM
config QEMU_KERNEL
string
depends on QEMU_LOADER_KERNEL
default "zImage" if QEMU_arm
default "Image" if QEMU_aarch64
default "bzImage" if QEMU_x86_64
default "../zImage" if QEMU_arm
default "../Image" if QEMU_aarch64
default "../bzImage" if QEMU_x86_64
config QEMU_BIOS
string
depends on !QEMU_LOADER_KERNEL
default "u-boot.bin" if QEMU_LOADER_UBOOT
default "OVMF.fd" if QEMU_LOADER_OVMF
default "../u-boot.bin" if QEMU_LOADER_UBOOT
default "../OVMF.fd" if QEMU_LOADER_OVMF
config QEMU_ROOTFS
string
default "@DISK_IMG@" if !QEMU_ROOTFS_INITRD
default "rootfs.squashfs" if QEMU_ROOTFS_INITRD
default "../rootfs.squashfs" if QEMU_ROOTFS_INITRD
config QEMU_DTB_EXTEND
bool
+45
View File
@@ -0,0 +1,45 @@
################################################################################
#
# qemu-scripts
#
################################################################################
QEMU_SCRIPTS_DIR := $(pkgdir)
qemu-kconfig = \
CONFIG_="CONFIG_" \
BR2_CONFIG="$(BINARIES_DIR)/qemu/.config" \
$(BUILD_DIR)/buildroot-config/$(1) $(2) "$(BINARIES_DIR)/qemu/Config.in"
ifeq ($(QEMU_SCRIPTS),y)
.PHONY: run
run:
@$(BINARIES_DIR)/qemu/run.sh
.PHONY: run-menuconfig
run-menuconfig: $(BUILD_DIR)/buildroot-config/mconf
@$(call qemu-kconfig,mconf)
qemu-scripts: \
$(BINARIES_DIR)/qemu/run.sh \
$(BINARIES_DIR)/qemu/Config.in \
$(BINARIES_DIR)/qemu/.config
$(BINARIES_DIR)/qemu/run.sh: $(QEMU_SCRIPTS_DIR)/run.sh
@$(call IXMSG,"Installing QEMU scripts")
@mkdir -p $(dir $@)
@cp $< $@
$(BINARIES_DIR)/qemu/Config.in: $(QEMU_SCRIPTS_DIR)/Config.in.in
@mkdir -p $(dir $@)
@sed \
-e "s:@ARCH@:QEMU_$(BR2_ARCH):" \
-e "s:@DISK_IMG@:../$(INFIX_ARTIFACT).qcow2:" \
< $< >$@
$(BINARIES_DIR)/qemu/.config: $(BINARIES_DIR)/qemu/Config.in
@$(call qemu-kconfig,conf,--olddefconfig)
@rm -f $@.old
TARGETS_ROOTFS += qemu-scripts
endif
@@ -10,17 +10,17 @@
#
# and then call this script with:
#
# ./qemu.sh -c
# ./run.sh -c
#
# To bring up a menuconfig dialog. Select `Exit` and save the changes.
# For more help, see:_
#
# ./qemu.sh -h
# ./run.sh -h
#
# shellcheck disable=SC3037
# Local variables
imgdir=$(readlink -f "$(dirname "$0")")
qdir=$(dirname "$(readlink -f "$0")")
imgdir=$(readlink -f "${qdir}/..")
prognm=$(basename "$0")
usage()
@@ -40,7 +40,7 @@ usage()
echo " Also, qemu.cfg has QEMU_APPEND which can affect this."
echo
echo "Example:"
echo " qemu.sh -- finit.debug"
echo " $prognm -- finit.debug"
echo "___________________________________________________________________"
echo "Note: 'kconfig-frontends' package (Debian/Ubuntu) must be installed"
echo " for -c to work: sudo apt install kconfig-frontents"
@@ -56,12 +56,8 @@ die()
load_qemucfg()
{
tmp=$(mktemp -p /tmp)
grep ^CONFIG_QEMU_ "$1" >"$tmp"
# shellcheck disable=SC1090
. "$tmp"
rm "$tmp"
. "./.config"
[ "$CONFIG_QEMU_MACHINE" ] || die "Missing QEMU_MACHINE"
[ "$CONFIG_QEMU_ROOTFS" ] || die "Missing QEMU_ROOTFS"
@@ -247,7 +243,7 @@ rocker_port_args()
net_args()
{
# Infix will pick up this file via fwcfg and install it to /etc
mactab=${imgdir}/mactab
mactab=${qdir}/mactab
:> "$mactab"
echo -n "-fw_cfg name=opt/mactab,file=$mactab "
@@ -286,7 +282,7 @@ vpd_args()
{
[ "$CONFIG_QEMU_VPD" = "y" ] || return
vpd_file="${imgdir}/vpd"
vpd_file="${qdir}/vpd"
if ! [ -f "$vpd_file" ]; then
onieprom="${imgdir}/onieprom"
@@ -430,7 +426,7 @@ dtb_args()
# Extend it with the environment and signing information in
# u-boot.dtb.
echo "qemu.dtb u-boot.dtb" | \
echo "qemu.dtb ../u-boot.dtb" | \
xargs -n 1 dtc -I dtb -O dts | \
{ echo "/dts-v1/;"; sed -e 's:/dts-v[0-9]\+/;::'; } | \
dtc >qemu-extended.dtb 2>/dev/null
@@ -439,7 +435,7 @@ dtb_args()
echo -n "-dtb qemu-extended.dtb "
else
# Otherwise we just use the unmodified one
echo -n "-dtb u-boot.dtb "
echo -n "-dtb ../u-boot.dtb "
fi
}
@@ -485,13 +481,12 @@ EOF
menuconfig()
{
grep -q QEMU_MACHINE Config.in || die "$prognm: must be run from the output/images directory"
grep -q QEMU_MACHINE Config.in || die "$prognm: must be run from the $$O/images/qemu directory"
command -v kconfig-mconf >/dev/null || die "$prognm: cannot find kconfig-mconf for menuconfig"
exec kconfig-mconf Config.in
}
scriptdir=$(dirname "$(readlink -f "$0")")
cd "$scriptdir" || (echo "Failed cd to $scriptdir"; exit 1)
cd "$qdir" || (echo "Failed cd to $qdir"; exit 1)
while [ "$1" != "" ]; do
case $1 in
@@ -510,13 +505,7 @@ while [ "$1" != "" ]; do
shift
done
if [ -f .config ]; then
# Customized settings from 'qemu.sh -c'
load_qemucfg .config
else
# Shipped defaults from release tarball
load_qemucfg qemu.cfg
fi
load_qemucfg
if [ -z "$QEMU_EXTRA_APPEND" ]; then
QEMU_EXTRA_APPEND="$*"
-28
View File
@@ -1,28 +0,0 @@
/dts-v1/;
/ {
description = "Infix";
creator = "infix";
#address-cells = <0x1>;
images {
rootfs {
description = "Infix";
type = "ramdisk";
os = "linux";
compression = "none";
data = /incbin/("rootfs.squashfs");
signature-1 {
algo = "sha256,rsa4096";
key-name-hint = "infix";
};
};
};
configurations {
default = "verity";
verity {
ramdisk = "rootfs";
};
};
};
+1 -1
View File
@@ -1,5 +1,5 @@
# /telemetry/optics is for streaming (not used atm)
location ~ ^/(restconf|yang|.well-known)/ {
location ~ ^/(restconf|yang|.well-known|streams)/ {
grpc_pass grpc://[::1]:10080;
grpc_set_header Host $host;
grpc_set_header X-Real-IP $remote_addr;
+33 -24
View File
@@ -90,9 +90,9 @@ reset-reason {
# Monitors file descriptor leaks based on /proc/sys/fs/file-nr
filenr {
# enabled = true
interval = 300
logmark = false
enabled = true
interval = 3600
logmark = true
warning = 0.9
critical = 1.0
# script = "/path/to/alt-reboot-action.sh"
@@ -102,33 +102,42 @@ filenr {
# The script is called with fsmon as the first argument and there
# are two environment variables FSMON_NAME, for the monitored path,
# and FSMON_TYPE indicating either 'blocks' or 'inodes'.
#fsmon /var {
# enabled = true
# interval = 300
# logmark = false
# warning = 0.95
# critical = 1.0
# script = "/path/to/alt-reboot-action.sh"
#}
# Monitors load average based on sysinfo() from /proc/loadavg
# The level is composed from the average of the 1 and 5 min marks.
loadavg {
# enabled = true
interval = 300
logmark = false
warning = 1.0
critical = 2.0
fsmon /var {
enabled = true
interval = 3600
logmark = true
warning = 0.95
critical = 1.0
# script = "/path/to/alt-reboot-action.sh"
}
fsmon /tmp {
enabled = true
interval = 3600
logmark = true
warning = 0.95
critical = 1.0
# script = "/path/to/alt-reboot-action.sh"
}
# Monitors load average based on sysinfo() from /proc/loadavg
# The level is composed from the average of the 1 and 5 min marks.
#loadavg {
# enabled = true
# interval = 300
# logmark = true
# warning = 1.0
# critical = 2.0
# script = "/path/to/alt-reboot-action.sh"
#}
# Monitors free RAM based on data from /proc/meminfo
meminfo {
# enabled = true
interval = 300
logmark = false
enabled = true
interval = 3600
logmark = true
warning = 0.9
critical = 0.95
critical = 0.97
# script = "/path/to/alt-reboot-action.sh"
}
@@ -1,13 +1,13 @@
#!/usr/bin/env python3
import importlib.machinery
import json
import onieprom
import os
import shutil
import struct
import subprocess
import sys
onieprom = importlib.machinery.SourceFileLoader("onieprom", "/bin/onieprom").load_module()
SYSTEM_JSON = "/run/system.json"
KKIT_IANA_PEM = 61046
-13
View File
@@ -1,13 +0,0 @@
#!/bin/sh
set -e
common=$(dirname $(readlink -f "$0"))
cd $BINARIES_DIR
cp $common/rootfs.its .
mkimage -E -p 0x1000 -B 0x1000 -k $2 -f rootfs.its rootfs.itb
cp rootfs.itb rootfs.itbh
truncate -s $((0x1000)) rootfs.itbh
+1
View File
@@ -0,0 +1 @@
include $(sort $(wildcard $(BR2_EXTERNAL_INFIX_PATH)/board/riscv64/*/*.mk))
+9 -1
View File
@@ -472,8 +472,16 @@ CONFIG_DEBUG_FS=y
# CONFIG_SLUB_DEBUG is not set
CONFIG_DEBUG_RODATA_TEST=y
CONFIG_DEBUG_WX=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=20
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
CONFIG_WQ_WATCHDOG=y
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
CONFIG_TEST_LOCKUP=m
# CONFIG_SCHED_DEBUG is not set
CONFIG_STACKTRACE=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60
+7 -1
View File
@@ -263,7 +263,13 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=20
CONFIG_DETECT_HUNG_TASK=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
CONFIG_WQ_WATCHDOG=y
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
CONFIG_TEST_LOCKUP=m
CONFIG_FUNCTION_TRACER=y
CONFIG_UNWINDER_FRAME_POINTER=y
+11 -6
View File
@@ -95,20 +95,23 @@ BR2_PACKAGE_RAUC_JSON=y
BR2_PACKAGE_SYSKLOGD=y
BR2_PACKAGE_SYSKLOGD_LOGGER=y
BR2_PACKAGE_WATCHDOGD=y
BR2_PACKAGE_WATCHDOGD_GENERIC=y
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
BR2_PACKAGE_WATCHDOGD_FILENR=y
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
BR2_PACKAGE_WATCHDOGD_FSMON=y
BR2_PACKAGE_WATCHDOGD_TEMPMON
BR2_PACKAGE_LESS=y
BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_DOSFSTOOLS=y
BR2_PACKAGE_HOST_E2FSPROGS=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
BR2_PACKAGE_HOST_GENEXT2FS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_KMOD_XZ=y
BR2_PACKAGE_HOST_MTOOLS=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_RASPBERRYPI_RPI2=y
INFIX_VENDOR_HOME="https://kernelkit.org"
INFIX_DESC="Infix is an immutable, friendly, and secure operating system that turns any ARM or x86 device into a powerful, manageable network appliance. Deploy on anything from $35 Raspberry Pi boards to enterprise switches as routers, IoT gateways, or edge devices. Infix models Linux networking features using YANG so you can manage your devices using NETCONF/RESTCONF APIs and focus on your business logic running in isolated containers."
@@ -135,11 +138,13 @@ BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
BR2_PACKAGE_LOWDOWN=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_MDNS_ALIAS=y
BR2_PACKAGE_ONIEPROM=y
BR2_PACKAGE_SHOW=y
BR2_PACKAGE_ROUSETTE=y
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
IMAGE_ITB_AUX=y
IMAGE_ITB_QCOW=y
IMAGE_ITB_RAUC=y
IMAGE_README=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
DISK_IMAGE_BOOT_BIN=y
GNS3_APPLIANCE_RAM=512
GNS3_APPLIANCE_IFNUM=10
+11 -6
View File
@@ -95,20 +95,23 @@ BR2_PACKAGE_RAUC_JSON=y
BR2_PACKAGE_SYSKLOGD=y
BR2_PACKAGE_SYSKLOGD_LOGGER=y
BR2_PACKAGE_WATCHDOGD=y
BR2_PACKAGE_WATCHDOGD_GENERIC=y
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
BR2_PACKAGE_WATCHDOGD_FILENR=y
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
BR2_PACKAGE_WATCHDOGD_FSMON=y
BR2_PACKAGE_WATCHDOGD_TEMPMON
BR2_PACKAGE_LESS=y
BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_DOSFSTOOLS=y
BR2_PACKAGE_HOST_E2FSPROGS=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
BR2_PACKAGE_HOST_GENEXT2FS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_KMOD_XZ=y
BR2_PACKAGE_HOST_MTOOLS=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_RASPBERRYPI_RPI2=y
INFIX_VENDOR_HOME="https://kernelkit.org"
INFIX_DESC="Infix is an immutable, friendly, and secure operating system that turns any ARM or x86 device into a powerful, manageable network appliance. Deploy on anything from $35 Raspberry Pi boards to enterprise switches as routers, IoT gateways, or edge devices. Infix models Linux networking features using YANG so you can manage your devices using NETCONF/RESTCONF APIs and focus on your business logic running in isolated containers."
@@ -135,11 +138,13 @@ BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
BR2_PACKAGE_LOWDOWN=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_MDNS_ALIAS=y
BR2_PACKAGE_ONIEPROM=y
BR2_PACKAGE_SHOW=y
BR2_PACKAGE_ROUSETTE=y
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
IMAGE_ITB_AUX=y
IMAGE_ITB_QCOW=y
IMAGE_ITB_RAUC=y
IMAGE_README=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
DISK_IMAGE_BOOT_BIN=y
GNS3_APPLIANCE_RAM=512
GNS3_APPLIANCE_IFNUM=10
+12 -9
View File
@@ -25,10 +25,9 @@ BR2_GENERATE_LOCALE="en_US en_CA C.UTF-8"
BR2_TARGET_TZ_INFO=y
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs"
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.60"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.62"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -120,19 +119,21 @@ BR2_PACKAGE_RAUC_JSON=y
BR2_PACKAGE_SYSKLOGD=y
BR2_PACKAGE_SYSKLOGD_LOGGER=y
BR2_PACKAGE_WATCHDOGD=y
BR2_PACKAGE_WATCHDOGD_GENERIC=y
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
BR2_PACKAGE_WATCHDOGD_FILENR=y
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
BR2_PACKAGE_WATCHDOGD_FSMON=y
BR2_PACKAGE_WATCHDOGD_TEMPMON
BR2_PACKAGE_LESS=y
BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_E2FSPROGS=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
BR2_PACKAGE_HOST_GENEXT2FS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_GO_BIN=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
INFIX_VENDOR_HOME="https://kernelkit.org"
@@ -171,6 +172,7 @@ BR2_PACKAGE_LOWDOWN=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_MDNS_ALIAS=y
BR2_PACKAGE_NETBROWSE=y
BR2_PACKAGE_ONIEPROM=y
BR2_PACKAGE_PODMAN=y
BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
@@ -180,8 +182,9 @@ BR2_PACKAGE_TETRIS=y
BR2_PACKAGE_ROUSETTE=y
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
BR2_PACKAGE_HOST_PYTHON_YANGDOC=y
IMAGE_ITB_AUX=y
IMAGE_ITB_QCOW=y
IMAGE_ITB_RAUC=y
IMAGE_README=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
DISK_IMAGE_BOOT_BIN=y
GNS3_APPLIANCE_RAM=512
GNS3_APPLIANCE_IFNUM=10
+12 -9
View File
@@ -24,10 +24,9 @@ BR2_GENERATE_LOCALE="en_US en_CA C.UTF-8"
BR2_TARGET_TZ_INFO=y
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/rootfs"
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.60"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.62"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -98,18 +97,20 @@ BR2_PACKAGE_RAUC_JSON=y
BR2_PACKAGE_SYSKLOGD=y
BR2_PACKAGE_SYSKLOGD_LOGGER=y
BR2_PACKAGE_WATCHDOGD=y
BR2_PACKAGE_WATCHDOGD_GENERIC=y
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
BR2_PACKAGE_WATCHDOGD_FILENR=y
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
BR2_PACKAGE_WATCHDOGD_FSMON=y
BR2_PACKAGE_WATCHDOGD_TEMPMON
BR2_PACKAGE_LESS=y
BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_E2FSPROGS=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
BR2_PACKAGE_HOST_GENEXT2FS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
INFIX_VENDOR_HOME="https://kernelkit.org"
@@ -144,13 +145,15 @@ BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
BR2_PACKAGE_LOWDOWN=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_MDNS_ALIAS=y
BR2_PACKAGE_ONIEPROM=y
BR2_PACKAGE_LIBINPUT=y
BR2_PACKAGE_ROUSETTE=y
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
BR2_DOWNLOAD_FORCE_CHECK_HASHES=y
BR2_PACKAGE_GETENT=y
DISK_IMAGE_BOOT_BIN=y
IMAGE_ITB_AUX=y
IMAGE_ITB_QCOW=y
IMAGE_ITB_RAUC=y
IMAGE_README=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
GNS3_APPLIANCE_RAM=512
GNS3_APPLIANCE_IFNUM=10
+2 -4
View File
@@ -11,7 +11,6 @@ BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_INFIX_PATH)/patches"
BR2_SSP_NONE=y
BR2_INIT_NONE=y
BR2_SYSTEM_BIN_SH_NONE=y
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
# BR2_PACKAGE_BUSYBOX is not set
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
# BR2_TARGET_ROOTFS_TAR is not set
@@ -22,9 +21,8 @@ BR2_TARGET_UBOOT_CUSTOM_VERSION_VALUE="2023.07.02"
BR2_TARGET_UBOOT_BOARD_DEFCONFIG="qemu_arm64"
BR2_TARGET_UBOOT_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_INFIX_PATH)/board/common/uboot/extras.config $(BR2_EXTERNAL_INFIX_PATH)/board/aarch64/qemu-uboot/extras.config"
BR2_TARGET_UBOOT_FORMAT_DTB=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
# GNS3_APPLIANCE is not set
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
-3
View File
@@ -39,6 +39,3 @@ BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
DISK_IMAGE_BOOT_BIN=y
DISK_IMAGE_BOOT_DATA="${BINARIES_DIR}/flash-image.bin"
DISK_IMAGE_BOOT_OFFSET=0x00200000
-3
View File
@@ -39,6 +39,3 @@ BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
DISK_IMAGE_BOOT_BIN=y
DISK_IMAGE_BOOT_DATA="${BINARIES_DIR}/flash-image.bin"
DISK_IMAGE_BOOT_OFFSET=0x00200000
+2 -2
View File
@@ -11,7 +11,6 @@ BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_INFIX_PATH)/patches"
BR2_SSP_NONE=y
BR2_INIT_NONE=y
BR2_SYSTEM_BIN_SH_NONE=y
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
# BR2_PACKAGE_BUSYBOX is not set
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
# BR2_TARGET_ROOTFS_TAR is not set
@@ -38,4 +37,5 @@ BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
# GNS3_APPLIANCE is not set
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
+1 -1
View File
@@ -22,4 +22,4 @@ BR2_TARGET_UBOOT_CUSTOM_REPO_VERSION="c3d9cdcc7d9e3eb490d4036f5eece3fb91a2485c"
BR2_TARGET_UBOOT_BOARD_DEFCONFIG="mscc_fireant_pcb135_emmc"
BR2_TARGET_UBOOT_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_INFIX_PATH)/board/common/uboot/extras.config"
BR2_TARGET_UBOOT_NEEDS_DTC=y
# GNS3_APPLIANCE is not set
+12 -7
View File
@@ -23,7 +23,7 @@ BR2_GENERATE_LOCALE="en_US en_CA C.UTF-8"
BR2_TARGET_TZ_INFO=y
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/riscv64/rootfs"
BR2_ROOTFS_POST_BUILD_SCRIPT="$(BR2_EXTERNAL_INFIX_PATH)/board/common/post-build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="$(BR2_EXTERNAL_INFIX_PATH)/board/common/post-image.sh support/scripts/genimage.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="support/scripts/genimage.sh"
BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BR2_EXTERNAL_INFIX_PATH)/board/riscv64/visionfive2/genimage.cfg"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
@@ -131,6 +131,12 @@ BR2_PACKAGE_RAUC_JSON=y
BR2_PACKAGE_SYSKLOGD=y
BR2_PACKAGE_SYSKLOGD_LOGGER=y
BR2_PACKAGE_WATCHDOGD=y
BR2_PACKAGE_WATCHDOGD_GENERIC=y
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
BR2_PACKAGE_WATCHDOGD_FILENR=y
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
BR2_PACKAGE_WATCHDOGD_FSMON=y
BR2_PACKAGE_WATCHDOGD_TEMPMON
BR2_PACKAGE_LESS=y
BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
@@ -139,7 +145,6 @@ BR2_TARGET_ROOTFS_EXT2_4=y
BR2_TARGET_ROOTFS_EXT2_SIZE="512M"
BR2_TARGET_ROOTFS_EXT2_INODE_SIZE=0
BR2_TARGET_ROOTFS_EXT2_MKFS_OPTIONS="-O ^64bit,large_file,ext_attr"
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_TARGET_OPENSBI=y
BR2_TARGET_OPENSBI_CUSTOM_VERSION=y
@@ -165,9 +170,6 @@ BR2_TARGET_UBOOT_SPL=y
BR2_TARGET_UBOOT_SPL_NAME="spl/u-boot-spl.bin.normal.out"
BR2_TARGET_UBOOT_CUSTOM_DTS_PATH="$(BR2_EXTERNAL_INFIX_PATH)/board/riscv64/visionfive2/uboot/visionfive2-env.dtsi"
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
INFIX_VENDOR_HOME="https://kernelkit.org"
@@ -195,6 +197,7 @@ BR2_PACKAGE_LOWDOWN=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_MDNS_ALIAS=y
BR2_PACKAGE_NETBROWSE=y
BR2_PACKAGE_ONIEPROM=y
BR2_PACKAGE_PODMAN=y
BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
@@ -204,7 +207,9 @@ BR2_PACKAGE_TETRIS=y
BR2_PACKAGE_ROUSETTE=y
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
BR2_PACKAGE_HOST_PYTHON_YANGDOC=y
IMAGE_ITB_AUX=y
IMAGE_ITB_QCOW=y
IMAGE_ITB_RAUC=y
IMAGE_README=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
# GNS3_APPLIANCE is not set
SDCARD_AUX=y
-1
View File
@@ -31,4 +31,3 @@ BR2_TARGET_BAREBOX_IMAGE_FILE="images/barebox-raspberry-pi-2.img"
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_RAUC=y
# GNS3_APPLIANCE is not set
+2 -2
View File
@@ -10,7 +10,6 @@ BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_INFIX_PATH)/patches"
BR2_SSP_NONE=y
BR2_INIT_NONE=y
BR2_SYSTEM_BIN_SH_NONE=y
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
# BR2_PACKAGE_BUSYBOX is not set
BR2_PACKAGE_RPI_FIRMWARE=y
BR2_PACKAGE_RPI_FIRMWARE_BOOTCODE_BIN=y
@@ -40,4 +39,5 @@ BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
BR2_PACKAGE_BOOTLOADER_SPLASHSCREEN=y
# GNS3_APPLIANCE is not set
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
+12 -8
View File
@@ -24,10 +24,9 @@ BR2_GENERATE_LOCALE="en_US en_CA C.UTF-8"
BR2_TARGET_TZ_INFO=y
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/rootfs"
BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.60"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.62"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -116,10 +115,15 @@ BR2_PACKAGE_RAUC_JSON=y
BR2_PACKAGE_SYSKLOGD=y
BR2_PACKAGE_SYSKLOGD_LOGGER=y
BR2_PACKAGE_WATCHDOGD=y
BR2_PACKAGE_WATCHDOGD_GENERIC=y
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
BR2_PACKAGE_WATCHDOGD_FILENR=y
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
BR2_PACKAGE_WATCHDOGD_FSMON=y
BR2_PACKAGE_WATCHDOGD_TEMPMON
BR2_PACKAGE_LESS=y
BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_TARGET_EDK2=y
BR2_TARGET_GRUB2=y
@@ -131,11 +135,8 @@ BR2_PACKAGE_HOST_DOSFSTOOLS=y
BR2_PACKAGE_HOST_E2FSPROGS=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
BR2_PACKAGE_HOST_GENEXT2FS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_GO_BIN=y
BR2_PACKAGE_HOST_MTOOLS=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
INFIX_VENDOR_HOME="https://kernelkit.org"
@@ -168,6 +169,7 @@ BR2_PACKAGE_LOWDOWN=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_MDNS_ALIAS=y
BR2_PACKAGE_NETBROWSE=y
BR2_PACKAGE_ONIEPROM=y
BR2_PACKAGE_PODMAN=y
BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
@@ -177,7 +179,9 @@ BR2_PACKAGE_TETRIS=y
BR2_PACKAGE_ROUSETTE=y
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
BR2_PACKAGE_HOST_PYTHON_YANGDOC=y
IMAGE_ITB_AUX=y
IMAGE_ITB_QCOW=y
IMAGE_ITB_RAUC=y
IMAGE_README=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
GNS3_APPLIANCE_RAM=512
GNS3_APPLIANCE_IFNUM=10
+12 -8
View File
@@ -24,10 +24,9 @@ BR2_GENERATE_LOCALE="en_US en_CA C.UTF-8"
BR2_TARGET_TZ_INFO=y
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/rootfs"
BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.60"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.62"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
@@ -94,10 +93,15 @@ BR2_PACKAGE_RAUC_JSON=y
BR2_PACKAGE_SYSKLOGD=y
BR2_PACKAGE_SYSKLOGD_LOGGER=y
BR2_PACKAGE_WATCHDOGD=y
BR2_PACKAGE_WATCHDOGD_GENERIC=y
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
BR2_PACKAGE_WATCHDOGD_FILENR=y
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
BR2_PACKAGE_WATCHDOGD_FSMON=y
BR2_PACKAGE_WATCHDOGD_TEMPMON=y
BR2_PACKAGE_LESS=y
BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_TARGET_EDK2=y
BR2_TARGET_GRUB2=y
@@ -109,10 +113,7 @@ BR2_PACKAGE_HOST_DOSFSTOOLS=y
BR2_PACKAGE_HOST_E2FSPROGS=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
BR2_PACKAGE_HOST_GENEXT2FS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_MTOOLS=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SUPPORT=y
BR2_PACKAGE_HOST_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
INFIX_VENDOR_HOME="https://kernelkit.org"
@@ -139,10 +140,13 @@ BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
BR2_PACKAGE_LOWDOWN=y
BR2_PACKAGE_MCD=y
BR2_PACKAGE_MDNS_ALIAS=y
BR2_PACKAGE_ONIEPROM=y
BR2_PACKAGE_SHOW=y
BR2_PACKAGE_ROUSETTE=y
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
IMAGE_ITB_AUX=y
IMAGE_ITB_QCOW=y
IMAGE_ITB_RAUC=y
IMAGE_README=y
TRUSTED_KEYS=y
TRUSTED_KEYS_DEVELOPMENT=y
GNS3_APPLIANCE_RAM=512
GNS3_APPLIANCE_IFNUM=10
+23
View File
@@ -3,6 +3,29 @@ Change Log
All notable changes to the project are documented in this file.
[v26.01.0][UNRELEASED]
-------------------------
### Changes
- Upgrade Linux kernel to 6.12.62 (LTS)
- Upgrade libyang to 4.2.2
- Upgrade sysrepo to 4.2.10
- Upgrade netopeer2 (NETCONF) to 2.7.0
- Add RIPv2 routing support, issue #582
- Add support for configurable OSPF debug logging, issue #1281. Debug options
can now be enabled per category (bfd, packet, ism, nsm, default-information,
nssa). All debug options are disabled by default to prevent log flooding in
production environments. See the documentation for usage examples
- Add support for "routing interfaces", issue #647. Lists interfaces with IP
forwarding. Inspect from CLI using `show interface`, look for `⇅` flag
- Add operational data journal to statd with hierarchical time-based retention
policy, keeping snapshots from every 5 minutes (recent) to yearly (historical)
### Fixes
N/A
[v25.11.0][] - 2025-12-02
-------------------------
+1 -1
View File
@@ -217,7 +217,7 @@ gathers data from local linux services and feeds it into sysrepo.
To apply changes, rebuild the image:
make python-statd-rebuild statd-rebuild all
make statd-rebuild all
Rebuilding the image and testing on target for every change during
development process can be tedious. Instead, `yanger` allows remote
+158
View File
@@ -1339,6 +1339,7 @@ Currently supported YANG models:
| ietf-ipv4-unicast-routing | Static IPv4 unicast routing |
| ietf-ipv6-unicast-routing | Static IPv6 unicast routing |
| ietf-ospf | OSPF routing |
| ietf-rip | RIP routing |
| infix-routing | Infix deviations and extensions |
The base model, ietf-routing, is where all the other models hook in. It
@@ -1502,6 +1503,163 @@ routes`.
admin@example:/>
For more detailed troubleshooting, OSPF debug logging can be enabled to
capture specific protocol events. Debug messages are written to the
routing log file (`/var/log/routing`).
> [!CAUTION]
> Debug logging significantly increases log output and may impact
> performance. Only enable debug categories needed for troubleshooting,
> and disable them when done.
To enable specific OSPF debug categories:
admin@example:/> configure
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf debug
admin@example:/config/routing/…/ospf/debug/> set bfd true
admin@example:/config/routing/…/ospf/debug/> set nsm true
admin@example:/config/routing/…/ospf/debug/> leave
admin@example:/>
Available debug categories include:
- `bfd`: BFD (Bidirectional Forwarding Detection) events
- `packet`: Detailed packet debugging (all OSPF packets)
- `ism`: Interface State Machine events
- `nsm`: Neighbor State Machine events
- `default-information`: Default route origination
- `nssa`: Not-So-Stubby Area events
All debug options are disabled by default. Refer to the `infix-routing`
YANG model for the complete list of available debug options.
To view current debug settings:
admin@example:/> show running-config routing control-plane-protocol
To disable all debug logging, simply delete the debug settings or set
all options back to `false`:
admin@example:/> configure
admin@example:/config/> delete routing control-plane-protocol ospfv2 name default ospf debug
admin@example:/config/> leave
admin@example:/>
### RIP Routing
The system supports RIP dynamic routing for IPv4, i.e., RIPv2. To enable
RIP and set active interfaces:
admin@example:/config/> edit routing control-plane-protocol ripv2 name default rip
admin@example:/config/routing/…/rip/> set interfaces interface e0
admin@example:/config/routing/…/rip/> set interfaces interface e1
admin@example:/config/routing/…/rip/> leave
admin@example:/>
> [!TIP]
> Remember to enable [IPv4 forwarding](#ipv4-forwarding) for all the
> interfaces you want to route between.
#### RIP interface settings
By default, interfaces send and receive RIPv2 packets. To control the
RIP version per interface:
admin@example:/config/routing/…/rip/> edit interfaces interface e0
admin@example:/config/routing/…/rip/interfaces/interface/e0/> set send-version 1
admin@example:/config/routing/…/rip/interfaces/interface/e0/> set receive-version 1-2
admin@example:/config/routing/…/rip/interfaces/interface/e0/> leave
admin@example:/>
Valid version values are `1`, `2`, or `1-2` (both versions).
To configure a passive interface (advertise network but don't send/receive
RIP updates):
admin@example:/config/routing/…/rip/> edit interfaces interface e0
admin@example:/config/routing/…/rip/interfaces/interface/e0/> set passive
admin@example:/config/routing/…/rip/interfaces/interface/e0/> leave
admin@example:/>
#### RIP global settings
RIP supports redistribution of connected and static routes:
admin@example:/config/routing/…/rip/> set redistribute connected
admin@example:/config/routing/…/rip/> set redistribute static
admin@example:/config/routing/…/rip/> leave
admin@example:/>
#### Debug RIPv2
The CLI provides various RIP status commands:
admin@example:/> show ip rip
Default version control: send version 2, receive version 2
Interface Send Recv Key-chain
e0 2 2
e1 2 2
Routing for Networks:
e0
e1
Routing Information Sources:
Gateway BadPackets BadRoutes Distance Last Update
10.0.1.2 0 0 120 00:00:16
Distance: (default is 120)
admin@example:/> show ip rip neighbor
ADDRESS BAD-PACKETS BAD-ROUTES
10.0.1.2 0 0
admin@example:/>
For more detailed troubleshooting, RIP debug logging can be enabled to
capture specific protocol events. Debug messages are written to the
routing log file (`/var/log/routing`).
> [!CAUTION]
> Debug logging significantly increases log output and may impact
> performance. Only enable debug categories needed for troubleshooting,
> and disable them when done.
To enable specific RIP debug categories:
admin@example:/> configure
admin@example:/config/> edit routing control-plane-protocol ripv2 name default rip debug
admin@example:/config/routing/…/rip/debug/> set events true
admin@example:/config/routing/…/rip/debug/> set packet true
admin@example:/config/routing/…/rip/debug/> leave
admin@example:/>
Available debug categories include:
- `events`: RIP events (sending/receiving packets, timers, interface changes)
- `packet`: Detailed packet debugging (packet dumps with origin and port)
- `kernel`: Kernel routing table updates (route add/delete, interface updates)
All debug options are disabled by default. Refer to the `infix-routing`
YANG model for the complete list of available debug options.
To view current debug settings:
admin@example:/> show running-config routing control-plane-protocol
To disable all debug logging, simply delete the debug settings or set
all options back to `false`:
admin@example:/> configure
admin@example:/config/> delete routing control-plane-protocol ripv2 name default rip debug
admin@example:/config/> leave
admin@example:/>
### View routing table
+91
View File
@@ -0,0 +1,91 @@
# Support Data Collection
When troubleshooting issues or seeking support, the `support` command
provides a convenient way to collect comprehensive system diagnostics.
This command gathers configuration files, logs, network state, and other
system information into a single compressed archive.
## Collecting Support Data
To collect support data and save it to a file:
```bash
admin@host:~$ support collect > support-data.tar.gz
(admin@host) Password: ***********
Starting support data collection from host...
This may take up to a minute. Please wait...
Tailing /var/log/messages for 30 seconds (please wait)...
Log tail complete.
Collection complete. Creating archive...
admin@host:~$ ls -l support-data.tar.gz
-rw-rw-r-- 1 admin admin 508362 nov 30 13:05 support-data.tar.gz
```
The command can also be run remotely via SSH from your workstation:
```bash
$ ssh admin@host support collect > support-data.tar.gz
...
```
The collection process may take up to a minute depending on system load
and the amount of logging data. Progress messages are shown during the
collection process.
## Encrypted Collection
For secure transmission of support data, the archive can be encrypted
with GPG using a password:
```bash
admin@host:~$ support collect -p mypassword > support-data.tar.gz.gpg
Starting support data collection from host...
This may take up to a minute. Please wait...
...
Collection complete. Creating archive...
Encrypting with GPG...
```
The `support collect` command even supports omitting `mypassword` and
will then prompt interactively for the password. This works over SSH too,
but the local ssh client may then echo the password.
> [!TIP]
> To hide the encryption password for an SSH session, the script supports
> reading from stdin:
> `echo "$MYSECRET" | ssh user@device support collect -p >
> file.tar.gz.gpg`
After transferring the resulting file to your workstation, decrypt it
with the password:
```bash
$ gpg -d support-data.tar.gz.gpg > support-data.tar.gz
$ tar xzf support-data.tar.gz
...
```
or
```bash
$ gpg -d support-data.tar.gz.gpg | tar xz
...
```
> [!IMPORTANT]
> Make sure to share `mypassword` out-of-band from the encrypted data
> with the recipient of the data. I.e., avoid sending both in the same
> plain-text email for example.
## What is Collected
The support archive includes:
- System identification (hostname, uptime, kernel version)
- Running and operational configuration (sysrepo datastores)
- System logs (`/var/log` directory and live tail of messages log)
- Network configuration and state (interfaces, routes, neighbors, bridges)
- FRRouting information (OSPF, BFD status)
- Container information (podman containers and their configuration)
- System resource usage (CPU, memory, disk, processes)
- Hardware information (PCI, USB devices, network interfaces)
-88
View File
@@ -323,94 +323,6 @@ reference ID, stratum, time offsets, frequency, and root delay.
> The system uses `chronyd` Network Time Protocol (NTP) daemon. The
> output shown here is best explained in the [Chrony documentation][4].
## Support Data Collection
When troubleshooting issues or seeking support, the `support` command
provides a convenient way to collect comprehensive system diagnostics.
This command gathers configuration files, logs, network state, and other
system information into a single compressed archive.
### Collecting Support Data
To collect support data and save it to a file:
```bash
admin@host:~$ support collect > support-data.tar.gz
(admin@host) Password: ***********
Starting support data collection from host...
This may take up to a minute. Please wait...
Tailing /var/log/messages for 30 seconds (please wait)...
Log tail complete.
Collection complete. Creating archive...
admin@host:~$ ls -l support-data.tar.gz
-rw-rw-r-- 1 admin admin 508362 nov 30 13:05 support-data.tar.gz
```
The command can also be run remotely via SSH from your workstation:
```bash
$ ssh admin@host support collect > support-data.tar.gz
...
```
The collection process may take up to a minute depending on system load
and the amount of logging data. Progress messages are shown during the
collection process.
### Encrypted Collection
For secure transmission of support data, the archive can be encrypted
with GPG using a password:
```bash
admin@host:~$ support collect -p mypassword > support-data.tar.gz.gpg
Starting support data collection from host...
This may take up to a minute. Please wait...
...
Collection complete. Creating archive...
Encrypting with GPG...
```
The `support collect` command even supports omitting `mypassword` and
will then prompt interactively for the password. This works over SSH too,
but the local ssh client may then echo the password.
> [!TIP]
> To hide the encryption password for an SSH session, the script supports reading from stdin:
> `echo "$MYSECRET" | ssh user@device support collect -p > file.tar.gz.gpg`
After transferring the resulting file to your workstation, decrypt it
with the password:
```bash
$ gpg -d support-data.tar.gz.gpg > support-data.tar.gz
$ tar xzf support-data.tar.gz
```
or
```bash
$ gpg -d support-data.tar.gz.gpg | tar xz
```
> [!IMPORTANT]
> Make sure to share `mypassword` out-of-band from the encrypted data
> with the recipient of the data. I.e., avoid sending both in the same
> plain-text email for example.
### What is Collected
The support archive includes:
- System identification (hostname, uptime, kernel version)
- Running and operational configuration (sysrepo datastores)
- System logs (`/var/log` directory and live tail of messages log)
- Network configuration and state (interfaces, routes, neighbors, bridges)
- FRRouting information (OSPF, BFD status)
- Container information (podman containers and their configuration)
- System resource usage (CPU, memory, disk, processes)
- Hardware information (PCI, USB devices, network interfaces)
[1]: https://www.rfc-editor.org/rfc/rfc7317
[2]: https://github.com/kernelkit/infix/blob/main/src/confd/yang/infix-system%402024-02-29.yang
[3]: https://www.rfc-editor.org/rfc/rfc8341
+4 -4
View File
@@ -18,11 +18,11 @@ QEMU
> relevant Qemu packages are pulled in as well. This trick, installing
> [virt-manager][virt], helps set up Qemu networking on your system.
A virtualized Infix x86_64 instance can easily be launched from a Linux
system, with [Qemu][] installed, by issuing:
A virtualized Infix x86_64 instance can be launched from a Linux system,
with [Qemu][] installed, by issuing:
```
$ ./qemu.sh
$ ./qemu/run.sh
...
```
@@ -35,7 +35,7 @@ $ make run
```
To change settings, e.g. networking, <kbd>make run-menuconfig</kbd>, or
from a pre-built Infix release tarball, using <kbd>./qemu.sh -c</kbd>
from a pre-built Infix release tarball, using <kbd>./qemu/run.sh -c</kbd>
The Infix test suite is built around Qemu and [Qeneth][qeth], see:
+1 -1
View File
@@ -84,7 +84,7 @@ and 63 characters
admin@example:/> configure
admin@example:/config/> edit keystore symmetric-key example
admin@example:/config/keystore/…/example/> set key-format wifi-preshared-key-format
admin@example:/config/keystore/…/example/> set cleartext-key mysecret
admin@example:/config/keystore/…/example/> set cleartext-symmetric-key mysecret
admin@example:/config/keystore/…/example/> leave
admin@example:/>
```
-11
View File
@@ -1,8 +1,6 @@
include $(BR2_EXTERNAL_INFIX_PATH)/infix.mk
include $(sort $(wildcard $(BR2_EXTERNAL_INFIX_PATH)/package/*/*.mk))
include $(BR2_EXTERNAL_INFIX_PATH)/board/common/common.mk
include $(BR2_EXTERNAL_INFIX_PATH)/board/board.mk
-include $(BR2_EXTERNAL_INFIX_PATH)/board/$(patsubst "%",%,$(BR2_ARCH))/board.mk
include $(BR2_EXTERNAL_INFIX_PATH)/test/test.mk
.PHONY: local.mk
@@ -10,15 +8,6 @@ local.mk:
@$(call IXMSG,"Installing local override for certain packages")
@(cd $O && ln -s $(BR2_EXTERNAL_INFIX_PATH)/local.mk .)
.PHONY: run
run:
@$(BINARIES_DIR)/qemu.sh
.PHONY: run-menuconfig
run-menuconfig: $(BUILD_DIR)/buildroot-config/mconf
CONFIG_="CONFIG_" BR2_CONFIG="$(BINARIES_DIR)/.config" \
$(BUILD_DIR)/buildroot-config/mconf $(BINARIES_DIR)/Config.in
#
# Buildroot package extensions
#
+1
View File
@@ -8,5 +8,6 @@ INFIX_TOPDIR = $(if $(oem-dir),$(oem-dir),$(BR2_EXTERNAL_INFIX_PATH))
# release is being built.
export INFIX_BUILD_ID ?= $(shell git -C $(INFIX_TOPDIR) describe --dirty --always --tags)
export INFIX_VERSION = $(if $(INFIX_RELEASE),$(INFIX_RELEASE),$(INFIX_BUILD_ID))
export INFIX_ARTIFACT = $(call qstrip,$(INFIX_IMAGE_ID)$(if $(INFIX_RELEASE),-$(INFIX_RELEASE)))
INFIX_CFLAGS:=-Wall -Werror -Wextra -Wno-unused-parameter -Wformat=2 -Wformat-overflow=2 -Winit-self -Wstrict-overflow=4 -Wno-format-truncation -Wno-format-nonliteral
+1
View File
@@ -43,6 +43,7 @@ nav:
- Hardware Info & Status: hardware.md
- Management: management.md
- Syslog Support: syslog.md
- Support Data: support.md
- Upgrade: upgrade.md
- Scripting:
- Introduction: scripting.md
+1 -1
View File
@@ -29,9 +29,9 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/lowdown/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/mcd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/mdns-alias/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/netbrowse/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/onieprom/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/podman/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/python-libyang/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/python-statd/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/python-yangdoc/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/skeleton-init-finit/Config.in"
source "$BR2_EXTERNAL_INFIX_PATH/package/show/Config.in"
+2 -2
View File
@@ -4,13 +4,13 @@
#
################################################################################
CONFD_VERSION = 1.6
CONFD_VERSION = 1.7
CONFD_SITE_METHOD = local
CONFD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/confd
CONFD_LICENSE = BSD-3-Clause
CONFD_LICENSE_FILES = LICENSE
CONFD_REDISTRIBUTE = NO
CONFD_DEPENDENCIES = host-sysrepo sysrepo netopeer2 jansson libite sysrepo libsrx libglib2
CONFD_DEPENDENCIES = host-sysrepo sysrepo rousette netopeer2 jansson libite sysrepo libsrx libglib2
CONFD_AUTORECONF = YES
CONFD_CONF_OPTS += --disable-silent-rules --with-crypt=$(BR2_PACKAGE_CONFD_DEFAULT_CRYPT)
CONFD_SYSREPO_SHM_PREFIX = sr_buildroot$(subst /,_,$(CONFIG_DIR))_confd
@@ -1,3 +1,3 @@
# Locally calculated
sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE
sha256 cfe1064849a158f3eb9e82f12a709723115fc9bc4d30056e0e96ea0ba03672a2 klish-plugin-sysrepo-4e86a836c9b09a14c9625ea3d3b56b6578be4833-git4.tar.gz
sha256 71802708c96521a8bf43e38d6e5ac36de5481e087eaabdbebbc282ec0e29b8d3 klish-plugin-sysrepo-0846fa6b8d5d665eebfc7b1664542646915a79f7-git4.tar.gz
@@ -4,7 +4,7 @@
#
################################################################################
KLISH_PLUGIN_SYSREPO_VERSION = 4e86a836c9b09a14c9625ea3d3b56b6578be4833
KLISH_PLUGIN_SYSREPO_VERSION = 0846fa6b8d5d665eebfc7b1664542646915a79f7
KLISH_PLUGIN_SYSREPO_SITE = https://github.com/kernelkit/klish-plugin-sysrepo.git
#KLISH_PLUGIN_SYSREPO_VERSION = cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb
#KLISH_PLUGIN_SYSREPO_SITE = https://src.libcode.org/pkun/klish-plugin-sysrepo.git
@@ -1,7 +1,7 @@
From 22b41e7ed8268b94ccc139138e2037c390a3a616 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bed=C5=99ich=20Schindler?= <bedrich.schindler@gmail.com>
Date: Thu, 10 Jul 2025 15:00:45 +0200
Subject: [PATCH] Implement `SchemaNode::actionRpcs()`
Subject: [PATCH 1/7] Implement `SchemaNode::actionRpcs()`
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@@ -0,0 +1,38 @@
From 1f8e502cf0308faa0336b1077308184de6a83ee0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= <jan.kundrat@cesnet.cz>
Date: Mon, 20 Oct 2025 11:45:06 +0200
Subject: [PATCH 2/7] CI: pin to libyang v3
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Wires
Change-Id: Idba085ad9c9c137874801f1d4089f8ee6bb390c7
Signed-off-by: Mattias Walström <lazzer@gmail.com>
---
.zuul.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.zuul.yaml b/.zuul.yaml
index 7b92766..fd89549 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -4,13 +4,13 @@
- f38-gcc-cover:
required-projects:
- name: github/CESNET/libyang
- override-checkout: devel
+ override-checkout: cesnet/2025-08-07
- name: github/doctest/doctest
override-checkout: v2.3.6
- f38-clang-asan-ubsan:
required-projects: &projects
- name: github/CESNET/libyang
- override-checkout: devel
+ override-checkout: cesnet/2025-08-07
- name: github/doctest/doctest
override-checkout: v2.4.11
- f38-clang-tsan:
--
2.43.0
@@ -0,0 +1,216 @@
From b27a65d5d5f6ffffbd2c26c1b5bea57a6de584d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <tomas.pecka@cesnet.cz>
Date: Mon, 20 Oct 2025 18:46:38 +0200
Subject: [PATCH 3/7] wrap lyd_validate_op
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Wires
This patch wraps lyd_validate_op from libyang. Downstream users can now
validate operations (RPC input, replies, and notifications).
Change-Id: Ib03070bbc3e1d0dccd6bf38eda82e944db1093b1
Signed-off-by: Mattias Walström <lazzer@gmail.com>
---
include/libyang-cpp/DataNode.hpp | 2 +
src/DataNode.cpp | 24 +++++++++++
tests/context.cpp | 2 +-
tests/data_node.cpp | 72 ++++++++++++++++++++++++++++++++
tests/example_schema.hpp | 22 ++++++++++
5 files changed, 121 insertions(+), 1 deletion(-)
diff --git a/include/libyang-cpp/DataNode.hpp b/include/libyang-cpp/DataNode.hpp
index 50d6c0e..e202a96 100644
--- a/include/libyang-cpp/DataNode.hpp
+++ b/include/libyang-cpp/DataNode.hpp
@@ -59,6 +59,7 @@ template <typename Operation, typename Siblings>
void handleLyTreeOperation(DataNode* affectedNode, Operation operation, Siblings siblings, std::shared_ptr<internal_refcount> newRefs);
LIBYANG_CPP_EXPORT void validateAll(std::optional<libyang::DataNode>& node, const std::optional<ValidationOptions>& opts = std::nullopt);
+LIBYANG_CPP_EXPORT void validateOp(libyang::DataNode& input, const std::optional<libyang::DataNode>& opsTree, OperationType opType);
LIBYANG_CPP_EXPORT Set<DataNode> findXPathAt(
const std::optional<libyang::DataNode>& contextNode,
@@ -147,6 +148,7 @@ public:
friend LIBYANG_CPP_EXPORT lyd_node* getRawNode(DataNode node);
friend LIBYANG_CPP_EXPORT void validateAll(std::optional<libyang::DataNode>& node, const std::optional<ValidationOptions>& opts);
+ friend LIBYANG_CPP_EXPORT void validateOp(libyang::DataNode& input, const std::optional<libyang::DataNode>& opsTree, OperationType opType);
friend LIBYANG_CPP_EXPORT Set<DataNode> findXPathAt(const std::optional<libyang::DataNode>& contextNode, const libyang::DataNode& forest, const std::string& xpath);
bool operator==(const DataNode& node) const;
diff --git a/src/DataNode.cpp b/src/DataNode.cpp
index 7e87917..e28ef30 100644
--- a/src/DataNode.cpp
+++ b/src/DataNode.cpp
@@ -1226,6 +1226,30 @@ void validateAll(std::optional<libyang::DataNode>& node, const std::optional<Val
}
}
+/** @brief Validate op after parsing with lyd_parse_op.
+ *
+ * Wraps `lyd_validate_op`.
+ *
+ * @param input The tree with the op to validate.
+ * @param opsTree The optional data tree to validate the input against.
+ * @param opType The operation type. Contrary to `lyd_validate_op`, we accept not only YANG but also NETCONF and RESTCONF operation types (and internally convert them to YANG).
+ */
+void validateOp(libyang::DataNode& input, const std::optional<libyang::DataNode>& opsTree, OperationType opType)
+{
+ if (opType == OperationType::RpcYang || opType == OperationType::RpcRestconf || opType == OperationType::RpcNetconf) {
+ opType = OperationType::RpcYang;
+ } else if (opType == OperationType::ReplyYang || opType == OperationType::ReplyRestconf || opType == OperationType::ReplyNetconf) {
+ opType = OperationType::ReplyYang;
+ } else if (opType == OperationType::NotificationYang || opType == OperationType::NotificationRestconf || opType == OperationType::NotificationNetconf) {
+ opType = OperationType::NotificationYang;
+ } else {
+ throw Error("validateOp: DataYang datatype is not supported");
+ }
+
+ auto ret = lyd_validate_op(input.m_node, opsTree ? opsTree->m_node : nullptr, utils::toOpType(opType), nullptr);
+ throwIfError(ret, "libyang:validateOp: lyd_validate_op failed");
+}
+
/** @short Find instances matching the provided XPath
*
* @param contextNode The node which serves as the "context node" for XPath evaluation. Use nullopt to start at root.
diff --git a/tests/context.cpp b/tests/context.cpp
index 6c5dde8..c0b7e09 100644
--- a/tests/context.cpp
+++ b/tests/context.cpp
@@ -154,7 +154,7 @@ TEST_CASE("context")
{
auto mod = ctx->parseModule(example_schema, libyang::SchemaFormat::YANG);
auto rpcs = mod.actionRpcs();
- REQUIRE(rpcs.size() == 1);
+ REQUIRE(rpcs.size() == 2);
REQUIRE(rpcs[0].module().name() == "example-schema");
REQUIRE(rpcs[0].name() == "myRpc");
diff --git a/tests/data_node.cpp b/tests/data_node.cpp
index db5a28e..9215b12 100644
--- a/tests/data_node.cpp
+++ b/tests/data_node.cpp
@@ -2430,6 +2430,78 @@ TEST_CASE("Data Node manipulation")
"Can't parse into operation data tree: LY_EVALID", libyang::Error);
}
}
+
+ DOCTEST_SUBCASE("Validation")
+ {
+ DOCTEST_SUBCASE("Valid input")
+ {
+ std::string rpcInput;
+ std::string rpcPath;
+ std::string expected;
+ std::optional<libyang::DataNode> depTree;
+
+ DOCTEST_SUBCASE("RPC")
+ {
+ rpcInput = R"({"example-schema:input": { "number": 42 } })";
+ rpcPath = "/example-schema:rpc-with-choice";
+ expected = R"({
+ "example-schema:rpc-with-choice": {
+ "number": 42
+ }
+}
+)";
+ }
+
+ DOCTEST_SUBCASE("Action")
+ {
+ rpcInput = R"({ "example-schema:input": { "friend": "Kuba" } })";
+ rpcPath = "/example-schema:person[name='Franta']/poke-a-friend";
+ expected = R"({
+ "example-schema:poke-a-friend": {
+ "friend": "Kuba"
+ }
+}
+)";
+ depTree = ctx.newPath("/example-schema:person[name='Kuba']");
+ }
+
+ auto [parent, rpcTree] = ctx.newPath2(rpcPath);
+ auto rpcOp = rpcTree->parseOp(rpcInput, dataTypeFor(rpcInput), libyang::OperationType::RpcRestconf);
+
+ REQUIRE(!rpcOp.op);
+ REQUIRE(rpcOp.tree);
+
+ libyang::validateOp(*rpcTree, depTree, libyang::OperationType::RpcRestconf);
+ REQUIRE(*rpcTree->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::KeepEmptyCont) == expected);
+ }
+
+ DOCTEST_SUBCASE("Nodes in disjunctive cases defined together")
+ {
+ auto rpcInput = R"({ "example-schema:input": { "number": 42, "text": "The ultimate answer" } })";
+
+ auto rpcTree = ctx.newPath("/example-schema:rpc-with-choice");
+ auto rpcOp = rpcTree.parseOp(rpcInput, dataTypeFor(rpcInput), libyang::OperationType::RpcRestconf);
+
+ REQUIRE(!rpcOp.op);
+ REQUIRE(rpcOp.tree);
+
+ REQUIRE_THROWS_WITH_AS(libyang::validateOp(rpcTree, std::nullopt, libyang::OperationType::RpcRestconf), "libyang:validateOp: lyd_validate_op failed: LY_EVALID", libyang::Error);
+ }
+
+ DOCTEST_SUBCASE("Action without the leafref node")
+ {
+ auto rpcInput = R"({ "example-schema:input": { "friend": "Kuba" } })";
+ auto rpcPath = "/example-schema:person[name='Franta']/poke-a-friend";
+
+ auto [parent, rpcTree] = ctx.newPath2(rpcPath);
+ auto rpcOp = rpcTree->parseOp(rpcInput, dataTypeFor(rpcInput), libyang::OperationType::RpcRestconf);
+
+ REQUIRE(!rpcOp.op);
+ REQUIRE(rpcOp.tree);
+
+ REQUIRE_THROWS_WITH_AS(libyang::validateOp(*rpcTree, std::nullopt, libyang::OperationType::RpcRestconf), "libyang:validateOp: lyd_validate_op failed: LY_EVALID", libyang::Error);
+ }
+ }
}
DOCTEST_SUBCASE("comparing") {
diff --git a/tests/example_schema.hpp b/tests/example_schema.hpp
index 02d3d74..acc6ecc 100644
--- a/tests/example_schema.hpp
+++ b/tests/example_schema.hpp
@@ -108,6 +108,16 @@ module example-schema {
}
action poke { }
+
+ action poke-a-friend {
+ input {
+ leaf friend {
+ type leafref {
+ path '../../../person/name';
+ }
+ }
+ }
+ }
}
leaf bossPerson {
@@ -284,6 +294,18 @@ module example-schema {
}
}
}
+ rpc rpc-with-choice {
+ input {
+ choice the-impossible-choice {
+ leaf text {
+ type string;
+ }
+ leaf number {
+ type int32;
+ }
+ }
+ }
+ }
anydata myData {
}
--
2.43.0
@@ -0,0 +1,435 @@
From 4c00c24dee6bbc694d62e7174b7ac14f8aa95f14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= <jan.kundrat@cesnet.cz>
Date: Thu, 30 Oct 2025 21:16:13 +0100
Subject: [PATCH 4/7] port to libyang v4
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Wires
Apart from the usual API/ABI changes, the default values of a `leaf` or
a `leaf-list` are no longer canonicalized.
This used to be missing from libyang v4, but it was added recently.
Sill, chances are that the form which was used in the YANG model's
source code is actually *the* intended presentation, so let's skip
canonicalization altogether.
Upstream has removed some flags and defines, so let's sync their list
with whatever is currently available in the `devel` branch.
Change-Id: I52dcec88eeee003b45dd6cf400f4d6875abbcc05
Signed-off-by: Mattias Walström <lazzer@gmail.com>
---
.zuul.yaml | 4 ++--
CMakeLists.txt | 4 ++--
README.md | 2 +-
include/libyang-cpp/Context.hpp | 6 +++++-
include/libyang-cpp/DataNode.hpp | 5 ++++-
include/libyang-cpp/Enum.hpp | 15 +++++++++++++--
src/Context.cpp | 12 ++++++++++--
src/DataNode.cpp | 11 +++++++++--
src/SchemaNode.cpp | 6 +++---
src/Type.cpp | 2 +-
src/utils/enum.hpp | 21 +++++++++++++++++++--
tests/context.cpp | 32 +++++++++++++++++---------------
tests/data_node.cpp | 2 +-
tests/schema_node.cpp | 4 ++--
14 files changed, 89 insertions(+), 37 deletions(-)
diff --git a/.zuul.yaml b/.zuul.yaml
index fd89549..7b92766 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -4,13 +4,13 @@
- f38-gcc-cover:
required-projects:
- name: github/CESNET/libyang
- override-checkout: cesnet/2025-08-07
+ override-checkout: devel
- name: github/doctest/doctest
override-checkout: v2.3.6
- f38-clang-asan-ubsan:
required-projects: &projects
- name: github/CESNET/libyang
- override-checkout: cesnet/2025-08-07
+ override-checkout: devel
- name: github/doctest/doctest
override-checkout: v2.4.11
- f38-clang-tsan:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c6db320..90f9aaa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,7 +20,7 @@ add_custom_target(libyang-cpp-version-cmake
cmake/ProjectGitVersionRunner.cmake
)
include(cmake/ProjectGitVersion.cmake)
-set(LIBYANG_CPP_PKG_VERSION "4")
+set(LIBYANG_CPP_PKG_VERSION "5")
prepare_git_version(LIBYANG_CPP_VERSION ${LIBYANG_CPP_PKG_VERSION})
find_package(Doxygen)
@@ -28,7 +28,7 @@ option(WITH_DOCS "Create and install internal documentation (needs Doxygen)" ${D
option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON)
find_package(PkgConfig REQUIRED)
-pkg_check_modules(LIBYANG REQUIRED libyang>=3.10.1 IMPORTED_TARGET)
+pkg_check_modules(LIBYANG REQUIRED libyang>=4.1.0 IMPORTED_TARGET)
# FIXME from gcc 14.1 on we should be able to use the calendar/time from libstdc++ and thus remove the date dependency
find_package(date)
diff --git a/README.md b/README.md
index 8291e00..0cef2ff 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
Object lifetimes are managed automatically via RAII.
## Dependencies
-- [libyang v3](https://github.com/CESNET/libyang) - the `devel` branch (even for the `master` branch of *libyang-cpp*)
+- [libyang v4](https://github.com/CESNET/libyang) - the `devel` branch (even for the `master` branch of *libyang-cpp*)
- C++20 compiler (e.g., GCC 10.x+, clang 10+)
- CMake 3.19+
- optionally for built-in tests, [Doctest](https://github.com/doctest/doctest/) as a C++ unit test framework
diff --git a/include/libyang-cpp/Context.hpp b/include/libyang-cpp/Context.hpp
index ca89063..e695914 100644
--- a/include/libyang-cpp/Context.hpp
+++ b/include/libyang-cpp/Context.hpp
@@ -108,7 +108,11 @@ public:
std::optional<SubmoduleParsed> getSubmodule(const std::string& name, const std::optional<std::string>& revision) const;
void registerModuleCallback(std::function<ModuleCallback> callback);
- ParsedOp parseOp(const std::string& input, const DataFormat format, const OperationType opType) const;
+ ParsedOp parseOp(
+ const std::string& input,
+ const DataFormat format,
+ const OperationType opType,
+ const std::optional<ParseOptions> parseOpts = std::nullopt) const;
DataNode newPath(const std::string& path, const std::optional<std::string>& value = std::nullopt, const std::optional<CreationOptions> options = std::nullopt) const;
CreatedNodes newPath2(const std::string& path, const std::optional<std::string>& value = std::nullopt, const std::optional<CreationOptions> options = std::nullopt) const;
diff --git a/include/libyang-cpp/DataNode.hpp b/include/libyang-cpp/DataNode.hpp
index e202a96..35e5936 100644
--- a/include/libyang-cpp/DataNode.hpp
+++ b/include/libyang-cpp/DataNode.hpp
@@ -123,7 +123,10 @@ public:
Collection<DataNode, IterationType::Sibling> siblings() const;
Collection<DataNode, IterationType::Sibling> immediateChildren() const;
- ParsedOp parseOp(const std::string& input, const DataFormat format, const OperationType opType) const;
+ ParsedOp parseOp(const std::string& input,
+ const DataFormat format,
+ const OperationType opType,
+ const std::optional<ParseOptions> parseOpts = std::nullopt) const;
void parseSubtree(
const std::string& data,
diff --git a/include/libyang-cpp/Enum.hpp b/include/libyang-cpp/Enum.hpp
index 85dcc83..32142f9 100644
--- a/include/libyang-cpp/Enum.hpp
+++ b/include/libyang-cpp/Enum.hpp
@@ -136,6 +136,7 @@ enum class DuplicationOptions : uint32_t {
WithFlags = 0x08,
NoExt = 0x10,
WithPriv = 0x20,
+ NoLyds = 0x40,
};
enum class NodeType : uint16_t {
@@ -167,6 +168,13 @@ enum class ContextOptions : uint16_t {
PreferSearchDirs = 0x20,
SetPrivParsed = 0x40,
ExplicitCompile = 0x80,
+ EnableImpFeatures = 0x100,
+ CompileObsolete = 0x200,
+ LybHashes = 0x400,
+ LeafrefExtended = 0x800,
+ LeafrefLinking = 0x1000,
+ BuiltinPluginsOnly = 0x2000,
+ StaticPluginsOnly = 0x4000,
};
/**
@@ -203,7 +211,6 @@ enum class AnydataValueType : uint32_t {
String,
XML,
JSON,
- LYB
};
/**
@@ -252,6 +259,7 @@ enum class ValidationOptions {
MultiError = 0x0004,
Operational = 0x0008,
NoDefaults = 0x0010,
+ NotFinal = 0x0020,
};
/**
@@ -262,11 +270,14 @@ enum class ParseOptions {
Strict = 0x020000,
Opaque = 0x040000,
NoState = 0x080000,
- LybModUpdate = 0x100000,
+ LybSkipCtxCheck = 0x100000,
Ordered = 0x200000,
Subtree = 0x400000, /**< Do not use this one for parsing of data subtrees */
WhenTrue = 0x800000,
NoNew = 0x1000000,
+ StoreOnly = 0x2010000,
+ JsonNull = 0x4000000,
+ JsonStringDataTypes = 0x8000000,
};
/**
diff --git a/src/Context.cpp b/src/Context.cpp
index fec2f27..f5bdc71 100644
--- a/src/Context.cpp
+++ b/src/Context.cpp
@@ -239,7 +239,7 @@ std::optional<DataNode> Context::parseExtData(
* Note: to parse a NETCONF RPC reply, you MUST parse the original NETCONF RPC request (that is, you have to use
* this method with OperationType::RpcNetconf).
*/
-ParsedOp Context::parseOp(const std::string& input, const DataFormat format, const OperationType opType) const
+ParsedOp Context::parseOp(const std::string& input, const DataFormat format, const OperationType opType, const std::optional<ParseOptions> parseOpts) const
{
auto in = wrap_ly_in_new_memory(input);
@@ -251,7 +251,15 @@ ParsedOp Context::parseOp(const std::string& input, const DataFormat format, con
case OperationType::NotificationYang: {
lyd_node* op = nullptr;
lyd_node* tree = nullptr;
- auto err = lyd_parse_op(m_ctx.get(), nullptr, in.get(), utils::toLydFormat(format), utils::toOpType(opType), &tree, &op);
+ auto err = lyd_parse_op(
+ m_ctx.get(),
+ nullptr,
+ in.get(),
+ utils::toLydFormat(format),
+ utils::toOpType(opType),
+ parseOpts ? utils::toParseOptions(*parseOpts) : 0,
+ &tree,
+ &op);
ParsedOp res;
res.tree = tree ? std::optional{libyang::wrapRawNode(tree)} : std::nullopt;
diff --git a/src/DataNode.cpp b/src/DataNode.cpp
index e28ef30..edabf9b 100644
--- a/src/DataNode.cpp
+++ b/src/DataNode.cpp
@@ -391,7 +391,7 @@ DataNodeAny DataNode::asAny() const
*
* Wraps `lyd_parse_op`.
*/
-ParsedOp DataNode::parseOp(const std::string& input, const DataFormat format, const OperationType opType) const
+ParsedOp DataNode::parseOp(const std::string& input, const DataFormat format, const OperationType opType, const std::optional<ParseOptions> parseOpts) const
{
auto in = wrap_ly_in_new_memory(input);
@@ -401,7 +401,14 @@ ParsedOp DataNode::parseOp(const std::string& input, const DataFormat format, co
case OperationType::ReplyRestconf: {
lyd_node* op = nullptr;
lyd_node* tree = nullptr;
- auto err = lyd_parse_op(m_node->schema->module->ctx, m_node, in.get(), utils::toLydFormat(format), utils::toOpType(opType), &tree, nullptr);
+ auto err = lyd_parse_op(m_node->schema->module->ctx,
+ m_node,
+ in.get(),
+ utils::toLydFormat(format),
+ utils::toOpType(opType),
+ parseOpts ? utils::toParseOptions(*parseOpts) : 0,
+ &tree,
+ nullptr);
ParsedOp res{
.tree = tree ? std::optional{libyang::wrapRawNode(tree)} : std::nullopt,
.op = op ? std::optional{libyang::wrapRawNode(op)} : std::nullopt
diff --git a/src/SchemaNode.cpp b/src/SchemaNode.cpp
index ce24203..2e0351a 100644
--- a/src/SchemaNode.cpp
+++ b/src/SchemaNode.cpp
@@ -564,7 +564,7 @@ std::vector<std::string> LeafList::defaultValuesStr() const
auto dflts = reinterpret_cast<const lysc_node_leaflist*>(m_node)->dflts;
std::vector<std::string> res;
for (const auto& it : std::span(dflts, LY_ARRAY_COUNT(dflts))) {
- res.emplace_back(lyd_value_get_canonical(m_ctx.get(), it));
+ res.emplace_back(it.str);
}
return res;
}
@@ -660,8 +660,8 @@ bool LeafList::isUserOrdered() const
std::optional<std::string> Leaf::defaultValueStr() const
{
auto dflt = reinterpret_cast<const lysc_node_leaf*>(m_node)->dflt;
- if (dflt) {
- return lyd_value_get_canonical(m_ctx.get(), dflt);
+ if (dflt.str) {
+ return std::string{dflt.str};
} else {
return std::nullopt;
}
diff --git a/src/Type.cpp b/src/Type.cpp
index 01b2c4f..4d2db46 100644
--- a/src/Type.cpp
+++ b/src/Type.cpp
@@ -240,7 +240,7 @@ std::optional<std::string> Type::description() const
*/
std::string Type::internalPluginId() const
{
- return m_type->plugin->id;
+ return lysc_get_type_plugin(m_type->plugin_ref)->id;
}
/**
diff --git a/src/utils/enum.hpp b/src/utils/enum.hpp
index 5e02d24..0b2e2d7 100644
--- a/src/utils/enum.hpp
+++ b/src/utils/enum.hpp
@@ -91,6 +91,7 @@ static_assert(LYD_DUP_WITH_FLAGS == toDuplicationOptions(DuplicationOptions::Wit
static_assert(LYD_DUP_WITH_PARENTS == toDuplicationOptions(DuplicationOptions::WithParents));
static_assert(LYD_DUP_NO_EXT == toDuplicationOptions(DuplicationOptions::NoExt));
static_assert(LYD_DUP_WITH_PRIV == toDuplicationOptions(DuplicationOptions::WithPriv));
+static_assert(LYD_DUP_NO_LYDS == toDuplicationOptions(DuplicationOptions::NoLyds));
static_assert((LYD_DUP_NO_META | LYD_DUP_NO_EXT) ==
toDuplicationOptions(DuplicationOptions::NoMeta | DuplicationOptions::NoExt));
@@ -131,6 +132,13 @@ static_assert(toContextOptions(ContextOptions::DisableSearchCwd) == LY_CTX_DISAB
static_assert(toContextOptions(ContextOptions::PreferSearchDirs) == LY_CTX_PREFER_SEARCHDIRS);
static_assert(toContextOptions(ContextOptions::SetPrivParsed) == LY_CTX_SET_PRIV_PARSED);
static_assert(toContextOptions(ContextOptions::ExplicitCompile) == LY_CTX_EXPLICIT_COMPILE);
+static_assert(toContextOptions(ContextOptions::EnableImpFeatures) == LY_CTX_ENABLE_IMP_FEATURES);
+static_assert(toContextOptions(ContextOptions::CompileObsolete) == LY_CTX_COMPILE_OBSOLETE);
+static_assert(toContextOptions(ContextOptions::LybHashes) == LY_CTX_LYB_HASHES);
+static_assert(toContextOptions(ContextOptions::LeafrefExtended) == LY_CTX_LEAFREF_EXTENDED);
+static_assert(toContextOptions(ContextOptions::LeafrefLinking) == LY_CTX_LEAFREF_LINKING);
+static_assert(toContextOptions(ContextOptions::BuiltinPluginsOnly) == LY_CTX_BUILTIN_PLUGINS_ONLY);
+static_assert(toContextOptions(ContextOptions::StaticPluginsOnly) == LY_CTX_STATIC_PLUGINS_ONLY);
constexpr uint16_t toLogOptions(const LogOptions options)
{
@@ -198,6 +206,10 @@ constexpr uint32_t toValidationOptions(const ValidationOptions opts)
static_assert(toValidationOptions(ValidationOptions::NoState) == LYD_VALIDATE_NO_STATE);
static_assert(toValidationOptions(ValidationOptions::Present) == LYD_VALIDATE_PRESENT);
+static_assert(toValidationOptions(ValidationOptions::MultiError) == LYD_VALIDATE_MULTI_ERROR);
+static_assert(toValidationOptions(ValidationOptions::Operational) == LYD_VALIDATE_OPERATIONAL);
+static_assert(toValidationOptions(ValidationOptions::NoDefaults) == LYD_VALIDATE_NO_DEFAULTS);
+static_assert(toValidationOptions(ValidationOptions::NotFinal) == LYD_VALIDATE_NOT_FINAL);
constexpr uint32_t toParseOptions(const ParseOptions opts)
{
@@ -208,8 +220,14 @@ static_assert(toParseOptions(ParseOptions::ParseOnly) == LYD_PARSE_ONLY);
static_assert(toParseOptions(ParseOptions::Strict) == LYD_PARSE_STRICT);
static_assert(toParseOptions(ParseOptions::Opaque) == LYD_PARSE_OPAQ);
static_assert(toParseOptions(ParseOptions::NoState) == LYD_PARSE_NO_STATE);
-static_assert(toParseOptions(ParseOptions::LybModUpdate) == LYD_PARSE_LYB_MOD_UPDATE);
+static_assert(toParseOptions(ParseOptions::LybSkipCtxCheck) == LYD_PARSE_LYB_SKIP_CTX_CHECK);
static_assert(toParseOptions(ParseOptions::Ordered) == LYD_PARSE_ORDERED);
+static_assert(toParseOptions(ParseOptions::Subtree) == LYD_PARSE_SUBTREE);
+static_assert(toParseOptions(ParseOptions::WhenTrue) == LYD_PARSE_WHEN_TRUE);
+static_assert(toParseOptions(ParseOptions::NoNew) == LYD_PARSE_NO_NEW);
+static_assert(toParseOptions(ParseOptions::StoreOnly) == LYD_PARSE_STORE_ONLY);
+static_assert(toParseOptions(ParseOptions::JsonNull) == LYD_PARSE_JSON_NULL);
+static_assert(toParseOptions(ParseOptions::JsonStringDataTypes) == LYD_PARSE_JSON_STRING_DATATYPES);
constexpr lyd_type toOpType(const OperationType type)
{
@@ -242,7 +260,6 @@ static_assert(toAnydataValueType(AnydataValueType::DataTree) == LYD_ANYDATA_DATA
static_assert(toAnydataValueType(AnydataValueType::String) == LYD_ANYDATA_STRING);
static_assert(toAnydataValueType(AnydataValueType::XML) == LYD_ANYDATA_XML);
static_assert(toAnydataValueType(AnydataValueType::JSON) == LYD_ANYDATA_JSON);
-static_assert(toAnydataValueType(AnydataValueType::LYB) == LYD_ANYDATA_LYB);
constexpr LYS_OUTFORMAT toLysOutFormat(const SchemaOutputFormat format)
{
diff --git a/tests/context.cpp b/tests/context.cpp
index c0b7e09..eaedebf 100644
--- a/tests/context.cpp
+++ b/tests/context.cpp
@@ -359,25 +359,27 @@ TEST_CASE("context")
ctx->loadModule("mod1", std::nullopt, {});
ctx->parseModule(valid_yang_model, libyang::SchemaFormat::YANG);
auto modules = ctx->modules();
- REQUIRE(modules.size() == 8);
+ REQUIRE(modules.size() == 9);
REQUIRE(modules.at(0).name() == "ietf-yang-metadata");
REQUIRE(modules.at(0).ns() == "urn:ietf:params:xml:ns:yang:ietf-yang-metadata");
REQUIRE(modules.at(1).name() == "yang");
REQUIRE(modules.at(1).ns() == "urn:ietf:params:xml:ns:yang:1");
- REQUIRE(modules.at(2).name() == "ietf-inet-types");
- REQUIRE(modules.at(2).ns() == "urn:ietf:params:xml:ns:yang:ietf-inet-types");
- REQUIRE(modules.at(3).name() == "ietf-yang-types");
- REQUIRE(modules.at(3).ns() == "urn:ietf:params:xml:ns:yang:ietf-yang-types");
- REQUIRE(modules.at(4).name() == "ietf-yang-schema-mount");
- REQUIRE(modules.at(4).ns() == "urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount");
- REQUIRE(modules.at(5).name() == "ietf-yang-structure-ext");
- REQUIRE(modules.at(5).ns() == "urn:ietf:params:xml:ns:yang:ietf-yang-structure-ext");
- REQUIRE(modules.at(6).name() == "mod1");
- REQUIRE(modules.at(6).ns() == "http://example.com");
- REQUIRE(*modules.at(6).revision() == "2021-11-15");
- REQUIRE(modules.at(7).name() == "test");
+ REQUIRE(modules.at(2).name() == "default");
+ REQUIRE(modules.at(2).ns() == "urn:ietf:params:xml:ns:netconf:default:1.0");
+ REQUIRE(modules.at(3).name() == "ietf-inet-types");
+ REQUIRE(modules.at(3).ns() == "urn:ietf:params:xml:ns:yang:ietf-inet-types");
+ REQUIRE(modules.at(4).name() == "ietf-yang-types");
+ REQUIRE(modules.at(4).ns() == "urn:ietf:params:xml:ns:yang:ietf-yang-types");
+ REQUIRE(modules.at(5).name() == "ietf-yang-schema-mount");
+ REQUIRE(modules.at(5).ns() == "urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount");
+ REQUIRE(modules.at(6).name() == "ietf-yang-structure-ext");
+ REQUIRE(modules.at(6).ns() == "urn:ietf:params:xml:ns:yang:ietf-yang-structure-ext");
+ REQUIRE(modules.at(7).name() == "mod1");
REQUIRE(modules.at(7).ns() == "http://example.com");
- REQUIRE(modules.at(7).revision() == std::nullopt);
+ REQUIRE(*modules.at(7).revision() == "2021-11-15");
+ REQUIRE(modules.at(8).name() == "test");
+ REQUIRE(modules.at(8).ns() == "http://example.com");
+ REQUIRE(modules.at(8).revision() == std::nullopt);
}
DOCTEST_SUBCASE("Module comparison")
@@ -704,7 +706,7 @@ TEST_CASE("context")
DOCTEST_SUBCASE("schema printing")
{
- std::optional<libyang::Context> ctx_pp{std::in_place, std::nullopt, libyang::ContextOptions::NoYangLibrary | libyang::ContextOptions::DisableSearchCwd | libyang::ContextOptions::SetPrivParsed};
+ std::optional<libyang::Context> ctx_pp{std::in_place, std::nullopt, libyang::ContextOptions::NoYangLibrary | libyang::ContextOptions::DisableSearchCwd | libyang::ContextOptions::SetPrivParsed | libyang::ContextOptions::CompileObsolete};
auto mod = ctx_pp->parseModule(type_module, libyang::SchemaFormat::YANG);
REQUIRE(mod.printStr(libyang::SchemaOutputFormat::Tree) == R"(module: type_module
diff --git a/tests/data_node.cpp b/tests/data_node.cpp
index 9215b12..88ca5b9 100644
--- a/tests/data_node.cpp
+++ b/tests/data_node.cpp
@@ -2426,7 +2426,7 @@ TEST_CASE("Data Node manipulation")
"WTF": "foo bar baz"
}
}
- )", libyang::DataFormat::JSON, libyang::OperationType::RpcRestconf),
+ )", libyang::DataFormat::JSON, libyang::OperationType::RpcRestconf, libyang::ParseOptions::Strict),
"Can't parse into operation data tree: LY_EVALID", libyang::Error);
}
}
diff --git a/tests/schema_node.cpp b/tests/schema_node.cpp
index 65ef462..58152a4 100644
--- a/tests/schema_node.cpp
+++ b/tests/schema_node.cpp
@@ -19,7 +19,7 @@ using namespace std::string_literals;
TEST_CASE("SchemaNode")
{
std::optional<libyang::Context> ctx{std::in_place, std::nullopt,
- libyang::ContextOptions::NoYangLibrary | libyang::ContextOptions::DisableSearchCwd};
+ libyang::ContextOptions::NoYangLibrary | libyang::ContextOptions::DisableSearchCwd | libyang::ContextOptions::CompileObsolete};
std::optional<libyang::Context> ctxWithParsed{std::in_place, std::nullopt,
libyang::ContextOptions::SetPrivParsed | libyang::ContextOptions::NoYangLibrary | libyang::ContextOptions::DisableSearchCwd};
ctx->parseModule(example_schema, libyang::SchemaFormat::YANG);
@@ -841,7 +841,7 @@ TEST_CASE("SchemaNode")
DOCTEST_SUBCASE("LeafList::defaultValuesStr")
{
- REQUIRE(ctx->findPath("/type_module:leafListWithDefault").asLeafList().defaultValuesStr() == std::vector<std::string>{"-1", "512", "1024", "2048"});
+ REQUIRE(ctx->findPath("/type_module:leafListWithDefault").asLeafList().defaultValuesStr() == std::vector<std::string>{"-1", "+512", "0x400", "04000"});
REQUIRE(ctx->findPath("/type_module:leafListBasic").asLeafList().defaultValuesStr().size() == 0);
}
--
2.43.0
@@ -0,0 +1,77 @@
From 51d7457bd281e34bac92ff8231978766c7784657 Mon Sep 17 00:00:00 2001
From: Martin Bohal <mb@mbohal.cz>
Date: Tue, 4 Nov 2025 14:26:05 +0100
Subject: [PATCH 5/7] Add SchemaNode::isOutput() method
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Wires
This commit introduces the `isOutput()` method to the `SchemaNode`
class, which checks whether the schema node is part of an output
statement subtree.
It complements an already existing `isInput()` method.
Change-Id: I8fe75f2e607c0159d8295d685a59d301155ca92e
Signed-off-by: Mattias Walström <lazzer@gmail.com>
---
include/libyang-cpp/SchemaNode.hpp | 1 +
src/SchemaNode.cpp | 10 ++++++++++
tests/schema_node.cpp | 7 +++++++
3 files changed, 18 insertions(+)
diff --git a/include/libyang-cpp/SchemaNode.hpp b/include/libyang-cpp/SchemaNode.hpp
index 9f49fd7..db5a63e 100644
--- a/include/libyang-cpp/SchemaNode.hpp
+++ b/include/libyang-cpp/SchemaNode.hpp
@@ -58,6 +58,7 @@ public:
Status status() const;
Config config() const;
bool isInput() const;
+ bool isOutput() const;
NodeType nodeType() const;
// It is possible to cast SchemaNode to another type via the following methods. The types are children classes of
// SchemaNode. No problems with slicing can occur, because these types are value-based and aren't constructible
diff --git a/src/SchemaNode.cpp b/src/SchemaNode.cpp
index 2e0351a..9241b23 100644
--- a/src/SchemaNode.cpp
+++ b/src/SchemaNode.cpp
@@ -193,6 +193,16 @@ bool SchemaNode::isInput() const
return m_node->flags & LYS_INPUT;
}
+/**
+ * @brief Checks whether this node is inside a subtree of an output statement.
+ *
+ * Wraps `LYS_OUTPUT`.
+ */
+bool SchemaNode::isOutput() const
+{
+ return m_node->flags & LYS_OUTPUT;
+}
+
/**
* Returns the node type of this node (e.g. leaf, container...).
*
diff --git a/tests/schema_node.cpp b/tests/schema_node.cpp
index 58152a4..01c2f19 100644
--- a/tests/schema_node.cpp
+++ b/tests/schema_node.cpp
@@ -135,6 +135,13 @@ TEST_CASE("SchemaNode")
REQUIRE(!ctx->findPath("/type_module:leafString").isInput());
}
+ DOCTEST_SUBCASE("SchemaNode::isOutput")
+ {
+ REQUIRE(ctx->findPath("/example-schema:myRpc/outputLeaf", libyang::InputOutputNodes::Output).isOutput());
+ REQUIRE(!ctx->findPath("/example-schema:myRpc/inputLeaf").isOutput());
+ REQUIRE(!ctx->findPath("/type_module:leafString").isOutput());
+ }
+
DOCTEST_SUBCASE("SchemaNode::module")
{
REQUIRE(ctx->findPath("/type_module:leafString").module().name() == "type_module");
--
2.43.0
@@ -0,0 +1,364 @@
From 38d5c10009df602594e1b9a53bac41111a9ba430 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= <jan.kundrat@cesnet.cz>
Date: Thu, 20 Nov 2025 15:32:03 +0100
Subject: [PATCH 6/7] adapt to changes in libyang v4.2
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Wires
I was *so* tempted to leave the C++ enums as-is, just to save us from
this needless sed exercise, but hey, let's not start confusing any
possible downstream consumers now that upstream has changed these
identifiers.
Change-Id: I9b34585822b41be0ca1578051f1c0eb8588a0a51
Signed-off-by: Mattias Walström <lazzer@gmail.com>
---
CMakeLists.txt | 4 +--
README.md | 2 +-
include/libyang-cpp/Enum.hpp | 4 +--
src/utils/enum.hpp | 4 +--
tests/context.cpp | 10 +++----
tests/data_node.cpp | 58 ++++++++++++++++++------------------
6 files changed, 41 insertions(+), 41 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 90f9aaa..cbaf82a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,7 +20,7 @@ add_custom_target(libyang-cpp-version-cmake
cmake/ProjectGitVersionRunner.cmake
)
include(cmake/ProjectGitVersion.cmake)
-set(LIBYANG_CPP_PKG_VERSION "5")
+set(LIBYANG_CPP_PKG_VERSION "6")
prepare_git_version(LIBYANG_CPP_VERSION ${LIBYANG_CPP_PKG_VERSION})
find_package(Doxygen)
@@ -28,7 +28,7 @@ option(WITH_DOCS "Create and install internal documentation (needs Doxygen)" ${D
option(BUILD_SHARED_LIBS "By default, shared libs are enabled. Turn off for a static build." ON)
find_package(PkgConfig REQUIRED)
-pkg_check_modules(LIBYANG REQUIRED libyang>=4.1.0 IMPORTED_TARGET)
+pkg_check_modules(LIBYANG REQUIRED libyang>=4.2.1 IMPORTED_TARGET)
# FIXME from gcc 14.1 on we should be able to use the calendar/time from libstdc++ and thus remove the date dependency
find_package(date)
diff --git a/README.md b/README.md
index 0cef2ff..842573f 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
Object lifetimes are managed automatically via RAII.
## Dependencies
-- [libyang v4](https://github.com/CESNET/libyang) - the `devel` branch (even for the `master` branch of *libyang-cpp*)
+- [libyang v4.2+](https://github.com/CESNET/libyang) - the `devel` branch (even for the `master` branch of *libyang-cpp*)
- C++20 compiler (e.g., GCC 10.x+, clang 10+)
- CMake 3.19+
- optionally for built-in tests, [Doctest](https://github.com/doctest/doctest/) as a C++ unit test framework
diff --git a/include/libyang-cpp/Enum.hpp b/include/libyang-cpp/Enum.hpp
index 32142f9..096e030 100644
--- a/include/libyang-cpp/Enum.hpp
+++ b/include/libyang-cpp/Enum.hpp
@@ -67,9 +67,9 @@ enum class OperationType : uint32_t {
*/
enum class PrintFlags : uint32_t {
WithDefaultsExplicit = 0x00,
- WithSiblings = 0x01,
+ Siblings = 0x01,
Shrink = 0x02,
- KeepEmptyCont = 0x04,
+ EmptyContainers = 0x04,
WithDefaultsTrim = 0x10,
WithDefaultsAll = 0x20,
WithDefaultsAllTag = 0x40,
diff --git a/src/utils/enum.hpp b/src/utils/enum.hpp
index 0b2e2d7..a8902ff 100644
--- a/src/utils/enum.hpp
+++ b/src/utils/enum.hpp
@@ -33,7 +33,7 @@ constexpr uint32_t toPrintFlags(const PrintFlags flags)
}
// These tests ensure that I used the right numbers when defining my enum.
// TODO: add asserts for operator|(PrintFlags, PrintFlags)
-static_assert(LYD_PRINT_KEEPEMPTYCONT == toPrintFlags(PrintFlags::KeepEmptyCont));
+static_assert(LYD_PRINT_EMPTY_CONT == toPrintFlags(PrintFlags::EmptyContainers));
static_assert(LYD_PRINT_SHRINK == toPrintFlags(PrintFlags::Shrink));
static_assert(LYD_PRINT_WD_ALL == toPrintFlags(PrintFlags::WithDefaultsAll));
static_assert(LYD_PRINT_WD_ALL_TAG == toPrintFlags(PrintFlags::WithDefaultsAllTag));
@@ -41,7 +41,7 @@ static_assert(LYD_PRINT_WD_EXPLICIT == toPrintFlags(PrintFlags::WithDefaultsExpl
static_assert(LYD_PRINT_WD_IMPL_TAG == toPrintFlags(PrintFlags::WithDefaultsImplicitTag));
static_assert(LYD_PRINT_WD_MASK == toPrintFlags(PrintFlags::WithDefaultsMask));
static_assert(LYD_PRINT_WD_TRIM == toPrintFlags(PrintFlags::WithDefaultsTrim));
-static_assert(LYD_PRINT_WITHSIBLINGS == toPrintFlags(PrintFlags::WithSiblings));
+static_assert(LYD_PRINT_SIBLINGS == toPrintFlags(PrintFlags::Siblings));
#ifndef _MSC_VER
// MSVC doesn't respect the underlying enum size
diff --git a/tests/context.cpp b/tests/context.cpp
index eaedebf..355860b 100644
--- a/tests/context.cpp
+++ b/tests/context.cpp
@@ -502,7 +502,7 @@ TEST_CASE("context")
auto errorsNode = node->findXPath("/ietf-restconf:errors");
REQUIRE(errorsNode.size() == 1);
REQUIRE(errorsNode.begin()->path() == "/ietf-restconf:errors");
- REQUIRE(*errorsNode.begin()->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings | libyang::PrintFlags::KeepEmptyCont) == R"({
+ REQUIRE(*errorsNode.begin()->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings | libyang::PrintFlags::EmptyContainers) == R"({
"ietf-restconf:errors": {
"error": [
{
@@ -589,7 +589,7 @@ TEST_CASE("context")
auto firstValue = edits.begin()->findPath("value");
REQUIRE(firstValue);
- REQUIRE(*firstValue->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::KeepEmptyCont) == R"({
+ REQUIRE(*firstValue->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::EmptyContainers) == R"({
"ietf-yang-patch:value": {
"example-schema:person": {
"name": "John"
@@ -597,7 +597,7 @@ TEST_CASE("context")
}
}
)");
- REQUIRE(*firstValue->printStr(libyang::DataFormat::XML, libyang::PrintFlags::KeepEmptyCont) == R"(<value xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-patch">
+ REQUIRE(*firstValue->printStr(libyang::DataFormat::XML, libyang::PrintFlags::EmptyContainers) == R"(<value xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-patch">
<person xmlns="http://example.com/coze">
<name>John</name>
</person>
@@ -607,8 +607,8 @@ TEST_CASE("context")
auto secondValueNode = (edits.begin() + 1)->findPath("value");
REQUIRE(secondValueNode);
auto secondValue = std::get<libyang::DataNode>(secondValueNode->asAny().releaseValue().value());
- REQUIRE(*secondValue.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::KeepEmptyCont) == "{\n \"example-schema:dummy\": \"I am a dummy\"\n}\n");
- REQUIRE(*secondValue.printStr(libyang::DataFormat::XML, libyang::PrintFlags::KeepEmptyCont) == "<dummy xmlns=\"http://example.com/coze\">I am a dummy</dummy>\n");
+ REQUIRE(*secondValue.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::EmptyContainers) == "{\n \"example-schema:dummy\": \"I am a dummy\"\n}\n");
+ REQUIRE(*secondValue.printStr(libyang::DataFormat::XML, libyang::PrintFlags::EmptyContainers) == "<dummy xmlns=\"http://example.com/coze\">I am a dummy</dummy>\n");
}
}
diff --git a/tests/data_node.cpp b/tests/data_node.cpp
index 88ca5b9..3f874de 100644
--- a/tests/data_node.cpp
+++ b/tests/data_node.cpp
@@ -137,7 +137,7 @@ TEST_CASE("Data Node manipulation")
DOCTEST_SUBCASE("Printing")
{
auto node = ctx.parseData(data, libyang::DataFormat::JSON);
- auto str = node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings | libyang::PrintFlags::KeepEmptyCont);
+ auto str = node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings | libyang::PrintFlags::EmptyContainers);
const auto expected = R"({
"example-schema:leafInt32": 420,
"example-schema:first": {
@@ -158,7 +158,7 @@ TEST_CASE("Data Node manipulation")
REQUIRE(str == expected);
auto emptyCont = ctx.newPath("/example-schema:first");
- REQUIRE(emptyCont.printStr(libyang::DataFormat::XML, libyang::PrintFlags::WithSiblings) == std::nullopt);
+ REQUIRE(emptyCont.printStr(libyang::DataFormat::XML, libyang::PrintFlags::Siblings) == std::nullopt);
}
DOCTEST_SUBCASE("Overwriting a tree with a different tree")
@@ -504,7 +504,7 @@ TEST_CASE("Data Node manipulation")
{
auto node = std::optional{ctx.newPath("/example-schema:leafInt32", "420")};
libyang::validateAll(node, libyang::ValidationOptions::NoState);
- auto str = node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings | libyang::PrintFlags::KeepEmptyCont);
+ auto str = node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings | libyang::PrintFlags::EmptyContainers);
REQUIRE(str == data);
}
@@ -725,7 +725,7 @@ TEST_CASE("Data Node manipulation")
}
// The original tree should still be accesible.
- node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings);
+ node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings);
}
}
@@ -855,7 +855,7 @@ TEST_CASE("Data Node manipulation")
auto cont = ctx.newPath2("/example-schema2:contWithTwoNodes").createdNode;
data->unlinkWithSiblings();
cont->insertChild(*data);
- REQUIRE(*cont->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings) == R"({
+ REQUIRE(*cont->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings) == R"({
"example-schema2:contWithTwoNodes": {
"one": 333,
"two": 666
@@ -1501,9 +1501,9 @@ TEST_CASE("Data Node manipulation")
REQUIRE(std::holds_alternative<libyang::DataNode>(rawVal));
auto retrieved = std::get<libyang::DataNode>(rawVal);
REQUIRE(retrieved.path() == "/key");
- REQUIRE(*retrieved.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*retrieved.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== R"|({"key":"value"})|");
- REQUIRE(*retrieved.printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*retrieved.printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== R"|(<key>value</key>)|");
}
}
@@ -1525,9 +1525,9 @@ TEST_CASE("Data Node manipulation")
REQUIRE(std::holds_alternative<libyang::DataNode>(rawVal));
auto retrieved = std::get<libyang::DataNode>(rawVal);
REQUIRE(retrieved.path() == "/something");
- REQUIRE(*retrieved.printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*retrieved.printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== R"|(<something>lol</something>)|");
- REQUIRE(*retrieved.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*retrieved.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== R"|({"something":"lol"})|");
}
}
@@ -1572,9 +1572,9 @@ TEST_CASE("Data Node manipulation")
val = jsonAnyXmlNode.createdNode->asAny().releaseValue();
}
- REQUIRE(*jsonAnyXmlNode.createdNode->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*jsonAnyXmlNode.createdNode->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== R"|({"example-schema:ax":[1,2,3]})|"s);
- REQUIRE(*jsonAnyXmlNode.createdNode->printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*jsonAnyXmlNode.createdNode->printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== R"|(<ax xmlns="http://example.com/coze">)|"s + origJSON + "</ax>");
}
@@ -1603,9 +1603,9 @@ TEST_CASE("Data Node manipulation")
}
REQUIRE(root);
- REQUIRE(*root->printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*root->printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== origXML);
- REQUIRE(*root->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*root->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== origJSON);
auto node = root->findPath("/example-schema:ax");
@@ -1665,9 +1665,9 @@ TEST_CASE("Data Node manipulation")
auto retrieved = std::get<libyang::DataNode>(*val);
val.reset();
REQUIRE(retrieved.path() == "/a");
- REQUIRE(*retrieved.printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*retrieved.printStr(libyang::DataFormat::XML, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== origXML);
- REQUIRE(*retrieved.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::WithSiblings)
+ REQUIRE(*retrieved.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Shrink | libyang::PrintFlags::Siblings)
== origJSON);
}
}
@@ -1806,7 +1806,7 @@ TEST_CASE("Data Node manipulation")
nodeX.parseSubtree(data, libyang::DataFormat::JSON,
libyang::ParseOptions::Strict | libyang::ParseOptions::NoState | libyang::ParseOptions::ParseOnly);
- REQUIRE(*nodeX.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings) == R"({
+ REQUIRE(*nodeX.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings) == R"({
"example-schema5:x": {
"x_b": {
"x_b_leaf": 666
@@ -1948,7 +1948,7 @@ TEST_CASE("Data Node manipulation")
{
netconfDeletePresenceCont.newMeta(netconf, "operation", "delete");
netconfDeletePresenceCont.newMeta(ietfOrigin, "origin", "ietf-origin:default");
- REQUIRE(*netconfDeletePresenceCont.printStr(libyang::DataFormat::XML, libyang::PrintFlags::WithSiblings)
+ REQUIRE(*netconfDeletePresenceCont.printStr(libyang::DataFormat::XML, libyang::PrintFlags::Siblings)
== R"(<presenceContainer xmlns="http://example.com/coze" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete" xmlns:or="urn:ietf:params:xml:ns:yang:ietf-origin" or:origin="or:default"/>)" "\n");
}
@@ -1957,7 +1957,7 @@ TEST_CASE("Data Node manipulation")
auto opaqueLeaf = ctx.newPath("/example-schema:leafInt32", std::nullopt, libyang::CreationOptions::Opaque);
REQUIRE_THROWS(opaqueLeaf.newMeta(netconf, "operation", "delete"));
opaqueLeaf.newAttrOpaqueJSON("ietf-netconf", "operation", "delete");
- REQUIRE(*opaqueLeaf.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings)
+ REQUIRE(*opaqueLeaf.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings)
== R"({
"example-schema:leafInt32": "",
"@example-schema:leafInt32": {
@@ -1976,7 +1976,7 @@ TEST_CASE("Data Node manipulation")
auto discard2 = ctx.newOpaqueJSON(libyang::OpaqueName{"sysrepo", "sysrepo", "discard-items"}, libyang::JSON{"/example-schema:b"});
REQUIRE(!!discard2);
discard1->insertSibling(*discard2);
- REQUIRE(*discard1->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings)
+ REQUIRE(*discard1->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings)
== R"({
"sysrepo:discard-items": "/example-schema:a",
"sysrepo:discard-items": "/example-schema:b"
@@ -1991,7 +1991,7 @@ TEST_CASE("Data Node manipulation")
auto leafInt16 = ctx.newPath("/example-schema:leafInt16", "666");
leafInt16.insertSibling(*discard1);
- REQUIRE(*discard1->firstSibling().printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings)
+ REQUIRE(*discard1->firstSibling().printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings)
== R"({
"example-schema:leafInt16": 666,
"sysrepo:discard-items": "/example-schema:a",
@@ -2020,7 +2020,7 @@ TEST_CASE("Data Node manipulation")
dummy.insertSibling(*discard3);
leafInt16.insertSibling(dummy);
- REQUIRE(*discard1->firstSibling().printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings)
+ REQUIRE(*discard1->firstSibling().printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings)
== R"({
"example-schema:dummy": "blah",
"example-schema:leafInt16": 666,
@@ -2112,8 +2112,8 @@ TEST_CASE("Data Node manipulation")
data->unlinkWithSiblings();
out->insertChild(*data);
- REQUIRE(*out->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings) == expectedJson);
- REQUIRE(*out->printStr(libyang::DataFormat::XML, libyang::PrintFlags::WithSiblings) == expectedXml);
+ REQUIRE(*out->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings) == expectedJson);
+ REQUIRE(*out->printStr(libyang::DataFormat::XML, libyang::PrintFlags::Siblings) == expectedXml);
}
DOCTEST_SUBCASE("libyang internal metadata")
@@ -2148,7 +2148,7 @@ TEST_CASE("Data Node manipulation")
auto node = ctx.newExtPath(ext, "/ietf-restconf:errors", std::nullopt, std::nullopt);
REQUIRE(node);
REQUIRE(node->schema().name() == "errors");
- REQUIRE(*node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings | libyang::PrintFlags::KeepEmptyCont) == R"({
+ REQUIRE(*node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings | libyang::PrintFlags::EmptyContainers) == R"({
"ietf-restconf:errors": {}
}
)");
@@ -2157,7 +2157,7 @@ TEST_CASE("Data Node manipulation")
REQUIRE(node->newPath("ietf-restconf:error[1]/error-tag", "invalid-attribute"));
REQUIRE(node->newExtPath(ext, "/ietf-restconf:errors/error[1]/error-message", "ahoj"));
REQUIRE_THROWS_WITH(node->newPath("ietf-restconf:error[1]/error-message", "duplicate create"), "Couldn't create a node with path 'ietf-restconf:error[1]/error-message': LY_EEXIST");
- REQUIRE(*node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings | libyang::PrintFlags::KeepEmptyCont) == R"({
+ REQUIRE(*node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings | libyang::PrintFlags::EmptyContainers) == R"({
"ietf-restconf:errors": {
"error": [
{
@@ -2173,7 +2173,7 @@ TEST_CASE("Data Node manipulation")
REQUIRE(node->newExtPath(ext, "/ietf-restconf:errors/error[2]/error-type", "transport"));
REQUIRE(node->newExtPath(ext, "/ietf-restconf:errors/error[2]/error-tag", "invalid-attribute"));
REQUIRE(node->newPath("ietf-restconf:error[2]/error-message", "aaa"));
- REQUIRE(*node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings | libyang::PrintFlags::KeepEmptyCont) == R"({
+ REQUIRE(*node->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings | libyang::PrintFlags::EmptyContainers) == R"({
"ietf-restconf:errors": {
"error": [
{
@@ -2397,8 +2397,8 @@ TEST_CASE("Data Node manipulation")
REQUIRE(response.tree->path() == "/example-schema:output");
REQUIRE(response.tree->isOpaque());
REQUIRE(!response.tree->child()); // nothing gets "parsed" here, the result is put into the tree that parseOp() operated on (!)
- CAPTURE(*response.tree->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings | libyang::PrintFlags::KeepEmptyCont));
- CAPTURE(*replyTree.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::WithSiblings | libyang::PrintFlags::KeepEmptyCont));
+ CAPTURE(*response.tree->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings | libyang::PrintFlags::EmptyContainers));
+ CAPTURE(*replyTree.printStr(libyang::DataFormat::JSON, libyang::PrintFlags::Siblings | libyang::PrintFlags::EmptyContainers));
node = replyTree.findPath("/example-schema:myRpc/outputLeaf", libyang::InputOutputNodes::Output);
REQUIRE(!!node);
@@ -2472,7 +2472,7 @@ TEST_CASE("Data Node manipulation")
REQUIRE(rpcOp.tree);
libyang::validateOp(*rpcTree, depTree, libyang::OperationType::RpcRestconf);
- REQUIRE(*rpcTree->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::KeepEmptyCont) == expected);
+ REQUIRE(*rpcTree->printStr(libyang::DataFormat::JSON, libyang::PrintFlags::EmptyContainers) == expected);
}
DOCTEST_SUBCASE("Nodes in disjunctive cases defined together")
--
2.43.0
@@ -0,0 +1,112 @@
From af187d1bc27a7390b358d7ad3b9f8f44cabe41ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= <jan.kundrat@cesnet.cz>
Date: Thu, 20 Nov 2025 12:46:49 +0100
Subject: [PATCH 7/7] don't segfault when listing module's features
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Wires
This is especially relevant when working with the "printed context" from
sysrepo, because that context has all the parsed info removed. As a
result, it is not possible to query a module's list of features. Let's
stop dereferencing a null pointer in that case.
Bug: https://github.com/sysrepo/sysrepo/issues/3695
Change-Id: I6258f580b4e5aa02cae2d60260b84593aefcf587
Signed-off-by: Mattias Walström <lazzer@gmail.com>
---
CMakeLists.txt | 1 +
include/libyang-cpp/Utils.hpp | 1 +
src/Module.cpp | 3 +++
src/utils/exception.cpp | 5 +++++
tests/context.cpp | 12 ++++++++++++
5 files changed, 22 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cbaf82a..b9da66b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -118,6 +118,7 @@ if(BUILD_TESTING)
endfunction()
libyang_cpp_test(context)
+ target_link_libraries(test_context PkgConfig::LIBYANG)
libyang_cpp_test(data_node)
target_link_libraries(test_data_node PkgConfig::LIBYANG)
libyang_cpp_test(schema_node)
diff --git a/include/libyang-cpp/Utils.hpp b/include/libyang-cpp/Utils.hpp
index 934714d..428b265 100644
--- a/include/libyang-cpp/Utils.hpp
+++ b/include/libyang-cpp/Utils.hpp
@@ -35,6 +35,7 @@ public:
class LIBYANG_CPP_EXPORT ParsedInfoUnavailable : public Error {
public:
explicit ParsedInfoUnavailable();
+ explicit ParsedInfoUnavailable(const std::string& what);
};
/**
diff --git a/src/Module.cpp b/src/Module.cpp
index d6d4023..8eb8fb4 100644
--- a/src/Module.cpp
+++ b/src/Module.cpp
@@ -155,6 +155,9 @@ void Module::setImplemented(const AllFeatures)
*/
std::vector<Feature> Module::features() const
{
+ if (!m_module->parsed) {
+ throw ParsedInfoUnavailable{"Module::features: lys_module::parsed is not available"};
+ }
std::vector<Feature> res;
for (const auto& feature : std::span(m_module->parsed->features, LY_ARRAY_COUNT(m_module->parsed->features))) {
res.emplace_back(Feature{&feature, m_ctx});
diff --git a/src/utils/exception.cpp b/src/utils/exception.cpp
index ecd2b85..a8d908b 100644
--- a/src/utils/exception.cpp
+++ b/src/utils/exception.cpp
@@ -22,6 +22,11 @@ ParsedInfoUnavailable::ParsedInfoUnavailable()
{
}
+ParsedInfoUnavailable::ParsedInfoUnavailable(const std::string& what)
+ : Error(what)
+{
+}
+
ErrorCode ErrorWithCode::code() const
{
return m_errCode;
diff --git a/tests/context.cpp b/tests/context.cpp
index 355860b..5fce0f4 100644
--- a/tests/context.cpp
+++ b/tests/context.cpp
@@ -10,6 +10,7 @@
#include <fstream>
#include <libyang-cpp/Context.hpp>
#include <libyang-cpp/Utils.hpp>
+#include <libyang/context.h>
#include "example_schema.hpp"
#include "pretty_printers.hpp"
#include "test_vars.hpp"
@@ -333,6 +334,17 @@ TEST_CASE("context")
REQUIRE(enabledFeatures == expectedEnabledFeatures);
}
+ DOCTEST_SUBCASE("printed context")
+ {
+ ctx->setSearchDir(TESTS_DIR / "yang");
+ auto mod = ctx->loadModule("mod1", std::nullopt, {"*"});
+ REQUIRE(mod.features().size() == 3);
+ ly_ctx_free_parsed(retrieveContext(*ctx));
+ REQUIRE_THROWS_WITH_AS(mod.features(),
+ "Module::features: lys_module::parsed is not available",
+ libyang::ParsedInfoUnavailable);
+ }
+
DOCTEST_SUBCASE("Module::setImplemented")
{
ctx->setSearchDir(TESTS_DIR / "yang");
--
2.43.0
+15
View File
@@ -0,0 +1,15 @@
menuconfig BR2_PACKAGE_ONIEPROM
bool "onieprom"
select BR2_PACKAGE_HOST_PYTHON3
help
ONIE EEPROM parser/generator
config BR2_PACKAGE_ONIEPROM_INSTALL_IMAGES
bool "install onieprom in images"
depends on BR2_PACKAGE_ONIEPROM
default y
help
Install the onieprom script in the images direcory. Useful
when the release is destined for someone who will have to
create ONIE EEPROM binaries for deployment during
manufacturing.
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
PYTHONPATH=$(readlink -f $(dirname $0)/..) \
exec python3 -m onieprom "$@"
+15
View File
@@ -0,0 +1,15 @@
ONIEPROM_VERSION = 1.0
ONIEPROM_SITE_METHOD = local
ONIEPROM_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/onieprom
ONIEPROM_LICENSE = GPLv2
ONIEPROM_LICENSE_FILES = COPYING
ONIEPROM_DEPENDENCIES = host-python3 python3 host-python-poetry-core
ONIEPROM_SETUP_TYPE = pep517 # poetry
ONIEPROM_INSTALL_IMAGES = $(if $(BR2_PACKAGE_ONIEPROM_INSTALL_IMAGES),YES,NO)
define ONIEPROM_INSTALL_IMAGES_CMDS
@cp -a $(@D)/onieprom $(BINARIES_DIR)/onieprom
@cp $(ONIEPROM_PKGDIR)/onieprom $(BINARIES_DIR)/onieprom/
endef
$(eval $(python-package))
+1 -1
View File
@@ -1,5 +1,5 @@
# md5, sha256 from https://pypi.org/pypi/libyang/json
md5 46332891cac852441b523f7e71a507f7 libyang-3.0.1.tar.gz
sha256 57f8b234131fb073518313351288194e535d74cc8fdff7f0ff7e31c0ab33e663 libyang-3.0.1.tar.gz
sha256 97da2c908a8a3607ac834f2acec224ea53a4b9e9770c13e5598513641decf637 libyang-3.3.0.tar.gz
# Locally computed sha256 checksums
sha256 c8d554f918d32b1467f35829e1cfb753764dd683c6edcecc877a4d7e9f05b2a7 LICENSE
+2 -2
View File
@@ -4,9 +4,9 @@
#
################################################################################
PYTHON_LIBYANG_VERSION = 3.0.1
PYTHON_LIBYANG_VERSION = 3.3.0
PYTHON_LIBYANG_SOURCE = libyang-$(PYTHON_LIBYANG_VERSION).tar.gz
PYTHON_LIBYANG_SITE = https://files.pythonhosted.org/packages/91/2e/ff13ee16c874d232d5d3fdff83f629cbc9ac47f9aaf2b59256b6a1bdbc16
PYTHON_LIBYANG_SITE = https://files.pythonhosted.org/packages/34/d8/ebe9de6d29eaf62a684b34d30118294e48a05d7fbd1bb0af002b7627140d
PYTHON_LIBYANG_SETUP_TYPE = setuptools
PYTHON_LIBYANG_LICENSE = MIT
PYTHON_LIBYANG_LICENSE_FILES = LICENSE

Some files were not shown because too many files have changed in this diff Show More