From 389e0c5f92fbd6f8bc72802dcbaad6778c2c3bf9 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 19 Jan 2026 16:49:40 +0100 Subject: [PATCH 01/29] package/feature-wifi: enable more realtek dongles Signed-off-by: Joachim Wiberg --- package/feature-wifi/Config.in | 1 + package/feature-wifi/feature-wifi.mk | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/package/feature-wifi/Config.in b/package/feature-wifi/Config.in index 946e22388..bbf293f30 100644 --- a/package/feature-wifi/Config.in +++ b/package/feature-wifi/Config.in @@ -18,6 +18,7 @@ config BR2_PACKAGE_FEATURE_WIFI_DONGLE_REALTEK bool "Realtek USB WiFi Dongles" depends on BR2_PACKAGE_FEATURE_WIFI select BR2_PACKAGE_LINUX_FIRMWARE + select BR2_PACKAGE_LINUX_FIRMWARE_RTL_81XX select BR2_PACKAGE_LINUX_FIRMWARE_RTL_RTW88 select BR2_PACKAGE_LINUX_FIRMWARE_RTL_RTW89 help diff --git a/package/feature-wifi/feature-wifi.mk b/package/feature-wifi/feature-wifi.mk index 90d5bdd3a..07e665f48 100644 --- a/package/feature-wifi/feature-wifi.mk +++ b/package/feature-wifi/feature-wifi.mk @@ -15,8 +15,9 @@ define FEATURE_WIFI_LINUX_CONFIG_FIXUPS $(if $(filter y,$(BR2_PACKAGE_FEATURE_WIFI_DONGLE_REALTEK)), $(call KCONFIG_ENABLE_OPT,CONFIG_WLAN_VENDOR_REALTEK) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTL8XXXU) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTL8XXXU_UNTESTED) $(call KCONFIG_ENABLE_OPT,CONFIG_RTW88) - $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89) $(call KCONFIG_ENABLE_OPT,CONFIG_RTW88_8703B) $(call KCONFIG_ENABLE_OPT,CONFIG_RTW88_8723CS) $(call KCONFIG_ENABLE_OPT,CONFIG_RTW88_8723D) @@ -35,6 +36,14 @@ define FEATURE_WIFI_LINUX_CONFIG_FIXUPS $(call KCONFIG_ENABLE_OPT,CONFIG_RTW88_8822C) $(call KCONFIG_ENABLE_OPT,CONFIG_RTW88_8822CU) $(call KCONFIG_ENABLE_OPT,CONFIG_RTW88_8822CE) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89_8851BE) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89_8852AE) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89_8852BE) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89_8852BTE) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89_8852CE) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89_8922AE) + $(call KCONFIG_ENABLE_OPT,CONFIG_RTW89_DEBUGMSG) ) endef From f5c6ac3905ed20c269f00195b59aad96fec7761d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 17:46:59 +0100 Subject: [PATCH 02/29] package/klish: bump for new command line mark/kill and quote chars Signed-off-by: Joachim Wiberg --- doc/cli/keybindings.md | 7 ++++++- package/klish/klish.hash | 2 +- package/klish/klish.mk | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/cli/keybindings.md b/doc/cli/keybindings.md index db5b2b0c2..cc85fbcd8 100644 --- a/doc/cli/keybindings.md +++ b/doc/cli/keybindings.md @@ -16,16 +16,21 @@ CLI has several keybindings, most significant first: | Meta-b | Ctrl-Left | Move cursor back one word | | Ctrl-e | End | Move cursor to end of line | | Ctrl-a | Home | Move cursor to beginning of line | +| Ctrl-@ | Ctrl-Space | Mark current position for region operations | +| Meta w | | Copy region to kill buffer without deleting | | Ctrl-k | | Kill (cut) text from cursor to end of line | | Ctrl-u | | Delete (cut) entire line | | Ctrl-y | | Yank (paste) from kill buffer to cursor | | Meta-. | | Yank (paste) last argument from previous line | -| Ctrl-w | Meta-Backspace | Delete (cut) word to the left | +| Ctrl-w | | Kill region if mark set, else kill word backward | +| | Meta-Backspace | Delete (cut) word to the left | | | Meta-Delete | Delete (cut) word to the right | | Ctrl-l | | Clear screen and refresh current line | | Ctrl-p | Up arrow | History, previous command | | Ctrl-n | Down arrow | History, next command | +| Ctrl-q | Ctrl-v | Insert next character literally | | Ctrl-r | | History, reversed interactive search (i-search) | +| Ctrl-t | | Transpose/Swap characters before and at cursor | ## What is Meta? diff --git a/package/klish/klish.hash b/package/klish/klish.hash index 5d0796cc9..3fbd5169b 100644 --- a/package/klish/klish.hash +++ b/package/klish/klish.hash @@ -1,3 +1,3 @@ # Locally calculated sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE -sha256 4c1b6b461a805f0cf80f797f85415e0663ee371df6495641bb494bfb18829fe8 klish-7c5f1c4045d9a868dea547bd7ef0143bff5a84d7-git4.tar.gz +sha256 39a73fdaa7e41001e804e2bbdebdc885da79d540f0246777e8fd1c0dd9fc9475 klish-1c31f50ab775d467fa18f2e0a798006949536a2a-git4.tar.gz diff --git a/package/klish/klish.mk b/package/klish/klish.mk index 71ff7968c..93c86395b 100644 --- a/package/klish/klish.mk +++ b/package/klish/klish.mk @@ -4,7 +4,7 @@ # ################################################################################ -KLISH_VERSION = 7c5f1c4045d9a868dea547bd7ef0143bff5a84d7 +KLISH_VERSION = 1c31f50ab775d467fa18f2e0a798006949536a2a KLISH_SITE = https://github.com/kernelkit/klish.git #KLISH_VERSION = tags/3.0.0 #KLISH_SITE = https://src.libcode.org/pkun/klish.git From ea076e27cce9fa65d4e32718c52f69cc0ba25ad5 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 17:48:59 +0100 Subject: [PATCH 03/29] board: update static factory-config files with new nacm groups Signed-off-by: Joachim Wiberg --- .../etc/factory-config.cfg | 62 ++++++++++++++++++- .../bananapi,bpi-r3/etc/factory-config.cfg | 62 ++++++++++++++++++- .../etc/factory-config.cfg | 62 ++++++++++++++++++- .../etc/factory-config.cfg | 62 ++++++++++++++++++- 4 files changed, 236 insertions(+), 12 deletions(-) diff --git a/board/aarch32/raspberrypi-rpi2/rootfs/usr/share/product/raspberrypi,2-model-b/etc/factory-config.cfg b/board/aarch32/raspberrypi-rpi2/rootfs/usr/share/product/raspberrypi,2-model-b/etc/factory-config.cfg index fcc963b9c..a38b08c4c 100644 --- a/board/aarch32/raspberrypi-rpi2/rootfs/usr/share/product/raspberrypi,2-model-b/etc/factory-config.cfg +++ b/board/aarch32/raspberrypi-rpi2/rootfs/usr/share/product/raspberrypi,2-model-b/etc/factory-config.cfg @@ -88,6 +88,9 @@ }, "ietf-netconf-acm:nacm": { "enable-nacm": true, + "read-default": "permit", + "write-default": "permit", + "exec-default": "permit", "groups": { "group": [ { @@ -95,6 +98,14 @@ "user-name": [ "admin" ] + }, + { + "name": "operator", + "user-name": [] + }, + { + "name": "guest", + "user-name": [] } ] }, @@ -114,6 +125,37 @@ } ] }, + { + "name": "operator-acl", + "group": [ + "operator" + ], + "rule": [ + { + "name": "permit-system-rpcs", + "module-name": "ietf-system", + "rpc-name": "*", + "access-operations": "exec", + "action": "permit", + "comment": "Operators can reboot, shutdown, and set system time." + } + ] + }, + { + "name": "guest-acl", + "group": [ + "guest" + ], + "rule": [ + { + "name": "deny-all-write+exec", + "module-name": "*", + "access-operations": "create update delete exec", + "action": "deny", + "comment": "Guests cannot change anything or exec rpcs." + } + ] + }, { "name": "default-deny-all", "group": [ @@ -121,11 +163,25 @@ ], "rule": [ { - "name": "deny-password-read", - "module-name": "ietf-system", + "name": "deny-password-access", "path": "/ietf-system:system/authentication/user/password", "access-operations": "*", - "action": "deny" + "action": "deny", + "comment": "No user except admins can access password hashes." + }, + { + "name": "deny-keystore-access", + "module-name": "ietf-keystore", + "access-operations": "*", + "action": "deny", + "comment": "No user except admins can access cryptographic keys." + }, + { + "name": "deny-truststore-access", + "module-name": "ietf-truststore", + "access-operations": "*", + "action": "deny", + "comment": "No user except admins can access trust store." } ] } diff --git a/board/aarch64/bananapi-bpi-r3/rootfs/usr/share/product/bananapi,bpi-r3/etc/factory-config.cfg b/board/aarch64/bananapi-bpi-r3/rootfs/usr/share/product/bananapi,bpi-r3/etc/factory-config.cfg index 255e094e0..672a768a5 100644 --- a/board/aarch64/bananapi-bpi-r3/rootfs/usr/share/product/bananapi,bpi-r3/etc/factory-config.cfg +++ b/board/aarch64/bananapi-bpi-r3/rootfs/usr/share/product/bananapi,bpi-r3/etc/factory-config.cfg @@ -226,6 +226,9 @@ }, "ietf-netconf-acm:nacm": { "enable-nacm": true, + "read-default": "permit", + "write-default": "permit", + "exec-default": "permit", "groups": { "group": [ { @@ -233,6 +236,14 @@ "user-name": [ "admin" ] + }, + { + "name": "operator", + "user-name": [] + }, + { + "name": "guest", + "user-name": [] } ] }, @@ -252,6 +263,37 @@ } ] }, + { + "name": "operator-acl", + "group": [ + "operator" + ], + "rule": [ + { + "name": "permit-system-rpcs", + "module-name": "ietf-system", + "rpc-name": "*", + "access-operations": "exec", + "action": "permit", + "comment": "Operators can reboot, shutdown, and set system time." + } + ] + }, + { + "name": "guest-acl", + "group": [ + "guest" + ], + "rule": [ + { + "name": "deny-all-write+exec", + "module-name": "*", + "access-operations": "create update delete exec", + "action": "deny", + "comment": "Guests cannot change anything or exec rpcs." + } + ] + }, { "name": "default-deny-all", "group": [ @@ -259,11 +301,25 @@ ], "rule": [ { - "name": "deny-password-read", - "module-name": "ietf-system", + "name": "deny-password-access", "path": "/ietf-system:system/authentication/user/password", "access-operations": "*", - "action": "deny" + "action": "deny", + "comment": "No user except admins can access password hashes." + }, + { + "name": "deny-keystore-access", + "module-name": "ietf-keystore", + "access-operations": "*", + "action": "deny", + "comment": "No user except admins can access cryptographic keys." + }, + { + "name": "deny-truststore-access", + "module-name": "ietf-truststore", + "access-operations": "*", + "action": "deny", + "comment": "No user except admins can access trust store." } ] } diff --git a/board/aarch64/friendlyarm-nanopi-r2s/rootfs/usr/share/product/friendlyarm,nanopi-r2s/etc/factory-config.cfg b/board/aarch64/friendlyarm-nanopi-r2s/rootfs/usr/share/product/friendlyarm,nanopi-r2s/etc/factory-config.cfg index a76a2291e..b99a3410a 100644 --- a/board/aarch64/friendlyarm-nanopi-r2s/rootfs/usr/share/product/friendlyarm,nanopi-r2s/etc/factory-config.cfg +++ b/board/aarch64/friendlyarm-nanopi-r2s/rootfs/usr/share/product/friendlyarm,nanopi-r2s/etc/factory-config.cfg @@ -126,6 +126,9 @@ }, "ietf-netconf-acm:nacm": { "enable-nacm": true, + "read-default": "permit", + "write-default": "permit", + "exec-default": "permit", "groups": { "group": [ { @@ -133,6 +136,14 @@ "user-name": [ "admin" ] + }, + { + "name": "operator", + "user-name": [] + }, + { + "name": "guest", + "user-name": [] } ] }, @@ -152,6 +163,37 @@ } ] }, + { + "name": "operator-acl", + "group": [ + "operator" + ], + "rule": [ + { + "name": "permit-system-rpcs", + "module-name": "ietf-system", + "rpc-name": "*", + "access-operations": "exec", + "action": "permit", + "comment": "Operators can reboot, shutdown, and set system time." + } + ] + }, + { + "name": "guest-acl", + "group": [ + "guest" + ], + "rule": [ + { + "name": "deny-all-write+exec", + "module-name": "*", + "access-operations": "create update delete exec", + "action": "deny", + "comment": "Guests cannot change anything or exec rpcs." + } + ] + }, { "name": "default-deny-all", "group": [ @@ -159,11 +201,25 @@ ], "rule": [ { - "name": "deny-password-read", - "module-name": "ietf-system", + "name": "deny-password-access", "path": "/ietf-system:system/authentication/user/password", "access-operations": "*", - "action": "deny" + "action": "deny", + "comment": "No user except admins can access password hashes." + }, + { + "name": "deny-keystore-access", + "module-name": "ietf-keystore", + "access-operations": "*", + "action": "deny", + "comment": "No user except admins can access cryptographic keys." + }, + { + "name": "deny-truststore-access", + "module-name": "ietf-truststore", + "access-operations": "*", + "action": "deny", + "comment": "No user except admins can access trust store." } ] } diff --git a/board/aarch64/raspberrypi-rpi64/rootfs/usr/share/product/raspberrypi,4-model-b/etc/factory-config.cfg b/board/aarch64/raspberrypi-rpi64/rootfs/usr/share/product/raspberrypi,4-model-b/etc/factory-config.cfg index 3ad9aea0a..bcacd51a8 100644 --- a/board/aarch64/raspberrypi-rpi64/rootfs/usr/share/product/raspberrypi,4-model-b/etc/factory-config.cfg +++ b/board/aarch64/raspberrypi-rpi64/rootfs/usr/share/product/raspberrypi,4-model-b/etc/factory-config.cfg @@ -103,6 +103,9 @@ }, "ietf-netconf-acm:nacm": { "enable-nacm": true, + "read-default": "permit", + "write-default": "permit", + "exec-default": "permit", "groups": { "group": [ { @@ -110,6 +113,14 @@ "user-name": [ "admin" ] + }, + { + "name": "operator", + "user-name": [] + }, + { + "name": "guest", + "user-name": [] } ] }, @@ -129,6 +140,37 @@ } ] }, + { + "name": "operator-acl", + "group": [ + "operator" + ], + "rule": [ + { + "name": "permit-system-rpcs", + "module-name": "ietf-system", + "rpc-name": "*", + "access-operations": "exec", + "action": "permit", + "comment": "Operators can reboot, shutdown, and set system time." + } + ] + }, + { + "name": "guest-acl", + "group": [ + "guest" + ], + "rule": [ + { + "name": "deny-all-write+exec", + "module-name": "*", + "access-operations": "create update delete exec", + "action": "deny", + "comment": "Guests cannot change anything or exec rpcs." + } + ] + }, { "name": "default-deny-all", "group": [ @@ -136,11 +178,25 @@ ], "rule": [ { - "name": "deny-password-read", - "module-name": "ietf-system", + "name": "deny-password-access", "path": "/ietf-system:system/authentication/user/password", "access-operations": "*", - "action": "deny" + "action": "deny", + "comment": "No user except admins can access password hashes." + }, + { + "name": "deny-keystore-access", + "module-name": "ietf-keystore", + "access-operations": "*", + "action": "deny", + "comment": "No user except admins can access cryptographic keys." + }, + { + "name": "deny-truststore-access", + "module-name": "ietf-truststore", + "access-operations": "*", + "action": "deny", + "comment": "No user except admins can access trust store." } ] } From 08a72cfd46cc3e251dcfae31332945e6cf535f5d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 17:15:52 +0100 Subject: [PATCH 04/29] board: fix SIGTERM handling in wan-monitor at shutdown When the shell is blocked on sleep, signal handlers don't execute until the command completes. This caused the script to ignore SIGTERM at shutdown, forcing Finit to wait and eventually SIGKILL it instead. Fix by running sleep in the background and using wait, which is interruptible by signals. Signed-off-by: Joachim Wiberg --- board/aarch64/rootfs/usr/sbin/wan-monitor.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/board/aarch64/rootfs/usr/sbin/wan-monitor.sh b/board/aarch64/rootfs/usr/sbin/wan-monitor.sh index 160578039..37810a3cc 100755 --- a/board/aarch64/rootfs/usr/sbin/wan-monitor.sh +++ b/board/aarch64/rootfs/usr/sbin/wan-monitor.sh @@ -20,6 +20,7 @@ cleanup() { rm -f "$LED_FILE" rm -f "$PID_FILE" + kill %% 2>/dev/null exit 0 } @@ -31,11 +32,13 @@ remaining_time=$((1800 - $(awk '{print int($1)}' /proc/uptime))) while [ "$remaining_time" -gt 0 ]; do check_wan - sleep 1 + sleep 1 & + wait $! remaining_time=$((remaining_time - 1)) done while :; do check_wan - sleep 5 + sleep 5 & + wait $! done From d75ba2064a38e9d9a5b28f7efa5f1ef8786864a9 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 19 Jan 2026 19:12:34 +0100 Subject: [PATCH 05/29] board: simplify usb debugging, allow announcement of new devices Simplify USB device debugging by allowing USB core to always announce details of every new USB device to syslog. Signed-off-by: Joachim Wiberg --- board/aarch32/linux_defconfig | 1 + board/aarch64/linux_defconfig | 1 + board/riscv64/linux_defconfig | 1 + board/x86_64/linux_defconfig | 1 + 4 files changed, 4 insertions(+) diff --git a/board/aarch32/linux_defconfig b/board/aarch32/linux_defconfig index d5358edea..9c8dc20d9 100644 --- a/board/aarch32/linux_defconfig +++ b/board/aarch32/linux_defconfig @@ -353,6 +353,7 @@ CONFIG_SND_SOC=y CONFIG_SND_BCM2835_SOC_I2S=y CONFIG_HID_GENERIC=m CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_OTG=y CONFIG_USB_STORAGE=y CONFIG_USB_DWC2=y diff --git a/board/aarch64/linux_defconfig b/board/aarch64/linux_defconfig index 54f230660..b1794ccb8 100644 --- a/board/aarch64/linux_defconfig +++ b/board/aarch64/linux_defconfig @@ -497,6 +497,7 @@ CONFIG_REGULATOR_QCOM_SPMI=y # CONFIG_HID_MONTEREY is not set CONFIG_USB_ULPI_BUS=y CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_OTG=y CONFIG_USB_XHCI_HCD=m CONFIG_USB_XHCI_MVEBU=m diff --git a/board/riscv64/linux_defconfig b/board/riscv64/linux_defconfig index f3815aef6..3d90e235f 100644 --- a/board/riscv64/linux_defconfig +++ b/board/riscv64/linux_defconfig @@ -358,6 +358,7 @@ CONFIG_SND_SOC_JH7110_TDM=y CONFIG_SND_SOC_WM8960=y CONFIG_SND_SIMPLE_CARD=y CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_HCD_PLATFORM=y diff --git a/board/x86_64/linux_defconfig b/board/x86_64/linux_defconfig index 3c9fd667e..dc497b95e 100644 --- a/board/x86_64/linux_defconfig +++ b/board/x86_64/linux_defconfig @@ -287,6 +287,7 @@ CONFIG_WATCHDOG_SYSFS=y CONFIG_SOFT_WATCHDOG=y CONFIG_I6300ESB_WDT=y CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=m CONFIG_USB_EHCI_HCD=m CONFIG_USB_UHCI_HCD=m From 5f737ed145ee034bace4a8a9de31a9e2214dc188 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 18:03:37 +0100 Subject: [PATCH 06/29] board: add missing readme for bsp overview + rebuild Signed-off-by: Joachim Wiberg --- board/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 board/README.md diff --git a/board/README.md b/board/README.md new file mode 100644 index 000000000..08808e238 --- /dev/null +++ b/board/README.md @@ -0,0 +1,18 @@ +Board Support +============= + +The board support for an architecture always starts with Qemu support, +this is what each `linux_defconfig` at the very least sets up. Then +each `$BR2_ARCH` has additional BSPs, e.g., Banana Pi BPI-R3. + +The `board/` directory is matched with the `configs/*_defconfigs` and +the only execption is `board/common/`, which holds all shared files for +Infix builds. + +Each `board/$BR2_ARCH/` can then have vendor/product sub-directories +for the BSPs which may contain "fixups" to the base kernel config and +any additional device tree files that should be included as well. + +To rebuild a board-specific package, e.g. NanoPi R2S: + + make friendlyarm-nanopi-r2s-rebuild all From 496eda7eb23702e0559b6a2f92f2a9b731f463f8 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 15:43:38 +0100 Subject: [PATCH 07/29] statd: remove double-close of file descriptor after fclose When fdopen() succeeds, the FILE stream takes ownership of the file descriptor. Calling fclose() automatically closes the underlying fd, so the subsequent close(fd) calls were double-close bugs that could cause undefined behavior. Signed-off-by: Joachim Wiberg --- src/statd/statd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/statd/statd.c b/src/statd/statd.c index da02b7300..b07ce04c1 100644 --- a/src/statd/statd.c +++ b/src/statd/statd.c @@ -96,7 +96,6 @@ static int ly_add_yanger_data(const struct ly_ctx *ctx, struct lyd_node **parent if (err) { ERROR("Error, running yanger"); fclose(stream); - close(fd); return SR_ERR_SYS; } @@ -105,7 +104,6 @@ static int ly_add_yanger_data(const struct ly_ctx *ctx, struct lyd_node **parent if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { ERROR("Error, unable reset stream (seek)"); fclose(stream); - close(fd); return SR_ERR_SYS; } @@ -114,7 +112,7 @@ static int ly_add_yanger_data(const struct ly_ctx *ctx, struct lyd_node **parent ERROR("Error, parsing yanger data (%d)", err); fclose(stream); - close(fd); + /* Note: fclose() already closes the underlying fd from fdopen() */ return err; } From 87a754eab14f7b0fc4fadf65ec28c2ecf5dc0177 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 19:16:57 +0100 Subject: [PATCH 08/29] statd: Add rx/tx bitrate to WiFi station operational data Extend the WiFi station mode with rx-speed and tx-speed leaves, mirroring what already exists for AP mode connected stations. Display bitrates in 'show interface ' detailed view. Also standardize speed units to kbps/Mbps across the YANG model. Signed-off-by: Joachim Wiberg --- src/confd/yang/confd/infix-if-wifi.yang | 50 +++++++++++++++---- src/statd/python/cli_pretty/cli_pretty.py | 8 ++- .../python/yanger/ietf_interfaces/wifi.py | 4 ++ 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/confd/yang/confd/infix-if-wifi.yang b/src/confd/yang/confd/infix-if-wifi.yang index c5d1615b1..309c3e40c 100644 --- a/src/confd/yang/confd/infix-if-wifi.yang +++ b/src/confd/yang/confd/infix-if-wifi.yang @@ -218,6 +218,36 @@ submodule infix-if-wifi { - Below -80 dBm: Very weak"; } + leaf rx-speed { + config false; + type uint32; + units "100 kbps"; + description + "Last received data rate from the access point in 100 kbps. + + Only available when connected. + + Examples: + - 10 = 1 Mbps + - 65 = 6.5 Mbps + - 866 = 86.6 Mbps"; + } + + leaf tx-speed { + config false; + type uint32; + units "100 kbps"; + description + "Last transmitted data rate to the access point in 100 kbps. + + Only available when connected. + + Examples: + - 10 = 1 Mbps + - 65 = 6.5 Mbps + - 866 = 86.6 Mbps"; + } + list scan-results { config false; key ssid; @@ -421,26 +451,26 @@ submodule infix-if-wifi { leaf rx-speed { type uint32; - units "100 kbit/s"; + units "100 kbps"; description - "Last received data rate from this client in 100 kbit/s. + "Last received data rate from this client in 100 kbps. Examples: - - 10 = 1 Mbit/s - - 65 = 6.5 Mbit/s - - 866 = 86.6 Mbit/s"; + - 10 = 1 Mbps + - 65 = 6.5 Mbps + - 866 = 86.6 Mbps"; } leaf tx-speed { type uint32; - units "100 kbit/s"; + units "100 kbps"; description - "Last transmitted data rate to this client in 100 kbit/s. + "Last transmitted data rate to this client in 100 kbps. Examples: - - 10 = 1 Mbit/s - - 65 = 6.5 Mbit/s - - 866 = 86.6 Mbit/s"; + - 10 = 1 Mbps + - 65 = 6.5 Mbps + - 866 = 86.6 Mbps"; } } } diff --git a/src/statd/python/cli_pretty/cli_pretty.py b/src/statd/python/cli_pretty/cli_pretty.py index f8fecba5e..8a6c5d340 100755 --- a/src/statd/python/cli_pretty/cli_pretty.py +++ b/src/statd/python/cli_pretty/cli_pretty.py @@ -1295,7 +1295,7 @@ def pr_wifi_stations(self): rx_bytes = station.get("rx-bytes", 0) tx_bytes = station.get("tx-bytes", 0) - # Speed in 100 kbit/s units, convert to Mbps for display + # Speed in 100 kbps units, convert to Mbps for display rx_speed = station.get("rx-speed", 0) tx_speed = station.get("tx-speed", 0) rx_speed_str = f"{rx_speed / 10:.1f}" if rx_speed else "-" @@ -1640,6 +1640,12 @@ def pr_iface(self): if rssi is not None: signal_status = rssi_to_status(rssi) print(f"{'signal':<{20}}: {rssi} dBm ({signal_status})") + rx_speed = station.get('rx-speed') + tx_speed = station.get('tx-speed') + if rx_speed is not None: + print(f"{'rx bitrate':<{20}}: {rx_speed / 10:.1f} Mbps") + if tx_speed is not None: + print(f"{'tx bitrate':<{20}}: {tx_speed / 10:.1f} Mbps") if "scan-results" in station: self.pr_wifi_ssids() diff --git a/src/statd/python/yanger/ietf_interfaces/wifi.py b/src/statd/python/yanger/ietf_interfaces/wifi.py index f6af9069f..56669a600 100644 --- a/src/statd/python/yanger/ietf_interfaces/wifi.py +++ b/src/statd/python/yanger/ietf_interfaces/wifi.py @@ -70,6 +70,10 @@ def wifi_station(ifname): station_data['ssid'] = link['ssid'] if link.get('rssi') is not None: station_data['rssi'] = link['rssi'] + if link.get('rx-speed') is not None: + station_data['rx-speed'] = link['rx-speed'] + if link.get('tx-speed') is not None: + station_data['tx-speed'] = link['tx-speed'] # Get scan results from wpa_supplicant (better scan support) try: From 693293952592daeedeb2cdfb3d042b813c6f1848 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 25 Jan 2026 01:11:23 +0100 Subject: [PATCH 09/29] statd: convert 'show ntp [opt]' tables to SimpleTable Signed-off-by: Joachim Wiberg --- src/statd/python/cli_pretty/cli_pretty.py | 75 ++++++++++------------- test/case/statd/system/cli/show-ntp | 8 +-- test/case/statd/system/cli/show-software | 9 ++- 3 files changed, 39 insertions(+), 53 deletions(-) diff --git a/src/statd/python/cli_pretty/cli_pretty.py b/src/statd/python/cli_pretty/cli_pretty.py index 8a6c5d340..348491d14 100755 --- a/src/statd/python/cli_pretty/cli_pretty.py +++ b/src/statd/python/cli_pretty/cli_pretty.py @@ -144,7 +144,7 @@ def set(ipv): class PadSoftware: - name = 10 + name = 11 date = 25 hash = 64 state = 10 @@ -170,14 +170,6 @@ def table_width(cls): return cls.name + cls.value + cls.status -class PadNtpSource: - address = 16 - mode = 13 - state = 13 - stratum = 11 - poll = 14 - - class PadLldp: interface = 16 rem_idx = 10 @@ -2056,11 +2048,10 @@ def show_software(json, name): if slot: slot.detail() else: - print(Decore.invert("BOOT ORDER")) - order="" + order = "" for boot in boot_order: - order+=f"{boot.strip()} " - print(order) + order += f"{boot.strip()} " + print(f"Boot order : {order}") print("") hdr = (f"{'NAME':<{PadSoftware.name}}" @@ -2575,12 +2566,14 @@ def show_ntp(json, address=None): show_ntp_source_detail_single(sources[0], is_server) return print() - hdr = (f"{'ADDRESS':<{PadNtpSource.address}}" - f"{'MODE':<{PadNtpSource.mode}}" - f"{'STATE':<{PadNtpSource.state}}" - f"{'STRATUM':>{PadNtpSource.stratum}}" - f"{'POLL':>{PadNtpSource.poll}}") - print(Decore.invert(hdr)) + table = SimpleTable([ + Column('ADDRESS'), + Column('MODE'), + Column('STATE'), + Column('STRATUM', 'right'), + Column('POLL', 'right') + ]) + for source in sources: # Extract fields - handle both association and ietf-system format address = source.get('address', 'N/A') @@ -2604,12 +2597,9 @@ def show_ntp(json, address=None): poll = source.get('poll', 0) poll_str = f"{2**poll}s" if poll else "-" - row = f"{address:<{PadNtpSource.address}}" - row += f"{mode_str:<{PadNtpSource.mode}}" - row += f"{state_str:<{PadNtpSource.state}}" - row += f"{stratum:>{PadNtpSource.stratum}}" - row += f"{poll_str:>{PadNtpSource.poll}}" - print(row) + table.row(address, mode_str, state_str, stratum, poll_str) + + table.print() def show_ntp_tracking(json): @@ -2827,21 +2817,18 @@ def show_ntp_source(json, address=None): show_ntp_association_detail(associations[0]) return - # First pass: determine maximum address width needed - max_addr_len = len("Name/IP address") # Minimum width to match chronyc header - for assoc in associations: - addr_len = len(assoc.get("address", "")) - if addr_len > max_addr_len: - max_addr_len = addr_len - - # Cap at reasonable maximum (IPv6 can be up to 39 chars uncompressed) - max_addr_len = min(max_addr_len, 39) - - # Table header - similar to chronyc sources - hdr = f"{'MS':<3}{f'Name/IP address':<{max_addr_len}} {'Stratum':>7} {'Poll':>4} {'Reach':>5} {'LastRx':>6} {'Last sample':>24}" - print(Decore.invert(hdr)) + # Table with chronyc-style columns + table = SimpleTable([ + Column('MS'), + Column('Name/IP address', flexible=True), + Column('Stratum', 'right'), + Column('Poll', 'right'), + Column('Reach', 'right'), + Column('LastRx', 'right'), + Column('Last sample', 'right') + ]) - # Display each association + # Build rows for assoc in associations: # State indicator: * = prefer (sync source), + = candidate prefer = assoc.get("prefer", False) @@ -2858,6 +2845,7 @@ def show_ntp_source(json, address=None): elif local_mode == "broadcast-client": mode_indicator = "#" + ms_col = f"{mode_indicator}{state}" address = assoc.get("address", "N/A") stratum = assoc.get("stratum", 0) @@ -2902,14 +2890,13 @@ def show_ntp_source(json, address=None): # Last sample column combines offset and delay like chronyc if offset_str != "-": - last_sample = f"{offset_str:>12} {delay_str}" + last_sample = f"{offset_str} {delay_str}" else: last_sample = "-" - # Format row - ms_col = f"{mode_indicator}{state}" - row = f"{ms_col:<3}{address:<{max_addr_len}} {stratum:>7} {poll_str:>4} {reach_str:>5} {now_str:>6} {last_sample:>24}" - print(row) + table.row(ms_col, address, stratum, poll_str, reach_str, now_str, last_sample) + + table.print() def _analyze_group_permissions(nacm): diff --git a/test/case/statd/system/cli/show-ntp b/test/case/statd/system/cli/show-ntp index 46b6a4229..c1eff476d 100644 --- a/test/case/statd/system/cli/show-ntp +++ b/test/case/statd/system/cli/show-ntp @@ -1,6 +1,6 @@ Mode : Client -ADDRESS MODE STATE STRATUM POLL -192.168.1.1 server candidate 1 64s -192.168.2.1 server candidate 1 64s -192.168.3.1 server selected 1 64s +ADDRESS MODE STATE STRATUM POLL +192.168.1.1 server candidate 1 64s +192.168.2.1 server candidate 1 64s +192.168.3.1 server selected 1 64s diff --git a/test/case/statd/system/cli/show-software b/test/case/statd/system/cli/show-software index dd6e4a9e3..e97750843 100644 --- a/test/case/statd/system/cli/show-software +++ b/test/case/statd/system/cli/show-software @@ -1,6 +1,5 @@ -BOOT ORDER -primary secondary net +Boot order : primary secondary net -NAME STATE VERSION DATE  -primary booted 94cd526 2025-01-15T10:00:56Z -secondary inactive 94cd526 2025-01-15T10:00:56Z +NAME STATE VERSION DATE  +primary booted 94cd526 2025-01-15T10:00:56Z +secondary inactive 94cd526 2025-01-15T10:00:56Z From 33f830b43276d176fbe66487fb2109abad9e9281 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 21:17:13 +0100 Subject: [PATCH 10/29] statd: add BSSID to table of available networks Also, spruce up the table a bit. Allow it to resize, let the SSID column be flexible, and right-align column(s) with numbers. Signed-off-by: Joachim Wiberg --- src/statd/python/cli_pretty/cli_pretty.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/statd/python/cli_pretty/cli_pretty.py b/src/statd/python/cli_pretty/cli_pretty.py index 348491d14..246d5d38a 100755 --- a/src/statd/python/cli_pretty/cli_pretty.py +++ b/src/statd/python/cli_pretty/cli_pretty.py @@ -345,8 +345,11 @@ def _format_column_value(self, value, column, width, is_last=False): # Add separator " " only between columns, not after the last one separator = "" if is_last else " " - # Don't pad the last column to avoid trailing spaces + # Don't add trailing spaces to the last column if is_last: + if column.align == 'right': + padding = width - visible_len + return ' ' * max(0, padding) + value_str return value_str elif column.align == 'right': padding = width - visible_len @@ -1230,22 +1233,26 @@ def pr_proto_loopack(self, pipe=''): print(row) def pr_wifi_ssids(self): - print("\nAVAILABLE NETWORKS:") + width = 70 + Decore.title("Available Networks", width) ssid_table = SimpleTable([ - Column('SSID'), + Column('SSID', flexible=True), + Column('BSSID'), Column('SECURITY'), Column('SIGNAL'), - Column('CHANNEL') - ]) + Column('CHANNEL', 'right') + ], min_width=width) station = self.wifi.get("station", {}) results = station.get("scan-results", {}) for result in results: + ssid = result.get('ssid', 'Hidden') + bssid = result.get("bssid", "unknown") encstr = ", ".join(result.get("encryption", ["Unknown"])) status = rssi_to_status(result.get("rssi", -100)) channel = result.get("channel", "?") - ssid_table.row(result.get('ssid', 'Hidden'), encstr, status, channel) + ssid_table.row(ssid, bssid, encstr, status, channel) ssid_table.print() def pr_wifi_stations(self): From 6c41dc3a7122f095c6c0ffe5d5a51f6be9178d59 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 23 Jan 2026 18:42:43 +0100 Subject: [PATCH 11/29] confd: add probe-timeout for wifi dongles Signed-off-by: Joachim Wiberg --- src/confd/src/if-wifi.c | 32 +++++++++++++++++++ src/confd/yang/confd.inc | 2 +- src/confd/yang/confd/infix-hardware.yang | 19 +++++++++++ ...04.yang => infix-hardware@2026-01-19.yang} | 0 4 files changed, 52 insertions(+), 1 deletion(-) rename src/confd/yang/confd/{infix-hardware@2025-12-04.yang => infix-hardware@2026-01-19.yang} (100%) diff --git a/src/confd/src/if-wifi.c b/src/confd/src/if-wifi.c index 101afa172..f6f54a88e 100644 --- a/src/confd/src/if-wifi.c +++ b/src/confd/src/if-wifi.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause */ #include +#include #include "interfaces.h" @@ -134,6 +135,25 @@ static int wifi_gen_station(struct lyd_node *cif) return rc; } +/* + * Get probe-timeout for a radio from sysrepo config. + * Returns 0 if not set. + */ +static int wifi_get_probe_timeout(sr_session_ctx_t *session, const char *radio) +{ + char *timeout_str; + int timeout = 0; + + timeout_str = srx_get_str(session, + "/ietf-hardware:hardware/component[name='%s']/infix-hardware:wifi-radio/probe-timeout", + radio); + if (timeout_str) { + timeout = atoi(timeout_str); + free(timeout_str); + } + return timeout; +} + /* * Add WiFi virtual interface using iw */ @@ -142,6 +162,7 @@ int wifi_add_iface(struct lyd_node *cif, struct dagger *net) const char *ifname, *radio; struct lyd_node *wifi; wifi_mode_t mode; + int probe_timeout; FILE *iw; int rc = SR_ERR_OK; @@ -166,11 +187,22 @@ int wifi_add_iface(struct lyd_node *cif, struct dagger *net) } mode = wifi_get_mode(wifi); + probe_timeout = wifi_get_probe_timeout(net->session, radio); fprintf(iw, "# Generated by Infix confd - WiFi Interface Creation\n"); fprintf(iw, "# Create %s interface %s on radio %s\n", mode == wifi_station ? "station" : "access point", ifname, radio); + /* Wait for PHY if probe-timeout is set (slow USB dongles) */ + if (probe_timeout > 0) { + fprintf(iw, "\n# Wait for PHY (USB dongle may be slow to initialize)\n"); + fprintf(iw, "timeout=%d\n", probe_timeout); + fprintf(iw, "while [ $timeout -gt 0 ]; do\n"); + fprintf(iw, " iw phy %s info >/dev/null 2>&1 && break\n", radio); + fprintf(iw, " sleep 1\n"); + fprintf(iw, " timeout=$((timeout - 1))\n"); + fprintf(iw, "done\n"); + } switch(mode) { case wifi_station: fprintf(iw, "iw phy %s interface add %s type managed\n", radio, ifname); diff --git a/src/confd/yang/confd.inc b/src/confd/yang/confd.inc index c8941cbe5..10ef69d5a 100644 --- a/src/confd/yang/confd.inc +++ b/src/confd/yang/confd.inc @@ -27,7 +27,7 @@ MODULES=( "infix-syslog@2025-11-17.yang" "iana-hardware@2018-03-13.yang" "ietf-hardware@2018-03-13.yang -e hardware-state -e hardware-sensor" - "infix-hardware@2025-12-04.yang" + "infix-hardware@2026-01-19.yang" "ieee802-dot1q-types@2022-10-29.yang" "infix-ip@2025-11-02.yang" "infix-if-type@2026-01-07.yang" diff --git a/src/confd/yang/confd/infix-hardware.yang b/src/confd/yang/confd/infix-hardware.yang index 36079e638..09b7b2a2b 100644 --- a/src/confd/yang/confd/infix-hardware.yang +++ b/src/confd/yang/confd/infix-hardware.yang @@ -21,6 +21,10 @@ module infix-hardware { contact "kernelkit@googlegroups.com"; description "Vital Product Data augmentation of ieee-hardware and deviations."; + revision 2026-01-19 { + description "Add probe-timeout for slow USB WiFi dongles."; + reference "internal"; + } revision 2025-12-04 { description "Add WiFi radio survey container for channel utilization data."; reference "internal"; @@ -262,6 +266,21 @@ module infix-hardware { congestion in most environments."; } + leaf probe-timeout { + type uint8; + description + "Seconds to wait for PHY detection at boot. + + USB WiFi dongles may be slow to initialize due to firmware + loading. Set this to a non-zero value (e.g., 30) to wait + for the radio PHY to appear before creating WiFi interfaces. + + If the PHY is not detected within the timeout, interface + creation is skipped gracefully instead of failing. + + Value 0 (default) disables waiting."; + } + /* * Operational state */ diff --git a/src/confd/yang/confd/infix-hardware@2025-12-04.yang b/src/confd/yang/confd/infix-hardware@2026-01-19.yang similarity index 100% rename from src/confd/yang/confd/infix-hardware@2025-12-04.yang rename to src/confd/yang/confd/infix-hardware@2026-01-19.yang From dabe4aed8d86f4d7cf25a5474d41220c00755d56 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 23 Jan 2026 18:45:06 +0100 Subject: [PATCH 12/29] confd: fix wifi class interence of radioN hardware components Signed-off-by: Joachim Wiberg --- src/confd/src/hardware.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/confd/src/hardware.c b/src/confd/src/hardware.c index ac36adeed..c1534cb60 100644 --- a/src/confd/src/hardware.c +++ b/src/confd/src/hardware.c @@ -145,9 +145,14 @@ static int hardware_cand_infer_class(json_t *root, sr_session_ctx_t *session, co inferred.data.string_val = "infix-hardware:usb"; err = srx_set_item(session, &inferred, 0, "%s/class", xpath); - break; + goto out_free_name; } } + + if (!fnmatch("radio+([0-9])", name, FNM_EXTMATCH)) { + inferred.data.string_val = "infix-hardware:wifi"; + err = srx_set_item(session, &inferred, 0, "%s/class", xpath); + } out_free_name: free(name); out_free_xpath: From a4b325c4e12914170748adcebebde03a7a9b04fb Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 23 Jan 2026 18:45:51 +0100 Subject: [PATCH 13/29] confd: refactor and code cleanup - Simplify, prefer readability - Fix nftw() 'nopenfd' argument - Constify The most interesting change is the argument to nftw(), 0 -> 20, to ensure it is allowed to open enough file descriptors to descend. In POSIX it is undefined if nopenfd is < 1. Signed-off-by: Joachim Wiberg --- src/confd/src/hardware.c | 65 ++++++++++++++++++-------------------- src/confd/src/interfaces.c | 10 +++--- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/src/confd/src/hardware.c b/src/confd/src/hardware.c index c1534cb60..b7d0cbc58 100644 --- a/src/confd/src/hardware.c +++ b/src/confd/src/hardware.c @@ -1,13 +1,13 @@ /* SPDX-License-Identifier: BSD-3-Clause */ +#include +#include #include +#include +#include #include #include #include -#include -#include -#include -#include #include "core.h" #include "interfaces.h" @@ -17,10 +17,10 @@ #define HOSTAPD_CONF "/etc/hostapd-%s.conf" #define HOSTAPD_CONF_NEXT HOSTAPD_CONF"+" -static int dir_cb(const char *fpath, const struct stat *sb, - int typeflag, struct FTW *ftwbuf) +static int dir_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { - char *filename; + const char *filename; + if (typeflag == FTW_DP) return 0; @@ -31,59 +31,55 @@ static int dir_cb(const char *fpath, const struct stat *sb, return FTW_STOP; } } + return 0; } static bool usb_authorize(struct json_t *root, const char *name, int enabled) { - json_t *usb_port, *usb_ports; + json_t *port, *ports; int index; - usb_ports = json_object_get(root, "usb-ports"); - if (!usb_ports) /* No Infix controlled USB ports is ok */ + ports = json_object_get(root, "usb-ports"); + if (!ports) return 0; - json_array_foreach(usb_ports, index, usb_port) { - struct json_t *jname; + json_array_foreach(ports, index, port) { + struct json_t *obj; - jname = json_object_get(usb_port, "name"); - if (!jname || !json_is_string(jname)) { + obj = json_object_get(port, "name"); + if (!obj || !json_is_string(obj)) { ERROR("Did not find USB hardware port (name) for %s", name); continue; } - if (!strcmp(name, json_string_value(jname))) { - struct json_t *jpath = json_object_get(usb_port, "path"); - char authorized_default_path[PATH_MAX]; + + if (!strcmp(name, json_string_value(obj))) { + char apath[PATH_MAX]; const char *path; - if (!jpath || !json_is_string(jpath)) { + obj = json_object_get(port, "path"); + if (!obj || !json_is_string(obj)) { ERROR("Did not find USB hardware port (path) for %s", name); continue; } - /* Path now points to USB device directory, not the attribute file */ - path = json_string_value(jpath); - snprintf(authorized_default_path, sizeof(authorized_default_path), - "%s/authorized_default", path); + path = json_string_value(obj); + snprintf(apath, sizeof(apath), "%s/authorized_default", path); if (!enabled) { - if (fexist(authorized_default_path)) { - if (writedf(0, "w", "%s", authorized_default_path)) { - ERROR("Failed to unauthorize %s", authorized_default_path); + if (fexist(apath)) { + if (writedf(0, "w", "%s", apath)) { + ERROR("Failed to unauthorize %s", apath); return 1; } } } else { - char *rpath; - - rpath = realpath(path, NULL); - if (rpath) { - nftw(rpath, dir_cb, 0, FTW_DEPTH | FTW_PHYS); - free(rpath); - } + if (realpath(path, apath)) + nftw(apath, dir_cb, 20, FTW_DEPTH | FTW_PHYS); } } } + return 0; } @@ -584,7 +580,8 @@ static int hardware_cand(sr_session_ctx_t *session, uint32_t sub_id, const char return err; } -int hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) +int hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, + sr_event_t event, struct confd *confd) { struct lyd_node *difs = NULL, *dif = NULL; int rc = SR_ERR_OK; @@ -623,7 +620,7 @@ int hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct l } continue; } - state = lydx_get_child(dif, "state"); + state = lydx_get_child(cif, "state"); admin_state = lydx_get_cattr(state, "admin-state"); if (usb_authorize(confd->root, name, !strcmp(admin_state, "unlocked"))) { rc = SR_ERR_INTERNAL; diff --git a/src/confd/src/interfaces.c b/src/confd/src/interfaces.c index 7df74980f..f16aa8eee 100644 --- a/src/confd/src/interfaces.c +++ b/src/confd/src/interfaces.c @@ -599,14 +599,16 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif, static sr_error_t netdag_gen_iface_timeout(struct dagger *net, const char *ifname, const char *iftype) { if (!strcmp(iftype, "infix-if-type:ethernet")) { - FILE *wait = dagger_fopen_net_init(net, ifname, NETDAG_INIT_TIMEOUT, "wait-interface.sh"); - if (!wait) { + FILE *wait; + + wait = dagger_fopen_net_init(net, ifname, NETDAG_INIT_TIMEOUT, "wait-interface.sh"); + if (!wait) return -EIO; - } fprintf(wait, "/usr/libexec/confd/wait-interface %s %d\n", ifname, IFACE_PROBE_TIMEOUT); fclose(wait); - } + } + return SR_ERR_OK; } From 480447c8f21f9def4b69160dfce156eecf54dfe4 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 23 Jan 2026 18:48:24 +0100 Subject: [PATCH 14/29] confd: interfaces depend on hardware, fix ordering Signed-off-by: Joachim Wiberg --- src/confd/src/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 5241e7748..4acce329a 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -354,6 +354,10 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod #endif } + /* ietf-hardware */ + if ((rc = hardware_change(session, config, diff, event, confd))) + goto free_diff; + /* ietf-interfaces */ if ((rc = interfaces_change(session, config, diff, event, confd))) goto free_diff; @@ -392,10 +396,6 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod goto free_diff; #endif - /* ietf-hardware */ - if ((rc = hardware_change(session, config, diff, event, confd))) - goto free_diff; - /* ietf-routing */ if ((rc = routing_change(session, config, diff, event, confd))) goto free_diff; From da80127ef0574eea4749d11610a174d59a09cab3 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 23 Jan 2026 18:49:51 +0100 Subject: [PATCH 15/29] confd: use dummy interface in lieu of missing radios If we time out waiting for a wifi dongle, or onboard chipset, instead of causing fatal error in dagger and b0rking startup, we cheat and create a dummy interface. Also, fix bug in HEAD, the condition was == wifi_ap but the comment said "if not station or scanning mode". Since wpa_supplicant is for station mode (not AP), the cleanup should happen when != wifi_ap. Signed-off-by: Joachim Wiberg --- src/confd/src/if-wifi.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/confd/src/if-wifi.c b/src/confd/src/if-wifi.c index f6f54a88e..84081f128 100644 --- a/src/confd/src/if-wifi.c +++ b/src/confd/src/if-wifi.c @@ -203,6 +203,18 @@ int wifi_add_iface(struct lyd_node *cif, struct dagger *net) fprintf(iw, " timeout=$((timeout - 1))\n"); fprintf(iw, "done\n"); } + + /* + * If radio doesn't exist, create a dummy interface as placeholder. This allows all + * downstream config (IP addresses, etc.) to work. User must reboot when radio becomes + * available. + */ + fprintf(iw, "if ! iw phy %s info >/dev/null 2>&1; then\n", radio); + fprintf(iw, " logger -t wifi \"%s: radio %s not available, creating dummy placeholder\"\n", ifname, radio); + fprintf(iw, " ip link add %s type dummy\n", ifname); + fprintf(iw, " exit 0\n"); + fprintf(iw, "fi\n\n"); + switch(mode) { case wifi_station: fprintf(iw, "iw phy %s interface add %s type managed\n", radio, ifname); @@ -241,16 +253,15 @@ int wifi_del_iface(struct lyd_node *dif, struct dagger *net) } fprintf(iw, "# Generated by Infix confd - WiFi Interface Deletion\n"); - fprintf(iw, "ip link set %s down\n", ifname); /* Required to change modes. */ - fprintf(iw, "iw dev %s disconnect\n", ifname); - fprintf(iw, "iw dev %s del\n", ifname); + fprintf(iw, "ip link set %s down\n", ifname); + fprintf(iw, "iw dev %s disconnect 2>/dev/null\n", ifname); + fprintf(iw, "iw dev %s del 2>/dev/null || ip link del %s 2>/dev/null || true\n", ifname, ifname); wifi = lydx_get_child(dif, "wifi"); - if (wifi && wifi_get_mode(wifi) == wifi_ap) { /* if not station or scanning mode */ + if (wifi && wifi_get_mode(wifi) != wifi_ap) { erasef(WPA_SUPPLICANT_CONF, ifname); fprintf(iw, "initctl -bfq disable wifi@%s\n", ifname); } - fclose(iw); return SR_ERR_OK; From a7422535c3232a8cceb0f87c2d585d93246ae52d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 16:41:38 +0100 Subject: [PATCH 16/29] confd: minor adjustments to wifi config file handling Ensure umask is properly managed around file creation to maintain consistent behavior across the codebase. Signed-off-by: Joachim Wiberg --- src/confd/src/hardware.c | 8 ++++++-- src/confd/src/if-wifi.c | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/confd/src/hardware.c b/src/confd/src/hardware.c index b7d0cbc58..2b6f13d54 100644 --- a/src/confd/src/hardware.c +++ b/src/confd/src/hardware.c @@ -458,12 +458,14 @@ static int wifi_gen_aps_on_radio(const char *radio_name, struct lyd_node *cifs, char hostapd_conf[256]; char **ap_list = NULL; FILE *hostapd = NULL; - int ap_count = 0; int rc = SR_ERR_OK; + int ap_count = 0; + mode_t oldmask; int i; - wifi_find_radio_aps(cifs, radio_name, &ap_list, &ap_count); + oldmask = umask(0077); + wifi_find_radio_aps(cifs, radio_name, &ap_list, &ap_count); if (ap_count == 0) { DEBUG("No APs found on radio %s", radio_name); goto cleanup; @@ -538,6 +540,8 @@ static int wifi_gen_aps_on_radio(const char *radio_name, struct lyd_node *cifs, fclose(hostapd); cleanup: + umask(oldmask); + for (i = 0; i < ap_count; i++) free(ap_list[i]); free(ap_list); diff --git a/src/confd/src/if-wifi.c b/src/confd/src/if-wifi.c index 84081f128..d6567d6b4 100644 --- a/src/confd/src/if-wifi.c +++ b/src/confd/src/if-wifi.c @@ -61,6 +61,7 @@ static int wifi_gen_station(struct lyd_node *cif) char *security_str = NULL; const char *country; int rc = SR_ERR_OK; + mode_t oldmask; ifname = lydx_get_cattr(cif, "name"); wifi = lydx_get_child(cif, "wifi"); @@ -95,6 +96,7 @@ static int wifi_gen_station(struct lyd_node *cif) secret = NULL; } + oldmask = umask(0077); wpa_supplicant = fopenf("w", WPA_SUPPLICANT_CONF, ifname); if (!wpa_supplicant) { rc = SR_ERR_INTERNAL; @@ -132,6 +134,8 @@ static int wifi_gen_station(struct lyd_node *cif) out: if (wpa_supplicant) fclose(wpa_supplicant); + umask(oldmask); + return rc; } From c7d219f5e3d56dbb0d6b23e0c781560a38657329 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 23:27:40 +0100 Subject: [PATCH 17/29] confd: add missing interface type descriptions Signed-off-by: Joachim Wiberg --- src/confd/yang/confd/infix-if-type.yang | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/confd/yang/confd/infix-if-type.yang b/src/confd/yang/confd/infix-if-type.yang index 052e6220c..f64338ef4 100644 --- a/src/confd/yang/confd/infix-if-type.yang +++ b/src/confd/yang/confd/infix-if-type.yang @@ -77,17 +77,22 @@ module infix-if-type { reference "RFC 3635"; } + identity gre { base infix-interface-type; + description "GRE tunnel interface."; } identity gretap { base infix-interface-type; + description "GRETAP (Ethernet over GRE) tunnel interface."; } identity vxlan { base infix-interface-type; + description "Virtual eXtensible LAN tunnel interface."; } identity wireguard { base infix-interface-type; + description "WireGuard VPN tunnel interface."; } identity lag { base infix-interface-type; From b060495525c2f7a6a2a8e4f01b3b148bef8740cc Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 15:59:44 +0100 Subject: [PATCH 18/29] utils: adjust ChangeLog update in kernel-upgrade.sh Signed-off-by: Joachim Wiberg --- utils/kernel-upgrade.sh | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/utils/kernel-upgrade.sh b/utils/kernel-upgrade.sh index 119c06808..d5487ebef 100755 --- a/utils/kernel-upgrade.sh +++ b/utils/kernel-upgrade.sh @@ -255,26 +255,16 @@ update_changelog() { fi # Extract just the UNRELEASED section (from start until next version header) - # Need to find the second [v occurrence (first is UNRELEASED itself, second is previous release) UNRELEASED_SECTION=$(awk '/^\[v[0-9]/ { count++; if (count == 2) exit } { print }' doc/ChangeLog.md) # Check if there's already a kernel upgrade entry in the UNRELEASED section - if echo "$UNRELEASED_SECTION" | grep -q "^- Upgrade Linux kernel to"; then - # Update existing kernel upgrade line in UNRELEASED section only - # Find a real release marker (not UNRELEASED), then replace before that - awk -v new_version="$NEW_VERSION" ' - /^\[v[0-9]/ && !/UNRELEASED/ { found_version=1 } - /^- Upgrade Linux kernel to/ && !found_version && !replaced { - print "- Upgrade Linux kernel to " new_version " (LTS)" - replaced=1 - next - } - {print} - ' doc/ChangeLog.md > doc/ChangeLog.md.tmp && mv doc/ChangeLog.md.tmp doc/ChangeLog.md + # Match both plain and bold formats: "- Upgrade Linux" or "- Upgrade **Linux" + if echo "$UNRELEASED_SECTION" | grep -qE "^- Upgrade (\*\*)?Linux kernel to"; then + # Update existing kernel upgrade line using sed (first match only) + sed -i '0,/^- Upgrade \(\*\*\)\?Linux kernel to .*/s//- Upgrade Linux kernel to '"$NEW_VERSION"' (LTS)/' doc/ChangeLog.md log_info "Updated existing kernel version entry to $NEW_VERSION" else # Add new kernel upgrade entry after first "### Changes" - # Use awk to insert at the right place awk -v new_line="- Upgrade Linux kernel to $NEW_VERSION (LTS)" ' /^### Changes/ && !done { print From 8f1c4d6bf2177aea2904be930364eb02154d0fcb Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 16:46:00 +0100 Subject: [PATCH 19/29] utils: new script, extract-changelog.md for releases Signed-off-by: Joachim Wiberg --- .github/workflows/release.yml | 6 +---- utils/extract-changelog.sh | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) create mode 100755 utils/extract-changelog.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8af138174..4975cdc9d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -104,11 +104,7 @@ jobs: - name: Extract ChangeLog entry ... run: | - awk '/^-----*$/{if (x == 1) exit; x=1;next}x' doc/ChangeLog.md \ - |head -n -1 > release.md - echo "" >> release.md - echo "> [!TIP]" >> release.md - echo "> **Try Infix in GNS3!** Download the appliance from the [GNS3 Marketplace](https://gns3.com/marketplace/appliances/infix) to test Infix in a virtual network environment without hardware." >> release.md + cat doc/ChangeLog.md | ./utils/extract-changelog.sh > release.md cat release.md - uses: ncipollo/release-action@v1 diff --git a/utils/extract-changelog.sh b/utils/extract-changelog.sh new file mode 100755 index 000000000..ad92f6e4b --- /dev/null +++ b/utils/extract-changelog.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Extract the latest release entry from ChangeLog.md and unwrap lines +# for GitHub's web view (lets the browser handle line wrapping). +# +# Usage: cat doc/ChangeLog.md | extract-changelog.sh > release.md +# +# Output goes to stdout. +# + +set -e -o pipefail + +# Extract section between first two --- lines, skip trailing blank lines +head -n -1 < <(awk '/^-----*$/{if (x == 1) exit; x=1;next}x') | + +# Unwrap lines for GitHub's web view (browser does wrapping) +# Preserves: blank lines, list items, headings, blockquotes, indented blocks +# Joins: soft-wrapped paragraph/list continuations +awk ' +{ + if (/^$/) { + if (buf) print buf + buf = "" + print + blank = 1 + next + } + if (/^ / && buf) { + # Indented continuation - strip indent and join + sub(/^ /, " ") + buf = buf $0 + } else if (/^[-*>#\[|]/ || /^[0-9]+\./ || blank || !buf || brk) { + # New block: special char, after blank, first line, or after md break + if (buf) print buf + buf = $0 + } else { + # Paragraph continuation - join with space + buf = buf " " $0 + } + blank = 0 + brk = / $/ +} +END { if (buf) print buf } +' + +# Append tip for GNS3 +cat < [!TIP] +> **Try Infix in GNS3!** Download the appliance from the [GNS3 Marketplace](https://gns3.com/marketplace/appliances/infix) to test Infix in a virtual network environment without hardware. +EOF From e60ca12733570c9cbf449c61082e7dedb55f687a Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 16:15:33 +0100 Subject: [PATCH 20/29] bin: capture cpu/soc/core temperture for 'show system' Signed-off-by: Joachim Wiberg --- src/bin/show/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bin/show/__init__.py b/src/bin/show/__init__.py index 391b010d7..9bccfac18 100755 --- a/src/bin/show/__init__.py +++ b/src/bin/show/__init__.py @@ -531,8 +531,9 @@ def system(args: List[str]) -> None: name = component.get("name", "") value_type = sensor_data.get("value-type") - # Only capture CPU temperature (ignore phy, sfp, etc.) - if value_type == "celsius" and name == "cpu" and cpu_temp is None: + # Only capture CPU/SoC temperature (ignore phy, sfp, etc.) + # Different platforms use different names: cpu, soc, core, etc. + if value_type == "celsius" and name in ("cpu", "soc", "core") and cpu_temp is None: temp_millidegrees = sensor_data.get("value", 0) cpu_temp = temp_millidegrees / 1000.0 From 5fdd2cb0f9fd5bb39a68db74607d69f6c0ea2aa3 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 15:40:31 +0100 Subject: [PATCH 21/29] bin: minor, coding style Reverse christmas tree. Signed-off-by: Joachim Wiberg --- src/bin/copy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/copy.c b/src/bin/copy.c index 2a561d41d..150af2cab 100644 --- a/src/bin/copy.c +++ b/src/bin/copy.c @@ -579,8 +579,8 @@ static int resolve_dst(const char **dst, const struct infix_ds **ds, char **path static int copy(const char *src, const char *dst) { - char *srcpath = NULL, *dstpath = NULL; const struct infix_ds *srcds = NULL, *dstds = NULL; + char *srcpath = NULL, *dstpath = NULL; bool rmsrc = false; mode_t oldmask; int err = 1; From 2b345972010d5252f7fcc27bca85bc67a7424c8e Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 21:18:50 +0100 Subject: [PATCH 22/29] doc: add cli terminal output styling for examples Signed-off-by: Joachim Wiberg --- doc/extra.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/extra.css b/doc/extra.css index ac6f593d3..94d833600 100644 --- a/doc/extra.css +++ b/doc/extra.css @@ -24,3 +24,14 @@ /* Reset alignment for table cells */ text-align: initial; } + +/* CLI terminal output styling */ +.md-typeset pre.cli .title { + font-weight: bold; +} + +.md-typeset pre.cli .header { + background-color: #e0e0e0; + color: #1a1a1a; + font-weight: bold; +} From ade6922862552a93df2bad85ae49955a38a364fa Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 23 Jan 2026 18:52:08 +0100 Subject: [PATCH 23/29] doc: update wifi.md, mnore realtek dongles tested, probe-timeout etc Signed-off-by: Joachim Wiberg --- doc/wifi.md | 408 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 250 insertions(+), 158 deletions(-) diff --git a/doc/wifi.md b/doc/wifi.md index e01d85214..3aa7d3f32 100644 --- a/doc/wifi.md +++ b/doc/wifi.md @@ -10,14 +10,35 @@ host virtual interfaces. Infix uses a two-layer WiFi architecture: 1. **WiFi Radio (PHY layer)**: Represents the physical wireless hardware - - Configured via `ietf-hardware` module - - Controls channel, transmit power, regulatory domain - - One radio can host multiple virtual interfaces + - Configured via `ietf-hardware` module + - Controls channel, transmit power, regulatory domain + - One radio can host multiple virtual interfaces 2. **WiFi Interface (Network layer)**: Virtual interface on a radio - - Configured via `infix-interfaces` module - - Can operate in Station (client) or Access Point mode - - Each interface references a parent radio + - Configured via `infix-interfaces` module + - Can operate in Station (client) or Access Point mode + - Each interface references a parent radio + +## Naming Conventions + +Like other interface types in Infix, WiFi components follow naming conventions +that allow the CLI to automatically infer types: + +| **Name Pattern** | **Type** | **Description** | +|------------------|-----------------|------------------------------------------| +| `radioN` | WiFi Radio | Hardware component for WiFi PHY | +| `wifiN` | WiFi Interface | Virtual WiFi interface on a radio | + +Where `N` is a number (0, 1, 2, ...). + +> [!TIP] +> Using these naming conventions simplifies configuration since type/class +> settings are automatically inferred. For example, creating a hardware +> component named `radio0` automatically sets its class to `wifi`, enabling +> the `wifi-radio` configuration container. +> +> **Note:** This inference only works with the CLI. Configuring WiFi over +> NETCONF or RESTCONF requires setting the class/type explicitly. ## Current Limitations @@ -31,15 +52,38 @@ Wi-Fi support is primarily tested with Realtek chipset-based adapters. ### Known Working Chipsets -- Built-in Wi-Fi on Banana Pi r3 +- Built-in Wi-Fi on Banana Pi BPi-R3 - Built-in Wi-Fi on Raspberry Pi 4/CM4 -- RTL8821CU -- Other Realtek chipsets may work but are not guaranteed +- Realtek: + - RTL8188CU + - RTL8188FU + - RTL8821CU + +Other Realtek chipsets may work but are not tested. +> [!NOTE] +> Some Realtek chipsets require proprietary drivers not included in the +> standard kernel. +> +> - Firmware requirements vary by chipset +> - Check kernel logs if your adapter is not detected -> [!NOTE] Some Realtek chipsets require proprietary drivers not included in the standard kernel -> Firmware requirements vary by chipset -> Check kernel logs if your adapter is not detected +### USB WiFi Dongles + +USB WiFi dongles may be slow to initialize at boot due to firmware +loading. If your USB dongle is not detected reliably, configure a +`probe-timeout` on the radio to wait for the PHY: + +
admin@example:/> configure
+admin@example:/config/> edit hardware component radio0 wifi-radio
+admin@example:/config/hardware/component/radio0/wifi-radio/> set probe-timeout 30
+admin@example:/config/hardware/component/radio0/wifi-radio/> leave
+
+ +This waits up to 30 seconds for the radio PHY to appear before creating +WiFi interfaces. If the PHY is not detected within the timeout, a dummy +interface is created as a placeholder, allowing IP configuration to proceed. +Reboot when the radio becomes available. ## Radio Configuration @@ -48,47 +92,73 @@ Radios are automatically discovered and named `radio0`, `radio1`, etc. ### Country Code and Regulatory Compliance -> [!IMPORTANT] -> The `country-code` setting is **legally required** and determines which WiFi channels and power levels are permitted in your location. Using an incorrect country code may violate local wireless regulations. - -**Factory default**: Systems may ship with a default country code (typically "DE" for Germany in European builds or "00" for World domain). **You must configure the correct country code for your deployment location.** - -**Common country codes**: -- Europe: DE (Germany), SE (Sweden), GB (UK), FR (France), ES (Spain) -- Americas: US (United States), CA (Canada), BR (Brazil) -- Asia-Pacific: JP (Japan), AU (Australia), CN (China) - -See [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) for the complete list. +The radio defaults to "00" for World domain, but some systems may ship with a +factory default country code (typically "DE" for the BPi-R3). + +> [!IMPORTANT] Legal notice! +> The `country-code` setting is **legally required** and determines +> which WiFi channels and power levels are permitted in your +> location. Using an incorrect country code may violate local wireless +> regulations. + +**Common country codes, see [ISO 3166-1 alpha-2][1] for the complete list**: + +- Europe: + - DE: Germany + - SE: Sweden + - GB: UK + - FR: France + - ES: Spain +- Americas: + - US: United States + - CA: Canada + - BR: Brazil +- Asia-Pacific: + - JP: Japan + - AU: Australia + - CN: China ### Basic Radio Setup Configure the radio with channel, power, and regulatory domain. **For Station (client) mode:** -``` -admin@example:/> configure -admin@example:/config/> edit hardware component radio0 wifi-radio -admin@example:/config/hardware/component/radio0/wifi-radio/> set country-code DE -admin@example:/config/hardware/component/radio0/wifi-radio/> leave -``` + +
admin@example:/> configure
+admin@example:/config/> edit hardware component radio0 wifi-radio
+admin@example:/config/hardware/component/radio0/wifi-radio/> set country-code DE
+admin@example:/config/hardware/component/radio0/wifi-radio/> leave
+
**For Access Point mode:** -``` -admin@example:/> configure -admin@example:/config/> edit hardware component radio0 wifi-radio -admin@example:/config/hardware/component/radio0/wifi-radio/> set country-code DE -admin@example:/config/hardware/component/radio0/wifi-radio/> set band 5GHz -admin@example:/config/hardware/component/radio0/wifi-radio/> set channel 36 -admin@example:/config/hardware/component/radio0/wifi-radio/> leave -``` + +
admin@example:/> configure
+admin@example:/config/> edit hardware component radio0 wifi-radio
+admin@example:/config/hardware/component/radio0/wifi-radio/> set country-code DE
+admin@example:/config/hardware/component/radio0/wifi-radio/> set band 5GHz
+admin@example:/config/hardware/component/radio0/wifi-radio/> set channel 36
+admin@example:/config/hardware/component/radio0/wifi-radio/> leave
+
**Key radio parameters:** -- `country-code`: Two-letter ISO 3166-1 code - determines allowed channels and maximum power. Examples: US, DE, GB, SE, FR, JP. **Must match your physical location for legal compliance.** -- `band`: 2.4GHz, 5GHz, or 6GHz (required for AP mode). Automatically enables appropriate WiFi standards (2.4GHz: 802.11n/ax, 5GHz: 802.11n/ac/ax, 6GHz: 802.11ax) -- `channel`: Channel number (1-196) or "auto" (required for AP mode). When set to "auto", defaults to channel 6 for 2.4GHz, channel 36 for 5GHz, or channel 109 for 6GHz + +- `country-code`: Two-letter [ISO 3166-1 alpha-2][1] code, determines allowed + channels and maximum power. Examples: US, DE, GB, SE, FR, JP. + **⚠ Must match your physical location for legal compliance! ⚠** +- `band`: 2.4GHz, 5GHz, or 6GHz (required for AP mode). Automatically enables + appropriate WiFi standards: + - 2.4GHz: 802.11n/ax + - 5GHz: 802.11n/ac/ax + - 6GHz: 802.11ax +- `channel`: Channel number (1-196) or "auto". When set to "auto", defaults to + channel 6 for 2.4GHz, channel 36 for 5GHz, or channel 109 for 6GHz +- `probe-timeout`: Seconds to wait for PHY detection at boot (default: 0). Set + to a non-zero value (e.g., 30) for USB WiFi dongles that are slow to + initialize due to firmware loading > [!NOTE] -> TX power and channel width are automatically determined by the driver based on regulatory constraints, PHY mode, and hardware capabilities. +> TX power and channel width are automatically determined by the driver +> based on regulatory constraints, PHY mode, and hardware capabilities. ### WiFi 6 (802.11ax) Support @@ -96,16 +166,18 @@ WiFi 6 (802.11ax) is always enabled in AP mode on all bands, providing improved performance through features like OFDMA, BSS Coloring, and beamforming. **WiFi 6 Features (always enabled):** + - **OFDMA**: Better multi-user efficiency in dense environments - **BSS Coloring**: Reduced interference from neighboring networks - **Beamforming**: Improved signal quality and range **Requirements:** + - Hardware must support 802.11ax - Client devices must support WiFi 6 for full benefits - Older WiFi 5/4 clients can still connect but won't use WiFi 6 features -## Discovering Available Networks (Scanning) +## Discovering Available Networks Before connecting to a WiFi network, you need to discover which networks are available. Infix automatically scans for networks when a WiFi interface @@ -118,21 +190,19 @@ interface referencing it: **Step 1: Configure the radio** -``` -admin@example:/> configure -admin@example:/config/> edit hardware component radio0 wifi-radio -admin@example:/config/hardware/component/radio0/wifi-radio/> set country-code DE -admin@example:/config/hardware/component/radio0/wifi-radio/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit hardware component radio0 wifi-radio
+admin@example:/config/hardware/component/radio0/wifi-radio/> set country-code DE
+admin@example:/config/hardware/component/radio0/wifi-radio/> leave
+
**Step 2: Create WiFi interface with radio reference only** -``` -admin@example:/> configure -admin@example:/config/> edit interface wifi0 -admin@example:/config/interface/wifi0/> set wifi radio radio0 -admin@example:/config/interface/wifi0/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit interface wifi0
+admin@example:/config/interface/wifi0/> set wifi radio radio0
+admin@example:/config/interface/wifi0/> leave
+
The system will now start scanning in the background. The interface will operate in scan-only mode until you configure a specific mode (station or @@ -142,25 +212,30 @@ access-point). Use `show interface` to see discovered networks and their signal strength: -``` -admin@example:/> show interface wifi0 +
admin@example:/> show interface wifi0
 name                : wifi0
 type                : wifi
 index               : 3
 mtu                 : 1500
-operational status  : down
+operational status  : up
+ip forwarding       : enabled
 physical address    : f0:09:0d:36:5f:86
-ipv4 addresses      :
+ipv4 addresses      : 192.168.1.100/24 (dhcp)
 ipv6 addresses      :
-SSID                : ----
-Signal              : ----
-
-SSID                                    SECURITY                      SIGNAL
-MyNetwork                               WPA2-Personal                 excellent
-GuestWiFi                               WPA2-WPA3-Personal            good
-CoffeeShop                              Open                          fair
-IoT-Devices                             WPA2-Personal                 good
-```
+in-octets           : 148388
+out-octets          : 24555
+mode                : station
+ssid                : MyNetwork
+signal              : -45 dBm (good)
+rx bitrate          : 72.2 Mbps
+tx bitrate          : 86.6 Mbps
+──────────────────────────────────────────────────────────────────────
+Available Networks
+SSID                 BSSID              SECURITY       SIGNAL  CHANNEL
+MyNetwork            b4:fb:e4:17:b6:a7  WPA2-Personal  good          6
+GuestWiFi            c8:3a:35:12:34:56  WPA2-Personal  fair         11
+CoffeeShop           00:1a:2b:3c:4d:5e  Open           bad           1
+
In the CLI, signal strength is reported as: excellent, good, fair or bad. For precise RSSI values in dBm, use NETCONF or RESTCONF to access the @@ -176,43 +251,44 @@ scan for available networks and identify the SSID you want to connect to. Create a keystore entry for your WiFi password (8-63 characters): -``` -admin@example:/> configure -admin@example:/config/> edit keystore symmetric-key my-wifi-key -admin@example:/config/keystore/…/my-wifi-key/> set key-format wifi-preshared-key-format -admin@example:/config/keystore/…/my-wifi-key/> set symmetric-key MyPassword123 -admin@example:/config/keystore/…/my-wifi-key/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit keystore symmetric-key my-wifi-key
+admin@example:/config/keystore/…/my-wifi-key/> set key-format wifi-preshared-key-format
+admin@example:/config/keystore/…/my-wifi-key/> set symmetric-key MyPassword123
+admin@example:/config/keystore/…/my-wifi-key/> leave
+
### Step 2: Connect to Network Configure station mode with the SSID and password to connect: -``` -admin@example:/> configure -admin@example:/config/> edit interface wifi0 -admin@example:/config/interface/wifi0/> set wifi station ssid MyHomeNetwork -admin@example:/config/interface/wifi0/> set wifi station security secret my-wifi-key -admin@example:/config/interface/wifi0/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit interface wifi0
+admin@example:/config/interface/wifi0/> set wifi station ssid MyHomeNetwork
+admin@example:/config/interface/wifi0/> set wifi station security secret my-wifi-key
+admin@example:/config/interface/wifi0/> leave
+
The connection attempt will start immediately. You can verify the connection status: -``` -admin@example:/> show interface wifi0 +
admin@example:/> show interface wifi0
 name                : wifi0
 type                : wifi
 operational status  : up
 physical address    : f0:09:0d:36:5f:86
 SSID                : MyHomeNetwork
 Signal              : excellent
-```
+
**Station configuration parameters:** + - `radio`: Reference to the WiFi radio (mandatory) - already set during scanning - `station ssid`: Network name to connect to (mandatory) -- `station security mode`: `auto` (default, WPA2/WPA3 auto-negotiation) or `disabled` (open network) -- `station security secret`: Reference to keystore entry (required unless mode is `disabled`) +- `station security mode`: + - `auto`: default, WPA2/WPA3 auto-negotiation + - `disabled`: open network +- `station security secret`: Reference to keystore entry, required unless mode + is `disabled` > [!NOTE] > The `auto` security mode automatically selects WPA3-SAE or WPA2-PSK based on @@ -228,23 +304,33 @@ a WiFi radio. ### Basic AP Configuration First, ensure the radio is configured (see Radio Configuration above). Then -create an AP interface: - -``` -admin@example:/> configure -admin@example:/config/> edit interface wifi0 -admin@example:/config/interface/wifi0/> set wifi radio radio0 -admin@example:/config/interface/wifi0/> set wifi access-point ssid MyNetwork -admin@example:/config/interface/wifi0/> set wifi access-point security mode wpa2-personal -admin@example:/config/interface/wifi0/> set wifi access-point security secret example -admin@example:/config/interface/wifi0/> leave -``` +create a keystore entry for your WiFi password and configure the AP interface: + +**Step 1: Create keystore entry for the WiFi password** + +
admin@example:/> configure
+admin@example:/config/> edit keystore symmetric-key my-wifi-secret
+admin@example:/config/keystore/…/my-wifi-secret/> set key-format wifi-preshared-key-format
+admin@example:/config/keystore/…/my-wifi-secret/> set symmetric-key MySecurePassword123
+admin@example:/config/keystore/…/my-wifi-secret/> end
+
+ +**Step 2: Create the AP interface** + +
admin@example:/config/> edit interface wifi0
+admin@example:/config/interface/wifi0/> set wifi radio radio0
+admin@example:/config/interface/wifi0/> set wifi access-point ssid MyNetwork
+admin@example:/config/interface/wifi0/> set wifi access-point security mode wpa2-personal
+admin@example:/config/interface/wifi0/> set wifi access-point security secret my-wifi-secret
+admin@example:/config/interface/wifi0/> leave
+
> [!NOTE] > Using `wifiN` as the interface name automatically sets the type to WiFi. > Alternatively, you can use any name and explicitly set `type wifi`. **Access Point configuration parameters:** + - `radio`: Reference to the WiFi radio (mandatory) - `access-point ssid`: Network name (SSID) to broadcast - `access-point hidden`: Set to `true` to hide SSID (optional, default: false) @@ -252,6 +338,7 @@ admin@example:/config/interface/wifi0/> leave - `access-point security secret`: Reference to keystore entry (for secured networks) **Security modes:** + - `open`: No encryption (not recommended) - `wpa2-personal`: WPA2-PSK (most compatible) - `wpa3-personal`: WPA3-SAE (more secure, requires WPA3-capable clients) @@ -261,9 +348,8 @@ admin@example:/config/interface/wifi0/> leave To create a hidden network that doesn't broadcast its SSID: -``` -admin@example:/config/interface/wifi0/> set wifi access-point hidden true -``` +
admin@example:/config/interface/wifi0/> set wifi access-point hidden true
+
### Multi-SSID Configuration @@ -273,59 +359,56 @@ IoT devices, or segregating traffic into different VLANs. **Step 1: Configure the radio** (shared by all APs) -``` -admin@example:/> configure -admin@example:/config/> edit hardware component radio0 wifi-radio -admin@example:/config/hardware/component/radio0/wifi-radio/> set country-code DE -admin@example:/config/hardware/component/radio0/wifi-radio/> set band 5GHz -admin@example:/config/hardware/component/radio0/wifi-radio/> set channel 36 -admin@example:/config/hardware/component/radio0/wifi-radio/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit hardware component radio0 wifi-radio
+admin@example:/config/hardware/component/radio0/wifi-radio/> set country-code DE
+admin@example:/config/hardware/component/radio0/wifi-radio/> set band 5GHz
+admin@example:/config/hardware/component/radio0/wifi-radio/> set channel 36
+admin@example:/config/hardware/component/radio0/wifi-radio/> leave
+
**Step 2: Configure keystore secrets** -``` -admin@example:/> configure -admin@example:/config/> edit keystore symmetric-key main-secret -admin@example:/config/keystore/…/main-secret/> set key-format wifi-preshared-key-format -admin@example:/config/keystore/…/main-secret/> set symmetric-key MyMainPassword -admin@example:/config/> edit keystore symmetric-key guest-secret -admin@example:/config/keystore/…/guest-secret/> set key-format wifi-preshared-key-format -admin@example:/config/keystore/…/guest-secret/> set symmetric-key GuestPassword123 -admin@example:/config/> edit keystore symmetric-key iot-secret -admin@example:/config/keystore/…/iot-secret/> set key-format wifi-preshared-key-format -admin@example:/config/keystore/…/iot-secret/> set symmetric-key IoTDevices2025 -admin@example:/config/keystore/…/iot-secret/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit keystore symmetric-key main-secret
+admin@example:/config/keystore/…/main-secret/> set key-format wifi-preshared-key-format
+admin@example:/config/keystore/…/main-secret/> set symmetric-key MyMainPassword
+admin@example:/config/> edit keystore symmetric-key guest-secret
+admin@example:/config/keystore/…/guest-secret/> set key-format wifi-preshared-key-format
+admin@example:/config/keystore/…/guest-secret/> set symmetric-key GuestPassword123
+admin@example:/config/> edit keystore symmetric-key iot-secret
+admin@example:/config/keystore/…/iot-secret/> set key-format wifi-preshared-key-format
+admin@example:/config/keystore/…/iot-secret/> set symmetric-key IoTDevices2025
+admin@example:/config/keystore/…/iot-secret/> leave
+
**Step 3: Create multiple AP interfaces** (all on radio0) -``` -admin@example:/> configure +
admin@example:/> configure
 # Primary AP - Main network (WPA3 for maximum security)
-admin@example:/config/> edit interface wifi0
-admin@example:/config/interface/wifi0/> set wifi radio radio0
-admin@example:/config/interface/wifi0/> set wifi access-point ssid MainNetwork
-admin@example:/config/interface/wifi0/> set wifi access-point security mode wpa3-personal
-admin@example:/config/interface/wifi0/> set wifi access-point security secret main-secret
+admin@example:/config/> edit interface wifi0
+admin@example:/config/interface/wifi0/> set wifi radio radio0
+admin@example:/config/interface/wifi0/> set wifi access-point ssid MainNetwork
+admin@example:/config/interface/wifi0/> set wifi access-point security mode wpa3-personal
+admin@example:/config/interface/wifi0/> set wifi access-point security secret main-secret
 
 # Guest AP - Guest network (WPA2/WPA3 mixed for compatibility)
-admin@example:/config/> edit interface wifi1
-admin@example:/config/interface/wifi1/> set wifi radio radio0
-admin@example:/config/interface/wifi1/> set wifi access-point ssid GuestNetwork
-admin@example:/config/interface/wifi1/> set wifi access-point security mode wpa2-wpa3-personal
-admin@example:/config/interface/wifi1/> set wifi access-point security secret guest-secret
-admin@example:/config/interface/wifi1/> set custom-phys-address static 00:0c:43:26:60:01
+admin@example:/config/> edit interface wifi1
+admin@example:/config/interface/wifi1/> set wifi radio radio0
+admin@example:/config/interface/wifi1/> set wifi access-point ssid GuestNetwork
+admin@example:/config/interface/wifi1/> set wifi access-point security mode wpa2-wpa3-personal
+admin@example:/config/interface/wifi1/> set wifi access-point security secret guest-secret
+admin@example:/config/interface/wifi1/> set custom-phys-address static 00:0c:43:26:60:01
 
 # IoT AP - IoT devices (WPA2 for older device compatibility)
-admin@example:/config/> edit interface wifi2
-admin@example:/config/interface/wifi2/> set wifi radio radio0
-admin@example:/config/interface/wifi2/> set wifi access-point ssid IoT-Devices
-admin@example:/config/interface/wifi2/> set wifi access-point security mode wpa2-personal
-admin@example:/config/interface/wifi2/> set wifi access-point security secret iot-secret
-admin@example:/config/interface/wifi2/> set custom-phys-address static 00:0c:43:26:60:02
-admin@example:/config/interface/wifi2/> leave
-```
+admin@example:/config/> edit interface wifi2
+admin@example:/config/interface/wifi2/> set wifi radio radio0
+admin@example:/config/interface/wifi2/> set wifi access-point ssid IoT-Devices
+admin@example:/config/interface/wifi2/> set wifi access-point security mode wpa2-personal
+admin@example:/config/interface/wifi2/> set wifi access-point security secret iot-secret
+admin@example:/config/interface/wifi2/> set custom-phys-address static 00:0c:43:26:60:02
+admin@example:/config/interface/wifi2/> leave
+
> [!IMPORTANT] > **MAC Address Requirement for Multi-SSID:** @@ -342,12 +425,14 @@ admin@example:/config/interface/wifi2/> leave > - Tertiary (wifi2): `00:0c:43:26:60:02` (increment last octet) **Result:** Three SSIDs broadcasting simultaneously on radio0: + - `MainNetwork` (WPA3, most secure) - `GuestNetwork` (WPA2/WPA3 mixed mode) - `IoT-Devices` (WPA2 for compatibility) All APs on the same radio share the same channel and physical layer settings (configured at the radio level). Each AP can have its own: + - SSID (network name) - Security mode and passphrase - Hidden/visible SSID setting @@ -365,25 +450,32 @@ radio settings, and `show interface` to see all active AP interfaces. WiFi AP interfaces can be added to bridges to integrate wireless devices into your LAN: -``` -admin@example:/> configure -admin@example:/config/> edit interface br0 -admin@example:/config/interface/br0/> set type bridge +
admin@example:/> configure
+admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> set type bridge
 
-admin@example:/config/> edit interface wifi0
-admin@example:/config/interface/wifi0/> set bridge-port bridge br0
-admin@example:/config/interface/wifi0/> leave
-```
+admin@example:/config/> edit interface wifi0
+admin@example:/config/interface/wifi0/> set bridge-port bridge br0
+admin@example:/config/interface/wifi0/> leave
+
-## Troubleshooting Connection Issues +## Troubleshooting Use `show interface wifi0` to verify signal strength and connection status. If issues arise, try the following troubleshooting steps: -1. **Verify signal strength**: Check that the target network shows "good" or "excellent" signal in scan results -2. **Check credentials**: Verify the preshared key in the keystore matches the network password -3. **Review logs**: Check system logs with `show log` for Wi-Fi related errors -4. **Regulatory compliance**: Ensure the country-code on the radio matches your location -5. **Hardware detection**: Confirm the WiFi radio appears in `show hardware` - -If issues persist, check the system log for specific error messages that can help identify the root cause. +1. **Verify signal strength**: Check that the target network shows + "good" or "excellent" signal in scan results +2. **Check credentials**: Verify the preshared key in the keystore + matches the network password +3. **Review logs**: Check system logs with `show log` for Wi-Fi related + errors +4. **Regulatory compliance**: Ensure the country-code on the radio + matches your location +5. **Hardware detection**: Confirm the WiFi radio appears in `show + hardware` + +If issues persist, check the system log for specific error messages that +can help identify the root cause. + +[1]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 From c19f62ff7000b2536e295369e544abbd19bd189d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 22:42:22 +0100 Subject: [PATCH 24/29] doc: update firewall and networking guides to new example format Signed-off-by: Joachim Wiberg --- doc/firewall.md | 38 +- doc/networking.md | 938 +++++++++++++++++++++++----------------------- 2 files changed, 486 insertions(+), 490 deletions(-) diff --git a/doc/firewall.md b/doc/firewall.md index c10a0498d..b685b02bf 100644 --- a/doc/firewall.md +++ b/doc/firewall.md @@ -151,7 +151,8 @@ allowed access to. See the [examples below](#enterprise-gateway) for how to set up a policy. The built-in help system can also be useful: -
admin@example:/config/firewall/policy/lan-to-dmz/> help masquerade
+
+
admin@example:/config/firewall/policy/lan-to-dmz/> help masquerade
 NAME
         masquerade 
DESCRIPTION @@ -159,7 +160,7 @@ built-in help system can also be useful: Matching traffic will have their source IP address changed on egress, using the IP address of the interface the traffic egresses.
admin@example:/config/firewall/policy/lan-to-dmz/> -
+
### Symbolic Names @@ -229,7 +230,8 @@ The firewall includes over 100 pre-defined services, such as: This is the default firewall setup, useful for end devices on untrusted networks. It provides maximum protection while allowing essential connectivity. -
admin@example:/> configure
+
+
admin@example:/> configure
 admin@example:/config/> edit firewall
 admin@example:/config/firewall/> show
 default public;
@@ -240,21 +242,21 @@ zone public {
   service ssh;
 }
 admin@example:/config/firewall/> leave
-
+
The `reject` action differs from `drop` in that it responds to ICMP messages, although maybe not how you may think. Pinging the device we may[^1] see this: -
-$ ping 192.168.122.161
+
+
$ ping 192.168.122.161
 From 192.168.122.161 icmp_seq=1 Packet filtered
-
+
If we run `tcpdump` it shows us why: -
-$ tcpdump -lni eth0
+
+
$ tcpdump -lni eth0
 20:10:40.245707 IP 192.168.122.1 > 192.168.122.161: ICMP echo request, id 56838, seq 1, length 64
 20:10:40.245961 IP 192.168.122.161 > 192.168.122.1: ICMP host 192.168.122.161 unreachable - admin prohibited filter, length 92
-
+
The key here is that, yes the device responds, but not with `ICMP reply` but `ICMP unreachable`, and a little helpful message. @@ -285,7 +287,8 @@ Zone matrix and firewall overview from show firewall. For typical routers that need to protect internal devices while providing internet access. The LAN zone trusts internal devices, while the WAN zone blocks external threats. -
admin@example:/> configure
+
+
admin@example:/> configure
 admin@example:/config/> edit firewall
 admin@example:/config/firewall/> set default wan
 admin@example:/config/firewall/> edit zone lan
@@ -308,14 +311,15 @@ admin@example:/config/firewall/…/loc-to-wan/> set egress wan
 admin@example:/config/firewall/…/loc-to-wan/> set action accept
 admin@example:/config/firewall/…/loc-to-wan/> set masquerade
 admin@example:/config/firewall/…/loc-to-wan/> leave
-
+
### Enterprise Gateway For businesses that need to host public services while protecting internal resources. We can build upon the Home/Office Router example above and add a DMZ zone with additional policies for controlled access. -
admin@example:/> configure
+
+
admin@example:/> configure
 admin@example:/config/> edit firewall zone dmz
 admin@example:/config/firewall/…/dmz/> set description "Semi-trusted public services"
 admin@example:/config/firewall/…/dmz/> set action drop
@@ -339,7 +343,7 @@ admin@example:/config/firewall/> edit zone wan port-forward 8080 tcp
 admin@example:/config/firewall/…/tcp/> set to addr 192.168.2.10
 admin@example:/config/firewall/…/tcp/> set to port 80
 admin@example:/config/firewall/…/tcp/> leave
-
+
This adds a DMZ zone for public services, updates the internet access policy to include DMZ traffic, allows LAN management of DMZ services, and forwards @@ -349,12 +353,12 @@ external web traffic to the DMZ server. Different log levels are available to monitor and debug firewall behavior. Configure logging using the CLI: -
-admin@example:/> configure
+
+
admin@example:/> configure
 admin@example:/config/> edit firewall
 admin@example:/config/firewall/> set logging all
 admin@example:/config/firewall/> leave
-
+
Firewall logs help you understand traffic patterns and security events. The CLI admin-exec command show firewall shows the last 10 log messages in the diff --git a/doc/networking.md b/doc/networking.md index e67974656..6867d6d00 100644 --- a/doc/networking.md +++ b/doc/networking.md @@ -112,37 +112,37 @@ for remote debugging, e.g., using the operational datastore. #### Fixed custom MAC -``` -admin@example:/config/> edit interface veth0a -admin@example:/config/interface/veth0a/> set custom-phys-address static 00:ab:00:11:22:33 +Use a fixed custom MAC address when the interface must present a +specific, deterministic identity on the network. This option bypasses +any chassis-derived logic and applies the configured address verbatim. + +
admin@example:/config/> edit interface veth0a
+admin@example:/config/interface/veth0a/> set custom-phys-address static 00:ab:00:11:22:33
 
 => 00:ab:00:11:22:33
-```
+
#### Chassis MAC Chassis MAC, sometimes also referred to as base MAC. In these two examples it is `00:53:00:c0:ff:ee`. -``` -admin@example:/config/> edit interface veth0a -admin@example:/config/interface/veth0a/> set custom-phys-address chassis +
admin@example:/config/> edit interface veth0a
+admin@example:/config/interface/veth0a/> set custom-phys-address chassis
 
 => 00:53:00:c0:ff:ee
-```
+
#### Chassis MAC, with offset When constructing a derived address it is recommended to set the locally administered bit. Same chassis MAC as before. -``` -admin@example:/config/> edit interface veth0a -admin@example:/config/interface/veth0a/> set custom-phys-address chassis offset 02:00:00:00:00:02 +
admin@example:/config/> edit interface veth0a
+admin@example:/config/interface/veth0a/> set custom-phys-address chassis offset 02:00:00:00:00:02
 
 => 02:53:00:c0:ff:f0
-```
-
+
### Bridging @@ -158,14 +158,13 @@ specific factory config sets it up this way. To enable switching, with offloading if you have a switch chipset, between ports you create a bridge and then add ports to that bridge. Like this: -``` -admin@example:/> configure -admin@example:/config/> edit interface br0 -admin@example:/config/interface/br0/> up -admin@example:/config/> set interface eth0 bridge-port bridge br0 -admin@example:/config/> set interface eth1 bridge-port bridge br0 -admin@example:/config/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> up
+admin@example:/config/> set interface eth0 bridge-port bridge br0
+admin@example:/config/> set interface eth1 bridge-port bridge br0
+admin@example:/config/> leave
+
Here we add two ports to bridge `br0`: `eth0` and `eth1`. @@ -195,17 +194,16 @@ or untagged member. Use the port default VID (PVID) setting to control VLAN association for traffic ingressing a port untagged (default PVID: 1). -``` -admin@example:/config/> edit interface br0 -admin@example:/config/interface/br0/> up -admin@example:/config/> set interface eth0 bridge-port bridge br0 -admin@example:/config/> set interface eth0 bridge-port pvid 10 -admin@example:/config/> set interface eth1 bridge-port bridge br0 -admin@example:/config/> set interface eth1 bridge-port pvid 20 -admin@example:/config/> edit interface br0 -admin@example:/config/interface/br0/> set bridge vlans vlan 10 untagged eth0 -admin@example:/config/interface/br0/> set bridge vlans vlan 20 untagged eth1 -``` +
admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> up
+admin@example:/config/> set interface eth0 bridge-port bridge br0
+admin@example:/config/> set interface eth0 bridge-port pvid 10
+admin@example:/config/> set interface eth1 bridge-port bridge br0
+admin@example:/config/> set interface eth1 bridge-port pvid 20
+admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> set bridge vlans vlan 10 untagged eth0
+admin@example:/config/interface/br0/> set bridge vlans vlan 20 untagged eth1
+
This sets `eth0` as an untagged member of VLAN 10 and `eth1` as an untagged member of VLAN 20. Switching between these ports is thus @@ -216,10 +214,9 @@ prohibited. To terminate a VLAN in the switch itself, either for switch management or for routing, the bridge must become a (tagged) member of the VLAN. -``` -admin@example:/config/interface/br0/> set bridge vlans vlan 10 tagged br0 -admin@example:/config/interface/br0/> set bridge vlans vlan 20 tagged br0 -``` +
admin@example:/config/interface/br0/> set bridge vlans vlan 10 tagged br0
+admin@example:/config/interface/br0/> set bridge vlans vlan 20 tagged br0
+
To route or to manage via a VLAN, a VLAN interface needs to be created on top of the bridge, see section [VLAN Interfaces](#vlan-interfaces) @@ -255,21 +252,19 @@ settings in this operating mode. In the following example we have a regular 8-port bridge without VLAN filtering. We focus on the multicast specific settings: -``` -admin@example:/> configure -admin@example:/config/> edit interface br0 -admin@example:/config/interface/br0/> set bridge multicast snooping -admin@example:/config/interface/br0/> set ipv4 address 192.168.2.1 prefix-length 24 -admin@example:/config/interface/br0/> leave -admin@example:/> copy running-config startup-config -``` +
admin@example:/> configure
+admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> set bridge multicast snooping
+admin@example:/config/interface/br0/> set ipv4 address 192.168.2.1 prefix-length 24
+admin@example:/config/interface/br0/> leave
+admin@example:/> copy running-config startup-config
+
Here we enable snooping and set a static IPv4 address so that the switch can take part in IGMP querier elections. (MLD querier election currently not supported.) We can inspect the current state: -``` -admin@example:/> show ip multicast +
admin@example:/> show ip multicast
 Multicast Overview
 Query Interval (default): 125 sec
 Router Timeout          : 255
@@ -277,13 +272,13 @@ Fast Leave Ports        :
 Router Ports            :
 Flood Ports             : e0, e1, e2, e3, e4, e5, e6, e7
 
-Interface       VID  Querier                     State  Interval  Timeout  Ver
+Interface       VID  Querier                     State  Interval  Timeout  Ver
 br0                  192.168.2.1                    Up       125     None    3
 
-Bridge          VID  Multicast Group       Ports
+Bridge          VID  Multicast Group       Ports                              
 br0                  224.1.1.1             e3, e2
 br0                  ff02::6a              br0
-```
+
This is a rather small LAN, so our bridge has already become the elected IGMP querier. We see it is ours because the timeout is `None`, and we @@ -296,19 +291,17 @@ VLAN filtering enabled. We skip the boring parts about how to move ports e4-e7 to `br1` and assign them to VLANs, and again, focus on the multicast bits only: -``` -admin@example:/> configure -admin@example:/config/> edit interface br1 -admin@example:/config/interface/br1/> set bridge vlans vlan 1 multicast snooping -admin@example:/config/interface/br1/> set bridge vlans vlan 2 multicast snooping -admin@example:/config/interface/br1/> leave -admin@example:/> copy running-config startup-config -``` +
admin@example:/> configure
+admin@example:/config/> edit interface br1
+admin@example:/config/interface/br1/> set bridge vlans vlan 1 multicast snooping
+admin@example:/config/interface/br1/> set bridge vlans vlan 2 multicast snooping
+admin@example:/config/interface/br1/> leave
+admin@example:/> copy running-config startup-config
+
Let us see what we get: -``` -admin@example:/> show ip multicast +
admin@example:/> show ip multicast
 Multicast Overview
 Query Interval (default): 125 sec
 Router Timeout          : 255
@@ -316,12 +309,12 @@ Fast Leave Ports        : e5
 Router Ports            : e1, e2, e5, e6, e7
 Flood Ports             : e1, e2, e3, e4, e5, e6, e7, e8
 
-Interface       VID  Querier                     State  Interval  Timeout  Ver
+Interface       VID  Querier                     State  Interval  Timeout  Ver
 br0                  192.168.2.1                    Up       125     None    3
 br1               1  0.0.0.0                        Up       125     None    3
 br1               2  0.0.0.0                        Up       125     None    3
 
-Bridge          VID  Multicast Group       Ports
+Bridge          VID  Multicast Group       Ports                              
 br0                  224.1.1.1             e2
 br0                  ff02::fb              br0
 br0                  ff02::6a              br0
@@ -330,7 +323,7 @@ br1               1  224.1.1.1             e5
 br1               2  224.1.1.1             e7
 br1               1  ff02::fb              br1
 br1               1  ff02::1:ff00:0        br1
-```
+
In this setup we have a lot more going on. Multiple multicast router ports have been detected, and behind the scenes someone has also added @@ -412,23 +405,21 @@ sometimes useful to let the bridge forward such packets, this can be done by specifying protocol names or the last address *nibble* as decimal value `0..15`: -``` -admin@example:/config/> edit interface br0 bridge -admin@example:/config/interface/br0/bridge/> set ieee-group-forward # Tap the ? ley for alternatives +
admin@example:/config/> edit interface br0 bridge
+admin@example:/config/interface/br0/bridge/> set ieee-group-forward     # Tap the ? key for alternatives
   [0..15]  List of IEEE link-local protocols to forward, e.g., STP, LLDP
   dot1x    802.1X Port-Based Network Access Control.
   lacp     802.3 Slow Protocols, e.g., LACP.
   lldp     802.1AB Link Layer Discovery Protocol (LLDP).
   stp      Spanning Tree (STP/RSPT/MSTP).
-admin@example:/config/interface/br0/bridge/> set ieee-group-forward
-```
+admin@example:/config/interface/br0/bridge/> set ieee-group-forward
+
The following example configures bridge *br0* to forward LLDP packets. -``` -admin@example:/config/interface/br0/bridge/> set ieee-group-forward lldp +
admin@example:/config/interface/br0/bridge/> set ieee-group-forward lldp
 admin@example:/config/interface/br0/bridge/>
-```
+
### Link Aggregation @@ -462,15 +453,14 @@ for communication between two specific devices. Creating a link aggregate interface and adding member ports: -``` -admin@example:/> configure -admin@example:/config/> edit interface lag0 -admin@example:/config/interface/lag0/> set lag mode static -admin@example:/config/interface/lag0/> end -admin@example:/config/> set interface eth7 lag-port lag lag0 -admin@example:/config/> set interface eth8 lag-port lag lag0 -admin@example:/config/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit interface lag0
+admin@example:/config/interface/lag0/> set lag mode static
+admin@example:/config/interface/lag0/> end
+admin@example:/config/> set interface eth7 lag-port lag lag0
+admin@example:/config/> set interface eth8 lag-port lag lag0
+admin@example:/config/> leave
+
A static lag responds only to link (carrier) changes of member ports. E.g., in this example egressing traffic is continuously distributed over @@ -483,14 +473,13 @@ traffic to be steered to the sole remaining link. LACP mode provides dynamic negotiation of the link aggregate. Key settings include: -``` -admin@example:/> configure -admin@example:/config/> edit interface lag0 -admin@example:/config/interface/lag0/> set lag mode lacp -admin@example:/config/interface/lag0/> set lag lacp mode passive -admin@example:/config/interface/lag0/> set lag lacp rate fast -admin@example:/config/interface/lag0/> set lag lacp system-priority 100 -``` +
admin@example:/> configure
+admin@example:/config/> edit interface lag0
+admin@example:/config/interface/lag0/> set lag mode lacp
+admin@example:/config/interface/lag0/> set lag lacp mode passive
+admin@example:/config/interface/lag0/> set lag lacp rate fast
+admin@example:/config/interface/lag0/> set lag lacp system-priority 100
+
LACP mode supports two operational modes: @@ -511,11 +500,10 @@ The LACP rate setting controls protocol timing: To protect against link flapping, debounce timers can be configured to delay link qualification. Usually only the `up` delay is needed: -``` -admin@example:/config/interface/lag0/lag/link-monitor/> edit debounce -admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set up 500 -admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set down 200 -``` +
admin@example:/config/interface/lag0/lag/link-monitor/> edit debounce
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set up 500
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set down 200
+
#### Operational Status, Overview @@ -523,9 +511,8 @@ Like other interfaces, link aggregates are also available in the general interfaces overview in the CLI admin-exec context. Here is the above static mode aggregate: -``` -admin@example:/> show interfaces -INTERFACE PROTOCOL STATE DATA +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
 lo              ethernet   UP          00:00:00:00:00:00
                 ipv4                   127.0.0.1/8 (static)
                 ipv6                   ::1/128 (static)
@@ -536,13 +523,12 @@ lag0            lag        UP          static: balance-xor, hash: layer2
 │               ethernet   UP          00:a0:85:00:02:00
 ├ eth7          lag        ACTIVE
 └ eth8          lag        ACTIVE
-```
+
Same aggregate, but in LACP mode: -``` -admin@example:/> show interfaces -INTERFACE PROTOCOL STATE DATA +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
 lo              ethernet   UP          00:00:00:00:00:00
                 ipv4                   127.0.0.1/8 (static)
                 ipv6                   ::1/128 (static)
@@ -553,7 +539,7 @@ lag0            lag        UP          lacp: active, rate: fast (1s), hash: laye
 │               ethernet   UP          00:a0:85:00:02:00
 ├ eth7          lag        ACTIVE      active, short_timeout, aggregating, in_sync, collecting, distributing
 └ eth8          lag        ACTIVE      active, short_timeout, aggregating, in_sync, collecting, distributing
-```
+
#### Operational Status, Detail @@ -561,8 +547,7 @@ lag0 lag UP lacp: active, rate: fast (1s), hash: laye In addition to basic status shown in the interface overview, detailed LAG status can be inspected: -``` -admin@example:/> show interface lag0 +
admin@example:/> show interface lag0
 name                : lag0
 index               : 25
 mtu                 : 1500
@@ -577,12 +562,11 @@ ipv4 addresses      :
 ipv6 addresses      :
 in-octets           : 0
 out-octets          : 2142
-```
+
Same aggregate, but in LACP mode: -``` -admin@example:/> show interface lag0 +
admin@example:/> show interface lag0
 name                : lag0
 index               : 24
 mtu                 : 1500
@@ -603,7 +587,7 @@ ipv4 addresses      :
 ipv6 addresses      :
 in-octets           : 100892
 out-octets          : 111776
-```
+
Member ports provide additional status information: @@ -623,8 +607,7 @@ Member ports provide additional status information: Example member port status: -``` -admin@example:/> show interface eth7 +
admin@example:/> show interface eth7
 name                : eth7
 index               : 8
 mtu                 : 1500
@@ -640,7 +623,7 @@ ipv4 addresses      :
 ipv6 addresses      :
 in-octets           : 473244
 out-octets          : 499037
-```
+
#### Example: Switch Uplink with LACP @@ -650,43 +633,38 @@ the link aggregate and detecting configuration mismatches. A common use case is connecting a switch to an upstream device: -``` -admin@example:/> configure -admin@example:/config/> edit interface lag0 -admin@example:/config/interface/lag0/> set lag mode lacp -``` +
admin@example:/> configure
+admin@example:/config/> edit interface lag0
+admin@example:/config/interface/lag0/> set lag mode lacp
+
Enable fast LACP for quicker fail-over: -``` -admin@example:/config/interface/lag0/> set lag lacp rate fast -``` +
admin@example:/config/interface/lag0/> set lag lacp rate fast
+
Add uplink ports -``` -admin@example:/config/interface/lag0/> end -admin@example:/config/> set interface eth7 lag-port lag lag0 -admin@example:/config/> set interface eth8 lag-port lag lag0 -``` +
admin@example:/config/interface/lag0/> end
+admin@example:/config/> set interface eth7 lag-port lag lag0
+admin@example:/config/> set interface eth8 lag-port lag lag0
+
Enable protection against "link flapping". -``` -admin@example:/config/interface/lag0/> edit lag link-monitor -admin@example:/config/interface/lag0/lag/link-monitor/> edit debounce -admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set up 500 -admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set down 200 -admin@example:/config/interface/lag0/lag/link-monitor/debounce/> top -``` +
admin@example:/config/interface/lag0/> edit lag link-monitor
+admin@example:/config/interface/lag0/lag/link-monitor/> edit debounce
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set up 500
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set down 200
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> top
+
Add to bridge for switching -``` -admin@example:/config/interface/lag0/lag/link-monitor/debounce/> end -admin@example:/config/> set interface lag0 bridge-port bridge br0 -admin@example:/config/> leave -``` +
admin@example:/config/interface/lag0/lag/link-monitor/debounce/> end
+admin@example:/config/> set interface lag0 bridge-port bridge br0
+admin@example:/config/> leave
+
### VLAN Interfaces @@ -703,29 +681,27 @@ A VLAN interface is basically a filtering abstraction. When you run VLAN ID of the interface, compared to *all* the VLAN IDs if you run `tcpdump` on the lower-layer interface. -``` -admin@example:/> configure -admin@example:/config/> edit interface eth0.20 -admin@example:/config/interface/eth0.20/> show +
admin@example:/> configure
+admin@example:/config/> edit interface eth0.20
+admin@example:/config/interface/eth0.20/> show
 type vlan;
 vlan {
   tag-type c-vlan;
   id 20;
   lower-layer-if eth0;
 }
-admin@example:/config/interface/eth0.20/> leave
-```
+admin@example:/config/interface/eth0.20/> leave
+
The example below assumes bridge br0 is already created, see [VLAN Filtering Bridge](#vlan-filtering-bridge). -``` -admin@example:/> configure -admin@example:/config/> edit interface vlan10 -admin@example:/config/interface/vlan10/> set vlan id 10 -admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0 -admin@example:/config/interface/vlan10/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit interface vlan10
+admin@example:/config/interface/vlan10/> set vlan id 10
+admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0
+admin@example:/config/interface/vlan10/> leave
+
As conventions, a VLAN interface for VID 20 on top of an Ethernet interface *eth0* is named *eth0.20*, and a VLAN interface for VID 10 on @@ -754,8 +730,7 @@ highest speeds supported by H1 and H2 respectively. The speed and duplex status for the links can be listed as shown below, assuming the link operational status is 'up'. -``` -admin@example:/> show interface eth1 +
admin@example:/> show interface eth1
 name                : eth1
 index               : 2
 mtu                 : 1500
@@ -765,11 +740,11 @@ duplex              : full
 speed               : 1000
 physical address    : 00:53:00:06:11:01
 ipv4 addresses      :
-ipv6 addresses      : 
+ipv6 addresses      :
 in-octets           : 75581
 out-octets          : 43130
 ...
-admin@example:/> show interface eth4
+admin@example:/> show interface eth4
 name                : eth4
 index               : 5
 mtu                 : 1500
@@ -779,12 +754,12 @@ duplex              : full
 speed               : 100
 physical address    : 00:53:00:06:11:04
 ipv4 addresses      :
-ipv6 addresses      : 
+ipv6 addresses      :
 in-octets           : 75439
 out-octets          : 550704
 ...
 admin@example:/>
-```
+
#### Configuring fixed speed and duplex @@ -801,21 +776,20 @@ a fixed speed and duplex mode. The example below configures port eth3 to fixed speed 100 Mbit/s half-duplex mode. -``` -admin@example:/> configure -admin@example:/config/> edit interface eth3 ethernet -admin@example:/config/interface/eth3/ethernet/> set speed 0.1 -admin@example:/config/interface/eth3/ethernet/> set duplex half -admin@example:/config/interface/eth3/ethernet/> set auto-negotiation enable false -admin@example:/config/interface/eth3/ethernet/> show +
admin@example:/> configure
+admin@example:/config/> edit interface eth3 ethernet
+admin@example:/config/interface/eth3/ethernet/> set speed 0.1
+admin@example:/config/interface/eth3/ethernet/> set duplex half
+admin@example:/config/interface/eth3/ethernet/> set auto-negotiation enable false
+admin@example:/config/interface/eth3/ethernet/> show
 auto-negotiation {
   enable false;
 }
 duplex half;
 speed 0.1;
-admin@example:/config/interface/eth3/ethernet/> leave
-admin@example:/> 
-```
+admin@example:/config/interface/eth3/ethernet/> leave
+admin@example:/>
+
Speed metric is in Gbit/s. Auto-negotiation needs to be disabled in order for fixed speed/duplex to apply. Only speeds `0.1`(100 Mbit/s) @@ -826,8 +800,7 @@ require auto-negotiation to be enabled. Ethernet packet statistics[^6] can be listed as shown below. -``` -admin@example:/> show interface eth1 +
admin@example:/> show interface eth1
 name                : eth1
 index               : 2
 mtu                 : 1500
@@ -837,7 +810,7 @@ duplex              : full
 speed               : 1000
 physical address    : 00:53:00:06:11:0a
 ipv4 addresses      :
-ipv6 addresses      : 
+ipv6 addresses      :
 in-octets           : 75581
 out-octets          : 43130
 
@@ -851,8 +824,8 @@ eth-out-multicast-frames     : 310
 eth-out-broadcast-frames     : 0
 eth-out-good-octets          : 76821
 eth-in-good-octets           : 60598
-admin@example:/> 
-```
+admin@example:/>
+
### VETH Pairs @@ -865,12 +838,11 @@ The latter example is useful if you have multiple bridges in the system with different properties (VLAN filtering, IEEE group forwarding, etc.), but still want some way of communicating between these domains. -``` -admin@example:/> configure -admin@example:/config/> edit interface veth0a -admin@example:/config/interface/veth0a/> set veth peer veth0b -admin@example:/config/interface/veth0a/> end -admin@example:/config/> diff +
admin@example:/> configure
+admin@example:/config/> edit interface veth0a
+admin@example:/config/interface/veth0a/> set veth peer veth0b
+admin@example:/config/interface/veth0a/> end
+admin@example:/config/> diff
 interfaces {
 +  interface veth0a {
 +    type veth;
@@ -886,7 +858,7 @@ interfaces {
 +  }
 }
 admin@example:/config/>
-```
+
> [!TIP] > This is another example of the automatic inference of the interface @@ -1013,14 +985,15 @@ will be ignored. For details on how to enable the NTP client, see the ![Switch example (eth0 and lo)](img/ip-address-example-switch.svg) - admin@example:/> show interfaces - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv6 fe80::ff:fe00:0/64 (link-layer) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
To illustrate IP address configuration, the examples below uses a switch with a single Ethernet interface (eth0) and a loopback @@ -1032,32 +1005,33 @@ default. ![Setting static IPv4 (and link-local IPv4)](img/ip-address-example-ipv4-static.svg) - admin@example:/> configure - admin@example:/config/> edit interface eth0 ipv4 - admin@example:/config/interface/eth0/ipv4/> set address 10.0.1.1 prefix-length 24 - admin@example:/config/interface/eth0/ipv4/> set autoconf - admin@example:/config/interface/eth0/ipv4/> diff - +interfaces { - + interface eth0 { - + ipv4 { - + address 10.0.1.1 { - + prefix-length 24; - + } - + autoconf; - + } - + } - +} - admin@example:/config/interface/eth0/ipv4/> leave - admin@example:/> show interfaces - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv4 169.254.1.3/16 (random) - ipv4 10.0.1.1/24 (static) - ipv6 fe80::ff:fe00:0/64 (link-layer) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv4
+admin@example:/config/interface/eth0/ipv4/> set address 10.0.1.1 prefix-length 24
+admin@example:/config/interface/eth0/ipv4/> set autoconf
+admin@example:/config/interface/eth0/ipv4/> diff
++interfaces {
++  interface eth0 {
++    ipv4 {
++      address 10.0.1.1 {
++        prefix-length 24;
++      }
++      autoconf;
++    }
++  }
++}
+admin@example:/config/interface/eth0/ipv4/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv4                   169.254.1.3/16 (random)
+                ipv4                   10.0.1.1/24 (static)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
As shown, the link-local IPv4 address is configured with `set autoconf`. The presence of the `autoconf` container enables IPv4 link-local address @@ -1068,45 +1042,46 @@ The IPv4LL client also supports a `request-address` setting which can be used to "seed" the client's starting address. If the address is free it will be used, otherwise it falls back to the default algorithm. - admin@example:/config/interface/eth0/ipv4/> edit autoconf - admin@example:/config/interface/eth0/ipv4/autoconf/> set request-address 169.254.1.2 - admin@example:/config/interface/eth0/ipv4/autoconf/> leave +
admin@example:/config/interface/eth0/ipv4/> edit autoconf
+admin@example:/config/interface/eth0/ipv4/autoconf/> set request-address 169.254.1.2
+admin@example:/config/interface/eth0/ipv4/autoconf/> leave
+
#### Use of DHCP for IPv4 address assignment ![Using DHCP for IPv4 address assignment](img/ip-address-example-ipv4-dhcp.svg) - admin@example:/> configure - admin@example:/config/> edit interface eth0 ipv4 - admin@example:/config/interface/eth0/ipv4/> set dhcp - admin@example:/config/interface/eth0/ipv4/> leave - admin@example:/> show interfaces - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv4 10.1.2.100/24 (dhcp) - ipv6 fe80::ff:fe00:0/64 (link-layer) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv4
+admin@example:/config/interface/eth0/ipv4/> set dhcp
+admin@example:/config/interface/eth0/ipv4/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv4                   10.1.2.100/24 (dhcp)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
The resulting address (10.1.2.100/24) is of type *dhcp*. To configure DHCP client options, such as sending a specific hostname to the server, you can specify options with values: -``` -admin@example:/> configure -admin@example:/config/> edit interface eth0 ipv4 dhcp -admin@example:/config/interface/eth0/ipv4/dhcp/> set option hostname value myhost -admin@example:/config/interface/eth0/ipv4/dhcp/> show +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv4 dhcp
+admin@example:/config/interface/eth0/ipv4/dhcp/> set option hostname value myhost
+admin@example:/config/interface/eth0/ipv4/dhcp/> show
 option hostname {
   value myhost;
 }
-admin@example:/config/interface/eth0/ipv4/dhcp/> leave
+admin@example:/config/interface/eth0/ipv4/dhcp/> leave
 admin@example:/>
-```
+
> [!TIP] > The special value `auto` can be used with the hostname option to @@ -1123,50 +1098,49 @@ For advanced usage with vendor-specific options, see the YANG model. ![Using DHCPv6 for IPv6 address assignment](img/ip-address-example-ipv6-dhcp.svg) - admin@example:/> configure - admin@example:/config/> edit interface eth0 ipv6 - admin@example:/config/interface/eth0/ipv6/> set dhcp - admin@example:/config/interface/eth0/ipv6/> leave - admin@example:/> show interface - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv6 2001:db8::42/128 (dhcp) - ipv6 fe80::ff:fe00:0/64 (link-layer) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set dhcp
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interface
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8::42/128 (dhcp)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
The resulting address (2001:db8::42/128) is of type *dhcp*. To configure DHCPv6 client options, such as requesting prefix delegation for downstream networks, you can specify options: -``` -admin@example:/> configure -admin@example:/config/> edit interface eth0 ipv6 dhcp -admin@example:/config/interface/eth0/ipv6/dhcp/> set option ia-pd -admin@example:/config/interface/eth0/ipv6/dhcp/> set option dns-server -admin@example:/config/interface/eth0/ipv6/dhcp/> show +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6 dhcp
+admin@example:/config/interface/eth0/ipv6/dhcp/> set option ia-pd
+admin@example:/config/interface/eth0/ipv6/dhcp/> set option dns-server
+admin@example:/config/interface/eth0/ipv6/dhcp/> show
 option dns-server;
 option ia-pd;
-admin@example:/config/interface/eth0/ipv6/dhcp/> leave
+admin@example:/config/interface/eth0/ipv6/dhcp/> leave
 admin@example:/>
-```
+
For stateless DHCPv6 (used with SLAAC to get only configuration information): -``` -admin@example:/> configure -admin@example:/config/> edit interface eth0 ipv6 dhcp -admin@example:/config/interface/eth0/ipv6/dhcp/> set information-only true -admin@example:/config/interface/eth0/ipv6/dhcp/> show +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6 dhcp
+admin@example:/config/interface/eth0/ipv6/dhcp/> set information-only true
+admin@example:/config/interface/eth0/ipv6/dhcp/> show
 information-only true;
 option dns-server;
 option domain-search;
-admin@example:/config/interface/eth0/ipv6/dhcp/> leave
+admin@example:/config/interface/eth0/ipv6/dhcp/> leave
 admin@example:/>
-```
+
Other useful DHCPv6 options include: @@ -1181,37 +1155,37 @@ For advanced usage with vendor-specific options, see the YANG model. The (only) way to disable IPv6 link-local addresses is by disabling IPv6 on the interface. -``` -admin@example:/> configure -admin@example:/config/> edit interface eth0 ipv6 -admin@example:/config/interface/eth0/ipv6/> set enabled false -admin@example:/config/interface/eth0/ipv6/> leave -admin@example:/> show interfaces -INTERFACE PROTOCOL STATE DATA +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set enabled false
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
 eth0            ethernet   UP          02:00:00:00:00:00
 lo              ethernet   UP          00:00:00:00:00:00
                 ipv4                   127.0.0.1/8 (static)
                 ipv6                   ::1/128 (static)
 admin@example:/>
-```
+
#### Static IPv6 address ![Setting static IPv6](img/ip-address-example-ipv6-static.svg) - admin@example:/> configure - admin@example:/config/> edit interface eth0 ipv6 - admin@example:/config/interface/eth0/ipv6/> set address 2001:db8::1 prefix-length 64 - admin@example:/config/interface/eth0/ipv6/> leave - admin@example:/> show interfaces - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv6 2001:db8::1/64 (static) - ipv6 fe80::ff:fe00:0/64 (link-layer) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set address 2001:db8::1 prefix-length 64
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8::1/64 (static)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
#### Stateless Auto-configuration of Global IPv6 Address @@ -1224,31 +1198,33 @@ advertised by the router (here 2001:db8:0:1::0/64) and the interface identifier. The resulting address is of type *link-layer*, as it is formed based on the interface identifier ([ietf-ip.yang][2]). - admin@example:/> show interfaces - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv6 2001:db8:0:1:0:ff:fe00:0/64 (link-layer) - ipv6 fe80::ff:fe00:0/64 (link-layer) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8:0:1:0:ff:fe00:0/64 (link-layer)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
Disabling auto-configuration of global IPv6 addresses can be done as shown below. - admin@example:/> configure - admin@example:/config/> edit interface eth0 ipv6 - admin@example:/config/interface/eth0/ipv6/> set autoconf create-global-addresses false - admin@example:/config/interface/eth0/ipv6/> leave - admin@example:/> show interfaces - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv6 fe80::ff:fe00:0/64 (link-layer) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set autoconf create-global-addresses false
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
#### Random Link Identifiers for IPv6 Stateless Autoconfiguration @@ -1258,33 +1234,35 @@ below. By default, the auto-configured link-local and global IPv6 addresses are formed from a link-identifier based on the MAC address. - admin@example:/> show interfaces - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv6 2001:db8:0:1:0:ff:fe00:0/64 (link-layer) - ipv6 fe80::ff:fe00:0/64 (link-layer) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8:0:1:0:ff:fe00:0/64 (link-layer)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
To avoid revealing identity information in the IPv6 address, it is possible to specify use of a random identifier ([ietf-ip.yang][2] and [RFC8981][3]). - admin@example:/> configure - admin@example:/config/> edit interface eth0 ipv6 - admin@example:/config/interface/eth0/ipv6/> set autoconf create-temporary-addresses true - admin@example:/config/interface/eth0/ipv6/> leave - admin@example:/> show interfaces - INTERFACE PROTOCOL STATE DATA - eth0 ethernet UP 02:00:00:00:00:00 - ipv6 2001:db8:0:1:b705:8374:638e:74a8/64 (random) - ipv6 fe80::ad3d:b274:885a:9ffb/64 (random) - lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set autoconf create-temporary-addresses true
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8:0:1:b705:8374:638e:74a8/64 (random)
+                ipv6                   fe80::ad3d:b274:885a:9ffb/64 (random)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
Both the link-local address (fe80::) and the global address (2001:) have changed type to *random*. @@ -1296,12 +1274,11 @@ To be able to route (static or dynamic) on the interface it is required to enable forwarding. This setting controls if packets received on this interface can be forwarded. -``` -admin@example:/config/> edit interface eth0 -admin@example:/config/interface/eth0/> set ipv4 forwarding -admin@example:/config/interface/eth0/> leave +
admin@example:/config/> edit interface eth0
+admin@example:/config/interface/eth0/> set ipv4 forwarding
+admin@example:/config/interface/eth0/> leave
 admin@example:/>
-```
+
### IPv6 forwarding @@ -1321,12 +1298,11 @@ setting control when it is *Enabled* or *Disabled: | Router Advertisements are ignored | Yes | Yes | | Accept Redirects | No | Yes | -``` -admin@example:/config/> edit interface eth0 -admin@example:/config/interface/eth0/> set ipv6 forwarding -admin@example:/config/interface/eth0/> leave +
admin@example:/config/> edit interface eth0
+admin@example:/config/interface/eth0/> set ipv6 forwarding
+admin@example:/config/interface/eth0/> leave
 admin@example:/>
-```
+
## Routing support @@ -1360,20 +1336,22 @@ control plane protocol. For our examples we use the instance name For a route with destination 192.168.200.0/24 via 192.168.1.1: - admin@example:/> configure - admin@example:/config/> edit routing control-plane-protocol static name default ipv4 - admin@example:/config/routing/…/ipv4/> set route 192.168.200.0/24 next-hop next-hop-address 192.168.1.1 - admin@example:/config/routing/…/ipv4/> leave - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit routing control-plane-protocol static name default ipv4
+admin@example:/config/routing/…/ipv4/> set route 192.168.200.0/24 next-hop next-hop-address 192.168.1.1
+admin@example:/config/routing/…/ipv4/> leave
+admin@example:/>
+
For a "floating" static route with destination 10.0.0.0/16 via a backup router 192.168.1.1, using the highest possible distance: - admin@example:/> configure - admin@example:/config/> edit routing control-plane-protocol static name default ipv4 - admin@example:/config/routing/…/ipv4/> set route 10.0.0.0/16 next-hop next-hop-address 192.168.1.1 route-preference 254 - admin@example:/config/routing/…/ipv4/> leave - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit routing control-plane-protocol static name default ipv4
+admin@example:/config/routing/…/ipv4/> set route 10.0.0.0/16 next-hop next-hop-address 192.168.1.1 route-preference 254
+admin@example:/config/routing/…/ipv4/> leave
+admin@example:/>
+
> [!TIP] > Remember to enable [IPv4 forwarding](#ipv4-forwarding) for the @@ -1382,11 +1360,12 @@ router 192.168.1.1, using the highest possible distance: ### IPv6 Static routes - admin@example:/> configure - admin@example:/config/> edit routing control-plane-protocol static name default ipv6 - admin@example:/config/routing/…/ipv6/> set route 2001:db8:3c4d:200::/64 next-hop next-hop-address 2001:db8:3c4d:1::1 - admin@example:/config/routing/…/ipv6/> leave - admin@example:/> +
admin@example:/> configure
+admin@example:/config/> edit routing control-plane-protocol static name default ipv6
+admin@example:/config/routing/…/ipv6/> set route 2001:db8:3c4d:200::/64 next-hop next-hop-address 2001:db8:3c4d:1::1
+admin@example:/config/routing/…/ipv6/> leave
+admin@example:/>
+
### OSPFv2 Routing @@ -1394,10 +1373,11 @@ router 192.168.1.1, using the highest possible distance: The system supports OSPF dynamic routing for IPv4, i.e., OSPFv2. To enable OSPF and set one active interface in area 0: - admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf - admin@example:/config/routing/…/ospf/> set area 0.0.0.0 interface e0 enabled - admin@example:/config/routing/…/ospf/> leave - admin@example:/> +
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@example:/config/routing/…/ospf/> set area 0.0.0.0 interface e0 enabled
+admin@example:/config/routing/…/ospf/> leave
+admin@example:/>
+
> [!TIP] > Remember to enable [IPv4 forwarding](#ipv4-forwarding) for all the @@ -1409,11 +1389,12 @@ enable OSPF and set one active interface in area 0: In addition to *regular* OSPF areas, area types *NSSA* and *Stub* are also supported. To configure an NSSA area with summary routes: - admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf - admin@example:/config/routing/…/ospf/> set area 0.0.0.1 area-type nssa-area - admin@example:/config/routing/…/ospf/> set area 0.0.0.1 summary true - admin@example:/config/routing/…/ospf/> leave - admin@example:/> +
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@example:/config/routing/…/ospf/> set area 0.0.0.1 area-type nssa-area
+admin@example:/config/routing/…/ospf/> set area 0.0.0.1 summary true
+admin@example:/config/routing/…/ospf/> leave
+admin@example:/>
+
#### Bidirectional Forwarding Detection (BFD) @@ -1421,10 +1402,11 @@ also supported. To configure an NSSA area with summary routes: It is possible to enable BFD per OSPF interface to speed up detection of link loss. - admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf - admin@example:/config/routing/…/ospf/> set area 0.0.0.0 interface e0 bfd enabled true - admin@example:/config/routing/…/ospf/> leave - admin@example:/> +
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@example:/config/routing/…/ospf/> set area 0.0.0.0 interface e0 bfd enabled true
+admin@example:/config/routing/…/ospf/> leave
+admin@example:/>
+
#### OSPF interface settings @@ -1434,40 +1416,41 @@ and BFD for OSPF per interface (*bfd enabled true*). These and other OSPF interface settings are done in context of an OSFP area, e.g., *area 0.0.0.0*. Available commands can be listed using the `?` mark. - admin@example:/config/routing/…/> edit ospf area 0.0.0.0 - admin@example:/config/routing/…/ospf/area/0.0.0.0/> edit interface e0 - admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set ? - bfd BFD interface configuration. - cost Interface's cost. - dead-interval Interval after which a neighbor is declared down - enabled Enables/disables the OSPF protocol on the interface. - hello-interval Interval between Hello packets (seconds). It must - interface-type Interface type. - passive Enables/disables a passive interface. A passive - retransmit-interval Interval between retransmitting unacknowledged Link - transmit-delay Estimated time needed to transmit Link State Update - admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set +
admin@example:/config/routing/…/> edit ospf area 0.0.0.0
+admin@example:/config/routing/…/ospf/area/0.0.0.0/> edit interface e0
+admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set ?
+  bfd                  BFD interface configuration.
+  cost                 Interface's cost.
+  dead-interval        Interval after which a neighbor is declared down
+  enabled              Enables/disables the OSPF protocol on the interface.
+  hello-interval       Interval between Hello packets (seconds).  It must
+  interface-type       Interface type.
+  passive              Enables/disables a passive interface.  A passive
+  retransmit-interval  Interval between retransmitting unacknowledged Link
+  transmit-delay       Estimated time needed to transmit Link State Update
+admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set
+
For example, setting the OSPF *interface type* to *point-to-point* for an Ethernet interface can be done as follows. - admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set interface-type point-to-point - admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> +
admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set interface-type point-to-point
+admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/>
+
#### OSPF global settings In addition to *area* and *interface* specific settings, OSPF provides global settings for route redistribution and OSPF router identifier. -``` -admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf -admin@example:/config/routing/…/ospf/> set ? +
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@example:/config/routing/…/ospf/> set ?
   area                     List of OSPF areas.
   default-route-advertise  Distribute default route to network
   explicit-router-id       Defined in RFC 2328.  A 32-bit number
   redistribute             Redistribute protocols into OSPF
 admin@example:/config/routing/…/ospf/> set
-```
+
- Explicit router ID: By default the router will pick an IP address from one of its OSPF interfaces as OSPF router ID. An explicit ID is @@ -1495,13 +1478,12 @@ debugging the OSPFv2 setup. The CLI has various OSPF status commands such as `show ospf neighbor`, `show ospf interface` and `show ospf routes`. - admin@example:/> show ospf neighbor - - Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL - 10.1.1.2 1 Full/- 3h46m59s 30.177s 10.1.1.2 e0:10.1.1.1 0 0 0 - 10.1.1.3 1 Full/- 3h46m55s 34.665s 10.1.1.3 e1:10.1.1.1 0 0 0 - - admin@example:/> +
admin@example:/> show ospf neighbor
+Neighbor ID     Pri State           Up Time         Dead Time Address         Interface                        RXmtL RqstL DBsmL
+10.1.1.2          1 Full/-          3h46m59s          30.177s 10.1.1.2        e0:10.1.1.1                          0     0     0
+10.1.1.3          1 Full/-          3h46m55s          34.665s 10.1.1.3        e1:10.1.1.1                          0     0     0
+admin@example:/>
+
For more detailed troubleshooting, OSPF debug logging can be enabled to capture specific protocol events. Debug messages are written to the @@ -1514,12 +1496,13 @@ routing log file (`/var/log/routing`). 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:/> +
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: @@ -1535,15 +1518,17 @@ YANG model for the complete list of available debug options. To view current debug settings: - admin@example:/> show running-config routing control-plane-protocol +
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:/> +
admin@example:/> configure
+admin@example:/config/> delete routing control-plane-protocol ospfv2 name default ospf debug
+admin@example:/config/> leave
+admin@example:/>
+
### RIP Routing @@ -1551,11 +1536,12 @@ all options back to `false`: 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:/> +
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 @@ -1567,59 +1553,60 @@ RIP and set active interfaces: 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:/> +
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:/> +
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:/> +
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 +
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 Information Sources:
-      Gateway          BadPackets BadRoutes  Distance Last Update
-      10.0.1.2                  0         0       120   00:00:16
-    Distance: (default is 120)
+Routing for Networks:
+  e0
+  e1
 
-    admin@example:/> show ip rip neighbor
+Routing Information Sources:
+  Gateway          BadPackets BadRoutes  Distance Last Update
+  10.0.1.2                  0         0       120    00:00:16
+Distance: (default is 120)
 
-    ADDRESS          BAD-PACKETS    BAD-ROUTES
-    10.0.1.2         0              0
-
-    admin@example:/>
+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 @@ -1632,12 +1619,13 @@ routing log file (`/var/log/routing`). 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:/> +
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: @@ -1650,15 +1638,17 @@ YANG model for the complete list of available debug options. To view current debug settings: - admin@example:/> show running-config routing control-plane-protocol +
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:/> +
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 @@ -1678,38 +1668,40 @@ model referred to as *active*), if there are more than one route with the same destination the `*` marks the next-hop used and installed in the kernel FIB (the YANG model refers to this as *installed*). - admin@example:/> show ip route - DESTINATION PREF NEXT-HOP PROTO UPTIME - >* 0.0.0.0/0 110/2 10.0.23.1 ospfv2 4h2m43s - >* 10.0.0.1/32 110/4000 10.0.13.1 ospfv2 4h2m43s - 10.0.0.3/32 110/0 lo ospfv2 4h2m57s - >* 10.0.0.3/32 0/0 lo direct 4h2m58s - 10.0.13.0/30 110/2000 e5 ospfv2 4h2m57s - >* 10.0.13.0/30 0/0 e5 direct 4h2m58s - 10.0.23.0/30 110/1 e6 ospfv2 4h2m57s - >* 10.0.23.0/30 0/0 e6 direct 4h2m58s - 192.168.3.0/24 110/1 e2 ospfv2 4h2m57s - >* 192.168.3.0/24 0/0 e2 direct 4h2m58s - admin@example:/> +
admin@example:/> show ip route
+   DESTINATION            PREF NEXT-HOP         PROTO     UPTIME
+>* 0.0.0.0/0             110/2 10.0.23.1        ospfv2   4h2m43s
+>* 10.0.0.1/32        110/4000 10.0.13.1        ospfv2   4h2m43s
+   10.0.0.3/32           110/0 lo               ospfv2   4h2m57s
+>* 10.0.0.3/32             0/0 lo               direct   4h2m58s
+   10.0.13.0/30       110/2000 e5               ospfv2   4h2m57s
+>* 10.0.13.0/30            0/0 e5               direct   4h2m58s
+   10.0.23.0/30          110/1 e6               ospfv2   4h2m57s
+>* 10.0.23.0/30            0/0 e6               direct   4h2m58s
+   192.168.3.0/24        110/1 e2               ospfv2   4h2m57s
+>* 192.168.3.0/24          0/0 e2               direct   4h2m58s
+admin@example:/>
+
#### IPv6 routing table This CLI example show the IPv6 routing table. - admin@example:/> show ipv6 route - DESTINATION PREF NEXT-HOP PROTO UPTIME - >* ::/0 1/0 2001:db8:3c4d:50::1 static 0h1m20s - >* 2001:db8:3c4d:50::/64 0/0 e6 direct 0h1m20s - >* 2001:db8:3c4d:200::1/128 0/0 lo direct 0h1m20s - * fe80::/64 0/0 e7 direct 0h1m20s - * fe80::/64 0/0 e6 direct 0h1m20s - * fe80::/64 0/0 e5 direct 0h1m20s - * fe80::/64 0/0 e4 direct 0h1m20s - * fe80::/64 0/0 e3 direct 0h1m20s - * fe80::/64 0/0 e2 direct 0h1m20s - >* fe80::/64 0/0 e1 direct 0h1m20s - admin@example:/> +
admin@example:/> show ipv6 route
+   DESTINATION                      PREF NEXT-HOP              PROTO     UPTIME
+>* ::/0                              1/0 2001:db8:3c4d:50::1   static   0h1m20s
+>* 2001:db8:3c4d:50::/64             0/0 e6                    direct   0h1m20s
+>* 2001:db8:3c4d:200::1/128          0/0 lo                    direct   0h1m20s
+ * fe80::/64                         0/0 e7                    direct   0h1m20s
+ * fe80::/64                         0/0 e6                    direct   0h1m20s
+ * fe80::/64                         0/0 e5                    direct   0h1m20s
+ * fe80::/64                         0/0 e4                    direct   0h1m20s
+ * fe80::/64                         0/0 e3                    direct   0h1m20s
+ * fe80::/64                         0/0 e2                    direct   0h1m20s
+>* fe80::/64                         0/0 e1                    direct   0h1m20s
+admin@example:/>
+
#### Route Preference From 0154d554e954e33ea5aa20deac2c5ce605b5d39d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 21:19:35 +0100 Subject: [PATCH 25/29] doc: fix mkdocs build warnings - Add missing SVG For dhcpv6 example - Fix link to static routes in WireGuard doc - Add WireGuard to a new VPN sub-section in nav bar Signed-off-by: Joachim Wiberg --- doc/img/ip-address-example-ipv6-dhcp.svg | 4 ++++ doc/vpn-wireguard.md | 2 +- mkdocs.yml | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 doc/img/ip-address-example-ipv6-dhcp.svg diff --git a/doc/img/ip-address-example-ipv6-dhcp.svg b/doc/img/ip-address-example-ipv6-dhcp.svg new file mode 100644 index 000000000..e640bd8c9 --- /dev/null +++ b/doc/img/ip-address-example-ipv6-dhcp.svg @@ -0,0 +1,4 @@ + + + +
example
eth0
DHCP
Server
Pool:
2001:db8::40-50
2001:db8::/64
.1
\ No newline at end of file diff --git a/doc/vpn-wireguard.md b/doc/vpn-wireguard.md index 1b8a8e2c9..38ab1e76b 100644 --- a/doc/vpn-wireguard.md +++ b/doc/vpn-wireguard.md @@ -141,7 +141,7 @@ for 192.168.2.0/24 through this peer. > [!NOTE] > When routing traffic to networks behind WireGuard peers, you also need > to configure static routes pointing to the WireGuard interface. See -> [Static Routes](networking.md#static-routes) for more information. +> [Static Routes](networking.md#routing-support) for more information. ## Peer Configuration and Key Bags diff --git a/mkdocs.yml b/mkdocs.yml index aa66e51cb..36a3d858e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -33,7 +33,9 @@ nav: - Quality of Service: qos.md - RMON Counters: eth-counters.md - Tunneling (L2/L3): tunnels.md - - VPN Tunnels: vpn.md + - VPN Tunnels: + - Overview: vpn.md + - WireGuard: vpn-wireguard.md - Wireless LAN (WiFi): wifi.md - Services: - Device Discovery: discovery.md From 1fb97055abfe0b3b1b1ef654ae6a6569d2fff024 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 23:30:29 +0100 Subject: [PATCH 26/29] doc: split networking.md into multiple files The networking guide has grown out of control for quite some time, it is time to split it up into multiple files. This will hopefully also make it a bit more accessible to users. Signed-off-by: Joachim Wiberg --- doc/bridging.md | 284 +++++++ doc/ethernet.md | 208 +++++ doc/firewall.md | 4 +- doc/iface.md | 143 ++++ doc/ip.md | 445 +++++++++++ doc/lag.md | 245 ++++++ doc/networking.md | 1719 +---------------------------------------- doc/routing.md | 453 +++++++++++ doc/scripting-prod.md | 4 +- doc/tunnels.md | 4 +- doc/vpn-wireguard.md | 2 +- mkdocs.yml | 8 +- 12 files changed, 1802 insertions(+), 1717 deletions(-) create mode 100644 doc/bridging.md create mode 100644 doc/ethernet.md create mode 100644 doc/iface.md create mode 100644 doc/ip.md create mode 100644 doc/lag.md create mode 100644 doc/routing.md diff --git a/doc/bridging.md b/doc/bridging.md new file mode 100644 index 000000000..c751b90c1 --- /dev/null +++ b/doc/bridging.md @@ -0,0 +1,284 @@ +# Bridging + +This is the most central part of the system. A bridge is a switch, and +a switch is a bridge. In Linux, setting up a bridge with ports +connected to physical switch fabric, means you manage the actual switch +fabric! + +## MAC Bridge + +In Infix ports are by default not switch ports, unless the customer +specific factory config sets it up this way. To enable switching, with +offloading if you have a switch chipset, between ports you create a +bridge and then add ports to that bridge. Like this: + +
admin@example:/> configure
+admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> up
+admin@example:/config/> set interface eth0 bridge-port bridge br0
+admin@example:/config/> set interface eth1 bridge-port bridge br0
+admin@example:/config/> leave
+
+ +Here we add two ports to bridge `br0`: `eth0` and `eth1`. + +> [!TIP] +> The CLI has several built-in helpers governed by convention. E.g., +> naming bridges `brN`, where `N` is a number, the type is *inferred* +> automatically and unlocks all bridge features. Other conventions are +> `vethNA`, where `N` is a number and `A` is a letter ('a' for access +> port and 'b' for bridge side is common), and `ethN.M` for VLAN M on +> top of `ethN`, or `dockerN` for a IP masquerading container bridge. +> +> Note, this inference only works with the CLI, configuring networking +> over NETCONF or RESTCONF requires setting the type explicitly. + +![A MAC bridge with two ports](img/mac-bridge.svg) + +It is possible to create multiple MAC bridges, however, it is +currently[^1] _not recommended_ to use more than one MAC bridge on +products with Marvell LinkStreet switching ASICs. A VLAN filtering +bridge should be used instead. + +## VLAN Filtering Bridge + +By default bridges in Linux do not filter based on VLAN tags. This can +be enabled when creating a bridge by adding a port to a VLAN as a tagged +or untagged member. Use the port default VID (PVID) setting to control +VLAN association for traffic ingressing a port untagged (default PVID: +1). + +
admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> up
+admin@example:/config/> set interface eth0 bridge-port bridge br0
+admin@example:/config/> set interface eth0 bridge-port pvid 10
+admin@example:/config/> set interface eth1 bridge-port bridge br0
+admin@example:/config/> set interface eth1 bridge-port pvid 20
+admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> set bridge vlans vlan 10 untagged eth0
+admin@example:/config/interface/br0/> set bridge vlans vlan 20 untagged eth1
+
+ +This sets `eth0` as an untagged member of VLAN 10 and `eth1` as an +untagged member of VLAN 20. Switching between these ports is thus +prohibited. + +![A VLAN bridge with two VLANs](img/vlan-bridge.svg) + +To terminate a VLAN in the switch itself, either for switch management +or for routing, the bridge must become a (tagged) member of the VLAN. + +
admin@example:/config/interface/br0/> set bridge vlans vlan 10 tagged br0
+admin@example:/config/interface/br0/> set bridge vlans vlan 20 tagged br0
+
+ +To route or to manage via a VLAN, a VLAN interface needs to be created +on top of the bridge, see section [VLAN Interfaces](ethernet.md#vlan-interfaces) +for more on this topic. + +> [!NOTE] +> In some use-cases only a single management VLAN on the bridge is used. +> For the example above, if the bridge itself is an untagged member only +> in VLAN 10, IP addresses can be set directly on the bridge without the +> need for dedicated VLAN interfaces on top of the bridge. + + +## Multicast Filtering and Snooping + +Multicast filtering in the bridge is handled by the bridge itself. It +can filter both IP multicast and MAC multicast. For IP multicast it +also supports "snooping", i.e., IGMP and MLD, to automatically reduce +the broadcast effects of multicast. See the next section for a summary +of the [terminology used](#terminology-abbreviations). + +> [!IMPORTANT] +> Currently there is no way to just enable multicast filtering without +> also enabling snooping. This may change in the future, in which case +> a `filtering` enabled setting will be made available along with the +> existing `snooping` setting. + +When creating your bridge you must decide if you need a VLAN filtering +bridge or a plain bridge (see previous section). Multicast filtering is +supported for either, but take note that it must be enabled and set up +per VLAN when VLAN filtering is enabled -- there are no global multicast +settings in this operating mode. + +In the following example we have a regular 8-port bridge without VLAN +filtering. We focus on the multicast specific settings: + +
admin@example:/> configure
+admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> set bridge multicast snooping
+admin@example:/config/interface/br0/> set ipv4 address 192.168.2.1 prefix-length 24
+admin@example:/config/interface/br0/> leave
+admin@example:/> copy running-config startup-config
+
+ +Here we enable snooping and set a static IPv4 address so that the switch +can take part in IGMP querier elections. (MLD querier election +currently not supported.) We can inspect the current state: + +
admin@example:/> show ip multicast
+Multicast Overview
+Query Interval (default): 125 sec
+Router Timeout          : 255
+Fast Leave Ports        :
+Router Ports            :
+Flood Ports             : e0, e1, e2, e3, e4, e5, e6, e7
+
+Interface       VID  Querier                     State  Interval  Timeout  Ver
+br0                  192.168.2.1                    Up       125     None    3
+
+Bridge          VID  Multicast Group       Ports                              
+br0                  224.1.1.1             e3, e2
+br0                  ff02::6a              br0
+
+ +This is a rather small LAN, so our bridge has already become the elected +IGMP querier. We see it is ours because the timeout is `None`, and we +recognize the IP address the system has detected, as ours. We can also +see two ports that have joined the same IPv4 multicast group, 224.1.1.1, +and one join from the system itself for the IPv6 group ff02::6a. + +Now, let us see what happens when we add another bridge, this time with +VLAN filtering enabled. We skip the boring parts about how to move +ports e4-e7 to `br1` and assign them to VLANs, and again, focus on the +multicast bits only: + +
admin@example:/> configure
+admin@example:/config/> edit interface br1
+admin@example:/config/interface/br1/> set bridge vlans vlan 1 multicast snooping
+admin@example:/config/interface/br1/> set bridge vlans vlan 2 multicast snooping
+admin@example:/config/interface/br1/> leave
+admin@example:/> copy running-config startup-config
+
+ +Let us see what we get: + +
admin@example:/> show ip multicast
+Multicast Overview
+Query Interval (default): 125 sec
+Router Timeout          : 255
+Fast Leave Ports        : e5
+Router Ports            : e1, e2, e5, e6, e7
+Flood Ports             : e1, e2, e3, e4, e5, e6, e7, e8
+
+Interface       VID  Querier                     State  Interval  Timeout  Ver
+br0                  192.168.2.1                    Up       125     None    3
+br1               1  0.0.0.0                        Up       125     None    3
+br1               2  0.0.0.0                        Up       125     None    3
+
+Bridge          VID  Multicast Group       Ports                              
+br0                  224.1.1.1             e2
+br0                  ff02::fb              br0
+br0                  ff02::6a              br0
+br0                  ff02::1:ff00:0        br0
+br1               1  224.1.1.1             e5
+br1               2  224.1.1.1             e7
+br1               1  ff02::fb              br1
+br1               1  ff02::1:ff00:0        br1
+
+ +In this setup we have a lot more going on. Multiple multicast router +ports have been detected, and behind the scenes someone has also added +an IGMP/MLD fast-leave port. + +### Terminology & Abbreviations + + - **IGMP**: Internet Group Membership Protocol, multicast subscription + for IPv4, for details see [RFC3376][] + - **MLD**: Multicast Listener Discovery (Protocol), multicast + subscription for IPv6, for details see [RFC3810][] + - **Unknown/Unregistered multicast**: multicast groups that are *not* + in the multicast forwarding database (MDB) + - **Known/Registered multicast**: multicast groups that *are* in the + multicast forwarding database (MDB) + - **MDB**: the multicast forwarding database, consists of filters for + multicast groups, directing where multicast is allowed to egress. A + filter entry consists of a group and a port list. The bridge filters + with a unique database per VLAN, in the same was as the unicast FDB + - **Join/Leave**: the terminology used in earlier versions of the two + protocols to subscribe and unsubscribe to a multicast group. For + more information, see *Membership Report* + - **Membership Report** A membership report is sent by end-devices and + forwarded by switches to the elected querier on the LAN. They + consist of multiple "join" and "leave" operations on groups. They + can also, per group, list which senders to allow or block. Switches + usually only support the group subscription, and even more common + also only support filtering on the MAC level[^2] + - **Querier election**: the process of determining who is the elected + IGMP/MLD querier on a LAN. Lowest numerical IP address wins, the + special address 0.0.0.0 (proxy querier) never wins + - **Proxy querier**: when no better querier exists on a LAN, one or + more devices can send proxy queries with source address 0.0.0.0 (or + :: for IPv6). See **Query Interval**, below, why this is a good + thing + - **Query interval**: the time in seconds between two queries from an + IGMP/MLD querier. It is not uncommon that end-devices do not send + their membership reports unless they first hear a query + - **Fast Leave**: set on a bridge port to ensure multicast is pruned as + quickly as possible when a "leave" membership report is received. In + effect, this option marks the port as directly connected to an + end-device. When not set (default), a query with timeout is first + sent to ensure no unintentional loss of multicast is incurred + - **Router port**: can be both configured statically and detected at + runtime based on connected devices, usually multicast routers. On + a router port *all* multicast is forwarded, both known and unknown + - **Flood port**: set on a bridge port (default: enabled) to ensure + all *unknown* multicast is forwarded + - **Router timeout**: the time in seconds until a querier is deemed to + have been lost and another device (switch/router) takes over. In the + tables shown above, a *None* timeout is declared when the current + device is the active querier + +> [!TIP] +> The reason why multicast flooding is enabled by default is to ensure +> safe co-existence with MAC multicast, which is common in industrial +> networks. It also allows end devices that do not know of IGMP/MLD to +> communicate over multicast as long as the group they have chosen is +> not used by other IGMP/MLD aware devices on the LAN. +> +> As soon as an IGMP/MLD membership report to "join" a group is received +> the group is added to the kernel MDB and forwarding to other ports +> stop. The only exception to this rule is multicast router ports. +> +> If your MAC multicast forwarding is not working properly, it may be +> because an IP multicast group maps to the same MAC address. Please +> see [RFC 1112][RFC1112] for details. Use static multicast router +> ports, or static multicast MAC filters, to mitigate. + +[RFC1112]: https://www.rfc-editor.org/rfc/rfc1112.html +[RFC3376]: https://www.rfc-editor.org/rfc/rfc3376.html +[RFC3810]: https://www.rfc-editor.org/rfc/rfc3810.html + +## Forwarding of IEEE Reserved Group Addresses + +Addresses in the range `01:80:C2:00:00:0X` are used by various bridge +signaling protocols, and are not forwarded by default. Still, it is +sometimes useful to let the bridge forward such packets, this can be +done by specifying protocol names or the last address *nibble* as +decimal value `0..15`: + +
admin@example:/config/> edit interface br0 bridge
+admin@example:/config/interface/br0/bridge/> set ieee-group-forward     # Tap the ? key for alternatives
+  [0..15]  List of IEEE link-local protocols to forward, e.g., STP, LLDP
+  dot1x    802.1X Port-Based Network Access Control.
+  lacp     802.3 Slow Protocols, e.g., LACP.
+  lldp     802.1AB Link Layer Discovery Protocol (LLDP).
+  stp      Spanning Tree (STP/RSPT/MSTP).
+admin@example:/config/interface/br0/bridge/> set ieee-group-forward
+
+ +The following example configures bridge *br0* to forward LLDP packets. + +
admin@example:/config/interface/br0/bridge/> set ieee-group-forward lldp
+admin@example:/config/interface/br0/bridge/>
+
+ +[^1]: MAC bridges on Marvell Linkstreet devices are currently limited to + a single MAC database, this may be a problem if the same MAC address + appears in different MAC bridges. +[^2]: For example, IPv4 groups are mapped to MAC multicast addresses by + mapping the low-order 23-bits of the IP address in the low-order 23 + bits of the Ethernet address 01:00:5E:00:00:00. Meaning, more than + one IP multicast group maps to the same MAC multicast group. diff --git a/doc/ethernet.md b/doc/ethernet.md new file mode 100644 index 000000000..84e8cb75c --- /dev/null +++ b/doc/ethernet.md @@ -0,0 +1,208 @@ +# Ethernet Interfaces + +This document covers VLAN interfaces, physical Ethernet interfaces, +and virtual Ethernet (VETH) pairs. + + +## VLAN Interfaces + +Creating a VLAN can be done in many ways. This section assumes VLAN +interfaces created atop another Linux interface. E.g., the VLAN +interfaces created on top of the Ethernet interface or bridge in the +picture below. + +![VLAN interface on top of Ethernet or Bridge interfaces](img/interface-vlan-variants.svg) + +A VLAN interface is basically a filtering abstraction. When you run +`tcpdump` on a VLAN interface you will only see the frames matching the +VLAN ID of the interface, compared to *all* the VLAN IDs if you run +`tcpdump` on the lower-layer interface. + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0.20
+admin@example:/config/interface/eth0.20/> show
+type vlan;
+vlan {
+  tag-type c-vlan;
+  id 20;
+  lower-layer-if eth0;
+}
+admin@example:/config/interface/eth0.20/> leave
+
+ +The example below assumes bridge br0 is already created, see [VLAN +Filtering Bridge](bridging.md#vlan-filtering-bridge). + +
admin@example:/> configure
+admin@example:/config/> edit interface vlan10
+admin@example:/config/interface/vlan10/> set vlan id 10
+admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0
+admin@example:/config/interface/vlan10/> leave
+
+ +As conventions, a VLAN interface for VID 20 on top of an Ethernet +interface *eth0* is named *eth0.20*, and a VLAN interface for VID 10 on +top of a bridge interface *br0* is named *vlan10*. + +> [!NOTE] +> If you name your VLAN interface `foo0.N` or `vlanN`, where `N` is a +> number, the CLI infers the interface type automatically. + + +## Physical Ethernet Interfaces + +### Ethernet Settings and Status + +Physical Ethernet interfaces provide low-level settings for speed/duplex as +well as packet status and [statistics](#ethernet-statistics). + +By default, Ethernet interfaces defaults to auto-negotiating +speed/duplex modes, advertising all speed and duplex modes available. +In the example below, the switch would by default auto-negotiate speed +1 Gbit/s on port eth1 and 100 Mbit/s on port eth4, as those are the +highest speeds supported by H1 and H2 respectively. + +![4-port Gbit/s switch connected to Gbit and Fast Ethernet Hosts](img/ethernet-autoneg.svg) + +The speed and duplex status for the links can be listed as shown +below, assuming the link operational status is 'up'. + +
admin@example:/> show interface eth1
+name                : eth1
+index               : 2
+mtu                 : 1500
+operational status  : up
+auto-negotiation    : on
+duplex              : full
+speed               : 1000
+physical address    : 00:53:00:06:11:01
+ipv4 addresses      :
+ipv6 addresses      :
+in-octets           : 75581
+out-octets          : 43130
+...
+admin@example:/> show interface eth4
+name                : eth4
+index               : 5
+mtu                 : 1500
+operational status  : up
+auto-negotiation    : on
+duplex              : full
+speed               : 100
+physical address    : 00:53:00:06:11:04
+ipv4 addresses      :
+ipv6 addresses      :
+in-octets           : 75439
+out-octets          : 550704
+...
+admin@example:/>
+
+ +### Configuring fixed speed and duplex + +Auto-negotiation of speed/duplex mode is desired in almost all +use-cases, but it is possible to disable auto-negotiation and specify +a fixed speed and duplex mode. + +> [!IMPORTANT] +> When setting a fixed speed and duplex mode, ensure both sides of the +> link have matching configuration. If speed does not match, the link +> will not come up. If duplex mode does not match, the result is +> reported collisions and/or bad throughput. + +The example below configures port eth3 to fixed speed 100 Mbit/s +half-duplex mode. + +
admin@example:/> configure
+admin@example:/config/> edit interface eth3 ethernet
+admin@example:/config/interface/eth3/ethernet/> set speed 0.1
+admin@example:/config/interface/eth3/ethernet/> set duplex half
+admin@example:/config/interface/eth3/ethernet/> set auto-negotiation enable false
+admin@example:/config/interface/eth3/ethernet/> show
+auto-negotiation {
+  enable false;
+}
+duplex half;
+speed 0.1;
+admin@example:/config/interface/eth3/ethernet/> leave
+admin@example:/>
+
+ +Speed metric is in Gbit/s. Auto-negotiation needs to be disabled in +order for fixed speed/duplex to apply. Only speeds `0.1`(100 Mbit/s) +and `0.01` (10 Mbit/s) can be specified. 1 Gbit/s and higher speeds +require auto-negotiation to be enabled. + +### Ethernet statistics + +Ethernet packet statistics[^1] can be listed as shown below. + +
admin@example:/> show interface eth1
+name                : eth1
+index               : 2
+mtu                 : 1500
+operational status  : up
+auto-negotiation    : on
+duplex              : full
+speed               : 1000
+physical address    : 00:53:00:06:11:0a
+ipv4 addresses      :
+ipv6 addresses      :
+in-octets           : 75581
+out-octets          : 43130
+
+eth-in-frames                : 434
+eth-in-multicast-frames      : 296
+eth-in-broadcast-frames      : 138
+eth-in-error-fcs-frames      : 0
+eth-in-error-oversize-frames : 0
+eth-out-frames               : 310
+eth-out-multicast-frames     : 310
+eth-out-broadcast-frames     : 0
+eth-out-good-octets          : 76821
+eth-in-good-octets           : 60598
+admin@example:/>
+
+ + +## VETH Pairs + +A Virtual Ethernet (VETH) pair is basically a virtual Ethernet cable. A +cable can be "plugged in" to a bridge and the other end can be given to +a [container](container.md), or plugged into another bridge. + +The latter example is useful if you have multiple bridges in the system +with different properties (VLAN filtering, IEEE group forwarding, etc.), +but still want some way of communicating between these domains. + +
admin@example:/> configure
+admin@example:/config/> edit interface veth0a
+admin@example:/config/interface/veth0a/> set veth peer veth0b
+admin@example:/config/interface/veth0a/> end
+admin@example:/config/> diff
+interfaces {
++  interface veth0a {
++    type veth;
++    veth {
++      peer veth0b;
++    }
++  }
++  interface veth0b {
++    type veth;
++    veth {
++      peer veth0a;
++    }
++  }
+}
+admin@example:/config/>
+
+ +> [!TIP] +> This is another example of the automatic inference of the interface +> type from the name. Any name can be used, but then you have to set +> the interface type to `veth` manually. + +[^1]: Ethernet counters are described in *ieee802-ethernet-interface.yang* + and *infix-ethernet-interface.yang*. There is a dedicated document on + [Ethernet Counters](eth-counters.md) that provide additional details + on the statistics support. diff --git a/doc/firewall.md b/doc/firewall.md index b685b02bf..1f33052ab 100644 --- a/doc/firewall.md +++ b/doc/firewall.md @@ -93,7 +93,7 @@ about this in the [example below](#end-device-protection). > [!IMPORTANT] Remember IP forwarding on interfaces! > Firewall policies only control whether traffic is allowed on input, to be > forwarded, or blocked (default). For the actual routing between interfaces -> to work, you must also enable [IP forwarding](networking.md#ipv4-forwarding) +> to work, you must also enable [IP forwarding](ip.md#ipv4-forwarding) > on the relevant interfaces. ### Intra-Zone Traffic @@ -461,4 +461,4 @@ You can check the current lockdown state: } ``` -[1]: networking.md#bridging +[1]: bridging.md diff --git a/doc/iface.md b/doc/iface.md new file mode 100644 index 000000000..3ec252850 --- /dev/null +++ b/doc/iface.md @@ -0,0 +1,143 @@ +# Common Interface Settings + +Common interface settings include `name`, `type`, `enabled`, `description`, +and custom MAC address. Type-specific settings are covered in the dedicated +sections for [Bridging](bridging.md), [Link Aggregation](lag.md), +[Ethernet](ethernet.md), [IP Addressing](ip.md), and [Routing](routing.md). + + +## Interface Name + +The interface name is limited to 1-15 characters due to Linux kernel +constraints. Physical interfaces use their system-assigned names (e.g., +`eth0`, `eth1`), while user-created interfaces can be named freely within +this limit. + +> [!TIP] +> Naming conventions like `br0`, `lag0`, `vlan10`, or `eth0.20` allow +> the CLI to automatically infer the interface type. + + +## Interface Type + +The `type` setting defines what kind of interface this is: `bridge`, `lag`, +`vlan`, `veth`, etc. When configuring via the CLI, the type is often +inferred from the interface name. However, when configuring remotely via +NETCONF or RESTCONF, the type *must* be set explicitly. + +
admin@example:/config/> edit interface br0
+admin@example:/config/interface/br0/> set type bridge
+
+ +Available types can be listed from the CLI: + +
admin@example:/config/interface/br0/> set type ?
+  bridge     IEEE bridge interface.
+  dummy      Linux dummy interface.  Useful mostly for testing.
+  ethernet   Any Ethernet interfaces, regardless of speed, RFC 3635.
+  gre        GRE tunnel interface.
+  gretap     GRETAP (Ethernet over GRE) tunnel interface.
+  lag        IEEE link aggregate interface.
+  loopback   Linux loopback interface.
+  other      Other interface, i.e., unknown.
+  veth       Linux virtual Ethernet pair.
+  vlan       Layer 2 Virtual LAN using 802.1Q.
+  vxlan      Virtual eXtensible LAN tunnel interface.
+  wifi       WiFi (802.11) interface
+  wireguard  WireGuard VPN tunnel interface.
+
+ + +## Enable/Disable + +An interface can be administratively disabled using the `enabled` setting. +By default, interfaces are enabled (`true`). + +
admin@example:/config/> edit interface eth0
+admin@example:/config/interface/eth0/> set enabled false
+admin@example:/config/interface/eth0/> leave
+
+ +The operational status can be inspected to see both administrative and +actual link state: + +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA
+eth0            ethernet   DISABLED    02:00:00:00:00:00
+eth1            ethernet   UP          02:00:00:00:00:01
+...
+
+ + +## Description + +The `description` is a free-form text string (max 64 characters) saved +as the Linux interface alias (`ifalias`). Use it to document an interface's +purpose or add notes for remote debugging. + +
admin@example:/config/> edit interface eth0
+admin@example:/config/interface/eth0/> set description "Uplink to core switch"
+admin@example:/config/interface/eth0/> leave
+
+ +The description is visible in the operational datastore and in `show` +commands: + +
admin@example:/> show interface eth0
+name                : eth0
+description         : Uplink to core switch
+index               : 2
+...
+
+ + +## Custom MAC Address + +The `custom-phys-address` can be used to set an interface's MAC address. +This is an extension to the ietf-interfaces YANG model, which defines +`phys-address` as read-only[^1]. + +> [!CAUTION] +> There is no validation or safety checks performed by the system when +> using `custom-phys-address`. In particular the `offset` variant can +> be dangerous to use -- pay attention to the meaning of bits in the +> upper-most octet: local bit, multicast/group, etc. + +### Fixed custom MAC + +Use a fixed custom MAC address when the interface must present a +specific, deterministic identity on the network. This option bypasses +any chassis-derived logic and applies the configured address verbatim. + +
admin@example:/config/> edit interface veth0a
+admin@example:/config/interface/veth0a/> set custom-phys-address static 00:ab:00:11:22:33
+
+=> 00:ab:00:11:22:33
+
+ +### Chassis MAC + +Chassis MAC, sometimes also referred to as base MAC. In these two +examples it is `00:53:00:c0:ff:ee`. + +
admin@example:/config/> edit interface veth0a
+admin@example:/config/interface/veth0a/> set custom-phys-address chassis
+
+=> 00:53:00:c0:ff:ee
+
+ +### Chassis MAC, with offset + +When constructing a derived address it is recommended to set the locally +administered bit. Same chassis MAC as before. + +
admin@example:/config/> edit interface veth0a
+admin@example:/config/interface/veth0a/> set custom-phys-address chassis offset 02:00:00:00:00:02
+
+=> 02:53:00:c0:ff:f0
+
+ + +[^1]: A YANG deviation was previously used to make it possible to set + `phys-address`, but this has been replaced with the more flexible + `custom-phys-address`. diff --git a/doc/ip.md b/doc/ip.md new file mode 100644 index 000000000..1f79b1211 --- /dev/null +++ b/doc/ip.md @@ -0,0 +1,445 @@ +# IP Address Configuration + +This section details IP Addresses And Other Per-Interface IP settings. + +Infix support several network interface types, each can be assigned one +or more IP addresses, both IPv4 and IPv6 are supported. (There is no +concept of a "primary" address.) + +![IP on top of network interface examples](img/ip-iface-examples.svg) + +## IPv4 Address Assignment + +Multiple address assignment methods are available: + +| **Type** | **Yang Model** | **Description** | +|:---------- |:----------------- |:-------------------------------------------------------------- | +| static | ietf-ip | Static assignment of IPv4 address, e.g., *10.0.1.1/24* | +| link-local | infix-ip | Auto-assignment of IPv4 address in 169.254.x.x/16 range | +| dhcp | infix-dhcp-client | Assignment of IPv4 address by DHCP server, e.g., *10.0.1.1/24* | + +> [!NOTE] +> The DHCP address method is only available for *LAN* interfaces +> (Ethernet, virtual Ethernet (veth), bridge, link aggregates, etc.) + +Supported DHCP (request) options, configurability (Cfg) and defaults, +are listed below. Configurable options can be disabled on a per client +interface basis, some options, like `clientid` and option 81, are +possible to set the value of as well. + +| **Opt** | **Name** | **Cfg** | **Description** | +|---------|-----------------------------|---------|-----------------------------------------------------| +| 1 | `netmask` | No | Request IP address and netmask | +| 3 | `router` | Yes | Default route(s), see also option 121 and 249 | +| 6 | `dns-server` | Yes | DNS server(s), static ones take precedence | +| 12 | `hostname` | Yes | DHCP cannot set hostname, only for informing server | +| 15 | `domain` | Yes | Default domain name, for name resolution | +| 28 | `broadcast` | Yes | Broadcast address, calculated if disabled | +| 42 | `ntp-server` | Yes | NTP server(s), static ones take precedence | +| 50 | `address` | Yes | Request (previously cached) address | +| 61 | `client-id` | Yes | Default MAC address (and option 12) | +| 81 | `fqdn` | Yes | Similar to option 12, request FQDN update in DNS | +| 119 | `search` | Yes | Request domain search list | +| 121 | `classless-static-route` | Yes | Classless static routes | +| 249 | `ms-classless-static-route` | Yes | Microsoft static route, same as option 121 | +| | | | | + +**Default:** `router`, `dns-server`, `domain`, `broadcast`, `ntp-server`, `search`, + `address`, `classless-static-route`, `ms-classless-static-route` + +When configuring a DHCP client, ensure that the NTP client is enabled +for the `ntp-server` DHCP option to be processed correctly. If the NTP +client is not enabled, any NTP servers provided by the DHCP server will +be ignored. For details on how to enable the NTP client, see the [NTP +Client Configuration](system.md#ntp-client-configuration) section. + +> [!IMPORTANT] +> Per [RFC3442][1], if the DHCP server returns both a Classless Static +> Routes option (121) and Router option (3), the DHCP client *must* +> ignore the latter. + + +## IPv6 Address Assignment + +Multiple address assignment methods are available: + +| **Type** | **Yang Model** | **Description** | +|:---------------- |:-------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------- | +| static | ietf-ip | Static assignment of IPv6 address, e.g., *2001:db8:0:1::1/64* | +| link-local | ietf-ip[^1] | (RFC4862) Auto-configured link-local IPv6 address (*fe80::0* prefix + interface identifier, e.g., *fe80::ccd2:82ff:fe52:728b/64*) | +| global auto-conf | ietf-ip | (RFC4862) Auto-configured (stateless) global IPv6 address (prefix from router + interface identifier, e.g., *2001:db8:0:1:ccd2:82ff:fe52:728b/64* | +| dhcp | infix-dhcpv6-client | Assignment of IPv6 address by DHCPv6 server, e.g., *2001:db8::42/128* | + +Both for *link-local* and *global auto-configuration*, it is possible +to auto-configure using a random suffix instead of the interface +identifier. + +> [!NOTE] +> The DHCPv6 address method is only available for *LAN* interfaces +> (Ethernet, virtual Ethernet (veth), bridge, link aggregates, etc.) + +Supported DHCPv6 (request) options, configurability (Cfg) and defaults, +are listed below. Configurable options can be disabled on a per client +interface basis, some options, like `client-id` and `client-fqdn`, are +possible to set the value of as well. + +| **Opt** | **Name** | **Cfg** | **Description** | +|---------|----------------------------|---------|--------------------------------------------------------| +| 1 | `client-id` | Yes | Client identifier (DUID), auto-generated by default | +| 2 | `server-id` | Yes | Server identifier (DUID) | +| 23 | `dns-server` | Yes | DNS recursive name servers, static ones take precedence| +| 24 | `domain-search` | Yes | Domain search list | +| 25 | `ia-pd` | Yes | Prefix delegation for downstream networks | +| 31 | `sntp-server` | Yes | Simple Network Time Protocol servers | +| 32 | `information-refresh-time` | Yes | Refresh time for stateless DHCPv6 | +| 39 | `client-fqdn` | Yes | Client FQDN, request DNS update from server | +| 56 | `ntp-server` | Yes | NTP time servers, static ones take precedence | +| | | | | + +**Default:** `dns-server`, `domain-search`, `ntp-server` + +DHCPv6 supports both **stateful** (address assignment) and **stateless** +(information-only) modes: + +- **Stateful DHCPv6**: The server assigns IPv6 addresses to clients. This is + the default mode when enabling the DHCPv6 client. +- **Stateless DHCPv6**: Used with SLAAC (Stateless Address Autoconfiguration) + when only configuration information (DNS, NTP, etc.) is needed. Enable with + the `information-only` setting. + +When configuring a DHCPv6 client, ensure that the NTP client is enabled +for the `ntp-server` DHCPv6 option to be processed correctly. If the +NTP client is not enabled, any NTP servers provided by the DHCPv6 server +will be ignored. For details on how to enable the NTP client, see the +[NTP Client Configuration](system.md#ntp-client-configuration) section. + +## Examples + +![Switch example (eth0 and lo)](img/ip-address-example-switch.svg) + +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ +To illustrate IP address configuration, the examples below uses a +switch with a single Ethernet interface (eth0) and a loopback +interface (lo). As shown above, these examples assume *eth0* has an +IPv6 link-local address and *lo* has static IPv4 and IPv6 addresses by +default. + +### Static and link-local IPv4 addresses + +![Setting static IPv4 (and link-local IPv4)](img/ip-address-example-ipv4-static.svg) + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv4
+admin@example:/config/interface/eth0/ipv4/> set address 10.0.1.1 prefix-length 24
+admin@example:/config/interface/eth0/ipv4/> set autoconf
+admin@example:/config/interface/eth0/ipv4/> diff
++interfaces {
++  interface eth0 {
++    ipv4 {
++      address 10.0.1.1 {
++        prefix-length 24;
++      }
++      autoconf;
++    }
++  }
++}
+admin@example:/config/interface/eth0/ipv4/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv4                   169.254.1.3/16 (random)
+                ipv4                   10.0.1.1/24 (static)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ +As shown, the link-local IPv4 address is configured with `set autoconf`. +The presence of the `autoconf` container enables IPv4 link-local address +assignment. The resulting address (169.254.1.3/16) is of type *random* +([ietf-ip.yang][2]). + +The IPv4LL client also supports a `request-address` setting which can be +used to "seed" the client's starting address. If the address is free it +will be used, otherwise it falls back to the default algorithm. + +
admin@example:/config/interface/eth0/ipv4/> edit autoconf
+admin@example:/config/interface/eth0/ipv4/autoconf/> set request-address 169.254.1.2
+admin@example:/config/interface/eth0/ipv4/autoconf/> leave
+
+ + +### Use of DHCP for IPv4 address assignment + +![Using DHCP for IPv4 address assignment](img/ip-address-example-ipv4-dhcp.svg) + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv4
+admin@example:/config/interface/eth0/ipv4/> set dhcp
+admin@example:/config/interface/eth0/ipv4/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv4                   10.1.2.100/24 (dhcp)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ +The resulting address (10.1.2.100/24) is of type *dhcp*. + +To configure DHCP client options, such as sending a specific hostname to the +server, you can specify options with values: + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv4 dhcp
+admin@example:/config/interface/eth0/ipv4/dhcp/> set option hostname value myhost
+admin@example:/config/interface/eth0/ipv4/dhcp/> show
+option hostname {
+  value myhost;
+}
+admin@example:/config/interface/eth0/ipv4/dhcp/> leave
+admin@example:/>
+
+ +> [!TIP] +> The special value `auto` can be used with the hostname option to +> automatically use the configured system hostname. + +Other useful DHCP options include: + +- `client-id` - Send a specific client identifier to the server +- `route-preference` - Set the administrative distance for DHCP-learned routes (default: 5) + +For advanced usage with vendor-specific options, see the YANG model. + +### Use of DHCPv6 for IPv6 address assignment + +![Using DHCPv6 for IPv6 address assignment](img/ip-address-example-ipv6-dhcp.svg) + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set dhcp
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interface
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8::42/128 (dhcp)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ +The resulting address (2001:db8::42/128) is of type *dhcp*. + +To configure DHCPv6 client options, such as requesting prefix delegation +for downstream networks, you can specify options: + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6 dhcp
+admin@example:/config/interface/eth0/ipv6/dhcp/> set option ia-pd
+admin@example:/config/interface/eth0/ipv6/dhcp/> set option dns-server
+admin@example:/config/interface/eth0/ipv6/dhcp/> show
+option dns-server;
+option ia-pd;
+admin@example:/config/interface/eth0/ipv6/dhcp/> leave
+admin@example:/>
+
+ +For stateless DHCPv6 (used with SLAAC to get only configuration information): + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6 dhcp
+admin@example:/config/interface/eth0/ipv6/dhcp/> set information-only true
+admin@example:/config/interface/eth0/ipv6/dhcp/> show
+information-only true;
+option dns-server;
+option domain-search;
+admin@example:/config/interface/eth0/ipv6/dhcp/> leave
+admin@example:/>
+
+ +Other useful DHCPv6 options include: + +- `duid` - Set a specific DHCPv6 Unique Identifier (auto-generated by default) +- `client-fqdn` - Request the server to update DNS records with client's FQDN +- `route-preference` - Set the administrative distance for DHCPv6-learned routes (default: 5) + +For advanced usage with vendor-specific options, see the YANG model. + +### Disabling IPv6 link-local address(es) + +The (only) way to disable IPv6 link-local addresses is by disabling IPv6 +on the interface. + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set enabled false
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ +### Static IPv6 address + +![Setting static IPv6](img/ip-address-example-ipv6-static.svg) + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set address 2001:db8::1 prefix-length 64
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8::1/64 (static)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ + +### Stateless Auto-configuration of Global IPv6 Address + +![Auto-configuration of global IPv6](img/ip-address-example-ipv6-auto-global.svg) + +Stateless address auto-configuration of global addresses is enabled by +default. The address is formed by concatenating the network prefix +advertised by the router (here 2001:db8:0:1::0/64) and the interface +identifier. The resulting address is of type *link-layer*, as it is +formed based on the interface identifier ([ietf-ip.yang][2]). + +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8:0:1:0:ff:fe00:0/64 (link-layer)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ +Disabling auto-configuration of global IPv6 addresses can be done as shown +below. + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set autoconf create-global-addresses false
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ + +### Random Link Identifiers for IPv6 Stateless Autoconfiguration + +![Auto-configuration of global IPv6](img/ip-address-example-ipv6-auto-global.svg) + +By default, the auto-configured link-local and global IPv6 addresses +are formed from a link-identifier based on the MAC address. + +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8:0:1:0:ff:fe00:0/64 (link-layer)
+                ipv6                   fe80::ff:fe00:0/64 (link-layer)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ +To avoid revealing identity information in the IPv6 address, it is +possible to specify use of a random identifier ([ietf-ip.yang][2] and +[RFC8981][3]). + +
admin@example:/> configure
+admin@example:/config/> edit interface eth0 ipv6
+admin@example:/config/interface/eth0/ipv6/> set autoconf create-temporary-addresses true
+admin@example:/config/interface/eth0/ipv6/> leave
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+eth0            ethernet   UP          02:00:00:00:00:00
+                ipv6                   2001:db8:0:1:b705:8374:638e:74a8/64 (random)
+                ipv6                   fe80::ad3d:b274:885a:9ffb/64 (random)
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+admin@example:/>
+
+ +Both the link-local address (fe80::) and the global address (2001:) +have changed type to *random*. + + +## IPv4 forwarding + +To be able to route (static or dynamic) on the interface it is +required to enable forwarding. This setting controls if packets +received on this interface can be forwarded. + +
admin@example:/config/> edit interface eth0
+admin@example:/config/interface/eth0/> set ipv4 forwarding
+admin@example:/config/interface/eth0/> leave
+admin@example:/>
+
+ + +## IPv6 forwarding + +Due to how the Linux kernel manages IPv6 forwarding, we can not fully +control it per interface via this setting like how IPv4 works. Instead, +IPv6 forwarding is globally enabled when at least one interface enable +forwarding, otherwise it is disabled. + +The following table shows the system IPv6 features that the `forwarding` +setting control when it is *Enabled* or *Disabled: + +| **IPv6 Feature** | **Enabled** | **Disabled** | +|:-----------------------------------------|:------------|:-------------| +| IsRouter set in Neighbour Advertisements | Yes | No | +| Transmit Router Solicitations | No | Yes | +| Router Advertisements are ignored | Yes | Yes | +| Accept Redirects | No | Yes | + +
admin@example:/config/> edit interface eth0
+admin@example:/config/interface/eth0/> set ipv6 forwarding
+admin@example:/config/interface/eth0/> leave
+admin@example:/>
+
+ +[1]: https://www.rfc-editor.org/rfc/rfc3442 +[2]: https://www.rfc-editor.org/rfc/rfc8344 +[3]: https://www.rfc-editor.org/rfc/rfc8981 + +[^1]: Link-local IPv6 addresses are implicitly enabled when enabling + IPv6. IPv6 can be enabled/disabled per interface in the + [ietf-ip][2] YANG model. diff --git a/doc/lag.md b/doc/lag.md new file mode 100644 index 000000000..b4c6b4f81 --- /dev/null +++ b/doc/lag.md @@ -0,0 +1,245 @@ +# Link Aggregation + +A link aggregate, or *lag*, allows multiple physical interfaces to be +combined into a single logical interface, providing increased bandwidth +(in some cases) and redundancy (primarily). Two modes of qualifying lag +member ports are available: + + 1. **static**: Active members selected based on link status (carrier) + 2. **lacp:** IEEE 802.3ad Link Aggregation Control Protocol + +In LACP mode, LACPDUs are exchanged by the link partners to qualify each +lag member, while in static mode only carrier is used. This additional +exchange in LACP ensures traffic can be forwarded in both directions. + +Traffic distribution, for both modes, across the active lag member ports +is determined by the hash policy[^1]. It uses an XOR of the source, +destination MAC addresses and the EtherType field. This, IEEE +802.3ad-compliant, algorithm will place all traffic to a particular +network peer on the same link. Meaning there is no increased bandwidth +for communication between two specific devices. + +> [!TIP] +> Similar to other interface types, naming your interface `lagN`, where +> `N` is a number, allows the CLI to automatically infer the interface +> type as LAG. + + +## Basic Configuration + +Creating a link aggregate interface and adding member ports: + +
admin@example:/> configure
+admin@example:/config/> edit interface lag0
+admin@example:/config/interface/lag0/> set lag mode static
+admin@example:/config/interface/lag0/> end
+admin@example:/config/> set interface eth7 lag-port lag lag0
+admin@example:/config/> set interface eth8 lag-port lag lag0
+admin@example:/config/> leave
+
+ +A static lag responds only to link (carrier) changes of member ports. +E.g., in this example egressing traffic is continuously distributed over +the two links until link down on one link is detected, triggering all +traffic to be steered to the sole remaining link. + + +## LACP Configuration + +LACP mode provides dynamic negotiation of the link aggregate. Key +settings include: + +
admin@example:/> configure
+admin@example:/config/> edit interface lag0
+admin@example:/config/interface/lag0/> set lag mode lacp
+admin@example:/config/interface/lag0/> set lag lacp mode passive
+admin@example:/config/interface/lag0/> set lag lacp rate fast
+admin@example:/config/interface/lag0/> set lag lacp system-priority 100
+
+ +LACP mode supports two operational modes: + + - **active:** Initiates negotiation by sending LACPDUs (default) + - **passive:** Waits for peer to initiate negotiation + +> [!NOTE] +> At least one end of the link must be in active mode for negotiation to occur. + +The LACP rate setting controls protocol timing: + + - **slow:** LACPDUs sent every 30 seconds, with 90 second timeout (default) + - **fast:** LACPDUs sent every second, with 3 second timeout + + +## Link Flapping + +To protect against link flapping, debounce timers can be configured to +delay link qualification. Usually only the `up` delay is needed: + +
admin@example:/config/interface/lag0/lag/link-monitor/> edit debounce
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set up 500
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set down 200
+
+ +## Operational Status, Overview + +Like other interfaces, link aggregates are also available in the general +interfaces overview in the CLI admin-exec context. Here is the above +static mode aggregate: + +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+.
+.
+.
+lag0            lag        UP          static: balance-xor, hash: layer2
+│               ethernet   UP          00:a0:85:00:02:00
+├ eth7          lag        ACTIVE
+└ eth8          lag        ACTIVE
+
+ +Same aggregate, but in LACP mode: + +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
+lo              ethernet   UP          00:00:00:00:00:00
+                ipv4                   127.0.0.1/8 (static)
+                ipv6                   ::1/128 (static)
+.
+.
+.
+lag0            lag        UP          lacp: active, rate: fast (1s), hash: layer2
+│               ethernet   UP          00:a0:85:00:02:00
+├ eth7          lag        ACTIVE      active, short_timeout, aggregating, in_sync, collecting, distributing
+└ eth8          lag        ACTIVE      active, short_timeout, aggregating, in_sync, collecting, distributing
+
+ + +## Operational Status, Detail + +In addition to basic status shown in the interface overview, detailed +LAG status can be inspected: + +
admin@example:/> show interface lag0
+name                : lag0
+index               : 25
+mtu                 : 1500
+operational status  : up
+physical address    : 00:a0:85:00:02:00
+lag mode            : static
+lag type            : balance-xor
+lag hash            : layer2
+link debounce up    : 0 msec
+link debounce down  : 0 msec
+ipv4 addresses      :
+ipv6 addresses      :
+in-octets           : 0
+out-octets          : 2142
+
+ +Same aggregate, but in LACP mode: + +
admin@example:/> show interface lag0
+name                : lag0
+index               : 24
+mtu                 : 1500
+operational status  : up
+physical address    : 00:a0:85:00:02:00
+lag mode            : lacp
+lag hash            : layer2
+lacp mode           : active
+lacp rate           : fast (1s)
+lacp aggregate id   : 1
+lacp system priority: 65535
+lacp actor key      : 9
+lacp partner key    : 9
+lacp partner mac    : 00:a0:85:00:03:00
+link debounce up    : 0 msec
+link debounce down  : 0 msec
+ipv4 addresses      :
+ipv6 addresses      :
+in-octets           : 100892
+out-octets          : 111776
+
+ +Member ports provide additional status information: + + - Link failure counter: number of detected link failures + - LACP state flags: various states of LACP negotiation: + - `active`: port is actively sending LACPDUs + - `short_timeout`: using fast rate (1s) vs. slow rate (30s) + - `aggregating`: port is allowed to aggregate in this LAG + - `in_sync`: port is synchronized with partner + - `collecting`: port is allowed to receive traffic + - `distributing`: port is allowed to send traffic + - `defaulted`: using default partner info (partner not responding) + - `expired`: partner info has expired (no LACPDUs received) + - Aggregator ID: unique identifier for this LAG group + - Actor state: LACP state flags for this port (local) + - Partner state: LACP state flags from the remote port + +Example member port status: + +
admin@example:/> show interface eth7
+name                : eth7
+index               : 8
+mtu                 : 1500
+operational status  : up
+physical address    : 00:a0:85:00:02:00
+lag member          : lag0
+lag member state    : active
+lacp aggregate id   : 1
+lacp actor state    : active, short_timeout, aggregating, in_sync, collecting, distributing
+lacp partner state  : active, short_timeout, aggregating, in_sync, collecting, distributing
+link failure count  : 0
+ipv4 addresses      :
+ipv6 addresses      :
+in-octets           : 473244
+out-octets          : 499037
+
+ + +## Example: Switch Uplink with LACP + +LACP mode provides the most robust operation, automatically negotiating +the link aggregate and detecting configuration mismatches. + +A common use case is connecting a switch to an upstream device: + +
admin@example:/> configure
+admin@example:/config/> edit interface lag0
+admin@example:/config/interface/lag0/> set lag mode lacp
+
+ +Enable fast LACP for quicker fail-over: + +
admin@example:/config/interface/lag0/> set lag lacp rate fast
+
+ +Add uplink ports + +
admin@example:/config/interface/lag0/> end
+admin@example:/config/> set interface eth7 lag-port lag lag0
+admin@example:/config/> set interface eth8 lag-port lag lag0
+
+ +Enable protection against "link flapping". + +
admin@example:/config/interface/lag0/> edit lag link-monitor
+admin@example:/config/interface/lag0/lag/link-monitor/> edit debounce
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set up 500
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set down 200
+admin@example:/config/interface/lag0/lag/link-monitor/debounce/> top
+
+ +Add to bridge for switching + +
admin@example:/config/interface/lag0/lag/link-monitor/debounce/> end
+admin@example:/config/> set interface lag0 bridge-port bridge br0
+admin@example:/config/> leave
+
+ +[^1]: `(source MAC XOR destination MAC XOR EtherType) MODULO num_links` diff --git a/doc/networking.md b/doc/networking.md index 6867d6d00..bbe10226f 100644 --- a/doc/networking.md +++ b/doc/networking.md @@ -45,16 +45,16 @@ other traffic would be bridged as usual. | **Type** | **Yang Model** | **Description** | |----------|----------------------------|--------------------------------------------------------------| -| bridge | infix-if-bridge | SW implementation of an IEEE 802.1Q bridge | -| ip | ietf-ip, infix-ip | IP address to the subordinate interface | -| vlan | infix-if-vlan | Capture all traffic belonging to a specific 802.1Q VID | -| lag | infix-if-lag | Link aggregation, static and IEEE 802.3ad (LACP) | -| lo | ietf-interfaces | Software loopback interface | -| eth | ieee802-ethernet-interface | Physical Ethernet device/port. | -| | infix-ethernet-interface | | -| veth | infix-if-veth | Virtual Ethernet pair, typically one end is in a container | -| *common* | ietf-interfaces, | Properties common to all interface types | -| | infix-interfaces | | +| [bridge](bridging.md) | infix-if-bridge | SW implementation of an IEEE 802.1Q bridge | +| [ip](ip.md) | ietf-ip, infix-ip | IP address to the subordinate interface | +| [vlan](ethernet.md#vlan-interfaces) | infix-if-vlan | Capture all traffic belonging to a specific 802.1Q VID | +| [lag](lag.md) | infix-if-lag | Link aggregation, static and IEEE 802.3ad (LACP) | +| lo | ietf-interfaces | Software loopback interface | +| [eth](ethernet.md#physical-ethernet-interfaces) | ieee802-ethernet-interface | Physical Ethernet device/port | +| | infix-ethernet-interface | | +| [veth](ethernet.md#veth-pairs) | infix-if-veth | Virtual Ethernet pair, typically one end is in a container | +| [*common*](iface.md) | ietf-interfaces, | Properties common to all interface types | +| | infix-interfaces | | ## Data Plane @@ -81,1704 +81,5 @@ used on the left hand side can also be used freely on the right hand side as well. -### General - -General interface settings include `type`, `enable`, custom MAC address, -and text `description`. Other settings have their own sections, below. - -The `type` is important to set when configuring devices remotely because -unlike the CLI, a NETCONF or RESTCONF session cannot guess the interface -type for you. The operating system provides an override of the -available interface types. - -An `enabled` interface can be inspected using the operational datastore, -nodes `admin-state` and `oper-state` show the status, . Possible values -are listed in the YANG model. - -The `custom-phys-address` can be used to set an interface's MAC address. -This is an extension to the ietf-interfaces YANG model, which defines -`phys-address` as read-only[^4]. The following shows the different -configuration options. - -The `description` is saved as Linux `ifalias` on an interface. It is a -free-form string, useful for describing purpose or just adding comments -for remote debugging, e.g., using the operational datastore. - -> [!CAUTION] -> There is no validation or safety checks performed by the system when -> using `custom-phys-address`. In particular the `offset` variant can -> be dangerous to use -- pay attention to the meaning of bits in the -> upper-most octet: local bit, multicast/group, etc. - -#### Fixed custom MAC - -Use a fixed custom MAC address when the interface must present a -specific, deterministic identity on the network. This option bypasses -any chassis-derived logic and applies the configured address verbatim. - -
admin@example:/config/> edit interface veth0a
-admin@example:/config/interface/veth0a/> set custom-phys-address static 00:ab:00:11:22:33
-
-=> 00:ab:00:11:22:33
-
- -#### Chassis MAC - -Chassis MAC, sometimes also referred to as base MAC. In these two -examples it is `00:53:00:c0:ff:ee`. - -
admin@example:/config/> edit interface veth0a
-admin@example:/config/interface/veth0a/> set custom-phys-address chassis
-
-=> 00:53:00:c0:ff:ee
-
- -#### Chassis MAC, with offset - -When constructing a derived address it is recommended to set the locally -administered bit. Same chassis MAC as before. - -
admin@example:/config/> edit interface veth0a
-admin@example:/config/interface/veth0a/> set custom-phys-address chassis offset 02:00:00:00:00:02
-
-=> 02:53:00:c0:ff:f0
-
- -### Bridging - -This is the most central part of the system. A bridge is a switch, and -a switch is a bridge. In Linux, setting up a bridge with ports -connected to physical switch fabric, means you manage the actual switch -fabric! - -#### MAC Bridge - -In Infix ports are by default not switch ports, unless the customer -specific factory config sets it up this way. To enable switching, with -offloading if you have a switch chipset, between ports you create a -bridge and then add ports to that bridge. Like this: - -
admin@example:/> configure
-admin@example:/config/> edit interface br0
-admin@example:/config/interface/br0/> up
-admin@example:/config/> set interface eth0 bridge-port bridge br0
-admin@example:/config/> set interface eth1 bridge-port bridge br0
-admin@example:/config/> leave
-
- -Here we add two ports to bridge `br0`: `eth0` and `eth1`. - -> [!TIP] -> The CLI has several built-in helpers governed by convention. E.g., -> naming bridges `brN`, where `N` is a number, the type is *inferred* -> automatically and unlocks all bridge features. Other conventions are -> `vethNA`, where `N` is a number and `A` is a letter ('a' for access -> port and 'b' for bridge side is common), and `ethN.M` for VLAN M on -> top of `ethN`, or `dockerN` for a IP masquerading container bridge. -> -> Note, this inference only works with the CLI, configuring networking -> over NETCONF or RESTCONF requires setting the type explicitly. - -![A MAC bridge with two ports](img/mac-bridge.svg) - -It is possible to create multiple MAC bridges, however, it is -currently[^5] _not recommended_ to use more than one MAC bridge on -products with Marvell LinkStreet switching ASICs. A VLAN filtering -bridge should be used instead. - -#### VLAN Filtering Bridge - -By default bridges in Linux do not filter based on VLAN tags. This can -be enabled when creating a bridge by adding a port to a VLAN as a tagged -or untagged member. Use the port default VID (PVID) setting to control -VLAN association for traffic ingressing a port untagged (default PVID: -1). - -
admin@example:/config/> edit interface br0
-admin@example:/config/interface/br0/> up
-admin@example:/config/> set interface eth0 bridge-port bridge br0
-admin@example:/config/> set interface eth0 bridge-port pvid 10
-admin@example:/config/> set interface eth1 bridge-port bridge br0
-admin@example:/config/> set interface eth1 bridge-port pvid 20
-admin@example:/config/> edit interface br0
-admin@example:/config/interface/br0/> set bridge vlans vlan 10 untagged eth0
-admin@example:/config/interface/br0/> set bridge vlans vlan 20 untagged eth1
-
- -This sets `eth0` as an untagged member of VLAN 10 and `eth1` as an -untagged member of VLAN 20. Switching between these ports is thus -prohibited. - -![A VLAN bridge with two VLANs](img/vlan-bridge.svg) - -To terminate a VLAN in the switch itself, either for switch management -or for routing, the bridge must become a (tagged) member of the VLAN. - -
admin@example:/config/interface/br0/> set bridge vlans vlan 10 tagged br0
-admin@example:/config/interface/br0/> set bridge vlans vlan 20 tagged br0
-
- -To route or to manage via a VLAN, a VLAN interface needs to be created -on top of the bridge, see section [VLAN Interfaces](#vlan-interfaces) -below for more on this topic. - -> [!NOTE] -> In some use-cases only a single management VLAN on the bridge is used. -> For the example above, if the bridge itself is an untagged member only -> in VLAN 10, IP addresses can be set directly on the bridge without the -> need for dedicated VLAN interfaces on top of the bridge. - - -#### Multicast Filtering and Snooping - -Multicast filtering in the bridge is handled by the bridge itself. It -can filter both IP multicast and MAC multicast. For IP multicast it -also supports "snooping", i.e., IGMP and MLD, to automatically reduce -the broadcast effects of multicast. See the next section for a summary -of the [terminology used](#terminology-abbreviations). - -> [!IMPORTANT] -> Currently there is no way to just enable multicast filtering without -> also enabling snooping. This may change in the future, in which case -> a `filtering` enabled setting will be made available along with the -> existing `snooping` setting. - -When creating your bridge you must decide if you need a VLAN filtering -bridge or a plain bridge (see previous section). Multicast filtering is -supported for either, but take note that it must be enabled and set up -per VLAN when VLAN filtering is enabled -- there are no global multicast -settings in this operating mode. - -In the following example we have a regular 8-port bridge without VLAN -filtering. We focus on the multicast specific settings: - -
admin@example:/> configure
-admin@example:/config/> edit interface br0
-admin@example:/config/interface/br0/> set bridge multicast snooping
-admin@example:/config/interface/br0/> set ipv4 address 192.168.2.1 prefix-length 24
-admin@example:/config/interface/br0/> leave
-admin@example:/> copy running-config startup-config
-
- -Here we enable snooping and set a static IPv4 address so that the switch -can take part in IGMP querier elections. (MLD querier election -currently not supported.) We can inspect the current state: - -
admin@example:/> show ip multicast
-Multicast Overview
-Query Interval (default): 125 sec
-Router Timeout          : 255
-Fast Leave Ports        :
-Router Ports            :
-Flood Ports             : e0, e1, e2, e3, e4, e5, e6, e7
-
-Interface       VID  Querier                     State  Interval  Timeout  Ver
-br0                  192.168.2.1                    Up       125     None    3
-
-Bridge          VID  Multicast Group       Ports                              
-br0                  224.1.1.1             e3, e2
-br0                  ff02::6a              br0
-
- -This is a rather small LAN, so our bridge has already become the elected -IGMP querier. We see it is ours because the timeout is `None`, and we -recognize the IP address the system has detected, as ours. We can also -see two ports that have joined the same IPv4 multicast group, 224.1.1.1, -and one join from the system itself for the IPv6 group ff02::6a. - -Now, let us see what happens when we add another bridge, this time with -VLAN filtering enabled. We skip the boring parts about how to move -ports e4-e7 to `br1` and assign them to VLANs, and again, focus on the -multicast bits only: - -
admin@example:/> configure
-admin@example:/config/> edit interface br1
-admin@example:/config/interface/br1/> set bridge vlans vlan 1 multicast snooping
-admin@example:/config/interface/br1/> set bridge vlans vlan 2 multicast snooping
-admin@example:/config/interface/br1/> leave
-admin@example:/> copy running-config startup-config
-
- -Let us see what we get: - -
admin@example:/> show ip multicast
-Multicast Overview
-Query Interval (default): 125 sec
-Router Timeout          : 255
-Fast Leave Ports        : e5
-Router Ports            : e1, e2, e5, e6, e7
-Flood Ports             : e1, e2, e3, e4, e5, e6, e7, e8
-
-Interface       VID  Querier                     State  Interval  Timeout  Ver
-br0                  192.168.2.1                    Up       125     None    3
-br1               1  0.0.0.0                        Up       125     None    3
-br1               2  0.0.0.0                        Up       125     None    3
-
-Bridge          VID  Multicast Group       Ports                              
-br0                  224.1.1.1             e2
-br0                  ff02::fb              br0
-br0                  ff02::6a              br0
-br0                  ff02::1:ff00:0        br0
-br1               1  224.1.1.1             e5
-br1               2  224.1.1.1             e7
-br1               1  ff02::fb              br1
-br1               1  ff02::1:ff00:0        br1
-
- -In this setup we have a lot more going on. Multiple multicast router -ports have been detected, and behind the scenes someone has also added -an IGMP/MLD fast-leave port. - -##### Terminology & Abbreviations - - - **IGMP**: Internet Group Membership Protocol, multicast subscription - for IPv4, for details see [RFC3376][] - - **MLD**: Multicast Listener Discovery (Protocol), multicast - subscription for IPv6, for details see [RFC3810][] - - **Unknown/Unregistered multicast**: multicast groups that are *not* - in the multicast forwarding database (MDB) - - **Known/Registered multicast**: multicast groups that *are* in the - multicast forwarding database (MDB) - - **MDB**: the multicast forwarding database, consists of filters for - multicast groups, directing where multicast is allowed to egress. A - filter entry consists of a group and a port list. The bridge filters - with a unique database per VLAN, in the same was as the unicast FDB - - **Join/Leave**: the terminology used in earlier versions of the two - protocols to subscribe and unsubscribe to a multicast group. For - more information, see *Membership Report* - - **Membership Report** A membership report is sent by end-devices and - forwarded by switches to the elected querier on the LAN. They - consist of multiple "join" and "leave" operations on groups. They - can also, per group, list which senders to allow or block. Switches - usually only support the group subscription, and even more common - also only support filtering on the MAC level[^3] - - **Querier election**: the process of determining who is the elected - IGMP/MLD querier on a LAN. Lowest numerical IP address wins, the - special address 0.0.0.0 (proxy querier) never wins - - **Proxy querier**: when no better querier exists on a LAN, one or - more devices can send proxy queries with source address 0.0.0.0 (or - :: for IPv6). See **Query Interval**, below, why this is a good - thing - - **Query interval**: the time in seconds between two queries from an - IGMP/MLD querier. It is not uncommon that end-devices do not send - their membership reports unless they first hear a query - - **Fast Leave**: set on a bridge port to ensure multicast is pruned as - quickly as possible when a "leave" membership report is received. In - effect, this option marks the port as directly connected to an - end-device. When not set (default), a query with timeout is first - sent to ensure no unintentional loss of multicast is incurred - - **Router port**: can be both configured statically and detected at - runtime based on connected devices, usually multicast routers. On - a router port *all* multicast is forwarded, both known and unknown - - **Flood port**: set on a bridge port (default: enabled) to ensure - all *unknown* multicast is forwarded - - **Router timeout**: the time in seconds until a querier is deemed to - have been lost and another device (switch/router) takes over. In the - tables shown above, a *None* timeout is declared when the current - device is the active querier - -> [!TIP] -> The reason why multicast flooding is enabled by default is to ensure -> safe co-existence with MAC multicast, which is common in industrial -> networks. It also allows end devices that do not know of IGMP/MLD to -> communicate over multicast as long as the group they have chosen is -> not used by other IGMP/MLD aware devices on the LAN. -> -> As soon as an IGMP/MLD membership report to "join" a group is received -> the group is added to the kernel MDB and forwarding to other ports -> stop. The only exception to this rule is multicast router ports. -> -> If your MAC multicast forwarding is not working properly, it may be -> because an IP multicast group maps to the same MAC address. Please -> see [RFC 1112][RFC1112] for details. Use static multicast router -> ports, or static multicast MAC filters, to mitigate. - -[RFC1112]: https://www.rfc-editor.org/rfc/rfc1112.html -[RFC3376]: https://www.rfc-editor.org/rfc/rfc3376.html -[RFC3810]: https://www.rfc-editor.org/rfc/rfc3810.html - -#### Forwarding of IEEE Reserved Group Addresses - -Addresses in the range `01:80:C2:00:00:0X` are used by various bridge -signaling protocols, and are not forwarded by default. Still, it is -sometimes useful to let the bridge forward such packets, this can be -done by specifying protocol names or the last address *nibble* as -decimal value `0..15`: - -
admin@example:/config/> edit interface br0 bridge
-admin@example:/config/interface/br0/bridge/> set ieee-group-forward     # Tap the ? key for alternatives
-  [0..15]  List of IEEE link-local protocols to forward, e.g., STP, LLDP
-  dot1x    802.1X Port-Based Network Access Control.
-  lacp     802.3 Slow Protocols, e.g., LACP.
-  lldp     802.1AB Link Layer Discovery Protocol (LLDP).
-  stp      Spanning Tree (STP/RSPT/MSTP).
-admin@example:/config/interface/br0/bridge/> set ieee-group-forward
-
- -The following example configures bridge *br0* to forward LLDP packets. - -
admin@example:/config/interface/br0/bridge/> set ieee-group-forward lldp
-admin@example:/config/interface/br0/bridge/>
-
- - -### Link Aggregation - -A link aggregate, or *lag*, allows multiple physical interfaces to be -combined into a single logical interface, providing increased bandwidth -(in some cases) and redundancy (primarily). Two modes of qualifying lag -member ports are available: - - 1. **static**: Active members selected based on link status (carrier) - 2. **lacp:** IEEE 802.3ad Link Aggregation Control Protocol - -In LACP mode, LACPDUs are exchanged by the link partners to qualify each -lag member, while in static mode only carrier is used. This additional -exchange in LACP ensures traffic can be forwarded in both directions. - -Traffic distribution, for both modes, across the active lag member ports -is determined by the hash policy[^1]. It uses an XOR of the source, -destination MAC addresses and the EtherType field. This, IEEE -802.3ad-compliant, algorithm will place all traffic to a particular -network peer on the same link. Meaning there is no increased bandwidth -for communication between two specific devices. - -> [!TIP] -> Similar to other interface types, naming your interface `lagN`, where -> `N` is a number, allows the CLI to automatically infer the interface -> type as LAG. - - -#### Basic Configuration - -Creating a link aggregate interface and adding member ports: - -
admin@example:/> configure
-admin@example:/config/> edit interface lag0
-admin@example:/config/interface/lag0/> set lag mode static
-admin@example:/config/interface/lag0/> end
-admin@example:/config/> set interface eth7 lag-port lag lag0
-admin@example:/config/> set interface eth8 lag-port lag lag0
-admin@example:/config/> leave
-
- -A static lag responds only to link (carrier) changes of member ports. -E.g., in this example egressing traffic is continuously distributed over -the two links until link down on one link is detected, triggering all -traffic to be steered to the sole remaining link. - - -#### LACP Configuration - -LACP mode provides dynamic negotiation of the link aggregate. Key -settings include: - -
admin@example:/> configure
-admin@example:/config/> edit interface lag0
-admin@example:/config/interface/lag0/> set lag mode lacp
-admin@example:/config/interface/lag0/> set lag lacp mode passive
-admin@example:/config/interface/lag0/> set lag lacp rate fast
-admin@example:/config/interface/lag0/> set lag lacp system-priority 100
-
- -LACP mode supports two operational modes: - - - **active:** Initiates negotiation by sending LACPDUs (default) - - **passive:** Waits for peer to initiate negotiation - -> [!NOTE] -> At least one end of the link must be in active mode for negotiation to occur. - -The LACP rate setting controls protocol timing: - - - **slow:** LACPDUs sent every 30 seconds, with 90 second timeout (default) - - **fast:** LACPDUs sent every second, with 3 second timeout - - -#### Link Flapping - -To protect against link flapping, debounce timers can be configured to -delay link qualification. Usually only the `up` delay is needed: - -
admin@example:/config/interface/lag0/lag/link-monitor/> edit debounce
-admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set up 500
-admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set down 200
-
- -#### Operational Status, Overview - -Like other interfaces, link aggregates are also available in the general -interfaces overview in the CLI admin-exec context. Here is the above -static mode aggregate: - -
admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-.
-.
-.
-lag0            lag        UP          static: balance-xor, hash: layer2
-│               ethernet   UP          00:a0:85:00:02:00
-├ eth7          lag        ACTIVE
-└ eth8          lag        ACTIVE
-
- -Same aggregate, but in LACP mode: - -
admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-.
-.
-.
-lag0            lag        UP          lacp: active, rate: fast (1s), hash: layer2
-│               ethernet   UP          00:a0:85:00:02:00
-├ eth7          lag        ACTIVE      active, short_timeout, aggregating, in_sync, collecting, distributing
-└ eth8          lag        ACTIVE      active, short_timeout, aggregating, in_sync, collecting, distributing
-
- - -#### Operational Status, Detail - -In addition to basic status shown in the interface overview, detailed -LAG status can be inspected: - -
admin@example:/> show interface lag0
-name                : lag0
-index               : 25
-mtu                 : 1500
-operational status  : up
-physical address    : 00:a0:85:00:02:00
-lag mode            : static
-lag type            : balance-xor
-lag hash            : layer2
-link debounce up    : 0 msec
-link debounce down  : 0 msec
-ipv4 addresses      :
-ipv6 addresses      :
-in-octets           : 0
-out-octets          : 2142
-
- -Same aggregate, but in LACP mode: - -
admin@example:/> show interface lag0
-name                : lag0
-index               : 24
-mtu                 : 1500
-operational status  : up
-physical address    : 00:a0:85:00:02:00
-lag mode            : lacp
-lag hash            : layer2
-lacp mode           : active
-lacp rate           : fast (1s)
-lacp aggregate id   : 1
-lacp system priority: 65535
-lacp actor key      : 9
-lacp partner key    : 9
-lacp partner mac    : 00:a0:85:00:03:00
-link debounce up    : 0 msec
-link debounce down  : 0 msec
-ipv4 addresses      :
-ipv6 addresses      :
-in-octets           : 100892
-out-octets          : 111776
-
- -Member ports provide additional status information: - - - Link failure counter: number of detected link failures - - LACP state flags: various states of LACP negotiation: - - `active`: port is actively sending LACPDUs - - `short_timeout`: using fast rate (1s) vs. slow rate (30s) - - `aggregating`: port is allowed to aggregate in this LAG - - `in_sync`: port is synchronized with partner - - `collecting`: port is allowed to receive traffic - - `distributing`: port is allowed to send traffic - - `defaulted`: using default partner info (partner not responding) - - `expired`: partner info has expired (no LACPDUs received) - - Aggregator ID: unique identifier for this LAG group - - Actor state: LACP state flags for this port (local) - - Partner state: LACP state flags from the remote port - -Example member port status: - -
admin@example:/> show interface eth7
-name                : eth7
-index               : 8
-mtu                 : 1500
-operational status  : up
-physical address    : 00:a0:85:00:02:00
-lag member          : lag0
-lag member state    : active
-lacp aggregate id   : 1
-lacp actor state    : active, short_timeout, aggregating, in_sync, collecting, distributing
-lacp partner state  : active, short_timeout, aggregating, in_sync, collecting, distributing
-link failure count  : 0
-ipv4 addresses      :
-ipv6 addresses      :
-in-octets           : 473244
-out-octets          : 499037
-
- - -#### Example: Switch Uplink with LACP - -LACP mode provides the most robust operation, automatically negotiating -the link aggregate and detecting configuration mismatches. - -A common use case is connecting a switch to an upstream device: - -
admin@example:/> configure
-admin@example:/config/> edit interface lag0
-admin@example:/config/interface/lag0/> set lag mode lacp
-
- -Enable fast LACP for quicker fail-over: - -
admin@example:/config/interface/lag0/> set lag lacp rate fast
-
- -Add uplink ports - -
admin@example:/config/interface/lag0/> end
-admin@example:/config/> set interface eth7 lag-port lag lag0
-admin@example:/config/> set interface eth8 lag-port lag lag0
-
- -Enable protection against "link flapping". - -
admin@example:/config/interface/lag0/> edit lag link-monitor
-admin@example:/config/interface/lag0/lag/link-monitor/> edit debounce
-admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set up 500
-admin@example:/config/interface/lag0/lag/link-monitor/debounce/> set down 200
-admin@example:/config/interface/lag0/lag/link-monitor/debounce/> top
-
- -Add to bridge for switching - -
admin@example:/config/interface/lag0/lag/link-monitor/debounce/> end
-admin@example:/config/> set interface lag0 bridge-port bridge br0
-admin@example:/config/> leave
-
- - -### VLAN Interfaces - -Creating a VLAN can be done in many ways. This section assumes VLAN -interfaces created atop another Linux interface. E.g., the VLAN -interfaces created on top of the Ethernet interface or bridge in the -picture below. - -![VLAN interface on top of Ethernet or Bridge interfaces](img/interface-vlan-variants.svg) - -A VLAN interface is basically a filtering abstraction. When you run -`tcpdump` on a VLAN interface you will only see the frames matching the -VLAN ID of the interface, compared to *all* the VLAN IDs if you run -`tcpdump` on the lower-layer interface. - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0.20
-admin@example:/config/interface/eth0.20/> show
-type vlan;
-vlan {
-  tag-type c-vlan;
-  id 20;
-  lower-layer-if eth0;
-}
-admin@example:/config/interface/eth0.20/> leave
-
- -The example below assumes bridge br0 is already created, see [VLAN -Filtering Bridge](#vlan-filtering-bridge). - -
admin@example:/> configure
-admin@example:/config/> edit interface vlan10
-admin@example:/config/interface/vlan10/> set vlan id 10
-admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0
-admin@example:/config/interface/vlan10/> leave
-
- -As conventions, a VLAN interface for VID 20 on top of an Ethernet -interface *eth0* is named *eth0.20*, and a VLAN interface for VID 10 on -top of a bridge interface *br0* is named *vlan10*. - -> [!NOTE] -> If you name your VLAN interface `foo0.N` or `vlanN`, where `N` is a -> number, the CLI infers the interface type automatically. - - -### Physical Ethernet Interfaces - -#### Ethernet Settings and Status - -Physical Ethernet interfaces provide low-level settings for speed/duplex as -well as packet status and [statistics](#ethernet-statistics). - -By default, Ethernet interfaces defaults to auto-negotiating -speed/duplex modes, advertising all speed and duplex modes available. -In the example below, the switch would by default auto-negotiate speed -1 Gbit/s on port eth1 and 100 Mbit/s on port eth4, as those are the -highest speeds supported by H1 and H2 respectively. - -![4-port Gbit/s switch connected to Gbit and Fast Ethernet Hosts](img/ethernet-autoneg.svg) - -The speed and duplex status for the links can be listed as shown -below, assuming the link operational status is 'up'. - -
admin@example:/> show interface eth1
-name                : eth1
-index               : 2
-mtu                 : 1500
-operational status  : up
-auto-negotiation    : on
-duplex              : full
-speed               : 1000
-physical address    : 00:53:00:06:11:01
-ipv4 addresses      :
-ipv6 addresses      :
-in-octets           : 75581
-out-octets          : 43130
-...
-admin@example:/> show interface eth4
-name                : eth4
-index               : 5
-mtu                 : 1500
-operational status  : up
-auto-negotiation    : on
-duplex              : full
-speed               : 100
-physical address    : 00:53:00:06:11:04
-ipv4 addresses      :
-ipv6 addresses      :
-in-octets           : 75439
-out-octets          : 550704
-...
-admin@example:/>
-
- -#### Configuring fixed speed and duplex - -Auto-negotiation of speed/duplex mode is desired in almost all -use-cases, but it is possible to disable auto-negotiation and specify -a fixed speed and duplex mode. - -> [!IMPORTANT] -> When setting a fixed speed and duplex mode, ensure both sides of the -> link have matching configuration. If speed does not match, the link -> will not come up. If duplex mode does not match, the result is -> reported collisions and/or bad throughput. - -The example below configures port eth3 to fixed speed 100 Mbit/s -half-duplex mode. - -
admin@example:/> configure
-admin@example:/config/> edit interface eth3 ethernet
-admin@example:/config/interface/eth3/ethernet/> set speed 0.1
-admin@example:/config/interface/eth3/ethernet/> set duplex half
-admin@example:/config/interface/eth3/ethernet/> set auto-negotiation enable false
-admin@example:/config/interface/eth3/ethernet/> show
-auto-negotiation {
-  enable false;
-}
-duplex half;
-speed 0.1;
-admin@example:/config/interface/eth3/ethernet/> leave
-admin@example:/>
-
- -Speed metric is in Gbit/s. Auto-negotiation needs to be disabled in -order for fixed speed/duplex to apply. Only speeds `0.1`(100 Mbit/s) -and `0.01` (10 Mbit/s) can be specified. 1 Gbit/s and higher speeds -require auto-negotiation to be enabled. - -#### Ethernet statistics - -Ethernet packet statistics[^6] can be listed as shown below. - -
admin@example:/> show interface eth1
-name                : eth1
-index               : 2
-mtu                 : 1500
-operational status  : up
-auto-negotiation    : on
-duplex              : full
-speed               : 1000
-physical address    : 00:53:00:06:11:0a
-ipv4 addresses      :
-ipv6 addresses      :
-in-octets           : 75581
-out-octets          : 43130
-
-eth-in-frames                : 434
-eth-in-multicast-frames      : 296
-eth-in-broadcast-frames      : 138
-eth-in-error-fcs-frames      : 0
-eth-in-error-oversize-frames : 0
-eth-out-frames               : 310
-eth-out-multicast-frames     : 310
-eth-out-broadcast-frames     : 0
-eth-out-good-octets          : 76821
-eth-in-good-octets           : 60598
-admin@example:/>
-
- - -### VETH Pairs - -A Virtual Ethernet (VETH) pair is basically a virtual Ethernet cable. A -cable can be "plugged in" to a bridge and the other end can be given to -a [container](container.md), or plugged into another bridge. - -The latter example is useful if you have multiple bridges in the system -with different properties (VLAN filtering, IEEE group forwarding, etc.), -but still want some way of communicating between these domains. - -
admin@example:/> configure
-admin@example:/config/> edit interface veth0a
-admin@example:/config/interface/veth0a/> set veth peer veth0b
-admin@example:/config/interface/veth0a/> end
-admin@example:/config/> diff
-interfaces {
-+  interface veth0a {
-+    type veth;
-+    veth {
-+      peer veth0b;
-+    }
-+  }
-+  interface veth0b {
-+    type veth;
-+    veth {
-+      peer veth0a;
-+    }
-+  }
-}
-admin@example:/config/>
-
- -> [!TIP] -> This is another example of the automatic inference of the interface -> type from the name. Any name can be used, but then you have to set -> the interface type to `veth` manually. - - -## Management Plane - -This section details IP Addresses And Other Per-Interface IP settings. - -Infix support several network interface types, each can be assigned one -or more IP addresses, both IPv4 and IPv6 are supported. (There is no -concept of a "primary" address.) - -![IP on top of network interface examples](img/ip-iface-examples.svg) - -### IPv4 Address Assignment - -Multiple address assignment methods are available: - -| **Type** | **Yang Model** | **Description** | -|:---------- |:----------------- |:-------------------------------------------------------------- | -| static | ietf-ip | Static assignment of IPv4 address, e.g., *10.0.1.1/24* | -| link-local | infix-ip | Auto-assignment of IPv4 address in 169.254.x.x/16 range | -| dhcp | infix-dhcp-client | Assignment of IPv4 address by DHCP server, e.g., *10.0.1.1/24* | - -> [!NOTE] -> The DHCP address method is only available for *LAN* interfaces -> (Ethernet, virtual Ethernet (veth), bridge, link aggregates, etc.) - -Supported DHCP (request) options, configurability (Cfg) and defaults, -are listed below. Configurable options can be disabled on a per client -interface basis, some options, like `clientid` and option 81, are -possible to set the value of as well. - -| **Opt** | **Name** | **Cfg** | **Description** | -|---------|-----------------------------|---------|-----------------------------------------------------| -| 1 | `netmask` | No | Request IP address and netmask | -| 3 | `router` | Yes | Default route(s), see also option 121 and 249 | -| 6 | `dns-server` | Yes | DNS server(s), static ones take precedence | -| 12 | `hostname` | Yes | DHCP cannot set hostname, only for informing server | -| 15 | `domain` | Yes | Default domain name, for name resolution | -| 28 | `broadcast` | Yes | Broadcast address, calculated if disabled | -| 42 | `ntp-server` | Yes | NTP server(s), static ones take precedence | -| 50 | `address` | Yes | Request (previously cached) address | -| 61 | `client-id` | Yes | Default MAC address (and option 12) | -| 81 | `fqdn` | Yes | Similar to option 12, request FQDN update in DNS | -| 119 | `search` | Yes | Request domain search list | -| 121 | `classless-static-route` | Yes | Classless static routes | -| 249 | `ms-classless-static-route` | Yes | Microsoft static route, same as option 121 | -| | | | | - -**Default:** `router`, `dns-server`, `domain`, `broadcast`, `ntp-server`, `search`, - `address`, `classless-static-route`, `ms-classless-static-route` - -When configuring a DHCP client, ensure that the NTP client is enabled -for the `ntp-server` DHCP option to be processed correctly. If the NTP -client is not enabled, any NTP servers provided by the DHCP server will -be ignored. For details on how to enable the NTP client, see the [NTP -Client Configuration](system.md#ntp-client-configuration) section. - -> [!IMPORTANT] -> Per [RFC3442][4], if the DHCP server returns both a Classless Static -> Routes option (121) and Router option (3), the DHCP client *must* -> ignore the latter. - - -### IPv6 Address Assignment - -Multiple address assignment methods are available: - -| **Type** | **Yang Model** | **Description** | -|:---------------- |:-------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------- | -| static | ietf-ip | Static assignment of IPv6 address, e.g., *2001:db8:0:1::1/64* | -| link-local | ietf-ip[^2] | (RFC4862) Auto-configured link-local IPv6 address (*fe80::0* prefix + interface identifier, e.g., *fe80::ccd2:82ff:fe52:728b/64*) | -| global auto-conf | ietf-ip | (RFC4862) Auto-configured (stateless) global IPv6 address (prefix from router + interface identifier, e.g., *2001:db8:0:1:ccd2:82ff:fe52:728b/64* | -| dhcp | infix-dhcpv6-client | Assignment of IPv6 address by DHCPv6 server, e.g., *2001:db8::42/128* | - -Both for *link-local* and *global auto-configuration*, it is possible -to auto-configure using a random suffix instead of the interface -identifier. - -> [!NOTE] -> The DHCPv6 address method is only available for *LAN* interfaces -> (Ethernet, virtual Ethernet (veth), bridge, link aggregates, etc.) - -Supported DHCPv6 (request) options, configurability (Cfg) and defaults, -are listed below. Configurable options can be disabled on a per client -interface basis, some options, like `client-id` and `client-fqdn`, are -possible to set the value of as well. - -| **Opt** | **Name** | **Cfg** | **Description** | -|---------|----------------------------|---------|--------------------------------------------------------| -| 1 | `client-id` | Yes | Client identifier (DUID), auto-generated by default | -| 2 | `server-id` | Yes | Server identifier (DUID) | -| 23 | `dns-server` | Yes | DNS recursive name servers, static ones take precedence| -| 24 | `domain-search` | Yes | Domain search list | -| 25 | `ia-pd` | Yes | Prefix delegation for downstream networks | -| 31 | `sntp-server` | Yes | Simple Network Time Protocol servers | -| 32 | `information-refresh-time` | Yes | Refresh time for stateless DHCPv6 | -| 39 | `client-fqdn` | Yes | Client FQDN, request DNS update from server | -| 56 | `ntp-server` | Yes | NTP time servers, static ones take precedence | -| | | | | - -**Default:** `dns-server`, `domain-search`, `ntp-server` - -DHCPv6 supports both **stateful** (address assignment) and **stateless** -(information-only) modes: - -- **Stateful DHCPv6**: The server assigns IPv6 addresses to clients. This is - the default mode when enabling the DHCPv6 client. -- **Stateless DHCPv6**: Used with SLAAC (Stateless Address Autoconfiguration) - when only configuration information (DNS, NTP, etc.) is needed. Enable with - the `information-only` setting. - -When configuring a DHCPv6 client, ensure that the NTP client is enabled -for the `ntp-server` DHCPv6 option to be processed correctly. If the -NTP client is not enabled, any NTP servers provided by the DHCPv6 server -will be ignored. For details on how to enable the NTP client, see the -[NTP Client Configuration](system.md#ntp-client-configuration) section. - -### Examples - -![Switch example (eth0 and lo)](img/ip-address-example-switch.svg) - -
admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv6                   fe80::ff:fe00:0/64 (link-layer)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- -To illustrate IP address configuration, the examples below uses a -switch with a single Ethernet interface (eth0) and a loopback -interface (lo). As shown above, these examples assume *eth0* has an -IPv6 link-local address and *lo* has static IPv4 and IPv6 addresses by -default. - -#### Static and link-local IPv4 addresses - -![Setting static IPv4 (and link-local IPv4)](img/ip-address-example-ipv4-static.svg) - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv4
-admin@example:/config/interface/eth0/ipv4/> set address 10.0.1.1 prefix-length 24
-admin@example:/config/interface/eth0/ipv4/> set autoconf
-admin@example:/config/interface/eth0/ipv4/> diff
-+interfaces {
-+  interface eth0 {
-+    ipv4 {
-+      address 10.0.1.1 {
-+        prefix-length 24;
-+      }
-+      autoconf;
-+    }
-+  }
-+}
-admin@example:/config/interface/eth0/ipv4/> leave
-admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv4                   169.254.1.3/16 (random)
-                ipv4                   10.0.1.1/24 (static)
-                ipv6                   fe80::ff:fe00:0/64 (link-layer)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- -As shown, the link-local IPv4 address is configured with `set autoconf`. -The presence of the `autoconf` container enables IPv4 link-local address -assignment. The resulting address (169.254.1.3/16) is of type *random* -([ietf-ip.yang][2]). - -The IPv4LL client also supports a `request-address` setting which can be -used to "seed" the client's starting address. If the address is free it -will be used, otherwise it falls back to the default algorithm. - -
admin@example:/config/interface/eth0/ipv4/> edit autoconf
-admin@example:/config/interface/eth0/ipv4/autoconf/> set request-address 169.254.1.2
-admin@example:/config/interface/eth0/ipv4/autoconf/> leave
-
- - -#### Use of DHCP for IPv4 address assignment - -![Using DHCP for IPv4 address assignment](img/ip-address-example-ipv4-dhcp.svg) - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv4
-admin@example:/config/interface/eth0/ipv4/> set dhcp
-admin@example:/config/interface/eth0/ipv4/> leave
-admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv4                   10.1.2.100/24 (dhcp)
-                ipv6                   fe80::ff:fe00:0/64 (link-layer)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- -The resulting address (10.1.2.100/24) is of type *dhcp*. - -To configure DHCP client options, such as sending a specific hostname to the -server, you can specify options with values: - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv4 dhcp
-admin@example:/config/interface/eth0/ipv4/dhcp/> set option hostname value myhost
-admin@example:/config/interface/eth0/ipv4/dhcp/> show
-option hostname {
-  value myhost;
-}
-admin@example:/config/interface/eth0/ipv4/dhcp/> leave
-admin@example:/>
-
- -> [!TIP] -> The special value `auto` can be used with the hostname option to -> automatically use the configured system hostname. - -Other useful DHCP options include: - -- `client-id` - Send a specific client identifier to the server -- `route-preference` - Set the administrative distance for DHCP-learned routes (default: 5) - -For advanced usage with vendor-specific options, see the YANG model. - -#### Use of DHCPv6 for IPv6 address assignment - -![Using DHCPv6 for IPv6 address assignment](img/ip-address-example-ipv6-dhcp.svg) - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv6
-admin@example:/config/interface/eth0/ipv6/> set dhcp
-admin@example:/config/interface/eth0/ipv6/> leave
-admin@example:/> show interface
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv6                   2001:db8::42/128 (dhcp)
-                ipv6                   fe80::ff:fe00:0/64 (link-layer)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- -The resulting address (2001:db8::42/128) is of type *dhcp*. - -To configure DHCPv6 client options, such as requesting prefix delegation -for downstream networks, you can specify options: - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv6 dhcp
-admin@example:/config/interface/eth0/ipv6/dhcp/> set option ia-pd
-admin@example:/config/interface/eth0/ipv6/dhcp/> set option dns-server
-admin@example:/config/interface/eth0/ipv6/dhcp/> show
-option dns-server;
-option ia-pd;
-admin@example:/config/interface/eth0/ipv6/dhcp/> leave
-admin@example:/>
-
- -For stateless DHCPv6 (used with SLAAC to get only configuration information): - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv6 dhcp
-admin@example:/config/interface/eth0/ipv6/dhcp/> set information-only true
-admin@example:/config/interface/eth0/ipv6/dhcp/> show
-information-only true;
-option dns-server;
-option domain-search;
-admin@example:/config/interface/eth0/ipv6/dhcp/> leave
-admin@example:/>
-
- -Other useful DHCPv6 options include: - -- `duid` - Set a specific DHCPv6 Unique Identifier (auto-generated by default) -- `client-fqdn` - Request the server to update DNS records with client's FQDN -- `route-preference` - Set the administrative distance for DHCPv6-learned routes (default: 5) - -For advanced usage with vendor-specific options, see the YANG model. - -#### Disabling IPv6 link-local address(es) - -The (only) way to disable IPv6 link-local addresses is by disabling IPv6 -on the interface. - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv6
-admin@example:/config/interface/eth0/ipv6/> set enabled false
-admin@example:/config/interface/eth0/ipv6/> leave
-admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- -#### Static IPv6 address - -![Setting static IPv6](img/ip-address-example-ipv6-static.svg) - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv6
-admin@example:/config/interface/eth0/ipv6/> set address 2001:db8::1 prefix-length 64
-admin@example:/config/interface/eth0/ipv6/> leave
-admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv6                   2001:db8::1/64 (static)
-                ipv6                   fe80::ff:fe00:0/64 (link-layer)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- - -#### Stateless Auto-configuration of Global IPv6 Address - -![Auto-configuration of global IPv6](img/ip-address-example-ipv6-auto-global.svg) - -Stateless address auto-configuration of global addresses is enabled by -default. The address is formed by concatenating the network prefix -advertised by the router (here 2001:db8:0:1::0/64) and the interface -identifier. The resulting address is of type *link-layer*, as it is -formed based on the interface identifier ([ietf-ip.yang][2]). - -
admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv6                   2001:db8:0:1:0:ff:fe00:0/64 (link-layer)
-                ipv6                   fe80::ff:fe00:0/64 (link-layer)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- -Disabling auto-configuration of global IPv6 addresses can be done as shown -below. - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv6
-admin@example:/config/interface/eth0/ipv6/> set autoconf create-global-addresses false
-admin@example:/config/interface/eth0/ipv6/> leave
-admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv6                   fe80::ff:fe00:0/64 (link-layer)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- - -#### Random Link Identifiers for IPv6 Stateless Autoconfiguration - -![Auto-configuration of global IPv6](img/ip-address-example-ipv6-auto-global.svg) - -By default, the auto-configured link-local and global IPv6 addresses -are formed from a link-identifier based on the MAC address. - -
admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv6                   2001:db8:0:1:0:ff:fe00:0/64 (link-layer)
-                ipv6                   fe80::ff:fe00:0/64 (link-layer)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- -To avoid revealing identity information in the IPv6 address, it is -possible to specify use of a random identifier ([ietf-ip.yang][2] and -[RFC8981][3]). - -
admin@example:/> configure
-admin@example:/config/> edit interface eth0 ipv6
-admin@example:/config/interface/eth0/ipv6/> set autoconf create-temporary-addresses true
-admin@example:/config/interface/eth0/ipv6/> leave
-admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA                                    
-eth0            ethernet   UP          02:00:00:00:00:00
-                ipv6                   2001:db8:0:1:b705:8374:638e:74a8/64 (random)
-                ipv6                   fe80::ad3d:b274:885a:9ffb/64 (random)
-lo              ethernet   UP          00:00:00:00:00:00
-                ipv4                   127.0.0.1/8 (static)
-                ipv6                   ::1/128 (static)
-admin@example:/>
-
- -Both the link-local address (fe80::) and the global address (2001:) -have changed type to *random*. - - -### IPv4 forwarding - -To be able to route (static or dynamic) on the interface it is -required to enable forwarding. This setting controls if packets -received on this interface can be forwarded. - -
admin@example:/config/> edit interface eth0
-admin@example:/config/interface/eth0/> set ipv4 forwarding
-admin@example:/config/interface/eth0/> leave
-admin@example:/>
-
- - -### IPv6 forwarding - -Due to how the Linux kernel manages IPv6 forwarding, we can not fully -control it per interface via this setting like how IPv4 works. Instead, -IPv6 forwarding is globally enabled when at least one interface enable -forwarding, otherwise it is disabled. - -The following table shows the system IPv6 features that the `forwarding` -setting control when it is *Enabled* or *Disabled: - -| **IPv6 Feature** | **Enabled** | **Disabled** | -|:-----------------------------------------|:------------|:-------------| -| IsRouter set in Neighbour Advertisements | Yes | No | -| Transmit Router Solicitations | No | Yes | -| Router Advertisements are ignored | Yes | Yes | -| Accept Redirects | No | Yes | - -
admin@example:/config/> edit interface eth0
-admin@example:/config/interface/eth0/> set ipv6 forwarding
-admin@example:/config/interface/eth0/> leave
-admin@example:/>
-
- - -## Routing support - -Currently supported YANG models: - -| **YANG Model** | **Description** | -|:--------------------------|:--------------------------------| -| ietf-routing | Base model for all other 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 -is used to set configuration and read operational status (RIB tables) in -the other models. - -> [!NOTE] -> The standard IETF routing models allows multiple instances, but Infix -> currently *only support one instance* per routing protocol! In the -> examples presented here, the instance name `default` is used. - - -### IPv4 Static routes - -The standard IETF model for static routes reside under the `static` -control plane protocol. For our examples we use the instance name -`default`, you can use any name. - -For a route with destination 192.168.200.0/24 via 192.168.1.1: - -
admin@example:/> configure
-admin@example:/config/> edit routing control-plane-protocol static name default ipv4
-admin@example:/config/routing/…/ipv4/> set route 192.168.200.0/24 next-hop next-hop-address 192.168.1.1
-admin@example:/config/routing/…/ipv4/> leave
-admin@example:/>
-
- -For a "floating" static route with destination 10.0.0.0/16 via a backup -router 192.168.1.1, using the highest possible distance: - -
admin@example:/> configure
-admin@example:/config/> edit routing control-plane-protocol static name default ipv4
-admin@example:/config/routing/…/ipv4/> set route 10.0.0.0/16 next-hop next-hop-address 192.168.1.1 route-preference 254
-admin@example:/config/routing/…/ipv4/> leave
-admin@example:/>
-
- -> [!TIP] -> Remember to enable [IPv4 forwarding](#ipv4-forwarding) for the -> interfaces you want to route between. - - -### IPv6 Static routes - -
admin@example:/> configure
-admin@example:/config/> edit routing control-plane-protocol static name default ipv6
-admin@example:/config/routing/…/ipv6/> set route 2001:db8:3c4d:200::/64 next-hop next-hop-address 2001:db8:3c4d:1::1
-admin@example:/config/routing/…/ipv6/> leave
-admin@example:/>
-
- - -### OSPFv2 Routing - -The system supports OSPF dynamic routing for IPv4, i.e., OSPFv2. To -enable OSPF and set one active interface in area 0: - -
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
-admin@example:/config/routing/…/ospf/> set area 0.0.0.0 interface e0 enabled
-admin@example:/config/routing/…/ospf/> leave
-admin@example:/>
-
- -> [!TIP] -> Remember to enable [IPv4 forwarding](#ipv4-forwarding) for all the -> interfaces you want to route between. - - -#### OSPF area types - -In addition to *regular* OSPF areas, area types *NSSA* and *Stub* are -also supported. To configure an NSSA area with summary routes: - -
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
-admin@example:/config/routing/…/ospf/> set area 0.0.0.1 area-type nssa-area
-admin@example:/config/routing/…/ospf/> set area 0.0.0.1 summary true
-admin@example:/config/routing/…/ospf/> leave
-admin@example:/>
-
- - -#### Bidirectional Forwarding Detection (BFD) - -It is possible to enable BFD per OSPF interface to speed up detection of -link loss. - -
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
-admin@example:/config/routing/…/ospf/> set area 0.0.0.0 interface e0 bfd enabled true
-admin@example:/config/routing/…/ospf/> leave
-admin@example:/>
-
- - -#### OSPF interface settings - -We have already seen how to enable OSPF per interface (*enabled true*) -and BFD for OSPF per interface (*bfd enabled true*). These and other -OSPF interface settings are done in context of an OSFP area, e.g., *area -0.0.0.0*. Available commands can be listed using the `?` mark. - -
admin@example:/config/routing/…/> edit ospf area 0.0.0.0
-admin@example:/config/routing/…/ospf/area/0.0.0.0/> edit interface e0
-admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set ?
-  bfd                  BFD interface configuration.
-  cost                 Interface's cost.
-  dead-interval        Interval after which a neighbor is declared down
-  enabled              Enables/disables the OSPF protocol on the interface.
-  hello-interval       Interval between Hello packets (seconds).  It must
-  interface-type       Interface type.
-  passive              Enables/disables a passive interface.  A passive
-  retransmit-interval  Interval between retransmitting unacknowledged Link
-  transmit-delay       Estimated time needed to transmit Link State Update
-admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set
-
- -For example, setting the OSPF *interface type* to *point-to-point* for -an Ethernet interface can be done as follows. - -
admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set interface-type point-to-point
-admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/>
-
- -#### OSPF global settings - -In addition to *area* and *interface* specific settings, OSPF provides -global settings for route redistribution and OSPF router identifier. - -
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
-admin@example:/config/routing/…/ospf/> set ?
-  area                     List of OSPF areas.
-  default-route-advertise  Distribute default route to network
-  explicit-router-id       Defined in RFC 2328.  A 32-bit number
-  redistribute             Redistribute protocols into OSPF
-admin@example:/config/routing/…/ospf/> set
-
- -- Explicit router ID: By default the router will pick an IP address - from one of its OSPF interfaces as OSPF router ID. An explicit ID is - used to get a deterministic behavior, e.g., `set explicit-router-id - 1.1.1.1`. -- Redistribution: `set redistribute static` and `set redistribute connected` - can be used to include static or connected routes into the OSPF routing - domain. These routes are redistributed as *external type-2* (E2) - routes. -- Advertising default route: An OSPF router can be made to distribute - a default route into the OSPF domain by command `set - default-route-advertise enabled`. This route is distributed as long - as the router itself has an *active* default route in its routing - table. By adding command `set default-route-advertise always` the - router will distribute a default route even when it lacks a default - route. The default route will be distributed as an *external type-2* - (E2) route. - - -#### Debug OSPFv2 - -Using NETCONF and the YANG model *ietf-routing* it is possible to read -the OSPF routing table, neighbors and more, that may be useful for -debugging the OSPFv2 setup. The CLI has various OSPF status commands -such as `show ospf neighbor`, `show ospf interface` and `show ospf -routes`. - -
admin@example:/> show ospf neighbor
-Neighbor ID     Pri State           Up Time         Dead Time Address         Interface                        RXmtL RqstL DBsmL
-10.1.1.2          1 Full/-          3h46m59s          30.177s 10.1.1.2        e0:10.1.1.1                          0     0     0
-10.1.1.3          1 Full/-          3h46m55s          34.665s 10.1.1.3        e1:10.1.1.1                          0     0     0
-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 - -The routing table can be inspected from the operational datastore, XPath -`/routing/ribs`, using sysrepocfg, NETCONF/RESTCONF, or using the CLI. - - -#### IPv4 routing table - -This CLI example shows the IPv4 routing table with a few connected -routes and some routes learned from OSPF. See the next section for -an explanation of route preferences (PREF). - -The `>` at the start of a line marks a selected route (in the IETF YANG -model referred to as *active*), if there are more than one route with -the same destination the `*` marks the next-hop used and installed in -the kernel FIB (the YANG model refers to this as *installed*). - -
admin@example:/> show ip route
-   DESTINATION            PREF NEXT-HOP         PROTO     UPTIME
->* 0.0.0.0/0             110/2 10.0.23.1        ospfv2   4h2m43s
->* 10.0.0.1/32        110/4000 10.0.13.1        ospfv2   4h2m43s
-   10.0.0.3/32           110/0 lo               ospfv2   4h2m57s
->* 10.0.0.3/32             0/0 lo               direct   4h2m58s
-   10.0.13.0/30       110/2000 e5               ospfv2   4h2m57s
->* 10.0.13.0/30            0/0 e5               direct   4h2m58s
-   10.0.23.0/30          110/1 e6               ospfv2   4h2m57s
->* 10.0.23.0/30            0/0 e6               direct   4h2m58s
-   192.168.3.0/24        110/1 e2               ospfv2   4h2m57s
->* 192.168.3.0/24          0/0 e2               direct   4h2m58s
-admin@example:/>
-
- - -#### IPv6 routing table - -This CLI example show the IPv6 routing table. - -
admin@example:/> show ipv6 route
-   DESTINATION                      PREF NEXT-HOP              PROTO     UPTIME
->* ::/0                              1/0 2001:db8:3c4d:50::1   static   0h1m20s
->* 2001:db8:3c4d:50::/64             0/0 e6                    direct   0h1m20s
->* 2001:db8:3c4d:200::1/128          0/0 lo                    direct   0h1m20s
- * fe80::/64                         0/0 e7                    direct   0h1m20s
- * fe80::/64                         0/0 e6                    direct   0h1m20s
- * fe80::/64                         0/0 e5                    direct   0h1m20s
- * fe80::/64                         0/0 e4                    direct   0h1m20s
- * fe80::/64                         0/0 e3                    direct   0h1m20s
- * fe80::/64                         0/0 e2                    direct   0h1m20s
->* fe80::/64                         0/0 e1                    direct   0h1m20s
-admin@example:/>
-
- - -#### Route Preference - -The operating system leverages FRRouting ([Frr][0]) as routing engine -for both static and dynamic routing. Even routes injected from a DHCP -client, and IPv4 link-local (IPv4) routes, are injected into Frr to let -it weigh all routes before installing them into the kernel routing table -(sometimes referred to as FIB). - -Routes have different weights made up from a *distance* and a *metric*. -The kernel routing table only talks about *metric*, which unfortunately -is **not the same** -- this is one of the reasons why the term *route -preference* is used instead. It is recommended to use the CLI, or any -of the other previously mentioned YANG based front-ends, to inspect the -routing table. - -Default distances used (lower numeric value wins): - -| **Distance** | **Protocol** | -|--------------|-----------------------------------------| -| 0 | Kernel routes, i.e., connected routes | -| 1 | Static routes | -| 5 | DHCP routes | -| 110 | OSPF | -| 254 | IPv4LL (ZeroConf) device routes | -| 255 | Route will not be used or redistributed | - -Hence, a route learned from OSPF may be overridden by a static route set -locally. By default, even a route to the same destination, but with a -different next-hop, learned from a DHCP server wins over an OSPF route. - -The distance used for static routes and DHCP routes can be changed by -setting a different *routing preference* value. - -> [!NOTE] -> The kernel metric is an unsigned 32-bit value, which is read by Frr as -> (upper) 8 bits distance and 24 bits metric. But it does not write it -> back to the kernel FIB this way, only selected routes are candidates -> to be installed in the FIB by Frr. - - -#### Source protocol - -The source protocol describes the origin of the route. - -| **Protocol** | **Description** | -|:-------------|:----------------------------------------------------| -| kernel | Added when setting a subnet address on an interface | -| static | User created, learned from DHCP, or IPv4LL | -| ospfv2 | Routes learned from OSPFv2 | - -The YANG model *ietf-routing* support multiple ribs but only two are -currently supported, namely `ipv4` and `ipv6`. - - [1]: https://www.rfc-editor.org/rfc/rfc8343 [2]: https://www.rfc-editor.org/rfc/rfc8344 -[3]: https://www.rfc-editor.org/rfc/rfc8981 -[4]: https://www.rfc-editor.org/rfc/rfc3442 -[0]: https://frrouting.org/ - -[^1]: `(source MAC XOR destination MAC XOR EtherType) MODULO num_links` -[^2]: Link-local IPv6 addresses are implicitly enabled when enabling - IPv6. IPv6 can be enabled/disabled per interface in the - [ietf-ip][2] YANG model. -[^3]: For example, IPv4 groups are mapped to MAC multicast addresses by - mapping the low-order 23-bits of the IP address in the low-order 23 - bits of the Ethernet address 01:00:5E:00:00:00. Meaning, more than - one IP multicast group maps to the same MAC multicast group. -[^4]: A YANG deviation was previously used to make it possible to set - `phys-address`, but this has been replaced with the more flexible - `custom-phys-address`. -[^5]: MAC bridges on Marvell Linkstreet devices are currently limited to - a single MAC database, this may be a problem if the same MAC address - appears in different MAC bridges. -[^6]: Ethernet counters are described in *ieee802-ethernet-interface.yang* - and *infix-ethernet-interface.yang*. There is a dedicated document on - [Ethernet Counters](eth-counters.md) that provide additional details - on the statistics support. diff --git a/doc/routing.md b/doc/routing.md new file mode 100644 index 000000000..13573b454 --- /dev/null +++ b/doc/routing.md @@ -0,0 +1,453 @@ +# Routing + +Currently supported YANG models: + +| **YANG Model** | **Description** | +|:--------------------------|:--------------------------------| +| ietf-routing | Base model for all other 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 +is used to set configuration and read operational status (RIB tables) in +the other models. + +> [!NOTE] +> The standard IETF routing models allows multiple instances, but Infix +> currently *only support one instance* per routing protocol! In the +> examples presented here, the instance name `default` is used. + + +## IPv4 Static routes + +The standard IETF model for static routes reside under the `static` +control plane protocol. For our examples we use the instance name +`default`, you can use any name. + +For a route with destination 192.168.200.0/24 via 192.168.1.1: + +
admin@example:/> configure
+admin@example:/config/> edit routing control-plane-protocol static name default ipv4
+admin@example:/config/routing/…/ipv4/> set route 192.168.200.0/24 next-hop next-hop-address 192.168.1.1
+admin@example:/config/routing/…/ipv4/> leave
+admin@example:/>
+
+ +For a "floating" static route with destination 10.0.0.0/16 via a backup +router 192.168.1.1, using the highest possible distance: + +
admin@example:/> configure
+admin@example:/config/> edit routing control-plane-protocol static name default ipv4
+admin@example:/config/routing/…/ipv4/> set route 10.0.0.0/16 next-hop next-hop-address 192.168.1.1 route-preference 254
+admin@example:/config/routing/…/ipv4/> leave
+admin@example:/>
+
+ +> [!TIP] +> Remember to enable [IPv4 forwarding](ip.md#ipv4-forwarding) for the +> interfaces you want to route between. + + +## IPv6 Static routes + +
admin@example:/> configure
+admin@example:/config/> edit routing control-plane-protocol static name default ipv6
+admin@example:/config/routing/…/ipv6/> set route 2001:db8:3c4d:200::/64 next-hop next-hop-address 2001:db8:3c4d:1::1
+admin@example:/config/routing/…/ipv6/> leave
+admin@example:/>
+
+ + +## OSPFv2 Routing + +The system supports OSPF dynamic routing for IPv4, i.e., OSPFv2. To +enable OSPF and set one active interface in area 0: + +
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@example:/config/routing/…/ospf/> set area 0.0.0.0 interface e0 enabled
+admin@example:/config/routing/…/ospf/> leave
+admin@example:/>
+
+ +> [!TIP] +> Remember to enable [IPv4 forwarding](ip.md#ipv4-forwarding) for all the +> interfaces you want to route between. + + +### OSPF area types + +In addition to *regular* OSPF areas, area types *NSSA* and *Stub* are +also supported. To configure an NSSA area with summary routes: + +
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@example:/config/routing/…/ospf/> set area 0.0.0.1 area-type nssa-area
+admin@example:/config/routing/…/ospf/> set area 0.0.0.1 summary true
+admin@example:/config/routing/…/ospf/> leave
+admin@example:/>
+
+ + +### Bidirectional Forwarding Detection (BFD) + +It is possible to enable BFD per OSPF interface to speed up detection of +link loss. + +
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@example:/config/routing/…/ospf/> set area 0.0.0.0 interface e0 bfd enabled true
+admin@example:/config/routing/…/ospf/> leave
+admin@example:/>
+
+ + +### OSPF interface settings + +We have already seen how to enable OSPF per interface (*enabled true*) +and BFD for OSPF per interface (*bfd enabled true*). These and other +OSPF interface settings are done in context of an OSFP area, e.g., *area +0.0.0.0*. Available commands can be listed using the `?` mark. + +
admin@example:/config/routing/…/> edit ospf area 0.0.0.0
+admin@example:/config/routing/…/ospf/area/0.0.0.0/> edit interface e0
+admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set ?
+  bfd                  BFD interface configuration.
+  cost                 Interface's cost.
+  dead-interval        Interval after which a neighbor is declared down
+  enabled              Enables/disables the OSPF protocol on the interface.
+  hello-interval       Interval between Hello packets (seconds).  It must
+  interface-type       Interface type.
+  passive              Enables/disables a passive interface.  A passive
+  retransmit-interval  Interval between retransmitting unacknowledged Link
+  transmit-delay       Estimated time needed to transmit Link State Update
+admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set
+
+ +For example, setting the OSPF *interface type* to *point-to-point* for +an Ethernet interface can be done as follows. + +
admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> set interface-type point-to-point
+admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/>
+
+ +### OSPF global settings + +In addition to *area* and *interface* specific settings, OSPF provides +global settings for route redistribution and OSPF router identifier. + +
admin@example:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@example:/config/routing/…/ospf/> set ?
+  area                     List of OSPF areas.
+  default-route-advertise  Distribute default route to network
+  explicit-router-id       Defined in RFC 2328.  A 32-bit number
+  redistribute             Redistribute protocols into OSPF
+admin@example:/config/routing/…/ospf/> set
+
+ +- Explicit router ID: By default the router will pick an IP address + from one of its OSPF interfaces as OSPF router ID. An explicit ID is + used to get a deterministic behavior, e.g., `set explicit-router-id + 1.1.1.1`. +- Redistribution: `set redistribute static` and `set redistribute connected` + can be used to include static or connected routes into the OSPF routing + domain. These routes are redistributed as *external type-2* (E2) + routes. +- Advertising default route: An OSPF router can be made to distribute + a default route into the OSPF domain by command `set + default-route-advertise enabled`. This route is distributed as long + as the router itself has an *active* default route in its routing + table. By adding command `set default-route-advertise always` the + router will distribute a default route even when it lacks a default + route. The default route will be distributed as an *external type-2* + (E2) route. + + +### Debug OSPFv2 + +Using NETCONF and the YANG model *ietf-routing* it is possible to read +the OSPF routing table, neighbors and more, that may be useful for +debugging the OSPFv2 setup. The CLI has various OSPF status commands +such as `show ospf neighbor`, `show ospf interface` and `show ospf +routes`. + +
admin@example:/> show ospf neighbor
+Neighbor ID     Pri State           Up Time         Dead Time Address         Interface                        RXmtL RqstL DBsmL
+10.1.1.2          1 Full/-          3h46m59s          30.177s 10.1.1.2        e0:10.1.1.1                          0     0     0
+10.1.1.3          1 Full/-          3h46m55s          34.665s 10.1.1.3        e1:10.1.1.1                          0     0     0
+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](ip.md#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 + +The routing table can be inspected from the operational datastore, XPath +`/routing/ribs`, using sysrepocfg, NETCONF/RESTCONF, or using the CLI. + + +### IPv4 routing table + +This CLI example shows the IPv4 routing table with a few connected +routes and some routes learned from OSPF. See the next section for +an explanation of route preferences (PREF). + +The `>` at the start of a line marks a selected route (in the IETF YANG +model referred to as *active*), if there are more than one route with +the same destination the `*` marks the next-hop used and installed in +the kernel FIB (the YANG model refers to this as *installed*). + +
admin@example:/> show ip route
+   DESTINATION            PREF NEXT-HOP         PROTO     UPTIME
+>* 0.0.0.0/0             110/2 10.0.23.1        ospfv2   4h2m43s
+>* 10.0.0.1/32        110/4000 10.0.13.1        ospfv2   4h2m43s
+   10.0.0.3/32           110/0 lo               ospfv2   4h2m57s
+>* 10.0.0.3/32             0/0 lo               direct   4h2m58s
+   10.0.13.0/30       110/2000 e5               ospfv2   4h2m57s
+>* 10.0.13.0/30            0/0 e5               direct   4h2m58s
+   10.0.23.0/30          110/1 e6               ospfv2   4h2m57s
+>* 10.0.23.0/30            0/0 e6               direct   4h2m58s
+   192.168.3.0/24        110/1 e2               ospfv2   4h2m57s
+>* 192.168.3.0/24          0/0 e2               direct   4h2m58s
+admin@example:/>
+
+ + +### IPv6 routing table + +This CLI example show the IPv6 routing table. + +
admin@example:/> show ipv6 route
+   DESTINATION                      PREF NEXT-HOP              PROTO     UPTIME
+>* ::/0                              1/0 2001:db8:3c4d:50::1   static   0h1m20s
+>* 2001:db8:3c4d:50::/64             0/0 e6                    direct   0h1m20s
+>* 2001:db8:3c4d:200::1/128          0/0 lo                    direct   0h1m20s
+ * fe80::/64                         0/0 e7                    direct   0h1m20s
+ * fe80::/64                         0/0 e6                    direct   0h1m20s
+ * fe80::/64                         0/0 e5                    direct   0h1m20s
+ * fe80::/64                         0/0 e4                    direct   0h1m20s
+ * fe80::/64                         0/0 e3                    direct   0h1m20s
+ * fe80::/64                         0/0 e2                    direct   0h1m20s
+>* fe80::/64                         0/0 e1                    direct   0h1m20s
+admin@example:/>
+
+ + +### Route Preference + +The operating system leverages FRRouting ([Frr][0]) as routing engine +for both static and dynamic routing. Even routes injected from a DHCP +client, and IPv4 link-local (IPv4) routes, are injected into Frr to let +it weigh all routes before installing them into the kernel routing table +(sometimes referred to as FIB). + +Routes have different weights made up from a *distance* and a *metric*. +The kernel routing table only talks about *metric*, which unfortunately +is **not the same** -- this is one of the reasons why the term *route +preference* is used instead. It is recommended to use the CLI, or any +of the other previously mentioned YANG based front-ends, to inspect the +routing table. + +Default distances used (lower numeric value wins): + +| **Distance** | **Protocol** | +|--------------|-----------------------------------------| +| 0 | Kernel routes, i.e., connected routes | +| 1 | Static routes | +| 5 | DHCP routes | +| 110 | OSPF | +| 254 | IPv4LL (ZeroConf) device routes | +| 255 | Route will not be used or redistributed | + +Hence, a route learned from OSPF may be overridden by a static route set +locally. By default, even a route to the same destination, but with a +different next-hop, learned from a DHCP server wins over an OSPF route. + +The distance used for static routes and DHCP routes can be changed by +setting a different *routing preference* value. + +> [!NOTE] +> The kernel metric is an unsigned 32-bit value, which is read by Frr as +> (upper) 8 bits distance and 24 bits metric. But it does not write it +> back to the kernel FIB this way, only selected routes are candidates +> to be installed in the FIB by Frr. + + +### Source protocol + +The source protocol describes the origin of the route. + +| **Protocol** | **Description** | +|:-------------|:----------------------------------------------------| +| kernel | Added when setting a subnet address on an interface | +| static | User created, learned from DHCP, or IPv4LL | +| ospfv2 | Routes learned from OSPFv2 | + +The YANG model *ietf-routing* support multiple ribs but only two are +currently supported, namely `ipv4` and `ipv6`. + +[0]: https://frrouting.org/ diff --git a/doc/scripting-prod.md b/doc/scripting-prod.md index 4f115b261..3836e51e9 100644 --- a/doc/scripting-prod.md +++ b/doc/scripting-prod.md @@ -350,5 +350,5 @@ the created configuration. [1]: scripting-sysrepocfg.md#backup-configuration [2]: scripting-sysrepocfg.md#restore-configuration -[8]: networking.md#bridging -[9]: networking.md#vlan-filtering-bridge +[8]: bridging.md +[9]: bridging.md#vlan-filtering-bridge diff --git a/doc/tunnels.md b/doc/tunnels.md index 4240c4795..8d9d211f0 100644 --- a/doc/tunnels.md +++ b/doc/tunnels.md @@ -55,7 +55,7 @@ admin@example:/> ``` GRETAP interfaces can be added to a bridge, bridging local and remote Ethernet -segments. See the [Bridge Configuration](networking.md#bridging) +segments. See the [Bridge Configuration](bridging.md) for more on bridges. ### OSPF over GRE @@ -99,7 +99,7 @@ admin@siteB:/> Once configured, OSPF will establish a neighbor relationship through the tunnel and exchange routes between the sites. For more info on OSPF -configuration, see [OSPFv2 Routing](networking.md#ospfv2-routing). +configuration, see [OSPFv2 Routing](routing.md#ospfv2-routing). > [!NOTE] > Consider adjusting MTU on the tunnel interface to account for GRE diff --git a/doc/vpn-wireguard.md b/doc/vpn-wireguard.md index 38ab1e76b..1daa13609 100644 --- a/doc/vpn-wireguard.md +++ b/doc/vpn-wireguard.md @@ -141,7 +141,7 @@ for 192.168.2.0/24 through this peer. > [!NOTE] > When routing traffic to networks behind WireGuard peers, you also need > to configure static routes pointing to the WireGuard interface. See -> [Static Routes](networking.md#routing-support) for more information. +> [Static Routes](routing.md) for more information. ## Peer Configuration and Key Bags diff --git a/mkdocs.yml b/mkdocs.yml index 36a3d858e..cc03ed1ef 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -28,7 +28,13 @@ nav: - Upgrading: cli/upgrade.md - Docker Containers: container.md - Networking: - - Network Configuration: networking.md + - Overview: networking.md + - Common Settings: iface.md + - Bridging: bridging.md + - Link Aggregation: lag.md + - Ethernet Interfaces: ethernet.md + - IP Addressing: ip.md + - Routing: routing.md - Firewall Configuration: firewall.md - Quality of Service: qos.md - RMON Counters: eth-counters.md From b031f5216a534e2706576604ff1e0c525a63c874 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 25 Jan 2026 02:08:53 +0100 Subject: [PATCH 27/29] doc: update remaining guides to new example format Signed-off-by: Joachim Wiberg --- doc/container.md | 535 +++++++++++++++++++++++-------------------- doc/dhcp.md | 100 ++++---- doc/hardware.md | 44 ++-- doc/management.md | 88 ++++--- doc/nacm.md | 48 ++-- doc/ntp.md | 136 ++++++----- doc/qos.md | 17 +- doc/syslog.md | 171 +++++++------- doc/system.md | 226 +++++++++--------- doc/tunnels.md | 127 +++++----- doc/upgrade.md | 182 +++++++-------- doc/vpn-wireguard.md | 281 +++++++++++------------ doc/wifi.md | 8 +- 13 files changed, 967 insertions(+), 996 deletions(-) diff --git a/doc/container.md b/doc/container.md index 02a0b7956..59aca114b 100644 --- a/doc/container.md +++ b/doc/container.md @@ -92,17 +92,18 @@ your container image and application to run. Classic Hello World: - admin@example:/> container run docker://hello-world - Starting docker://hello-world :: use Ctrl-p Ctrl-q to detach - Trying to pull docker.io/library/hello-world:latest... - Getting image source signatures - Copying blob c1ec31eb5944 done - Copying config d2c94e258d done - Writing manifest to image destination - Storing signatures - - Hello from Docker! - This message shows that your installation appears to be working correctly. +
admin@example:/> container run docker://hello-world
+Starting docker://hello-world :: use Ctrl-p Ctrl-q to detach
+Trying to pull docker.io/library/hello-world:latest...
+Getting image source signatures
+Copying blob c1ec31eb5944 done
+Copying config d2c94e258d done
+Writing manifest to image destination
+Storing signatures
+
+Hello from Docker!
+This message shows that your installation appears to be working correctly.
+
### Example: Web Server @@ -110,22 +111,24 @@ A web server with [nginx][], using standard docker bridge. Podman will automatically create a VETH pair for us, connecting the container to the `docker0` bridge: - admin@example:/> configure - admin@example:/config/> edit interface docker0 - admin@example:/config/interface/docker0/> set container-network - admin@example:/config/interface/docker0/> end - admin@example:/config/> edit container web - admin@example:/config/container/web/> set image docker://nginx:alpine - admin@example:/config/container/web/> set network publish 8080:80 - admin@example:/config/container/web/> set network interface docker0 - admin@example:/config/container/web/> set volume cache target /var/cache - admin@example:/config/container/web/> leave - admin@example:/> show container +
admin@example:/> configure
+admin@example:/config/> edit interface docker0
+admin@example:/config/interface/docker0/> set container-network
+admin@example:/config/interface/docker0/> end
+admin@example:/config/> edit container web
+admin@example:/config/container/web/> set image docker://nginx:alpine
+admin@example:/config/container/web/> set network publish 8080:80
+admin@example:/config/container/web/> set network interface docker0
+admin@example:/config/container/web/> set volume cache target /var/cache
+admin@example:/config/container/web/> leave
+admin@example:/> show container
+
Exit to the shell and verify the service with curl, or try to attach to your device's IP address using your browser: - admin@example:~$ curl http://localhost:8080 +
admin@example:~$ curl http://localhost:8080
+
or connect to port 8080 of your running Infix system with a browser. See the following sections for how to add more interfaces and manage @@ -142,31 +145,32 @@ how to upgrade to a newer base image. The CLI help shows: - admin@example:/config/container/system/> help image - NAME - image +
admin@example:/config/container/system/> help image
+NAME
+    image <string>
 
-    DESCRIPTION
-        Docker image for the container: [transport]name[:tag|@digest]
+DESCRIPTION
+    Docker image for the container: [transport]name[:tag|@digest]
 
-        quay.io/username/myimage     -- Pull myimage:latest
-        docker://busybox             -- Pull busybox:latest from Docker Hub
-        docker://ghcr.io/usr/img     -- Pull img:latest from GitHub packages
-        dir:/media/usb/myimage:1.1   -- Use myimage v1.1 from USB media
-        docker-archive:/tmp/archive  -- Use archive:latest from tarball
-        oci-archive:/lib/oci/archive -- Use archive:latest from OCI archive
-                                        May be in .tar or .tar.gz format
+    quay.io/username/myimage     -- Pull myimage:latest
+    docker://busybox             -- Pull busybox:latest from Docker Hub
+    docker://ghcr.io/usr/img     -- Pull img:latest from GitHub packages
+    dir:/media/usb/myimage:1.1   -- Use myimage v1.1 from USB media
+    docker-archive:/tmp/archive  -- Use archive:latest from tarball
+    oci-archive:/lib/oci/archive -- Use archive:latest from OCI archive
+                                    May be in .tar or .tar.gz format
 
-        Additionally, the following URIs are also supported for setups
-        that do not use a HUB or similar.  Recommend using 'checksum'!
+    Additionally, the following URIs are also supported for setups
+    that do not use a HUB or similar.  Recommend using 'checksum'!
 
-        ftp://addr/path/to/archive   -- Downloaded using wget
-        http://addr/path/to/archive  -- Downloaded using curl
-        https://addr/path/to/archive -- Downloaded using curl
+    ftp://addr/path/to/archive   -- Downloaded using wget
+    http://addr/path/to/archive  -- Downloaded using curl
+    https://addr/path/to/archive -- Downloaded using curl
 
-        Note: if a remote repository cannot be reached, the creation of the
-              container will be put on a queue that retries pull every time
-              there is a route change in the host's system.
+    Note: if a remote repository cannot be reached, the creation of the
+          container will be put on a queue that retries pull every time
+          there is a route change in the host's system.
+
> [!TIP] > The built-in help system in the CLI is generated from the YANG model, @@ -198,26 +202,28 @@ mind. **Shell OCI Example:** - admin@example:~$ cd /var/tmp/ - admin@example:/var/tmp$ sudo wget https://github.com/kernelkit/curiOS/releases/download/edge/curios-oci-amd64.tar.gz - Connecting to github.com (140.82.121.3:443) - wget: note: TLS certificate validation not implemented - Connecting to objects.githubusercontent.com (185.199.109.133:443) - saving to 'curios-oci-amd64.tar.gz' - curios-oci-amd64.tar 100% |*********************************| 7091k 0:00:00 ETA - 'curios-oci-amd64.tar.gz' saved - admin@example:/var/tmp$ ll - total 7104 - drwxr-xr-x 3 root root 4096 Mar 27 14:22 ./ - drwxr-xr-x 14 root root 4096 Mar 27 11:57 ../ - -rw-r--r-- 1 root root 7261785 Mar 27 14:22 curios-oci-amd64.tar.gz - drwx------ 6 frr frr 4096 Mar 27 11:57 frr/ +
admin@example:~$ cd /var/tmp/
+admin@example:/var/tmp$ sudo wget https://github.com/kernelkit/curiOS/releases/download/edge/curios-oci-amd64.tar.gz
+Connecting to github.com (140.82.121.3:443)
+wget: note: TLS certificate validation not implemented
+Connecting to objects.githubusercontent.com (185.199.109.133:443)
+saving to 'curios-oci-amd64.tar.gz'
+curios-oci-amd64.tar 100% |*********************************| 7091k  0:00:00 ETA
+'curios-oci-amd64.tar.gz' saved
+admin@example:/var/tmp$ ll
+total 7104
+drwxr-xr-x    3 root     root          4096 Mar 27 14:22 ./
+drwxr-xr-x   14 root     root          4096 Mar 27 11:57 ../
+-rw-r--r--    1 root     root       7261785 Mar 27 14:22 curios-oci-amd64.tar.gz
+drwx------    6 frr      frr           4096 Mar 27 11:57 frr/
+
Importing the image into Podman can be done either from the CLI admin-exec context ... - admin@example:/var/tmp$ cli - admin@example:/> container load /var/tmp/curios-oci-amd64.tar.gz name curios:edge +
admin@example:/var/tmp$ cli
+admin@example:/> container load /var/tmp/curios-oci-amd64.tar.gz name curios:edge
+
> [!TIP] > The `name curios:edge` is the tag you give the imported (raw) archive @@ -227,31 +233,33 @@ admin-exec context ... ... or by giving the container configuration the full path to the OCI archive, which helps greatly with container upgrades (see below): - admin@example:/config/container/system/> set image oci-archive:/var/tmp/curios-oci-amd64.tar.gz +
admin@example:/config/container/system/> set image oci-archive:/var/tmp/curios-oci-amd64.tar.gz
+
**Checksum Example:** - admin@example:/> configure - admin@example:/config/> edit container sys - admin@example:/config/container/sys/> set hostname sys - admin@example:/config/container/sys/> set image ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz - admin@example:/config/container/sys/> set checksum - md5 sha256 sha512 - admin@example:/config/container/sys/> set checksum sha256 4f01077036527498ed910f1a3e80645ae3eff629d10043cf80ebc6850c99c629 - admin@example:/config/container/sys/> leave - admin@example:/> copy running-config startup-config - admin@example:/> show container - CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - b02e945c43c9 localhost/curios-oci-amd64-v24.05.0:latest 5 seconds ago Up 5 seconds sys - - admin@example:/> show log - ... - Nov 20 07:24:56 example container[5040]: Fetching ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz - Nov 20 07:24:56 example container[5040]: curios-oci-amd64-v24.05.0.tar.gz downloaded successfully. - Nov 20 07:24:56 example container[5040]: curios-oci-amd64-v24.05.0.tar.gz checksum verified OK. - Nov 20 07:24:57 example container[5040]: Cleaning up extracted curios-oci-amd64-v24.05.0 - Nov 20 07:24:57 example container[5040]: podman create --name sys --conmon-pidfile=/run/container:sys.pid --read-only --replace --quiet --cgroup-parent=containers --restart=always --systemd=false --tz=local --hostname sys --log-driver k8s-file --log-opt path=/run/containers/sys.fifo --network=none curios-oci-amd64-v24.05.0 - Nov 20 07:24:57 example container[3556]: b02e945c43c9bce2c4be88e31d6f63cfdb1a3c8bdd02179376eb059a49ae05e4 +
admin@example:/> configure
+admin@example:/config/> edit container sys
+admin@example:/config/container/sys/> set hostname sys
+admin@example:/config/container/sys/> set image ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz
+admin@example:/config/container/sys/> set checksum
+    md5 sha256 sha512
+admin@example:/config/container/sys/> set checksum sha256 4f01077036527498ed910f1a3e80645ae3eff629d10043cf80ebc6850c99c629
+admin@example:/config/container/sys/> leave
+admin@example:/> copy running-config startup-config
+admin@example:/> show container
+NAME  STATUS         NETWORK  MEMORY (KiB)  CPU%
+sys   Up 5 seconds                  72/512  0.02
+
+admin@example:/> show log
+...
+Nov 20 07:24:56 example container[5040]: Fetching ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz
+Nov 20 07:24:56 example container[5040]: curios-oci-amd64-v24.05.0.tar.gz downloaded successfully.
+Nov 20 07:24:56 example container[5040]: curios-oci-amd64-v24.05.0.tar.gz checksum verified OK.
+Nov 20 07:24:57 example container[5040]: Cleaning up extracted curios-oci-amd64-v24.05.0
+Nov 20 07:24:57 example container[5040]: podman create --name sys --conmon-pidfile=/run/container:sys.pid --read-only --replace --quiet --cgroup-parent=containers  --restart=always --systemd=false --tz=local --hostname sys --log-driver k8s-file --log-opt path=/run/containers/sys.fifo --network=none curios-oci-amd64-v24.05.0
+Nov 20 07:24:57 example container[3556]: b02e945c43c9bce2c4be88e31d6f63cfdb1a3c8bdd02179376eb059a49ae05e4
+
Understanding Image Tags @@ -359,12 +367,11 @@ writable paths provided by Podman (`/dev`, `/dev/shm`, `/run`, `/tmp`, When using version-specific tags, you upgrade by explicitly changing the image reference in your configuration: -``` -admin@example:/> configure -admin@example:/config/> edit container web -admin@example:/config/container/web/> set image docker://nginx:1.25.3 -admin@example:/config/container/web/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit container web
+admin@example:/config/container/web/> set image docker://nginx:1.25.3
+admin@example:/config/container/web/> leave
+
**What happens:** @@ -375,29 +382,27 @@ admin@example:/config/container/web/> leave **Example:** Upgrading from one version to another: -``` -admin@example:/> configure -admin@example:/config/> edit container system -admin@example:/config/container/system/> show image +
admin@example:/> configure
+admin@example:/config/> edit container system
+admin@example:/config/container/system/> show image
 image ghcr.io/kernelkit/curios:v24.11.0;
-admin@example:/config/container/system/> set image ghcr.io/kernelkit/curios:v24.12.0
-admin@example:/config/container/system/> leave
-admin@example:/> show log
+admin@example:/config/container/system/> set image ghcr.io/kernelkit/curios:v24.12.0
+admin@example:/config/container/system/> leave
+admin@example:/> show log
 ...
 Dec 13 14:32:15 example container[1523]: Pulling ghcr.io/kernelkit/curios:v24.12.0...
 Dec 13 14:32:18 example container[1523]: Stopping old container instance...
 Dec 13 14:32:19 example container[1523]: Creating new container with updated image...
 Dec 13 14:32:20 example container[1523]: Container system started successfully
-```
+
### Method 2: Upgrading Mutable Tags For images using mutable tags like `:latest` or `:edge`, use the `container upgrade` command: -``` -admin@example:/> container upgrade NAME -``` +
admin@example:/> container upgrade NAME
+
This command: @@ -408,8 +413,7 @@ This command: **Example using registry:** -``` -admin@example:/> container upgrade system +
admin@example:/> container upgrade system
 system
 Trying to pull ghcr.io/kernelkit/curios:edge...
 Getting image source signatures
@@ -420,7 +424,7 @@ Storing signatures
 0cb6059c0f4111650ddbc7dbc4880c64ab8180d4bdbb7269c08034defc348f17
 system: not running.
 59618cc3c84bef341c1f5251a62be1592e459cc990f0b8864bc0f5be70e60719
-```
+
**Example using local OCI archive:** @@ -429,11 +433,10 @@ new archive onto the system (see Container Images section above), then, provided the `oci-archive:/path/to/archive` format is used in your configuration, call the upgrade command: -``` -admin@example:/> container upgrade system +
admin@example:/> container upgrade system
 Upgrading container system with local archive: oci-archive:/var/tmp/curios-oci-amd64.tar.gz ...
 7ab4a07ee0c6039837419b7afda4da1527a70f0c60c0f0ac21cafee05ba24b52
-```
+
OCI archives can also be fetched from ftp/http/https URLs. In that case, the upgrade works the same way as a registry image — Infix downloads the @@ -472,15 +475,16 @@ occasions where they are too restricted and users start looking for the For example, a system container from which `ping` does not work: - admin@example:/config/container/system/> edit capabilities - admin@example:/config/container/system/capabilities/> set add net_raw - admin@example:/config/container/system/capabilities/> end - admin@infix-00-00-00:/config/container/system/> show - ... - capabilities { - add net_raw; - } - ... +
admin@example:/config/container/system/> edit capabilities
+admin@example:/config/container/system/capabilities/> set add net_raw
+admin@example:/config/container/system/capabilities/> end
+admin@infix-00-00-00:/config/container/system/> show
+...
+capabilities {
+  add net_raw;
+}
+...
+
Infix supports a subset of all [capabilities][6] that are relevant for containers. Please note, that this is an advanced topic that require @@ -504,12 +508,13 @@ Resource limits are set per container and include: Example configuration limiting a container to 512 MiB of memory and 1.5 CPU cores: - admin@example:/> configure - admin@example:/config/> edit container web - admin@example:/config/container/web/> edit resource-limit - admin@example:/config/container/web/resource-limit/> set memory 524288 - admin@example:/config/container/web/resource-limit/> set cpu 1500 - admin@example:/config/container/web/resource-limit/> leave +
admin@example:/> configure
+admin@example:/config/> edit container web
+admin@example:/config/container/web/> edit resource-limit
+admin@example:/config/container/web/resource-limit/> set memory 524288
+admin@example:/config/container/web/resource-limit/> set cpu 1500
+admin@example:/config/container/web/resource-limit/> leave
+
Common CPU limit examples: @@ -521,8 +526,9 @@ Common CPU limit examples: Runtime resource usage statistics are available in the operational datastore: - admin@example:/> show container web - ... +
admin@example:/> show container web
+...
+
Use `show container usage` to see resource consumption across all containers, including memory, CPU, block I/O, network I/O, and process counts. @@ -563,10 +569,11 @@ container use seem to be so simple. All interface configuration is done in configure context. - admin@example:/> configure - admin@example:/config> edit interface docker0 - admin@example:/config/interface/docker0/> set container-network - admin@example:/config/interface/docker0/> leave +
admin@example:/> configure
+admin@example:/config> edit interface docker0
+admin@example:/config/interface/docker0/> set container-network
+admin@example:/config/interface/docker0/> leave
+
There is more to this story. When using the CLI, and sticking to common interface nomenclature, Infix helps you with some of the boring stuff. @@ -574,8 +581,9 @@ E.g., creating a new interface with a name like `brN` or `dockerN` automatically *infers* the interface types, which you would otherwise have to set manually: - admin@example:/config/interface/docker0/> set type bridge - admin@example:/config/interface/docker0/> set container-network type bridge +
admin@example:/config/interface/docker0/> set type bridge
+admin@example:/config/interface/docker0/> set container-network type bridge
+
> [!IMPORTANT] > When configuring the system via an API such as NETCONF or RESTCONF, no @@ -601,16 +609,17 @@ other networking parameters (DNS, default route) are set up. Some of the defaults of a container `bridge` can be changed, e.g., instead of `set container-network type bridge`, above, do: - admin@example:/config/interface/docker0/> edit container-network - admin@example:/config/interface/docker0/container-network/> set type bridge - admin@example:/config/interface/docker0/container-network/> edit subnet 192.168.0.0/16 - admin@example:/config/interface/docker0/container-network/subnet/192.168.0.0/16/> set gateway 192.168.255.254 - admin@example:/config/interface/docker0/container-network/subnet/192.168.0.0/16/> end - admin@example:/config/interface/docker0/container-network/> edit route 10.0.10.0/24 - admin@example:/config/interface/docker0/container-network/route/10.0.10.0/24/> set gateway 192.168.10.254 - admin@example:/config/interface/docker0/container-network/route/10.0.10.0/24/> end - admin@example:/config/interface/docker0/container-network/> end - admin@example:/config/interface/docker0/> leave +
admin@example:/config/interface/docker0/> edit container-network
+admin@example:/config/…/container-network/> set type bridge
+admin@example:/config/…/container-network/> edit subnet 192.168.0.0/16
+admin@example:/config/…/subnet/192.168.0.0/16/> set gateway 192.168.255.254
+admin@example:/config/…/subnet/192.168.0.0/16/> end
+admin@example:/config/…/container-network/> edit route 10.0.10.0/24
+admin@example:/config/…/route/10.0.10.0/24/> set gateway 192.168.10.254
+admin@example:/config/…/route/10.0.10.0/24/> end
+admin@example:/config/…/container-network/> end
+admin@example:/config/interface/docker0/> leave
+
Other network settings, like DNS and domain, use built-in defaults, but can be overridden from each container. Other common settings per @@ -622,24 +631,25 @@ in a `bridge`. Below an example of a system container calls `set network interface docker0`, here we show how to set options for that network: - admin@example:/config/container/ntpd/> edit network interface docker0 - admin@example:/config/container/ntpd/network/interface/docker0/> - admin@example:/config/container/ntpd/network/interface/docker0/> set option - Options for masquerading container bridges. - admin@example:/config/container/ntpd/network/interface/docker0/> help option - NAME - option - - DESCRIPTION - Options for masquerading container bridges. - - Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6) - mac=00:01:02:c0:ff:ee -- set fixed MAC address in container - interface_name=foo0 -- set interface name inside container - - admin@example:/config/container/ntpd/network/interface/docker0/> set option ip=172.17.0.2 - admin@example:/config/container/ntpd/network/interface/docker0/> set option interface_name=wan - admin@example:/config/container/ntpd/network/interface/docker0/> leave +
admin@example:/config/container/ntpd/> edit network interface docker0
+admin@example:/config/…/network/interface/docker0/>
+admin@example:/config/…/network/interface/docker0/> set option
+<string>  Options for masquerading container bridges.
+admin@example:/config/…/network/interface/docker0/> help option
+NAME
+        option <string>
+
+DESCRIPTION
+        Options for masquerading container bridges.
+
+        Example: ip=1.2.3.4            -- request a specific IP (IPv4 or IPv6)
+                 mac=00:01:02:c0:ff:ee -- set fixed MAC address in container
+                 interface_name=foo0   -- set interface name inside container
+
+admin@example:/config/…/network/interface/docker0/> set option ip=172.17.0.2
+admin@example:/config/…/network/interface/docker0/> set option interface_name=wan
+admin@example:/config/…/network/interface/docker0/> leave
+
### Container Host Interface @@ -674,14 +684,15 @@ container-end of pair `ntpd`. This is just a convenience for us when reading the configuration later. The *real action* happens on the last line where we declare the `ntpd` end as a container network interface: - admin@example:/config/> edit interface veth0 - admin@example:/config/interface/veth0/> set veth peer ntpd - admin@example:/config/interface/veth0/> set ipv4 address 192.168.0.1 prefix-length 24 - admin@example:/config/interface/veth0/> end - admin@example:/config/> edit interface ntpd - admin@example:/config/interface/ntpd/> set ipv4 address 192.168.0.2 prefix-length 24 - admin@example:/config/interface/ntpd/> set custom-phys-address static 00:c0:ff:ee:00:01 - admin@example:/config/interface/ntpd/> set container-network +
admin@example:/config/> edit interface veth0
+admin@example:/config/interface/veth0/> set veth peer ntpd
+admin@example:/config/interface/veth0/> set ipv4 address 192.168.0.1 prefix-length 24
+admin@example:/config/interface/veth0/> end
+admin@example:/config/> edit interface ntpd
+admin@example:/config/interface/ntpd/> set ipv4 address 192.168.0.2 prefix-length 24
+admin@example:/config/interface/ntpd/> set custom-phys-address static 00:c0:ff:ee:00:01
+admin@example:/config/interface/ntpd/> set container-network
+
> [!TIP] > Notice how you can also set a custom MAC address at the same time. @@ -690,8 +701,9 @@ Adding the interface to the container is the same as before, but since everything for host interfaces is set up in the interfaces context, we can take a bit of a shortcut. - admin@example:/config/container/ntpd/> set network interface ntpd - admin@example:/config/container/ntpd/> leave +
admin@example:/config/container/ntpd/> set network interface ntpd
+admin@example:/config/container/ntpd/> leave
+
> [!TIP] > Use the `set network interface ntpd option interface_name=foo0` to set @@ -712,9 +724,10 @@ pair to give our container two interfaces: We start by adding the second VETH pair: - admin@example:/config/> edit interface veth1a - admin@example:/config/interface/veth1a/> set veth peer veth1 - admin@example:/config/interface/veth1a/> set ipv4 address 192.168.1.2 prefix-length 24 +
admin@example:/config/> edit interface veth1a
+admin@example:/config/interface/veth1a/> set veth peer veth1
+admin@example:/config/interface/veth1a/> set ipv4 address 192.168.1.2 prefix-length 24
+
> [!NOTE] > The LAN bridge (br1) in this example has IP address 192.168.1.1. @@ -723,20 +736,21 @@ When a container has multiple host interfaces it can often be useful to have a default route installed. This can be added from the host with a `0.0.0.0/0` route on one of the interfaces: - admin@example:/config/interface/veth1a/> set container-network route 0.0.0.0/0 gateway 192.168.1.1 - admin@example:/config/interface/veth1a/> show - type veth; - container-network { - type host; - route 0.0.0.0/0 { - gateway 192.168.1.1; - } - } - veth { - peer veth1; - } - admin@example:/config/interface/veth1a/> end - admin@example:/config/> set interface veth1 bridge-port bridge br1 +
admin@example:/config/interface/veth1a/> set container-network route 0.0.0.0/0 gateway 192.168.1.1
+admin@example:/config/interface/veth1a/> show
+type veth;
+container-network {
+  type host;
+  route 0.0.0.0/0 {
+    gateway 192.168.1.1;
+  }
+}
+veth {
+  peer veth1;
+}
+admin@example:/config/interface/veth1a/> end
+admin@example:/config/> set interface veth1 bridge-port bridge br1
+
Please note, container network routes require the base interface also have a static IP address set. Setting only the route, but no address, @@ -762,11 +776,12 @@ It is possible to mount files, directories, and even files matching a glob, into a container. This gives precise control over the container's file system: - admin@example:/config/container/system/> edit mount leds - admin@example:/config/container/system/mount/leds> set source /sys/class/leds - admin@example:/config/container/system/mount/leds> set target /sys/class/leds - admin@example:/config/container/system/mount/leds> end - admin@example:/config/container/system/> +
admin@example:/config/container/system/> edit mount leds
+admin@example:/config/container/system/mount/leds> set source /sys/class/leds
+admin@example:/config/container/system/mount/leds> set target /sys/class/leds
+admin@example:/config/container/system/mount/leds> end
+admin@example:/config/container/system/>
+
Any type of file can be *bind mounted* into the container, just watch out for permissions though. In the example above, `/sys/class/leds` is @@ -782,7 +797,8 @@ trigger a container restart. Other times *volumes* are a better fit. A volume is an automatically created read-writable entity that follows the life of your container. - admin@example:/config/container/ntpd/> set volume varlib target /var/lib +
admin@example:/config/container/ntpd/> set volume varlib target /var/lib
+
Volumes are persistent across both reboots and upgrades of the base image. They are created by Podman when the container first starts up, @@ -812,14 +828,15 @@ where: To clean up unused volumes and reclaim disk space, use the admin-exec command: - admin@example:/> container prune - Deleted Images - ... - Deleted Volumes - ntpd-varlib - system-data +
admin@example:/> container prune
+Deleted Images
+...
+Deleted Volumes
+ntpd-varlib
+system-data
 
-    Total reclaimed space: 45.2MB
+Total reclaimed space: 45.2MB
+
The `container prune` command safely removes: @@ -830,14 +847,16 @@ The `container prune` command safely removes: > [!TIP] > You can monitor container resource usage with the command: > -> admin@example:/> show container usage +>
admin@example:/> show container usage
+> 
> > This displays disk space used by images, containers, and volumes, > helping you decide when to run the prune command. > > To see which volumes exist and which containers use them: > -> admin@example:/> show container volumes +>
admin@example:/> show container volumes
+> 
### Content Mounts @@ -847,12 +866,13 @@ when deploying similar systems at multiple sites. When the host loads its `startup-config` (or even `factory-config`) a temporary file is created using the decoded base64 data from the `content` node. - admin@example:/config/container/ntpd/> edit mount ntpd.conf - admin@example:/config/container/ntpd/mount/ntpd.conf> text-editor content - ... interactive editor starts up ... - admin@example:/config/container/ntpd/mount/ntpd.conf> set target /etc/ntpd.conf - admin@example:/config/container/ntpd/mount/ntpd.conf> end - admin@example:/config/container/ntpd/> +
admin@example:/config/container/ntpd/> edit mount ntpd.conf
+admin@example:/config/container/ntpd/mount/ntpd.conf> text-editor content
+... interactive editor starts up ...
+admin@example:/config/container/ntpd/mount/ntpd.conf> set target /etc/ntpd.conf
+admin@example:/config/container/ntpd/mount/ntpd.conf> end
+admin@example:/config/container/ntpd/>
+
The editor is a small [Emacs clone called Mg][2], see the built-in help text, or press Ctrl-x Ctrl-c to exit and save. When the editor exits @@ -876,12 +896,13 @@ Let's try out what we've learned by setting up a system container, a container providing multiple services, using the `docker0` interface we created previously: - admin@example:/> configure - admin@example:/config> edit container system - admin@example:/config/container/system/> set image ghcr.io/kernelkit/curios:edge - admin@example:/config/container/system/> set network interface docker0 - admin@example:/config/container/system/> set publish 222:22 - admin@example:/config/container/system/> leave +
admin@example:/> configure
+admin@example:/config> edit container system
+admin@example:/config/container/system/> set image ghcr.io/kernelkit/curios:edge
+admin@example:/config/container/system/> set network interface docker0
+admin@example:/config/container/system/> set publish 222:22
+admin@example:/config/container/system/> leave
+
> [!NOTE] > Ensure you have a network connection to the registry. If the image @@ -896,26 +917,29 @@ container configuration context for the full syntax.) Available containers can be accessed from admin-exec: - admin@example:/> show container - CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES - 439af2917b44 ghcr.io/kernelkit/curios:edge 41 hours ago Up 16 hours 0.0.0.0:222->222/tcp system +
admin@example:/> show container
+NAME     STATUS        NETWORK  MEMORY (KiB)  CPU%
+system   Up 16 hours   docker0       136/512  0.02
+
This is a system container, so you can "attach" to it by starting a shell (or logging in with SSH): - admin@example:/> container shell system - root@439af2917b44:/# +
admin@example:/> container shell system
+root@439af2917b44:/#
+
Notice how the hostname inside the container changes. By default the container ID (hash) is used, but this can be easily changed: - root@439af2917b44:/# exit - admin@example:/> configure - admin@example:/config/> edit container system - admin@example:/config/container/system/> set hostname sys101 - admin@example:/config/container/system/> leave - admin@example:/> container shell system - root@sys101:/# +
root@439af2917b44:/# exit
+admin@example:/> configure
+admin@example:/config/> edit container system
+admin@example:/config/container/system/> set hostname sys101
+admin@example:/config/container/system/> leave
+admin@example:/> container shell system
+root@sys101:/#
+
In fact, the container `hostname` setting supports the same format specifiers as the host's `hostname` setting: @@ -940,16 +964,17 @@ Infix currently does not have a native firewall configuration, and even when it does it will never expose the full capabilities of `nftables`. For advanced setups, the following is an interesting alternative. - admin@example:/> configure - admin@example:/config> edit container nftables - admin@example:/config/container/nftables/> set image ghcr.io/kernelkit/curios-nftables:edge - admin@example:/config/container/nftables/> set network host - admin@example:/config/container/nftables/> set privileged - admin@example:/config/container/nftables/> edit mount nftables.conf - admin@example:/config/container/nftables/mount/nftables.conf/> set target /etc/nftables.conf - admin@example:/config/container/nftables/mount/nftables.conf/> text-editor content - ... interactive editor starts up where you can paste your rules ... - admin@example:/config/container/nftables/mount/nftables.conf/> leave +
admin@example:/> configure
+admin@example:/config> edit container nftables
+admin@example:/config/container/nftables/> set image ghcr.io/kernelkit/curios-nftables:edge
+admin@example:/config/container/nftables/> set network host
+admin@example:/config/container/nftables/> set privileged
+admin@example:/config/container/nftables/> edit mount nftables.conf
+admin@example:/config/…/mount/nftables.conf/> set target /etc/nftables.conf
+admin@example:/config/…/mount/nftables.conf/> text-editor content
+... interactive editor starts up where you can paste your rules ...
+admin@example:/config/…/mount/nftables.conf/> leave
+
Notice how we `set network host`, so the container can see and act on all the host's interfaces, and that we also have to run the container @@ -968,19 +993,20 @@ file system and store in the host's `startup-config`. However, `ntpd` also saves clock drift information in `/var/lib/ntpd`, so we will also use volumes in this example. - admin@example:/> configure - admin@example:/config> edit container ntpd - admin@example:/config/container/ntpd/> set image ghcr.io/kernelkit/curios-ntpd:edge - admin@example:/config/container/ntpd/> set network interface ntpd # From veth0 above - admin@example:/config/container/ntpd/> edit mount ntp.conf - admin@example:/config/container/ntpd/mount/ntp.conf/> set target /etc/ntp.conf - admin@example:/config/container/ntpd/mount/ntp.conf/> text-editor content - ... interactive editor starts up where you can paste your rules ... - admin@example:/config/container/ntpd/mount/ntp.conf/> end - admin@example:/config/container/ntpd/> edit volume varlib - admin@example:/config/container/ntpd/volume/varlib/> set target /var/lib - admin@example:/config/container/ntpd/volume/varlib/> leave - admin@example:/> copy running-config startup-config +
admin@example:/> configure
+admin@example:/config> edit container ntpd
+admin@example:/config/container/ntpd/> set image ghcr.io/kernelkit/curios-ntpd:edge
+admin@example:/config/container/ntpd/> set network interface ntpd    # From veth0 above
+admin@example:/config/container/ntpd/> edit mount ntp.conf
+admin@example:/config/container/ntpd/mount/ntp.conf/> set target /etc/ntp.conf
+admin@example:/config/container/ntpd/mount/ntp.conf/> text-editor content
+... interactive editor starts up where you can paste your rules ...
+admin@example:/config/container/ntpd/mount/ntp.conf/> end
+admin@example:/config/container/ntpd/> edit volume varlib
+admin@example:/config/container/ntpd/volume/varlib/> set target /var/lib
+admin@example:/config/container/ntpd/volume/varlib/> leave
+admin@example:/> copy running-config startup-config
+
The `ntp.conf` file is stored in the host's `startup-config` and any state data in the container's `/var/lib` is retained between reboots @@ -1015,25 +1041,28 @@ First, enable *Privileged* mode, this unlocks the door and allows the container to manage resources on the host system. An example is the `nftables` container mentioned previously. - admin@example:/config/container/system/> set privileged +
admin@example:/config/container/system/> set privileged
+
Second, mount the host's `/proc/1` directory to somewhere inside your container. Here we pick `/1`: - admin@example:/config/container/system/> edit mount host - admin@example:/config/container/system/mount/host/> set source /proc/1 - admin@example:/config/container/system/mount/host/> set target /1 - admin@example:/config/container/system/mount/host/> leave +
admin@example:/config/container/system/> edit mount host
+admin@example:/config/container/system/mount/host/> set source /proc/1
+admin@example:/config/container/system/mount/host/> set target /1
+admin@example:/config/container/system/mount/host/> leave
+
Third, from inside the container, use the host's PID 1 namespaces with the `nsenter`[^2] command to slide through the container's walls. Here we show two example calls to `hostname`, first the container's own name and then asking what the hostname is on the host: - root@sys101:/# hostname - sys101 - root@sys101:/# nsenter -m/1/ns/mnt -u/1/ns/uts -i/1/ns/ipc -n/1/ns/net hostname - example +
root@sys101:/# hostname
+sys101
+root@sys101:/# nsenter -m/1/ns/mnt -u/1/ns/uts -i/1/ns/ipc -n/1/ns/net hostname
+example
+
One use-case for this method is when extending Infix with a management container that connects to other systems. For some tips on how to diff --git a/doc/dhcp.md b/doc/dhcp.md index f04442151..c2792930d 100644 --- a/doc/dhcp.md +++ b/doc/dhcp.md @@ -19,20 +19,18 @@ servers[^1]. The following example configures a DHCP server for subnet 192.168.2.0/24 with an address pool: -``` -admin@example:/> configure -admin@example:/config/> edit dhcp-server subnet 192.168.2.0/24 -admin@example:/config/dhcp-server/…/192.168.2.0/24/> set pool start-address 192.168.2.100 end-address 192.168.2.200 -admin@example:/config/dhcp-server/…/192.168.2.0/24/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit dhcp-server subnet 192.168.2.0/24
+admin@example:/config/dhcp-server/…/192.168.2.0/24/> set pool start-address 192.168.2.100 end-address 192.168.2.200
+admin@example:/config/dhcp-server/…/192.168.2.0/24/> leave
+
When setting up the server from the CLI, the system automatically adds a few default DHCP options that will be sent to clients: both DNS server and default gateway will use the system address on the matching interface. -``` -admin@example:/> show running-config +
admin@example:/> show running-config
   "infix-dhcp-server:dhcp-server": {
     "subnet": [
       {
@@ -54,7 +52,7 @@ admin@example:/> show running-config
       }
     ]
   }
-```
+
> [!IMPORTANT] > Remember to set up an interface in this subnet, avoid using addresses @@ -68,23 +66,21 @@ admin@example:/> show running-config To reserve specific IP addresses for clients based on their MAC address, hostname, or client ID: -``` -admin@example:/config/dhcp-server/…/192.168.2.0/24/> edit host 192.168.2.10 -admin@example:/config/dhcp-server/…/192.168.2.10/> set match mac-address 00:11:22:33:44:55 -admin@example:/config/dhcp-server/…/192.168.2.10/> set hostname printer -admin@example:/config/dhcp-server/…/192.168.2.10/> leave -``` +
admin@example:/config/dhcp-server/…/192.168.2.0/24/> edit host 192.168.2.10
+admin@example:/config/dhcp-server/…/192.168.2.10/> set match mac-address 00:11:22:33:44:55
+admin@example:/config/dhcp-server/…/192.168.2.10/> set hostname printer
+admin@example:/config/dhcp-server/…/192.168.2.10/> leave
+
Match hosts using a client identifier instead of MAC address: -``` -admin@example:/config/dhcp-server/…/192.168.1.0/24/> edit host 192.168.1.50 -admin@example:/config/dhcp-server/…/192.168.1.50/> edit match -admin@example:/config/dhcp-server/…/match/> set client-id hex c0:ff:ee -admin@example:/config/dhcp-server/…/match/> leave -admin@example:/config/dhcp-server/…/192.168.1.50/> set lease-time infinite -admin@example:/config/dhcp-server/…/192.168.1.50/> leave -``` +
admin@example:/config/dhcp-server/…/192.168.1.0/24/> edit host 192.168.1.50
+admin@example:/config/dhcp-server/…/192.168.1.50/> edit match
+admin@example:/config/dhcp-server/…/match/> set client-id hex c0:ff:ee
+admin@example:/config/dhcp-server/…/match/> leave
+admin@example:/config/dhcp-server/…/192.168.1.50/> set lease-time infinite
+admin@example:/config/dhcp-server/…/192.168.1.50/> leave
+
The `hex` prefix here ensures matching of client ID is done using the hexadecimal octets `c0:ff:ee`, three bytes. Without the prefix the @@ -100,32 +96,30 @@ ASCII string "c0:ff:ee", eight bytes, is used. Configure additional DHCP options globally, per subnet, or per host: -``` -admin@example:/config/dhcp-server/> edit subnet 192.168.2.0/24 -admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> edit option dns-server -admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/dns-server/> set address 8.8.8.8 -admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/dns-server/> leave -admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> edit option ntp-server -admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/ntp-server/> set address 192.168.2.1 -admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/ntp-server/> leave -``` +
admin@example:/config/dhcp-server/> edit subnet 192.168.2.0/24
+admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> edit option dns-server
+admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/dns-server/> set address 8.8.8.8
+admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/dns-server/> leave
+admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> edit option ntp-server
+admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/ntp-server/> set address 192.168.2.1
+admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/ntp-server/> leave
+
When configuring, e.g., `dns-server`, or `router` options with the value `auto`, the system uses the IP address from the interface matching the subnet. For example: -``` -admin@example:/> show interfaces -INTERFACE PROTOCOL STATE DATA +
admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
 eth0            ethernet   UP          02:00:00:00:00:00
                 ipv4                   192.168.1.1/24 (static)
 eth1            ethernet   UP          02:00:00:00:00:01
                 ipv4                   192.168.2.1/24 (static)
 
-admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> edit option dns-server
-admin@example:/config/dhcp-server/subnet/192.168.1.0/24/option/dns-server/> set address auto
-admin@example:/config/dhcp-server/subnet/192.168.1.0/24/option/dns-server/> leave
-```
+admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> edit option dns-server
+admin@example:/config/dhcp-server/subnet/192.168.1.0/24/option/dns-server/> set address auto
+admin@example:/config/dhcp-server/subnet/192.168.1.0/24/option/dns-server/> leave
+
In this case, clients in subnet 192.168.1.0/24 will receive 192.168.1.1 as their DNS server address. @@ -135,29 +129,27 @@ as their DNS server address. Configure DHCP for multiple networks: -``` -admin@example:/> configure -admin@example:/config/> edit dhcp-server -admin@example:/config/dhcp-server/> edit subnet 192.168.1.0/24 -admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> set pool start-address 192.168.1.100 end-address 192.168.1.200 -admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> leave -admin@example:/config/dhcp-server/> edit subnet 192.168.2.0/24 -admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> set pool start-address 192.168.2.100 end-address 192.168.2.200 -admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit dhcp-server
+admin@example:/config/dhcp-server/> edit subnet 192.168.1.0/24
+admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> set pool start-address 192.168.1.100 end-address 192.168.1.200
+admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> leave
+admin@example:/config/dhcp-server/> edit subnet 192.168.2.0/24
+admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> set pool start-address 192.168.2.100 end-address 192.168.2.200
+admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> leave
+
## Monitoring View active leases and server statistics: -``` -admin@example:/> show dhcp-server -IP ADDRESS MAC HOSTNAME CLIENT ID EXPIRES +
admin@example:/> show dhcp-server
+IP ADDRESS       MAC                HOSTNAME            CLIENT ID             EXPIRES
 192.168.2.22     00:a0:85:00:02:05                      00:c0:ff:ee           3591s
 192.168.1.11     00:a0:85:00:04:06  foo                 01:00:a0:85:00:04:06  3591s
 
-admin@example:/> show dhcp-server statistics
+admin@example:/> show dhcp-server statistics
 DHCP offers sent                : 6
 DHCP ACK messages sent          : 5
 DHCP NAK messages sent          : 0
@@ -166,7 +158,7 @@ DHCP discover messages received : 6
 DHCP request messages received  : 5
 DHCP release messages received  : 6
 DHCP inform messages received   : 6
-```
+
[^1]: This requires the system DNS resolver to be configured. diff --git a/doc/hardware.md b/doc/hardware.md index 3370f9aa7..814fec296 100644 --- a/doc/hardware.md +++ b/doc/hardware.md @@ -8,7 +8,7 @@ hardware][1], with deviations and augmentations in _infix-hardware_. For Infix to be able to control USB port(s), a device tree modification is needed (see _alder.dtsi_ for full example). -``` +```json chosen { infix { usb-ports = <&cp0_usb3_1>; @@ -24,26 +24,38 @@ All USB ports in the system will be disabled during boot due to the file Infix to control USB port(s), remove the file or manually enable the USB bus, here is an example: -``` +```bash # Enable the bus echo 1 > /sys/bus/usb/devices/usb1/authorized ``` And then enable sub-devices (e.g. USB memory) -``` +```bash # Enable a device plugged into usb1 echo 1 > /sys/bus/usb/devices/usb1/1-1/authorized ``` ### Current status -``` -admin@example:/> show hardware - USB PORTS - NAME STATE - USB unlocked -``` +
admin@example:/> show hardware
+HARDWARE COMPONENTS                                           
+──────────────────────────────────────────────────────────────
+Board Information                                            
+Model               : FriendlyElec NanoPi R2S
+Manufacturer        : FriendlyElec
+Serial Number       : 9d1fbfdab6d171ce
+Base MAC Address    : 4a:dc:d8:20:0d:85
+──────────────────────────────────────────────────────────────
+USB Ports                                                    
+NAME                                         STATE     OPER   
+USB                                          unlocked  enabled
+──────────────────────────────────────────────────────────────
+Sensors                                                      
+NAME                          VALUE                 STATUS    
+soc                           44.1 °C               ok        
+soc                           44.5 °C               ok        
+
An USB port can be in two states _unlocked_ and _locked_. When a port is locked, all connected devices will get power, but never authorized by @@ -56,12 +68,11 @@ Linux to use. > command `show hardware` in admin-exec context. (Use `do` prefix in > configure context.) -``` -admin@example:/> configure -admin@example:/config/> set hardware component USB state admin-state unlocked -admin@example:/config/> leave +
admin@example:/> configure
+admin@example:/config/> set hardware component USB state admin-state unlocked
+admin@example:/config/> leave
 admin@example:/>
-```
+
### Using a USB Stick @@ -81,8 +92,7 @@ The only way currently to safely "eject" a USB memory stick is to use `umount` command from a UNIX shell, which explicitly synchronizes any cached data to disk before returning the prompt: -``` -admin@example:~$ sudo umount /media/log -``` +
admin@example:~$ sudo umount /media/log
+
[1]: https://www.rfc-editor.org/rfc/rfc8348.html diff --git a/doc/management.md b/doc/management.md index fafb3a325..ece5abca4 100644 --- a/doc/management.md +++ b/doc/management.md @@ -9,22 +9,20 @@ as NETCONF, RESTCONF, and CLI via SSH or Console. An SSH server (SSHv2) is provided for remote management. It can be enabled/disabled as shown below. -``` -admin@example:/> configure -admin@example:/config/> edit ssh -admin@example:/config/ssh/> set enabled +
admin@example:/> configure
+admin@example:/config/> edit ssh
+admin@example:/config/ssh/> set enabled
 admin@example:/config/ssh/>
-```
+
By default the SSH server accepts connections to port 22 on all its IP addresses, but this can be adjusted using the `listen` command. To make the server (only) listen for incoming connections to IP address _192.168.1.1_ and port _12345_ the following commands can be used. -``` -admin@example:/> configure -admin@example:/config/> edit ssh -admin@example:/config/ssh/> show +
admin@example:/> configure
+admin@example:/config/> edit ssh
+admin@example:/config/ssh/> show
 enabled true;
 hostkey genkey;
 listen ipv4 {
@@ -35,12 +33,12 @@ listen ipv6 {
   address ::;
   port 22;
 }
-admin@example:/config/ssh/> no listen ipv6
-admin@example:/config/ssh/> edit listen ipv4
-admin@example:/config/ssh/listen/ipv4/> set address 192.168.1.1
-admin@example:/config/ssh/listen/ipv4/> set port 12345
+admin@example:/config/ssh/> no listen ipv6
+admin@example:/config/ssh/> edit listen ipv4
+admin@example:/config/ssh/listen/ipv4/> set address 192.168.1.1
+admin@example:/config/ssh/listen/ipv4/> set port 12345
 admin@example:/config/ssh/listen/ipv4/>
-```
+
The default SSH hostkey is generated on first boot and is used in both SSH and NETCONF (SSH transport). Custom keys can be added to the @@ -62,9 +60,10 @@ created by OpenSSL. After the key has been stored in the keystore and given the name _mykey_ it can be added to SSH configuration: - admin@example:/> configure - admin@example:/config/> edit ssh - admin@example:/config/ssh/> set hostkey mykey +
admin@example:/> configure
+admin@example:/config/> edit ssh
+admin@example:/config/ssh/> set hostkey mykey
+
## Console Port @@ -78,9 +77,8 @@ connected to the console port of the device. The serial port is typically setup to run at 115200 baud, 8N1. -``` -Infix OS — Immutable.Friendly.Secure v24.11.1 (ttyS0) -example login: admin +
Infix OS — Immutable.Friendly.Secure v24.11.1 (ttyS0)
+example login: admin
 Password:
 .-------.
 |  . .  | Infix OS — Immutable.Friendly.Secure
@@ -90,26 +88,24 @@ Password:
 Run the command 'cli' for interactive OAM
 
 admin@example:~$
-```
+
The `resize` command can be used to update terminal settings to the size of your terminal window. -``` -admin@example:~$ resize +
admin@example:~$ resize
 COLUMNS=115;LINES=59;export COLUMNS LINES;
 admin@example:~$
-```
+
CLI can be entered from shell in the same way as for SSH. -``` -admin@example:~$ cli +
admin@example:~$ cli
 
 See the 'help' command for an introduction to the system
 
-admin@example:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA
+admin@example:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                    
 lo              ethernet   UP          00:00:00:00:00:00
                 ipv4                   127.0.0.1/8 (static)
                 ipv6                   ::1/128 (static)
@@ -117,7 +113,7 @@ e1              ethernet   LOWER-DOWN  00:53:00:06:03:01
 e2              ethernet   LOWER-DOWN  00:53:00:06:03:02
 ...
 admin@example:/>
-```
+
## Web, Web-console and RESTCONF @@ -132,27 +128,25 @@ There is also a *Netbrowse* Web service presenting information about the unit's neighbors, collected via mDNS (see [Discovery](discovery.md) for more details). -``` -admin@example:/> configure -admin@example:/config/> edit web -admin@example:/config/web/> help +
admin@example:/> configure
+admin@example:/config/> edit web
+admin@example:/config/web/> help
   enabled                           Enable or disable on all web services.
   console                           Web console interface.
   netbrowse                         mDNS Network Browser.
   restconf                          IETF RESTCONF Server.
 admin@example:/config/web/>
-```
+
### Enable/disable Web Service and Server The Web service can be enabled as shown below. -``` -admin@example:/> configure -admin@example:/config/> edit web -admin@example:/config/web/> set enabled -admin@example:/config/web/> -``` +
admin@example:/> configure
+admin@example:/config/> edit web
+admin@example:/config/web/> set enabled
+admin@example:/config/web/>
+
Enabling the Web service implies that a Web server is enabled. Currently this Web server provides generic Infix information, @@ -172,11 +166,10 @@ The Web console has its own enable/disable setting, but will only be activated if the Web service is enabled. The example below shows how to disable the Web console. -``` -admin@example:/config/web/> edit console -admin@example:/config/web/console/> no enabled +
admin@example:/config/web/> edit console
+admin@example:/config/web/console/> no enabled
 admin@example:/config/web/console/>
-```
+
### Enable/disable RESTCONF Service @@ -188,11 +181,10 @@ The RESTCONF service has its own enable/disable setting, but will only be activated if the Web service is enabled. The example below shows how to disable the RESTCONF service. -``` -admin@example:/config/web/> edit restconf -admin@example:/config/web/restconf/> no enabled +
admin@example:/config/web/> edit restconf
+admin@example:/config/web/restconf/> no enabled
 admin@example:/config/web/restconf/>
-```
+
## System Upgrade diff --git a/doc/nacm.md b/doc/nacm.md index 4e641bcac..4635f0204 100644 --- a/doc/nacm.md +++ b/doc/nacm.md @@ -399,11 +399,11 @@ operators can immediately configure them without updating NACM rules. **Effective permissions by group:** -| Group | Read | Write | Exec | Exceptions | -|-------|------|-------|------|------------| -| admin | All | All | All | None | -| operator | All | All | All | Cannot access passwords, keystore, truststore | -| guest | All | None | None | Read-only access | +| Group | Read | Write | Exec | Exceptions | +|----------|------|-------|------|-----------------------------------------------| +| admin | All | All | All | None | +| operator | All | All | All | Cannot access passwords, keystore, truststore | +| guest | All | None | None | Read-only access | ## Common Patterns @@ -505,8 +505,7 @@ Deny access to sensitive data for all users (except admins with permit-all): Check what NACM groups a user belongs to: -``` -admin@example:/> show nacm +
admin@example:/> show nacm
 enabled              : yes
 default read access  : permit
 default write access : permit
@@ -524,77 +523,74 @@ denied notifications : 0
           └──────────┴─────────┴─────────┴─────────┘
               ✓ Full    ⚠ Restricted    ✗ Denied
 
-USER                   SHELL   LOGIN
+USER                   SHELL   LOGIN                            
 admin                  bash    password+key
 jacky                  bash    password
 monitor                false   key
 
-GROUP                  USERS
+GROUP                  USERS                                    
 admin                  admin
 operator               jacky
 guest                  monitor
-```
+
For details about a group's restrictions, use `show nacm group `: -``` -admin@example:/> show nacm group operator +
admin@example:/> show nacm group operator
 members          : jacky
 read permission  : restricted
 write permission : restricted
 exec permission  : restricted
 applicable rules : 4
 ──────────────────────────────────────────────────────────────────────
-permit-system-rpcs
+permit-system-rpcs
   action     : permit
   operations : exec
   target     : ietf-system (rpc: *)
 
 ──────────────────────────────────────────────────────────────────────
-deny-password-access (via '*')
+deny-password-access (via '*')
   action     : deny
   operations : *
   target     : /ietf-system:system/authentication/user/password
 
 ──────────────────────────────────────────────────────────────────────
-deny-keystore-access (via '*')
+deny-keystore-access (via '*')
   action     : deny
   operations : *
   target     : ietf-keystore
 
 ──────────────────────────────────────────────────────────────────────
-deny-truststore-access (via '*')
+deny-truststore-access (via '*')
   action     : deny
   operations : *
   target     : ietf-truststore
-```
+
### Testing Access The easiest way to test NACM permissions is to log in as the user and try the operation: -```bash -$ ssh jacky@host -jacky@example:/> configure -jacky@example:/config/> edit system authentication user admin -jacky@example:/config/system/authentication/user/admin/> set authorized-key foo +
$ ssh jacky@host
+jacky@example:/> configure
+jacky@example:/config/> edit system authentication user admin
+jacky@example:/config/system/authentication/user/admin/> set authorized-key foo
 Error: Access to the data model "ietf-system" is denied because "jacky" NACM authorization failed.
 Error: Failed applying changes (2).
-```
+
### NACM Statistics NACM tracks denied operations. If you suspect permission issues, check the statistics: -``` -admin@example:/> show nacm +
admin@example:/> show nacm
 ...
   denied operations      : 5
   denied data writes     : 12
 ...
-```
+
Increasing counters indicate permission denials are occurring. diff --git a/doc/ntp.md b/doc/ntp.md index 9fa07ab3e..67ea2bbc8 100644 --- a/doc/ntp.md +++ b/doc/ntp.md @@ -13,37 +13,34 @@ while serving time to downstream clients. Configure a standalone NTP server using only a local reference clock: -``` -admin@example:/> configure -admin@example:/config/> edit ntp -admin@example:/config/ntp/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit ntp
+admin@example:/config/ntp/> leave
+
When setting up NTP via the CLI the system automatically configures a local reference clock. The default [stratum](#ntp-stratum-levels) is 16 (unsynchronized), which is suitable for isolated networks. For production use, configure a specific stratum level: -``` -admin@example:/config/> edit ntp -admin@example:/config/ntp/> set refclock-master master-stratum 10 -admin@example:/config/ntp/> leave -``` +
admin@example:/config/> edit ntp
+admin@example:/config/ntp/> set refclock-master master-stratum 10
+admin@example:/config/ntp/> leave
+
## Server Mode Synchronize from upstream NTP servers while serving time to clients: -``` -admin@example:/config/> edit ntp -admin@example:/config/ntp/> edit unicast-configuration 0.pool.ntp.org type uc-server -admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> set iburst true -admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> end -admin@example:/config/ntp/> edit unicast-configuration 1.pool.ntp.org type uc-server -admin@example:/config/ntp/…/1.pool.ntp.org/type/uc-server/> set iburst true -admin@example:/config/ntp/…/1.pool.ntp.org/type/uc-server/> end -admin@example:/config/ntp/> leave -``` +
admin@example:/config/> edit ntp
+admin@example:/config/ntp/> edit unicast-configuration 0.pool.ntp.org type uc-server
+admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> set iburst true
+admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> end
+admin@example:/config/ntp/> edit unicast-configuration 1.pool.ntp.org type uc-server
+admin@example:/config/ntp/…/1.pool.ntp.org/type/uc-server/> set iburst true
+admin@example:/config/ntp/…/1.pool.ntp.org/type/uc-server/> end
+admin@example:/config/ntp/> leave
+
The `unicast-configuration` uses a composite key with both address and type. Both hostnames and IP addresses are supported. The `iburst` option enables @@ -56,23 +53,21 @@ Each server acts as both client and server to the other: **First peer:** -``` -admin@peer1:/config/> edit ntp -admin@peer1:/config/ntp/> edit unicast-configuration 192.168.1.2 type uc-peer -admin@peer1:/config/ntp/…/192.168.1.2/type/uc-peer/> end -admin@peer1:/config/ntp/> set refclock-master master-stratum 8 -admin@peer1:/config/ntp/> leave -``` +
admin@peer1:/config/> edit ntp
+admin@peer1:/config/ntp/> edit unicast-configuration 192.168.1.2 type uc-peer
+admin@peer1:/config/ntp/…/192.168.1.2/type/uc-peer/> end
+admin@peer1:/config/ntp/> set refclock-master master-stratum 8
+admin@peer1:/config/ntp/> leave
+
**Second peer:** -``` -admin@peer2:/config/> edit ntp -admin@peer2:/config/ntp/> edit unicast-configuration 192.168.1.1 type uc-peer -admin@peer2:/config/ntp/…/192.168.1.1/type/uc-peer/> end -admin@peer2:/config/ntp/> set refclock-master master-stratum 8 -admin@peer2:/config/ntp/> leave -``` +
admin@peer2:/config/> edit ntp
+admin@peer2:/config/ntp/> edit unicast-configuration 192.168.1.1 type uc-peer
+admin@peer2:/config/ntp/…/192.168.1.1/type/uc-peer/> end
+admin@peer2:/config/ntp/> set refclock-master master-stratum 8
+admin@peer2:/config/ntp/> leave
+
This configuration provides mutual synchronization between peers. If one peer fails, the other continues to serve time to clients. @@ -103,12 +98,11 @@ the other peer. Control how often the NTP server polls upstream sources: -``` -admin@example:/config/ntp/> edit unicast-configuration 0.pool.ntp.org type uc-server -admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> set minpoll 4 -admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> set maxpoll 10 -admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> end -``` +
admin@example:/config/ntp/> edit unicast-configuration 0.pool.ntp.org type uc-server
+admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> set minpoll 4
+admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> set maxpoll 10
+admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> end
+
Poll intervals are specified as powers of 2: - `minpoll 4` = poll every 2^4 = 16 seconds (minimum polling rate) @@ -126,12 +120,11 @@ critical for embedded systems without RTC that boot with epoch time. To customize the values: -``` -admin@example:/config/ntp/> edit makestep -admin@example:/config/ntp/makestep/> set threshold 2.0 -admin@example:/config/ntp/makestep/> set limit 1 -admin@example:/config/ntp/makestep/> end -``` +
admin@example:/config/ntp/> edit makestep
+admin@example:/config/ntp/makestep/> set threshold 2.0
+admin@example:/config/ntp/makestep/> set limit 1
+admin@example:/config/ntp/makestep/> end
+
- **threshold** - If clock offset exceeds this (in seconds), step immediately instead of slewing slowly @@ -143,19 +136,44 @@ correct time within seconds instead of hours. ## Monitoring -Check NTP server statistics: - -``` -admin@example:/> show ntp server -NTP SERVER CONFIGURATION -Local Stratum : 10 - -SERVER STATISTICS -Packets Received : 142 -Packets Sent : 142 -Packets Dropped : 0 -Send Failures : 0 -``` +For a quick overview: + +To view the sources being used by the NTP client, run: + +
admin@example:/> show ntp
+Mode                : Client
+Stratum             : 3
+Ref time (UTC)      : Sat Jan 24 23:41:42 2026
+
+ADDRESS         MODE    STATE     STRATUM  POLL
+147.78.228.41   server  outlier         2   64s
+192.168.0.1     server  unusable        0  128s
+176.126.86.247  server  selected        2   64s
+
+ +Check NTP source status: + +
admin@example:/> show ntp source
+MS  Name/IP address  Stratum  Poll  Reach  LastRx          Last sample
+^+  147.78.228.41          2     6    007      15  -431us +/- 33.573ms
+^*  176.126.86.247         2     6    007      14   -389us +/- 4.307ms
+
+ +For detailed information about a specific source: + +
admin@example:/> show ntp source 176.126.86.247
+Address             : 176.126.86.247
+Mode                : Server (client mode) [^]
+State               : Selected sync source [*]
+Configured          : Yes
+Stratum             : 2
+Poll interval       : 7 (2^7 seconds = 128s)
+Reachability        : 377 (octal) = 11111111b
+Last RX             : 75s ago
+Offset              : +2.0us (+0.002000ms)
+Delay               : 4.270ms (0.004270s)
+Dispersion          : 205.0us (0.205000ms)
+
## NTP Stratum Levels diff --git a/doc/qos.md b/doc/qos.md index 25e3b0474..d937104f6 100644 --- a/doc/qos.md +++ b/doc/qos.md @@ -91,15 +91,14 @@ These `ingress-qos` and `egress-qos` settings are done per VLAN, both defaulting to '0'. The example below shows how to keep the PCP priority for packets being routed between two VLAN interfaces. -``` -admin@example:/config/> edit interface e1.10 -admin@example:/config/interface/e1.10/> set vlan ingress-qos priority from-pcp -admin@example:/config/interface/e1.10/> up -admin@example:/config/> edit interface e1.20 -admin@example:/config/interface/e1.20/> set vlan egress-qos pcp from-priority -admin@example:/config/interface/e1.20/> leave -admin@example:/> -``` +
admin@example:/config/> edit interface e1.10
+admin@example:/config/interface/e1.10/> set vlan ingress-qos priority from-pcp
+admin@example:/config/interface/e1.10/> up
+admin@example:/config/> edit interface e1.20
+admin@example:/config/interface/e1.20/> set vlan egress-qos pcp from-priority
+admin@example:/config/interface/e1.20/> leave
+admin@example:/>
+
## A complex example diff --git a/doc/syslog.md b/doc/syslog.md index 002e98ec5..ead621bd5 100644 --- a/doc/syslog.md +++ b/doc/syslog.md @@ -21,20 +21,19 @@ an example. For a list of available log facilities, see the table in a later section. -``` -admin@example:/> configure -admin@example:/config/> edit syslog actions log-file file:/media/log/mylog -admin@example:/config/syslog/…/file:/media/log/mylog/> set facility-list +
admin@example:/> configure
+admin@example:/config/> edit syslog actions log-file file:/media/log/mylog
+admin@example:/config/syslog/…/file:/media/log/mylog/> set facility-list
       all    audit     auth authpriv  console     cron    cron2   daemon      ftp     kern
    local0   local1   local2   local3   local4   local5   local6   local7      lpr     mail
      news      ntp   syslog     user     uucp
-admin@example:/config/syslog/…/file:/media/log/mylog/> set facility-list all severity
+admin@example:/config/syslog/…/file:/media/log/mylog/> set facility-list all severity
      alert       all  critical     debug emergency     error      info      none    notice   warning
-admin@example:/config/syslog/…/file:/media/log/mylog/> set facility-list all severity critical
-admin@example:/config/syslog/…/file:/media/log/mylog/> set facility-list mail severity warning
-admin@example:/config/syslog/…/file:/media/log/mylog/> leave
+admin@example:/config/syslog/…/file:/media/log/mylog/> set facility-list all severity critical
+admin@example:/config/syslog/…/file:/media/log/mylog/> set facility-list mail severity warning
+admin@example:/config/syslog/…/file:/media/log/mylog/> leave
 admin@example:/>
-```
+
> [!IMPORTANT] > The `log-file` syntax requires the leading prefix `file:`. If the @@ -50,11 +49,10 @@ disk with outdated logs. A rotated file is saved in stages and older ones are also compressed (using `gzip`). Use the `show log` command in admin-exec context to start the log file viewer: -``` -admin@example:/config/syslog/> do show log +
admin@example:/config/syslog/> do show log
 log  log.0  log.1.gz  log.2.gz  log.3.gz  log.4.gz  log.5.gz
-admin@example:/config/syslog/> do show log log.1.gz
-```
+admin@example:/config/syslog/> do show log log.1.gz
+
> [!TIP] > Use the Tab key on your keyboard list available log files. The `do` @@ -68,51 +66,48 @@ Log file rotation can be configured both globally and per log file. Here we show the global settings, the set up is the same for per log file, which if unset inherit the global settings: -``` -admin@example:/> configure -admin@example:/config/> edit syslog file-rotation -admin@example:/config/syslog/file-rotation/> show +
admin@example:/> configure
+admin@example:/config/> edit syslog file-rotation
+admin@example:/config/syslog/file-rotation/> show
 admin@example:/config/syslog/file-rotation/>
-```
+
The defaults are not shown. We can inspect them by asking the YANG model for the help texts: -``` -admin@example:/config/syslog/file-rotation/> help +
admin@example:/config/syslog/file-rotation/> help
    max-file-size    number-of-files
-admin@example:/config/syslog/file-rotation/> help max-file-size 
-NAME
+admin@example:/config/syslog/file-rotation/> help max-file-size
+NAME
         max-file-size kilobytes
 
-DESCRIPTION
+DESCRIPTION
         Maximum log file size (kiB), before rotation.
 
-DEFAULT
+DEFAULT
         1024
-admin@example:/config/syslog/file-rotation/> help number-of-files 
-NAME
+admin@example:/config/syslog/file-rotation/> help number-of-files
+NAME
         number-of-files [0..4294967295]
 
-DESCRIPTION
+DESCRIPTION
         Maximum number of log files retained.
 
-DEFAULT
+DEFAULT
         10
-```
+
To change the defaults to something smaller, 512 kiB and 20 (remember everything after .0 is compressed, and text compresses well): -``` -admin@example:/config/syslog/file-rotation/> set max-file-size 512 -admin@example:/config/syslog/file-rotation/> set number-of-files 20 -admin@example:/config/syslog/file-rotation/> show +
admin@example:/config/syslog/file-rotation/> set max-file-size 512
+admin@example:/config/syslog/file-rotation/> set number-of-files 20
+admin@example:/config/syslog/file-rotation/> show
 number-of-files 20;
 max-file-size 512;
-admin@example:/config/syslog/file-rotation/> leave
+admin@example:/config/syslog/file-rotation/> leave
 admin@example:/>
-```
+
## Log Format @@ -135,14 +130,13 @@ perform time stamping at the time of arrival. Configuring the log format is the same for log files and remotes: -``` -admin@example:/config/> edit syslog actions log-file file:foobar -admin@example:/config/syslog/…/file:foobar/> set log-format +
admin@example:/config/> edit syslog actions log-file file:foobar
+admin@example:/config/syslog/…/file:foobar/> set log-format
                   bsd               rfc3164              rfc5424
-admin@example:/config/syslog/…/file:foobar/> set log-format rfc5424
-admin@example:/config/syslog/…/file:foobar/> leave
+admin@example:/config/syslog/…/file:foobar/> set log-format rfc5424
+admin@example:/config/syslog/…/file:foobar/> leave
 admin@example:/>
-```
+
## Log to Remote Server @@ -158,19 +152,18 @@ remote syslog servers do not support receiving time stamped log messages -- this is of course entirely dependent on how the remote server is set up, as well as local policy. -``` -admin@example:/config/> edit syslog +
admin@example:/config/> edit syslog
        actions file-rotation        server
-admin@example:/config/> edit syslog actions destination moon
-admin@example:/config/syslog/…/moon/> set
+admin@example:/config/> edit syslog actions destination moon
+admin@example:/config/syslog/…/moon/> set
  facility-list    log-format           udp
-admin@example:/config/syslog/…/moon/> set udp
+admin@example:/config/syslog/…/moon/> set udp
  address    port
-admin@example:/config/syslog/…/moon/> set udp address 192.168.0.12
-admin@example:/config/syslog/…/moon/> set facility-list container severity all
-admin@example:/config/syslog/…/moon/> leave
+admin@example:/config/syslog/…/moon/> set udp address 192.168.0.12
+admin@example:/config/syslog/…/moon/> set facility-list container severity all
+admin@example:/config/syslog/…/moon/> leave
 admin@example:/>
-```
+
> [!TIP] > The alternatives shown below each prompt in the example above can be @@ -181,14 +174,13 @@ admin@example:/> The syslog server can act as a log sink for other devices on a LAN. For this to work you need a static IP address, here we use 10.0.0.1/24. -``` -admin@example:/> configure -admin@example:/config/> edit syslog server -admin@example:/config/syslog/server/> set enabled true -admin@example:/config/syslog/server/> set listen udp 514 address 10.0.0.1 -admin@example:/config/syslog/server/> leave +
admin@example:/> configure
+admin@example:/config/> edit syslog server
+admin@example:/config/syslog/server/> set enabled true
+admin@example:/config/syslog/server/> set listen udp 514 address 10.0.0.1
+admin@example:/config/syslog/server/> leave
 admin@example:/>
-```
+
See the above [Log to File](#log-to-file) section on how to set up filtering of received logs to local files. Advanced filtering based @@ -208,13 +200,12 @@ Messages can be filtered using regular expressions (POSIX extended regex) on the message content. This is useful when you want to log only messages containing specific keywords or patterns: -``` -admin@example:/config/> edit syslog actions log-file file:errors -admin@example:/config/syslog/…/file:errors/> set pattern-match "ERROR|CRITICAL|FATAL" -admin@example:/config/syslog/…/file:errors/> set facility-list all severity info -admin@example:/config/syslog/…/file:errors/> leave +
admin@example:/config/> edit syslog actions log-file file:errors
+admin@example:/config/syslog/…/file:errors/> set pattern-match "ERROR|CRITICAL|FATAL"
+admin@example:/config/syslog/…/file:errors/> set facility-list all severity info
+admin@example:/config/syslog/…/file:errors/> leave
 admin@example:/>
-```
+
This will log all messages containing ERROR, CRITICAL, or FATAL. @@ -224,22 +215,20 @@ By default, severity filtering uses "equals-or-higher" comparison, meaning a severity of `error` will match error, critical, alert, and emergency messages. You can change this behavior: -``` -admin@example:/config/> edit syslog actions log-file file:daemon-errors -admin@example:/config/syslog/…/file:daemon-errors/> set facility-list daemon -admin@example:/config/syslog/…/daemon/> set severity error -admin@example:/config/syslog/…/daemon/> set advanced-compare compare equals -admin@example:/config/syslog/…/daemon/> leave +
admin@example:/config/> edit syslog actions log-file file:daemon-errors
+admin@example:/config/syslog/…/file:daemon-errors/> set facility-list daemon
+admin@example:/config/syslog/…/daemon/> set severity error
+admin@example:/config/syslog/…/daemon/> set advanced-compare compare equals
+admin@example:/config/syslog/…/daemon/> leave
 admin@example:/>
-```
+
This will log only `error` severity messages, not higher severities. You can also block specific severities: -``` -admin@example:/config/syslog/…/daemon/> set advanced-compare action block -``` +
admin@example:/config/syslog/…/daemon/> set advanced-compare action block
+
This will exclude `error` messages from the log. @@ -248,13 +237,12 @@ This will exclude `error` messages from the log. When acting as a log server, you can filter messages by hostname. This is useful for directing logs from different devices to separate files: -``` -admin@example:/config/> edit syslog actions log-file file:router1 -admin@example:/config/syslog/…/file:router1/> set hostname-filter router1 -admin@example:/config/syslog/…/file:router1/> set facility-list all severity info -admin@example:/config/syslog/…/file:router1/> leave +
admin@example:/config/> edit syslog actions log-file file:router1
+admin@example:/config/syslog/…/file:router1/> set hostname-filter router1
+admin@example:/config/syslog/…/file:router1/> set facility-list all severity info
+admin@example:/config/syslog/…/file:router1/> leave
 admin@example:/>
-```
+
Multiple hostnames can be added to the filter list. @@ -263,15 +251,14 @@ Multiple hostnames can be added to the filter list. For more advanced filtering, you can match on specific message properties using various comparison operators: -``` -admin@example:/config/> edit syslog actions log-file file:myapp -admin@example:/config/syslog/…/file:myapp/> edit property-filter -admin@example:/config/syslog/…/property-filter/> set property programname -admin@example:/config/syslog/…/property-filter/> set operator isequal -admin@example:/config/syslog/…/property-filter/> set value myapp -admin@example:/config/syslog/…/property-filter/> leave +
admin@example:/config/> edit syslog actions log-file file:myapp
+admin@example:/config/syslog/…/file:myapp/> edit property-filter
+admin@example:/config/syslog/…/property-filter/> set property programname
+admin@example:/config/syslog/…/property-filter/> set operator isequal
+admin@example:/config/syslog/…/property-filter/> set value myapp
+admin@example:/config/syslog/…/property-filter/> leave
 admin@example:/>
-```
+
Available properties: - `msg`: Message body @@ -290,15 +277,13 @@ Available operators: The comparison can be made case-insensitive: -``` -admin@example:/config/syslog/…/property-filter/> set case-insensitive true -``` +
admin@example:/config/syslog/…/property-filter/> set case-insensitive true
+
Or negated to exclude matching messages: -``` -admin@example:/config/syslog/…/property-filter/> set negate true -``` +
admin@example:/config/syslog/…/property-filter/> set negate true
+
### Facilities diff --git a/doc/system.md b/doc/system.md index d4c8cbb9c..f2394086e 100644 --- a/doc/system.md +++ b/doc/system.md @@ -22,13 +22,12 @@ hostname is included below. User management, including passwords, SSH keys, remote authentication is available in the system authentication configuration context. -``` -admin@example:/config/> edit system authentication user admin -admin@example:/config/system/authentication/user/admin/> change password +
admin@example:/config/> edit system authentication user admin
+admin@example:/config/system/…/user/admin/> change password
 New password:
 Retype password:
-admin@example:/config/system/authentication/user/admin/> leave
-```
+admin@example:/config/system/…/user/admin/> leave
+
The `change password` command starts an interactive dialogue that asks for the new password, with a confirmation, and then salts and encrypts @@ -56,16 +55,15 @@ are supported. With SSH keys in place it is possible to disable password login, just remember to verify SSH login and network connectivity before doing so. -``` -admin@example:/config/> edit system authentication user admin -admin@example:/config/system/authentication/user/admin/> edit authorized-key admin@example -admin@example:/config/system/authentication/user/admin/authorized-key/example@host/> set algorithm ssh-rsa -admin@example:/config/system/authentication/user/admin/authorized-key/example@host/> set key-data AAAAB3NzaC1yc2EAAAADAQABAAABgQC8iBL42yeMBioFay7lty1C4ZDTHcHyo739gc91rTTH8SKvAE4g8Rr97KOz/8PFtOObBrE9G21K7d6UBuPqmd0RUF2CkXXN/eN2PBSHJ50YprRFt/z/304bsBYkDdflKlPDjuSmZ/+OMp4pTsq0R0eNFlX9wcwxEzooIb7VPEdvWE7AYoBRUdf41u3KBHuvjGd1M6QYJtbFLQMMTiVe5IUfyVSZ1RCxEyAB9fR9CBhtVheTVsY3iG0fZc9eCEo89ErDgtGUTJK4Hxt5yCNwI88YaVmkE85cNtw8YwubWQL3/tGZHfbbQ0fynfB4kWNloyRHFr7E1kDxuX5+pbv26EqRdcOVGucNn7hnGU6C1+ejLWdBD7vgsoilFrEaBWF41elJEPKDzpszEijQ9gTrrWeYOQ+x++lvmOdssDu4KvGmj2K/MQTL2jJYrMJ7GDzsUu3XikChRL7zNfS2jYYQLzovboUCgqfPUsVba9hqeX3U67GsJo+hy5MG9RSry4+ucHs= -admin@example:/config/system/authentication/user/admin/authorized-key/example@host/> show +
admin@example:/config/> edit system authentication user admin
+admin@example:/config/system/…/user/admin/> edit authorized-key admin@example
+admin@example:/config/system/…/example@host/> set algorithm ssh-rsa
+admin@example:/config/system/…/example@host/> set key-data AAAAB3NzaC1yc2EAAAADAQABAAABgQC8iBL42yeMBioFay7lty1C4ZDTHcHyo739gc91rTTH8SKvAE4g8Rr97KOz/8PFtOObBrE9G21K7d6UBuPqmd0RUF2CkXXN/eN2PBSHJ50YprRFt/z/304bsBYkDdflKlPDjuSmZ/+OMp4pTsq0R0eNFlX9wcwxEzooIb7VPEdvWE7AYoBRUdf41u3KBHuvjGd1M6QYJtbFLQMMTiVe5IUfyVSZ1RCxEyAB9fR9CBhtVheTVsY3iG0fZc9eCEo89ErDgtGUTJK4Hxt5yCNwI88YaVmkE85cNtw8YwubWQL3/tGZHfbbQ0fynfB4kWNloyRHFr7E1kDxuX5+pbv26EqRdcOVGucNn7hnGU6C1+ejLWdBD7vgsoilFrEaBWF41elJEPKDzpszEijQ9gTrrWeYOQ+x++lvmOdssDu4KvGmj2K/MQTL2jJYrMJ7GDzsUu3XikChRL7zNfS2jYYQLzovboUCgqfPUsVba9hqeX3U67GsJo+hy5MG9RSry4+ucHs=
+admin@example:/config/system/…/example@host/> show
 algorithm ssh-rsa;
 key-data AAAAB3NzaC1yc2EAAAADAQABAAABgQC8iBL42yeMBioFay7lty1C4ZDTHcHyo739gc91rTTH8SKvAE4g8Rr97KOz/8PFtOObBrE9G21K7d6UBuPqmd0RUF2CkXXN/eN2PBSHJ50YprRFt/z/304bsBYkDdflKlPDjuSmZ/+OMp4pTsq0R0eNFlX9wcwxEzooIb7VPEdvWE7AYoBRUdf41u3KBHuvjGd1M6QYJtbFLQMMTiVe5IUfyVSZ1RCxEyAB9fR9CBhtVheTVsY3iG0fZc9eCEo89ErDgtGUTJK4Hxt5yCNwI88YaVmkE85cNtw8YwubWQL3/tGZHfbbQ0fynfB4kWNloyRHFr7E1kDxuX5+pbv26EqRdcOVGucNn7hnGU6C1+ejLWdBD7vgsoilFrEaBWF41elJEPKDzpszEijQ9gTrrWeYOQ+x++lvmOdssDu4KvGmj2K/MQTL2jJYrMJ7GDzsUu3XikChRL7zNfS2jYYQLzovboUCgqfPUsVba9hqeX3U67GsJo+hy5MG9RSry4+ucHs=;
-admin@example:/config/system/authentication/user/admin/authorized-key/example@host/> leave
-```
+admin@example:/config/system/…/example@host/> leave
+
> [!NOTE] > The `ssh-keygen` program already base64 encodes the public key data, @@ -112,8 +110,7 @@ way to regain full access is to perform a *factory reset*. For an overview of users and groups on the system, there is an admin-exec command: -``` -admin@example:/> show nacm +
admin@example:/> show nacm
 enabled              : yes
 default read access  : permit
 default write access : permit
@@ -131,16 +128,16 @@ denied notifications : 0
           └──────────┴─────────┴─────────┴─────────┘
               ✓ Full    ⚠ Restricted    ✗ Denied
 
-USER                   SHELL   LOGIN
+USER                   SHELL   LOGIN                            
 admin                  bash    password+key
 jacky                  clish   password
 monitor                false   key
 
-GROUP                  USERS
+GROUP                  USERS                                    
 admin                  admin
 operator               jacky
 guest                  monitor
-```
+
The permissions matrix shows effective access for each NACM group: @@ -151,46 +148,44 @@ The permissions matrix shows effective access for each NACM group: For detailed information about a specific group's rules: -``` -admin@example:/> show nacm group operator +
admin@example:/> show nacm group operator
 members          : jacky
 read permission  : restricted
 write permission : restricted
 exec permission  : restricted
 applicable rules : 4
 ──────────────────────────────────────────────────────────────────────
-permit-system-rpcs
+permit-system-rpcs
   action     : permit
   operations : exec
   target     : ietf-system (rpc: *)
   comment    : Operators can reboot, shutdown, and set system time.
 
 ──────────────────────────────────────────────────────────────────────
-deny-password-access (via '*')
+deny-password-access (via '*')
   action     : deny
   operations : *
   target     : /ietf-system:system/authentication/user/password
   comment    : No user except admins can access password hashes.
 
 ──────────────────────────────────────────────────────────────────────
-deny-keystore-access (via '*')
+deny-keystore-access (via '*')
   action     : deny
   operations : *
   target     : ietf-keystore
   comment    : No user except admins can access cryptographic keys.
 
 ──────────────────────────────────────────────────────────────────────
-deny-truststore-access (via '*')
+deny-truststore-access (via '*')
   action     : deny
   operations : *
   target     : ietf-truststore
   comment    : No user except admins can access trust store.
-```
+
For user details: -``` -admin@example:/> show nacm user jacky +
admin@example:/> show nacm user jacky
 shell            : clish
 login            : password
 nacm group       : operator
@@ -198,20 +193,26 @@ read permission  : restricted
 write permission : restricted
 exec permission  : restricted
 
-For detailed rules, use: show nacm group 
-```
+For detailed rules, use: show nacm group <name>
+
### Adding a User Creating a new user starts with defining the user account in the system: -``` -admin@example:/config/> edit system authentication user jacky -admin@example:/config/system/authentication/user/jacky/> change password +
admin@example:/config/> edit system authentication user jacky
+admin@example:/config/system/…/user/jacky/> change password
 New password:
 Retype password:
-admin@example:/config/system/authentication/user/jacky/> leave
-```
+admin@example:/config/system/…/user/jacky/> leave
+
+ +> [!TIP] +> It is also possible to use set password ... if you have the +> fully crypted and salted string ready. This can be created offline +> with the [`mkpasswd(1)`][5] tool, or the built-in CLI version do +> password encrypt [OPTS]. The `do` prefix is handy for reaching +> all top-level commands when in configure context. An authorized SSH key can be added the same way as described in the previous sections. @@ -219,11 +220,10 @@ previous sections. By default, shell access is disabled (`shell false`). To allow CLI/SSH access, set the shell: -``` -admin@example:/config/> edit system authentication user jacky -admin@example:/config/system/authentication/user/jacky/> set shell clish -admin@example:/config/system/authentication/user/jacky/> leave -``` +
admin@example:/config/> edit system authentication user jacky
+admin@example:/config/system/…/user/jacky/> set shell clish
+admin@example:/config/system/…/user/jacky/> leave
+
Available shells: @@ -250,27 +250,24 @@ corresponding NACM group: **Operator user:** -``` -admin@example:/config/> edit nacm group operator -admin@example:/config/nacm/group/operator/> set user-name jacky -admin@example:/config/nacm/group/operator/> leave -``` +
admin@example:/config/> edit nacm group operator
+admin@example:/config/nacm/group/operator/> set user-name jacky
+admin@example:/config/nacm/group/operator/> leave
+
**Adding another admin:** -``` -admin@example:/config/> edit nacm group admin -admin@example:/config/nacm/group/admin/> set user-name alice -admin@example:/config/nacm/group/admin/> leave -``` +
admin@example:/config/> edit nacm group admin
+admin@example:/config/nacm/group/admin/> set user-name alice
+admin@example:/config/nacm/group/admin/> leave
+
**Guest user:** -``` -admin@example:/config/> edit nacm group guest -admin@example:/config/nacm/group/guest/> set user-name monitor -admin@example:/config/nacm/group/guest/> leave -``` +
admin@example:/config/> edit nacm group guest
+admin@example:/config/nacm/group/guest/> set user-name monitor
+admin@example:/config/nacm/group/guest/> leave
+
> [!TIP] > For technical details about NACM rule evaluation, module-name vs path @@ -363,12 +360,11 @@ cryptographic key material through global NACM rules. Notice how the hostname in the prompt does not change until the change is committed by issuing the `leave` command. -``` -admin@example:/config/> edit system -admin@example:/config/system/> set hostname myrouter -admin@example:/config/system/> leave +
admin@example:/config/> edit system
+admin@example:/config/system/> set hostname myrouter
+admin@example:/config/system/> leave
 admin@myrouter:/>
-```
+
The hostname is advertised over mDNS-SD in the `.local` domain. If another device already has claimed the `myrouter.local` CNAME, in our @@ -379,12 +375,11 @@ available devices on your LAN. In some cases you may want to set the device's *domain name* as well. This is handled the same way: -``` -admin@example:/config/> edit system -admin@example:/config/system/> set hostname foo.example.com -admin@example:/config/system/> leave +
admin@example:/config/> edit system
+admin@example:/config/system/> set hostname foo.example.com
+admin@example:/config/system/> leave
 admin@foo:/>
-```
+
Both host and domain name are stored in the system files `/etc/hosts` and `/etc/hostname`. The latter is exclusively for the host name. The @@ -406,12 +401,11 @@ built-in [`text-editor` command](cli/text-editor.md). > See the next section for how to change the editor used to something > you may be more familiar with. -``` -admin@example:/config/> edit system -admin@example:/config/system/> text-editor motd-banner -admin@example:/config/system/> leave +
admin@example:/config/> edit system
+admin@example:/config/system/> text-editor motd-banner
+admin@example:/config/system/> leave
 admin@example:/>
-```
+
Log out and log back in again to inspect the changes. @@ -427,13 +421,12 @@ as the `text-editor` command: To change the editor to GNU Nano: -``` -admin@example:/> configure -admin@example:/config/> edit system -admin@example:/config/system/> set text-editor nano -admin@example:/config/system/> leave +
admin@example:/> configure
+admin@example:/config/> edit system
+admin@example:/config/system/> set text-editor nano
+admin@example:/config/system/> leave
 admin@example:/>
-```
+
> [!IMPORTANT] > Configuration changes only take effect after issuing the `leave` @@ -447,18 +440,17 @@ The system supports both static and dynamic (DHCP) DNS setup. The locally configured (static) server is preferred over any acquired from a DHCP client. -``` -admin@example:/> configure -admin@example:/config/> edit system dns-resolver -admin@example:/config/system/dns-resolver/> set server google udp-and-tcp address 8.8.8.8 -admin@example:/config/system/dns-resolver/> show +
admin@example:/> configure
+admin@example:/config/> edit system dns-resolver
+admin@example:/config/system/dns-resolver/> set server google udp-and-tcp address 8.8.8.8
+admin@example:/config/system/dns-resolver/> show
 server google {
   udp-and-tcp {
     address 8.8.8.8;
   }
 }
-admin@example:/config/system/dns-resolver/> leave
-```
+admin@example:/config/system/dns-resolver/> leave
+
It is also possible to configure resolver options like timeout and retry attempts. See the YANG model for details, or use the built-in @@ -475,16 +467,15 @@ help system in the CLI. Below is an example configuration for enabling NTP with a specific server and the `iburst` option for faster initial synchronization. -``` -admin@example:/> configure -admin@example:/config/> edit system ntp -admin@example:/config/system/ntp/> set enabled -admin@example:/config/system/ntp/> set server ntp-pool -admin@example:/config/system/ntp/> set server ntp-pool udp address pool.ntp.org -admin@example:/config/system/ntp/> set server ntp-pool iburst -admin@example:/config/system/ntp/> set server ntp-pool prefer -admin@example:/config/system/ntp/> leave -``` +
admin@example:/> configure
+admin@example:/config/> edit system ntp
+admin@example:/config/system/ntp/> set enabled
+admin@example:/config/system/ntp/> set server ntp-pool
+admin@example:/config/system/ntp/> set server ntp-pool udp address pool.ntp.org
+admin@example:/config/system/ntp/> set server ntp-pool iburst
+admin@example:/config/system/ntp/> set server ntp-pool prefer
+admin@example:/config/system/ntp/> leave
+
This configuration enables the NTP client and sets the NTP server to `pool.ntp.org` with the `iburst` and `prefer` options. The `iburst` @@ -504,36 +495,38 @@ The status for NTP sources is availble in YANG and accessable with CLI/NETCONF/RESTCONF. To view the sources being used by the NTP client, run: -``` -admin@target:/> show ntp -ADDRESS MODE STATE STRATUM POLL-INTERVAL -192.168.1.1 server candidate 1 6 -192.168.2.1 server candidate 1 6 -192.168.3.1 server selected 1 6 -``` + +
admin@example:/> show ntp
+Mode                : Client
+Stratum             : 3
+Ref time (UTC)      : Sat Jan 24 23:41:42 2026
+
+ADDRESS         MODE    STATE     STRATUM  POLL
+147.78.228.41   server  outlier         2   64s
+192.168.0.1     server  unusable        0  128s
+176.126.86.247  server  selected        2   64s
+
### Show NTP Status To check the status of NTP synchronization (only availble in CLI), use the following command: -``` -admin@example:/> show ntp tracking -Reference ID : C0248F86 (192.36.143.134) -Stratum : 2 -Ref time (UTC) : Mon Oct 21 10:06:45 2024 -System time : 0.000000001 seconds slow of NTP time -Last offset : -3845.151367188 seconds -RMS offset : 3845.151367188 seconds -Frequency : 4.599 ppm slow -Residual freq : +1293.526 ppm -Skew : 12.403 ppm -Root delay : 1.024467230 seconds -Root dispersion : 0.273462683 seconds -Update interval : 0.0 seconds -Leap status : Normal -admin@example:/> -``` +
admin@example:/> show ntp tracking
+Reference ID        : 176.126.86.247
+Stratum             : 3
+Ref time (UTC)      : Sat Jan 24 23:41:42 2026
+System time         : 0.000000 seconds slow of NTP time
+Last offset         : -454779.375000000 seconds
+RMS offset          : 454779.375000000 seconds
+Frequency           : 0.000 ppm slow
+Residual freq       : -26.383 ppm
+Skew                : 1000000.000 ppm
+Root delay          : 0.007395 seconds
+Root dispersion     : 39.181149 seconds
+Update interval     : 0.0 seconds
+Leap status         : Normal
+
This output provides detailed information about the NTP status, including reference ID, stratum, time offsets, frequency, and root delay. @@ -546,3 +539,4 @@ reference ID, stratum, time offsets, frequency, and root delay. [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]: https://chrony-project.org/doc/4.6.1/chronyc.html +[5]: https://linux.die.net/man/1/mkpasswd diff --git a/doc/tunnels.md b/doc/tunnels.md index 8d9d211f0..a79f1413f 100644 --- a/doc/tunnels.md +++ b/doc/tunnels.md @@ -28,14 +28,13 @@ IPv6 tunnels in two modes: A basic GRE tunnel for routing between two sites: -``` -admin@example:/> configure -admin@example:/config/> edit interface gre0 -admin@example:/config/interface/gre0/> set gre local 192.168.3.1 remote 192.168.3.2 -admin@example:/config/interface/gre0/> set ipv4 address 10.255.0.1 prefix-length 30 -admin@example:/config/interface/gre0/> leave +
admin@example:/> configure
+admin@example:/config/> edit interface gre0
+admin@example:/config/interface/gre0/> set gre local 192.168.3.1 remote 192.168.3.2
+admin@example:/config/interface/gre0/> set ipv4 address 10.255.0.1 prefix-length 30
+admin@example:/config/interface/gre0/> leave
 admin@example:/>
-```
+
This creates a Layer 3 tunnel between 192.168.3.1 and 192.168.3.2 using the outer IP addresses, with the tunnel itself using 10.255.0.0/30 for @@ -45,14 +44,13 @@ the inner IP addressing. GRETAP tunnels operate at Layer 2, allowing bridging across the tunnel: -``` -admin@example:/> configure -admin@example:/config/> edit interface gretap0 -admin@example:/config/interface/gretap0/> set type gretap -admin@example:/config/interface/gretap0/> set gre local 192.168.3.1 remote 192.168.3.2 -admin@example:/config/interface/gretap0/> leave +
admin@example:/> configure
+admin@example:/config/> edit interface gretap0
+admin@example:/config/interface/gretap0/> set type gretap
+admin@example:/config/interface/gretap0/> set gre local 192.168.3.1 remote 192.168.3.2
+admin@example:/config/interface/gretap0/> leave
 admin@example:/>
-```
+
GRETAP interfaces can be added to a bridge, bridging local and remote Ethernet segments. See the [Bridge Configuration](bridging.md) @@ -69,33 +67,31 @@ exchange routes. **Site A configuration:** -``` -admin@siteA:/> configure -admin@siteA:/config/> edit interface gre0 -admin@siteA:/config/interface/gre0/> set gre local 203.0.113.1 remote 203.0.113.2 -admin@siteA:/config/interface/gre0/> set ipv4 address 10.255.0.1 prefix-length 30 -admin@siteA:/config/interface/gre0/> set ipv4 forwarding -admin@siteA:/config/interface/gre0/> end -admin@siteA:/config/> edit routing control-plane-protocol ospfv2 name default ospf -admin@siteA:/config/routing/…/ospf/> set area 0.0.0.0 interface gre0 -admin@siteA:/config/routing/…/ospf/> leave +
admin@siteA:/> configure
+admin@siteA:/config/> edit interface gre0
+admin@siteA:/config/interface/gre0/> set gre local 203.0.113.1 remote 203.0.113.2
+admin@siteA:/config/interface/gre0/> set ipv4 address 10.255.0.1 prefix-length 30
+admin@siteA:/config/interface/gre0/> set ipv4 forwarding
+admin@siteA:/config/interface/gre0/> end
+admin@siteA:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@siteA:/config/routing/…/ospf/> set area 0.0.0.0 interface gre0
+admin@siteA:/config/routing/…/ospf/> leave
 admin@siteA:/>
-```
+
**Site B configuration:** -``` -admin@siteB:/> configure -admin@siteB:/config/> edit interface gre0 -admin@siteB:/config/interface/gre0/> set gre local 203.0.113.2 remote 203.0.113.1 -admin@siteB:/config/interface/gre0/> set ipv4 address 10.255.0.2 prefix-length 30 -admin@siteB:/config/interface/gre0/> set ipv4 forwarding -admin@siteB:/config/interface/gre0/> end -admin@siteB:/config/> edit routing control-plane-protocol ospfv2 name default ospf -admin@siteB:/config/routing/…/ospf/> set area 0.0.0.0 interface gre0 -admin@siteB:/config/routing/…/ospf/> leave +
admin@siteB:/> configure
+admin@siteB:/config/> edit interface gre0
+admin@siteB:/config/interface/gre0/> set gre local 203.0.113.2 remote 203.0.113.1
+admin@siteB:/config/interface/gre0/> set ipv4 address 10.255.0.2 prefix-length 30
+admin@siteB:/config/interface/gre0/> set ipv4 forwarding
+admin@siteB:/config/interface/gre0/> end
+admin@siteB:/config/> edit routing control-plane-protocol ospfv2 name default ospf
+admin@siteB:/config/routing/…/ospf/> set area 0.0.0.0 interface gre0
+admin@siteB:/config/routing/…/ospf/> leave
 admin@siteB:/>
-```
+
Once configured, OSPF will establish a neighbor relationship through the tunnel and exchange routes between the sites. For more info on OSPF @@ -118,11 +114,10 @@ The TTL setting controls the Time To Live value for the outer tunnel packets. By default, tunnels use a fixed TTL of 64, which allows packets to traverse multiple hops between tunnel endpoints. -``` -admin@example:/config/> edit interface gre0 -admin@example:/config/interface/gre0/> set gre ttl 255 -admin@example:/config/interface/gre0/> leave -``` +
admin@example:/config/> edit interface gre0
+admin@example:/config/interface/gre0/> set gre ttl 255
+admin@example:/config/interface/gre0/> leave
+
Valid values are 1-255, or the special value `inherit` which copies the TTL from the encapsulated packet. @@ -136,11 +131,10 @@ from the encapsulated packet. The ToS setting controls QoS marking for tunnel traffic: -``` -admin@example:/config/> edit interface gre0 -admin@example:/config/interface/gre0/> set gre tos 0x10 -admin@example:/config/interface/gre0/> leave -``` +
admin@example:/config/> edit interface gre0
+admin@example:/config/interface/gre0/> set gre tos 0x10
+admin@example:/config/interface/gre0/> leave
+
Valid values are 0-255 for fixed ToS/DSCP marking, or `inherit` (default) to copy the ToS value from the encapsulated packet. @@ -151,11 +145,10 @@ The `pmtu-discovery` setting can be used to control the Path MTU Discovery on GRE tunnels. When enabled (default), the tunnel respects the Don't Fragment (DF) bit and performs PMTU discovery: -``` -admin@example:/config/> edit interface gre0 -admin@example:/config/interface/gre0/> set gre pmtudisc false -admin@example:/config/interface/gre0/> leave -``` +
admin@example:/config/> edit interface gre0
+admin@example:/config/interface/gre0/> set gre pmtudisc false
+admin@example:/config/interface/gre0/> leave
+
Disabling PMTU discovery may be necessary in networks with broken ICMP filtering but can lead to suboptimal performance and fragmentation. @@ -175,15 +168,14 @@ Infix supports both IPv4 and IPv6 for VXLAN tunnel endpoints. > If you name your VXLAN interface `vxlanN`, where `N` is a number, the > CLI infers the interface type automatically. -``` -admin@example:/> configure -admin@example:/config/> edit interface vxlan100 -admin@example:/config/interface/vxlan100/> set vxlan local 192.168.3.1 -admin@example:/config/interface/vxlan100/> set vxlan remote 192.168.3.2 -admin@example:/config/interface/vxlan100/> set vxlan vni 100 -admin@example:/config/interface/vxlan100/> leave +
admin@example:/> configure
+admin@example:/config/> edit interface vxlan100
+admin@example:/config/interface/vxlan100/> set vxlan local 192.168.3.1
+admin@example:/config/interface/vxlan100/> set vxlan remote 192.168.3.2
+admin@example:/config/interface/vxlan100/> set vxlan vni 100
+admin@example:/config/interface/vxlan100/> leave
 admin@example:/>
-```
+
The VNI uniquely identifies the VXLAN segment and must match on both tunnel endpoints. @@ -193,16 +185,15 @@ tunnel endpoints. The default VXLAN UDP destination port is 4789 (IANA assigned). In some cases you may need to use a different port: -``` -admin@example:/> configure -admin@example:/config/> edit interface vxlan100 -admin@example:/config/interface/vxlan100/> set vxlan local 192.168.3.1 -admin@example:/config/interface/vxlan100/> set vxlan remote 192.168.3.2 -admin@example:/config/interface/vxlan100/> set vxlan vni 100 -admin@example:/config/interface/vxlan100/> set vxlan remote-port 8472 -admin@example:/config/interface/vxlan100/> leave +
admin@example:/> configure
+admin@example:/config/> edit interface vxlan100
+admin@example:/config/interface/vxlan100/> set vxlan local 192.168.3.1
+admin@example:/config/interface/vxlan100/> set vxlan remote 192.168.3.2
+admin@example:/config/interface/vxlan100/> set vxlan vni 100
+admin@example:/config/interface/vxlan100/> set vxlan remote-port 8472
+admin@example:/config/interface/vxlan100/> leave
 admin@example:/>
-```
+
The remote-port setting allows interoperability with systems using non-standard VXLAN ports. diff --git a/doc/upgrade.md b/doc/upgrade.md index 97ce32b90..88dd91b88 100644 --- a/doc/upgrade.md +++ b/doc/upgrade.md @@ -8,16 +8,14 @@ The _boot order_ defines which image is tried first, and is listed with the CLI `show software` command. It also shows Infix version installed per partition, and which image was used when booting (`STATE booted`). -``` -admin@example:/> show software -BOOT ORDER -primary secondary net +
admin@example:/> show software
+Boot order : primary secondary net
 
-NAME      STATE     VERSION                DATE
-primary   booted    v25.01.0               2025-04-25T10:15:00+00:00
-secondary inactive  v25.01.0               2025-04-25T10:07:20+00:00
+NAME       STATE     VERSION                DATE                     
+primary    booted    v25.01.0               2025-04-25T10:15:00+00:00
+secondary  inactive  v25.01.0               2025-04-25T10:07:20+00:00
 admin@example:/>
-```
+
YANG support for upgrading Infix, inspecting and _modifying_ the boot-order, is defined in [infix-system-software][2]. @@ -41,52 +39,47 @@ valid values. Example: View current boot order and change it: -``` -admin@example:/> show boot-order +
admin@example:/> show boot-order
 primary secondary net
-admin@example:/> set boot-order secondary primary net
-admin@example:/> show boot-order
+admin@example:/> set boot-order secondary primary net
+admin@example:/> show boot-order
 secondary primary net
 admin@example:/>
-```
+
Example: Set boot order to only try primary partition: -``` -admin@example:/> show boot-order +
admin@example:/> show boot-order
 secondary primary net
-admin@example:/> set boot-order primary
-admin@example:/> show boot-order
+admin@example:/> set boot-order primary
+admin@example:/> show boot-order
 primary
 admin@example:/>
-```
+
Example: Using tab-completion (press TAB to see available options): -``` -admin@example:/> set boot-order +
admin@example:/> set boot-order TAB
 net        primary    secondary
-admin@example:/> set boot-order secondary 
+admin@example:/> set boot-order secondary TAB
 net        primary    secondary
-admin@example:/> set boot-order secondary primary
-admin@example:/> show boot-order
+admin@example:/> set boot-order secondary primary
+admin@example:/> show boot-order
 secondary primary
 admin@example:/>
-```
+
The new boot order takes effect on the next reboot and can be verified with `show boot-order` or `show software`: -``` -admin@example:/> show software -BOOT ORDER -secondary primary +
admin@example:/> show software
+Boot order : secondary primary
 
-NAME      STATE     VERSION                DATE
-primary   booted    v25.01.0               2025-04-25T10:15:00+00:00
-secondary inactive  v25.01.0               2025-04-25T10:07:20+00:00
+NAME       STATE     VERSION                DATE                     
+primary    booted    v25.01.0               2025-04-25T10:15:00+00:00
+secondary  inactive  v25.01.0               2025-04-25T10:07:20+00:00
 admin@example:/>
-```
+
> [!NOTE] > The boot order is automatically updated when performing an upgrade. @@ -127,27 +120,28 @@ configuration before performing an upgrade. The backup is useful if the upgrade fails, and makes a later [downgrade](#downgrading) a smoother process. -``` -admin@example:/> dir /cfg +
admin@example:/> dir /cfg
 /cfg directory
 backup/             ssl/                startup-config.cfg
 
-admin@example:/> copy /cfg/startup-config.cfg /cfg/v25.01.0-startup-config.cfg
-admin@example:/> dir /cfg
+admin@example:/> copy /cfg/startup-config.cfg /cfg/v25.01.0-startup-config.cfg
+admin@example:/> dir /cfg
 /cfg directory
 backup/             ssl/                startup-config.cfg           v25.01.0-startup-config.cfg
 
-admin@example:/> 
-```
+admin@example:/>
+
*Upgrade:* Here the image *pkg bundle* was made available via TFTP. -``` -admin@example:/> upgrade tftp://198.18.117.1/infix-aarch64-25.03.1.pkg +
admin@example:/> upgrade tftp://198.18.117.1/infix-aarch64-25.03.1.pkg
 installing
   0% Installing
   0% Determining slot states
  10% Determining slot states done.
+...
+ 40% Checking slot rootfs.1 (secondary)
+ 46% Checking slot rootfs.1 (secondary) done.
 ...
  98% Copying image to rootfs.1
  99% Copying image to rootfs.1
@@ -156,14 +150,13 @@ installing
 100% Installing done.
 Installing `tftp://198.18.117.1/infix-aarch64-25.03.1.pkg` succeeded
 admin@example:/>
-```
+
*Reboot:* The unit will boot on the other partition, with the newly installed image. The `Loading startup-config` step conducts migration of startup configuration if applicable. -``` -admin@example:/> reboot +
admin@example:/> reboot
 [ OK ] Stopping Static routing daemon
 [ OK ] Stopping Zebra routing daemon
 ...
@@ -173,7 +166,7 @@ admin@example:/> reboot
 [ OK ] Starting Status daemon
 
 Infix OS — Immutable.Friendly.Secure v25.03.1 (ttyS0)
-example login: admin
+example login: admin
 Password:
 .-------.
 |  . .  | Infix OS — Immutable.Friendly.Secure
@@ -182,19 +175,18 @@ Password:
 
 Run the command 'cli' for interactive OAM
 
-admin@example:~$ cli
+admin@example:~$ cli
 
 See the 'help' command for an introduction to the system
 
-admin@example:/> show software
-BOOT ORDER
-secondary primary net
+admin@example:/> show software
+Boot order : secondary primary net
 
-NAME      STATE     VERSION                DATE
-primary   inactive  v25.01.0               2025-04-25T10:15:00+00:00
-secondary booted    v25.03.1               2025-04-25T10:24:31+00:00
+NAME       STATE     VERSION                DATE                     
+primary    inactive  v25.01.0               2025-04-25T10:15:00+00:00
+secondary  booted    v25.03.1               2025-04-25T10:24:31+00:00
 admin@example:/>
-```
+
As shown, the *boot order* has been updated, so that *secondary* is now the preferred boot source. @@ -217,20 +209,18 @@ numbering). The startup configuration is migrated to `1.5` definitions and stored, while a backup previous startup configuration is stored in directory `/cfg/backup/`. -``` -admin@example:/> dir /cfg/backup/ +
admin@example:/> dir /cfg/backup/
 /cfg/backup/ directory
 startup-config-1.4.cfg
 
 admin@example:/>
-```
+
The modifications made to the startup configuration can be viewed by comparing the files from the *shell*. An example is shown below. -``` -admin@example:/> exit -admin@example:~$ diff /cfg/backup/startup-config-1.4.cfg /cfg/startup-config.cfg +
admin@example:/> exit
+admin@example:~$ diff /cfg/backup/startup-config-1.4.cfg /cfg/startup-config.cfg
 --- /cfg/backup/startup-config-1.4.cfg
 +++ /cfg/startup-config.cfg
 ...
@@ -244,7 +234,7 @@ admin@example:~$ diff /cfg/backup/startup-config-1.4.cfg /cfg/startup-config.cfg
 +    "version": "1.5"
 ...
 admin@example:~$
-```
+
## Downgrading @@ -259,16 +249,14 @@ startup configuration before rebooting. In both cases we start out with a unit running Infix v25.03.1, and wish to downgrade to v25.01.0. -``` -admin@example:/> show software -BOOT ORDER -primary secondary net +
admin@example:/> show software
+Boot order : primary secondary net
 
-NAME      STATE     VERSION                DATE
-primary   booted    v25.03.1               2025-04-25T11:36:26+00:00
-secondary inactive  v25.03.1               2025-04-25T10:24:31+00:00
+NAME       STATE     VERSION                DATE                     
+primary    booted    v25.03.1               2025-04-25T11:36:26+00:00
+secondary  inactive  v25.03.1               2025-04-25T10:24:31+00:00
 admin@example:/>
-```
+
### With Backup `startup-config` @@ -292,24 +280,22 @@ running Infix v25.01.0 on the unit. See section [Upgrading](#upgrading) above for more information. In the following example, there is a backup file available named `v25.01.0-startup-config.cfg`: -``` -admin@example:/> dir /cfg +
admin@example:/> dir /cfg
 /cfg directory
 backup/       ssl/       startup-config.cfg    v25.01.0-startup-config.cfg
 
-admin@example:/> 
-```
+admin@example:/>
+
The alternative is to use a startup config implicitly backed up by the system as part of [Configuration Migration](#configuration-migration). -``` -admin@example:/> dir /cfg/backup/ +
admin@example:/> dir /cfg/backup/
 /cfg/backup/ directory
 startup-config-1.4.cfg
 
 admin@example:/>
-```
+
> [!CAUTION] > Using a backup configuration file stored when the unit was running the @@ -330,8 +316,7 @@ config*. *Use `upgrade` command to downgrade:* -``` -admin@example:/> upgrade tftp://198.18.117.1/infix-aarch64-25.01.0.pkg +
admin@example:/> upgrade tftp://198.18.117.1/infix-aarch64-25.01.0.pkg
 installing
   0% Installing
   0% Determining slot states
@@ -342,35 +327,32 @@ installing
 100% Installing done.
 Installing `tftp://198.18.117.1/infix-aarch64-25.01.0.pkg` succeeded
 admin@example:/>
-```
+
*Apply the backup configuration file:* It is recommended to use a backup configuration file for the Infix version to downgrade to, if there is one available. -``` -admin@example:/> copy /cfg/v25.01.0-startup-config.cfg /cfg/startup-config.cfg -Overwrite existing file /cfg/startup-config.cfg (y/N)? y +
admin@example:/> copy /cfg/v25.01.0-startup-config.cfg /cfg/startup-config.cfg
+Overwrite existing file /cfg/startup-config.cfg (y/N)? y
 admin@example:/>
-```
+
An alternative is to use a backup file stored when the system conducted a [configuration migration](#configuration-migration). See the *caution* note above. -``` -admin@example:/> copy /cfg/backup/startup-config-1.4.cfg /cfg/startup-config.cfg -Overwrite existing file /cfg/startup-config.cfg (y/N)? y +
admin@example:/> copy /cfg/backup/startup-config-1.4.cfg /cfg/startup-config.cfg
+Overwrite existing file /cfg/startup-config.cfg (y/N)? y
 admin@example:/>
-```
+
*Reboot:* The unit will come up with the applied backup configuration. -``` -admin@example:/> reboot +
admin@example:/> reboot
 [ OK ] Saving system clock to file
 [ OK ] Stopping Software update service
 [ OK ] Stopping Status daemon
@@ -384,7 +366,7 @@ admin@example:/> reboot
 
 Infix OS — Immutable.Friendly.Secure v25.01.0 (ttyS0)
 example login:
-```
+
> [!NOTE] > If the unit despite these measures ends up in *failure config*, see @@ -403,8 +385,7 @@ its default login credentials[^1]. *Use `upgrade` command to downgrade:* -``` -admin@example:/> upgrade tftp://198.18.117.1/infix-aarch64-25.01.0.pkg +
admin@example:/> upgrade tftp://198.18.117.1/infix-aarch64-25.01.0.pkg
 installing
   0% Installing
   0% Determining slot states
@@ -415,7 +396,7 @@ installing
 100% Installing done.
 Installing `tftp://198.18.117.1/infix-aarch64-25.01.0.pkg` succeeded
 admin@example:/>
-```
+
*Reboot:* @@ -426,8 +407,7 @@ config][3]. This is what is seen on the console when this situation occurs. Note that the login prompt displays `failed` as part of the *hostname*. -``` -admin@example:/> reboot +
admin@example:/> reboot
 [ OK ] Saving system clock to file
 [ OK ] Stopping Software update service
 [ OK ] Stopping Status daemon
@@ -444,32 +424,30 @@ Infix OS — Immutable.Friendly.Secure v25.01.0 (ttyS0)
 
 ERROR: Corrupt startup-config, system has reverted to default login credentials
 failed-00-00-00 login:
-```
+
To remedy a situation like this, you can login with the unit's *default login credentials*, preferrably via a [console port][4]. The unit's default credentials are typically printed on a sticker on the unit. -``` -failed-00-00-00 login: admin +
failed-00-00-00 login: admin
 Password:
 
 Run the command 'cli' for interactive OAM
 
 admin@failed-00-00-00:~$
-```
+
When it is *safe* from a network operations perspective, you can conduct a factory reset and reboot. It is recommended to remove the unit from any production network before doing this, as a factory reset may enable undesired connectivity between the unit's ports. -``` -admin@failed-00-00-00:~$ factory -Factory reset device (y/N)? y +
admin@failed-00-00-00:~$ factory
+Factory reset device (y/N)? y
 factory: scheduled factory reset on next boot.
-Reboot now to perform reset, (y/N)? y
+Reboot now to perform reset, (y/N)? y
 [ OK ] Saving system time (UTC) to RTC
 [ OK ] Stopping mDNS alias advertiser
 ...
@@ -485,7 +463,7 @@ Please press Enter to activate this console.
 
 Infix OS — Immutable.Friendly.Secure v25.01.0 (ttyS0)
 example login:
-```
+
Continued configuration is done as with any unit after factory reset. diff --git a/doc/vpn-wireguard.md b/doc/vpn-wireguard.md index 1daa13609..a5ceff8db 100644 --- a/doc/vpn-wireguard.md +++ b/doc/vpn-wireguard.md @@ -41,27 +41,25 @@ and saves it to `publickey`. **Import the private key into the keystore:** -``` -admin@example:/> configure -admin@example:/config/> edit keystore asymmetric-key wg-site-a -admin@example:/config/keystore/asymmetric-key/wg-site-a/> set public-key-format x25519-public-key-format -admin@example:/config/keystore/asymmetric-key/wg-site-a/> set private-key-format x25519-private-key-format -admin@example:/config/keystore/asymmetric-key/wg-site-a/> set public-key bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP= -admin@example:/config/keystore/asymmetric-key/wg-site-a/> set private-key aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP= -admin@example:/config/keystore/asymmetric-key/wg-site-a/> leave +
admin@example:/> configure
+admin@example:/config/> edit keystore asymmetric-key wg-site-a
+admin@example:/config/keystore/asymmetric-key/wg-site-a/> set public-key-format x25519-public-key-format
+admin@example:/config/keystore/asymmetric-key/wg-site-a/> set private-key-format x25519-private-key-format
+admin@example:/config/keystore/asymmetric-key/wg-site-a/> set public-key bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=
+admin@example:/config/keystore/asymmetric-key/wg-site-a/> set private-key aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=
+admin@example:/config/keystore/asymmetric-key/wg-site-a/> leave
 admin@example:/>
-```
+
**Import peer public keys into the truststore:** -``` -admin@example:/> configure -admin@example:/config/> edit truststore public-key-bag wg-peers public-key peer-b -admin@example:/config/truststore/…/peer-b/> set public-key-format x25519-public-key-format -admin@example:/config/truststore/…/peer-b/> set public-key PEER_PUBLIC_KEY_HERE -admin@example:/config/truststore/…/peer-b/> leave +
admin@example:/> configure
+admin@example:/config/> edit truststore public-key-bag wg-peers public-key peer-b
+admin@example:/config/truststore/…/peer-b/> set public-key-format x25519-public-key-format
+admin@example:/config/truststore/…/peer-b/> set public-key PEER_PUBLIC_KEY_HERE
+admin@example:/config/truststore/…/peer-b/> leave
 admin@example:/>
-```
+
> [!IMPORTANT] > Keep private keys secure! Never share your private key. Only exchange @@ -78,37 +76,35 @@ A basic WireGuard tunnel between two sites: **Site A configuration:** -``` -admin@siteA:/> configure -admin@siteA:/config/> edit interface wg0 -admin@siteA:/config/interface/wg0/> set wireguard listen-port 51820 -admin@siteA:/config/interface/wg0/> set wireguard private-key wg-site-a -admin@siteA:/config/interface/wg0/> set ipv4 address 10.0.0.1 prefix-length 24 -admin@siteA:/config/interface/wg0/> edit wireguard peer wg-peers peer-b -admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> set endpoint 203.0.113.2 -admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> set endpoint-port 51820 -admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> set allowed-ips 10.0.0.2/32 -admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> set persistent-keepalive 25 -admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> leave +
admin@siteA:/> configure
+admin@siteA:/config/> edit interface wg0
+admin@siteA:/config/interface/wg0/> set wireguard listen-port 51820
+admin@siteA:/config/interface/wg0/> set wireguard private-key wg-site-a
+admin@siteA:/config/interface/wg0/> set ipv4 address 10.0.0.1 prefix-length 24
+admin@siteA:/config/interface/wg0/> edit wireguard peer wg-peers peer-b
+admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> set endpoint 203.0.113.2
+admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> set endpoint-port 51820
+admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> set allowed-ips 10.0.0.2/32
+admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> set persistent-keepalive 25
+admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> leave
 admin@siteA:/>
-```
+
**Site B configuration:** -``` -admin@siteB:/> configure -admin@siteB:/config/> edit interface wg0 -admin@siteB:/config/interface/wg0/> set wireguard listen-port 51820 -admin@siteB:/config/interface/wg0/> set wireguard private-key wg-site-b -admin@siteB:/config/interface/wg0/> set ipv4 address 10.0.0.2 prefix-length 24 -admin@siteB:/config/interface/wg0/> edit wireguard peer wg-peers peer-a -admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> set endpoint 203.0.113.1 -admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> set endpoint-port 51820 -admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> set allowed-ips 10.0.0.1/32 -admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> set persistent-keepalive 25 -admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> leave +
admin@siteB:/> configure
+admin@siteB:/config/> edit interface wg0
+admin@siteB:/config/interface/wg0/> set wireguard listen-port 51820
+admin@siteB:/config/interface/wg0/> set wireguard private-key wg-site-b
+admin@siteB:/config/interface/wg0/> set ipv4 address 10.0.0.2 prefix-length 24
+admin@siteB:/config/interface/wg0/> edit wireguard peer wg-peers peer-a
+admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> set endpoint 203.0.113.1
+admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> set endpoint-port 51820
+admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> set allowed-ips 10.0.0.1/32
+admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> set persistent-keepalive 25
+admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> leave
 admin@siteB:/>
-```
+
This creates an encrypted tunnel with Site A at 10.0.0.1 and Site B at 10.0.0.2. @@ -130,10 +126,9 @@ For a simple point-to-point tunnel, you typically allow only the peer's tunnel IP address (e.g., `10.0.0.2/32`). For site-to-site VPNs connecting entire networks, include the remote network prefixes: -``` -admin@example:/config/interface/…/wg-peers/peer/peer-a/> set allowed-ips 10.0.0.2/32 -admin@example:/config/interface/…/wg-peers/peer/peer-a/> set allowed-ips 192.168.2.0/24 -``` +
admin@example:/config/interface/…/wg-peers/peer/peer-a/> set allowed-ips 10.0.0.2/32
+admin@example:/config/interface/…/wg-peers/peer/peer-a/> set allowed-ips 192.168.2.0/24
+
This allows traffic to/from the peer at 10.0.0.2 and routes traffic destined for 192.168.2.0/24 through this peer. @@ -174,35 +169,34 @@ Settings that support bag-level defaults and per-peer overrides: **Example with bag-level defaults:** -``` -admin@example:/> configure -admin@example:/config/> edit interface wg0 -admin@example:/config/interface/wg0/> set wireguard listen-port 51820 -admin@example:/config/interface/wg0/> set wireguard private-key wg-key -admin@example:/config/interface/wg0/> set ipv4 address 10.0.0.1 prefix-length 24 +
admin@example:/> configure
+admin@example:/config/> edit interface wg0
+admin@example:/config/interface/wg0/> set wireguard listen-port 51820
+admin@example:/config/interface/wg0/> set wireguard private-key wg-key
+admin@example:/config/interface/wg0/> set ipv4 address 10.0.0.1 prefix-length 24
 
 # Configure defaults for all peers in the 'branch-offices' bag
-admin@example:/config/interface/wg0/> edit wireguard peers branch-offices
-admin@example:/config/interface/…/wireguard/peers/branch-offices/> set endpoint-port 51820
-admin@example:/config/interface/…/wireguard/peers/branch-offices/> set persistent-keepalive 25
-admin@example:/config/interface/…/wireguard/peers/branch-offices/> end
+admin@example:/config/interface/wg0/> edit wireguard peers branch-offices
+admin@example:/config/interface/…/wireguard/peers/branch-offices/> set endpoint-port 51820
+admin@example:/config/interface/…/wireguard/peers/branch-offices/> set persistent-keepalive 25
+admin@example:/config/interface/…/wireguard/peers/branch-offices/> end
 
 # Configure peer-specific settings (inherits endpoint-port and keepalive from bag)
-admin@example:/config/interface/…/wireguard/peers/branch-offices/> edit peer office-east
-admin@example:/config/interface/…/branch-offices/peer/office-east/> set endpoint 203.0.113.10
-admin@example:/config/interface/…/branch-offices/peer/office-east/> set allowed-ips 10.0.0.10/32
-admin@example:/config/interface/…/branch-offices/peer/office-east/> set allowed-ips 192.168.10.0/24
-admin@example:/config/interface/…/branch-offices/peer/office-east/> end
+admin@example:/config/interface/…/wireguard/peers/branch-offices/> edit peer office-east
+admin@example:/config/interface/…/branch-offices/peer/office-east/> set endpoint 203.0.113.10
+admin@example:/config/interface/…/branch-offices/peer/office-east/> set allowed-ips 10.0.0.10/32
+admin@example:/config/interface/…/branch-offices/peer/office-east/> set allowed-ips 192.168.10.0/24
+admin@example:/config/interface/…/branch-offices/peer/office-east/> end
 
 # Another peer with an override for persistent-keepalive
-admin@example:/config/interface/…/wireguard/peers/branch-offices/> edit peer office-west
-admin@example:/config/interface/…/branch-offices/peer/office-west/> set endpoint 203.0.113.20
-admin@example:/config/interface/…/branch-offices/peer/office-west/> set allowed-ips 10.0.0.20/32
-admin@example:/config/interface/…/branch-offices/peer/office-west/> set allowed-ips 192.168.20.0/24
-admin@example:/config/interface/…/branch-offices/peer/office-west/> set persistent-keepalive 10
-admin@example:/config/interface/…/branch-offices/peer/office-west/> leave
+admin@example:/config/interface/…/wireguard/peers/branch-offices/> edit peer office-west
+admin@example:/config/interface/…/branch-offices/peer/office-west/> set endpoint 203.0.113.20
+admin@example:/config/interface/…/branch-offices/peer/office-west/> set allowed-ips 10.0.0.20/32
+admin@example:/config/interface/…/branch-offices/peer/office-west/> set allowed-ips 192.168.20.0/24
+admin@example:/config/interface/…/branch-offices/peer/office-west/> set persistent-keepalive 10
+admin@example:/config/interface/…/branch-offices/peer/office-west/> leave
 admin@example:/>
-```
+
In this example: - Both peers inherit `endpoint-port 51820` and `persistent-keepalive 25` from the bag @@ -235,13 +229,12 @@ then add the remote network to `allowed-ips` and configure static routes. For mobile clients or peers without fixed IPs, omit the `endpoint` setting. WireGuard learns the peer's endpoint from authenticated incoming packets: -``` -admin@hub:/> configure -admin@hub:/config/> edit interface wg0 wireguard peers wg-peers peer mobile-client -admin@hub:/config/interface/…/wg-peers/peer/mobile-client/> set allowed-ips 10.0.0.10/32 -admin@hub:/config/interface/…/wg-peers/peer/mobile-client/> leave +
admin@hub:/> configure
+admin@hub:/config/> edit interface wg0 wireguard peers wg-peers peer mobile-client
+admin@hub:/config/interface/…/wg-peers/peer/mobile-client/> set allowed-ips 10.0.0.10/32
+admin@hub:/config/interface/…/wg-peers/peer/mobile-client/> leave
 admin@hub:/>
-```
+
The mobile client configures the hub's endpoint normally. The hub learns and tracks the mobile client's changing IP address automatically. @@ -256,59 +249,57 @@ sites connect to a central hub. **Hub configuration:** -``` -admin@hub:/> configure -admin@hub:/config/> edit interface wg0 -admin@hub:/config/interface/wg0/> set ipv4 address 10.0.0.1 prefix-length 24 -admin@hub:/config/interface/wg0/> set wireguard listen-port 51820 -admin@hub:/config/interface/wg0/> set wireguard private-key wg-hub -admin@hub:/config/interface/wg0/> edit wireguard peers wg-peers +
admin@hub:/> configure
+admin@hub:/config/> edit interface wg0
+admin@hub:/config/interface/wg0/> set ipv4 address 10.0.0.1 prefix-length 24
+admin@hub:/config/interface/wg0/> set wireguard listen-port 51820
+admin@hub:/config/interface/wg0/> set wireguard private-key wg-hub
+admin@hub:/config/interface/wg0/> edit wireguard peers wg-peers
 
 # Spoke 1
-admin@hub:/config/interface/…/wireguard/peers/wg-peers/> edit peer spoke1
-admin@hub:/config/interface/…/wg-peers/peer/spoke1/> set allowed-ips 10.0.0.2/32
-admin@hub:/config/interface/…/wg-peers/peer/spoke1/> set allowed-ips 192.168.1.0/24
-admin@hub:/config/interface/…/wg-peers/peer/spoke1/> end
+admin@hub:/config/interface/…/wireguard/peers/wg-peers/> edit peer spoke1
+admin@hub:/config/interface/…/wg-peers/peer/spoke1/> set allowed-ips 10.0.0.2/32
+admin@hub:/config/interface/…/wg-peers/peer/spoke1/> set allowed-ips 192.168.1.0/24
+admin@hub:/config/interface/…/wg-peers/peer/spoke1/> end
 
 # Spoke 2
-admin@hub:/config/interface/…/wireguard/peers/wg-peers/> edit peer spoke2
-admin@hub:/config/interface/…/wg-peers/peer/spoke2/> set allowed-ips 10.0.0.3/32
-admin@hub:/config/interface/…/wg-peers/peer/spoke2/> set allowed-ips 192.168.2.0/24
-admin@hub:/config/interface/…/wg-peers/peer/spoke2/> leave
+admin@hub:/config/interface/…/wireguard/peers/wg-peers/> edit peer spoke2
+admin@hub:/config/interface/…/wg-peers/peer/spoke2/> set allowed-ips 10.0.0.3/32
+admin@hub:/config/interface/…/wg-peers/peer/spoke2/> set allowed-ips 192.168.2.0/24
+admin@hub:/config/interface/…/wg-peers/peer/spoke2/> leave
 
 # Add routes for spoke networks
-admin@hub:/> configure
-admin@hub:/config/> edit routing control-plane-protocol static name default
-admin@hub:/config/routing/…/static/name/default/> set ipv4 route 192.168.1.0/24 wg0
-admin@hub:/config/routing/…/static/name/default/> set ipv4 route 192.168.2.0/24 wg0
-admin@hub:/config/routing/…/static/name/default/> leave
+admin@hub:/> configure
+admin@hub:/config/> edit routing control-plane-protocol static name default
+admin@hub:/config/routing/…/static/name/default/> set ipv4 route 192.168.1.0/24 wg0
+admin@hub:/config/routing/…/static/name/default/> set ipv4 route 192.168.2.0/24 wg0
+admin@hub:/config/routing/…/static/name/default/> leave
 admin@hub:/>
-```
+
**Spoke 1 configuration:** -``` -admin@spoke1:/> configure -admin@spoke1:/config/> edit interface wg0 -admin@spoke1:/config/interface/wg0/> set wireguard listen-port 51820 -admin@spoke1:/config/interface/wg0/> set wireguard private-key wg-spoke1 -admin@spoke1:/config/interface/wg0/> set ipv4 address 10.0.0.2 prefix-length 24 -admin@spoke1:/config/interface/wg0/> edit wireguard peers wg-peers peer hub -admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set endpoint 203.0.113.1 -admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set endpoint-port 51820 -admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set allowed-ips 10.0.0.1/32 -admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set allowed-ips 10.0.0.3/32 -admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set allowed-ips 192.168.0.0/24 -admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set allowed-ips 192.168.2.0/24 -admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set persistent-keepalive 25 -admin@spoke1:/config/interface/…/wg-peers/peer/hub/> leave -admin@spoke1:/> configure -admin@spoke1:/config/> edit routing control-plane-protocol static name default -admin@spoke1:/config/routing/…/static/name/default/> set ipv4 route 192.168.0.0/24 wg0 -admin@spoke1:/config/routing/…/static/name/default/> set ipv4 route 192.168.2.0/24 wg0 -admin@spoke1:/config/routing/…/static/name/default/> leave +
admin@spoke1:/> configure
+admin@spoke1:/config/> edit interface wg0
+admin@spoke1:/config/interface/wg0/> set wireguard listen-port 51820
+admin@spoke1:/config/interface/wg0/> set wireguard private-key wg-spoke1
+admin@spoke1:/config/interface/wg0/> set ipv4 address 10.0.0.2 prefix-length 24
+admin@spoke1:/config/interface/wg0/> edit wireguard peers wg-peers peer hub
+admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set endpoint 203.0.113.1
+admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set endpoint-port 51820
+admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set allowed-ips 10.0.0.1/32
+admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set allowed-ips 10.0.0.3/32
+admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set allowed-ips 192.168.0.0/24
+admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set allowed-ips 192.168.2.0/24
+admin@spoke1:/config/interface/…/wg-peers/peer/hub/> set persistent-keepalive 25
+admin@spoke1:/config/interface/…/wg-peers/peer/hub/> leave
+admin@spoke1:/> configure
+admin@spoke1:/config/> edit routing control-plane-protocol static name default
+admin@spoke1:/config/routing/…/static/name/default/> set ipv4 route 192.168.0.0/24 wg0
+admin@spoke1:/config/routing/…/static/name/default/> set ipv4 route 192.168.2.0/24 wg0
+admin@spoke1:/config/routing/…/static/name/default/> leave
 admin@spoke1:/>
-```
+
This configuration allows Spoke 1 to reach both the hub network (192.168.0.0/24) and Spoke 2's network (192.168.2.0/24) via the hub, enabling spoke-to-spoke @@ -319,9 +310,8 @@ communication through the central hub. The `persistent-keepalive` setting sends periodic packets to keep the tunnel active through NAT devices and firewalls: -``` -admin@example:/config/interface/…/wg-peers/peer/hub/> set persistent-keepalive 25 -``` +
admin@example:/config/interface/…/wg-peers/peer/hub/> set persistent-keepalive 25
+
This is particularly important when: @@ -340,21 +330,20 @@ for peers with public static IPs that initiate connections. WireGuard fully supports IPv6 for tunnel endpoints: -``` -admin@example:/> configure -admin@example:/config/> edit interface wg0 -admin@example:/config/interface/wg0/> set wireguard listen-port 51820 -admin@example:/config/interface/wg0/> set wireguard private-key wg-key -admin@example:/config/interface/wg0/> set ipv4 address 10.0.0.1 prefix-length 24 -admin@example:/config/interface/wg0/> set ipv6 address fd00::1 prefix-length 64 -admin@example:/config/interface/wg0/> edit wireguard peers wg-peers peer remote -admin@example:/config/interface/…/wg-peers/peer/remote/> set endpoint 2001:db8::2 -admin@example:/config/interface/…/wg-peers/peer/remote/> set endpoint-port 51820 -admin@example:/config/interface/…/wg-peers/peer/remote/> set allowed-ips 10.0.0.2/32 -admin@example:/config/interface/…/wg-peers/peer/remote/> set allowed-ips fd00::2/128 -admin@example:/config/interface/…/wg-peers/peer/remote/> leave +
admin@example:/> configure
+admin@example:/config/> edit interface wg0
+admin@example:/config/interface/wg0/> set wireguard listen-port 51820
+admin@example:/config/interface/wg0/> set wireguard private-key wg-key
+admin@example:/config/interface/wg0/> set ipv4 address 10.0.0.1 prefix-length 24
+admin@example:/config/interface/wg0/> set ipv6 address fd00::1 prefix-length 64
+admin@example:/config/interface/wg0/> edit wireguard peers wg-peers peer remote
+admin@example:/config/interface/…/wg-peers/peer/remote/> set endpoint 2001:db8::2
+admin@example:/config/interface/…/wg-peers/peer/remote/> set endpoint-port 51820
+admin@example:/config/interface/…/wg-peers/peer/remote/> set allowed-ips 10.0.0.2/32
+admin@example:/config/interface/…/wg-peers/peer/remote/> set allowed-ips fd00::2/128
+admin@example:/config/interface/…/wg-peers/peer/remote/> leave
 admin@example:/>
-```
+
WireGuard can carry both IPv4 and IPv6 traffic regardless of whether the tunnel endpoints use IPv4 or IPv6. @@ -363,13 +352,12 @@ tunnel endpoints use IPv4 or IPv6. Check WireGuard interface status and peer connections: -``` -admin@example:/> show interfaces +
admin@example:/> show interfaces
 wg0             wireguard  UP          2 peers (1 up)
                 ipv4                   10.0.0.1/24 (static)
                 ipv6                   fd00::1/64 (static)
 
-admin@example:/> show interfaces wg0
+admin@example:/> show interfaces wg0
 name                : wg0
 type                : wireguard
 index               : 12
@@ -389,7 +377,7 @@ peers               : 2
     latest handshake  : 2025-12-09T09:15:22+0000
     transfer tx       : 45120 bytes
     transfer rx       : 32768 bytes
-```
+
The connection status shows `UP` if a handshake occurred within the last 3 minutes, indicating an active tunnel. The `latest handshake` timestamp shows @@ -416,17 +404,16 @@ cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m= **Import the preshared key into the keystore:** -``` -admin@example:/> configure -admin@example:/config/> edit keystore symmetric-key wg-psk -admin@example:/config/keystore/symmetric-key/wg-psk/> set key-format wireguard-symmetric-key-format -admin@example:/config/keystore/symmetric-key/wg-psk/> set key cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m= -admin@example:/config/keystore/symmetric-key/wg-psk/> end -admin@example:/config/interface/wg0/> edit wireguard peers wg-peers peer remote -admin@example:/config/interface/…/wg-peers/peer/remote/> set preshared-key wg-psk -admin@example:/config/interface/…/wg-peers/peer/remote/> leave +
admin@example:/> configure
+admin@example:/config/> edit keystore symmetric-key wg-psk
+admin@example:/config/keystore/symmetric-key/wg-psk/> set key-format wireguard-symmetric-key-format
+admin@example:/config/keystore/symmetric-key/wg-psk/> set key cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=
+admin@example:/config/keystore/symmetric-key/wg-psk/> end
+admin@example:/config/interface/wg0/> edit wireguard peers wg-peers peer remote
+admin@example:/config/interface/…/wg-peers/peer/remote/> set preshared-key wg-psk
+admin@example:/config/interface/…/wg-peers/peer/remote/> leave
 admin@example:/>
-```
+
The preshared key must be securely shared between both peers and configured on both sides. diff --git a/doc/wifi.md b/doc/wifi.md index 3aa7d3f32..da47f85fb 100644 --- a/doc/wifi.md +++ b/doc/wifi.md @@ -90,7 +90,7 @@ Reboot when the radio becomes available. Before configuring WiFi interfaces, you must first configure the WiFi radio. Radios are automatically discovered and named `radio0`, `radio1`, etc. -### Country Code and Regulatory Compliance +### Country Code ⚠ The radio defaults to "00" for World domain, but some systems may ship with a factory default country code (typically "DE" for the BPi-R3). @@ -160,7 +160,7 @@ admin@example:/config/hardware/component/radio0/wifi-radio/> leave > TX power and channel width are automatically determined by the driver > based on regulatory constraints, PHY mode, and hardware capabilities. -### WiFi 6 (802.11ax) Support +### WiFi 6 Support WiFi 6 (802.11ax) is always enabled in AP mode on all bands, providing improved performance through features like OFDMA, BSS Coloring, and beamforming. @@ -247,7 +247,7 @@ Station mode connects to an existing Wi-Fi network. Before configuring station mode, follow the "Discovering Available Networks (Scanning)" section above to scan for available networks and identify the SSID you want to connect to. -### Step 1: Configure WiFi Password +### Step 1: Configure Password Create a keystore entry for your WiFi password (8-63 characters): @@ -344,7 +344,7 @@ admin@example:/config/interface/wifi0/> leave - `wpa3-personal`: WPA3-SAE (more secure, requires WPA3-capable clients) - `wpa2-wpa3-personal`: Mixed mode (maximum compatibility) -### Hidden Network (SSID Hiding) +### SSID Hiding To create a hidden network that doesn't broadcast its SSID: From d938d48975f7297c27fe6539b714fd6e3ca557b8 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 24 Jan 2026 16:00:26 +0100 Subject: [PATCH 28/29] doc: update ChangeLog Signed-off-by: Joachim Wiberg --- doc/ChangeLog.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index 610010e7b..7e1ee2e25 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -21,10 +21,9 @@ All notable changes to the project are documented in this file. ### Changes -- Upgrade Linux kernel to 6.18.7 (LTS) Noteworthy changes and additions in this release are marked below in bold text. -- Upgrade **Linux kernel to 6.18.6** (LTS) +- Upgrade **Linux kernel to 6.18.7** (LTS) - Upgrade Buildroot to 2025.02.10 (LTS) - Upgrade libyang to 4.2.2 - Upgrade sysrepo to 4.2.10 @@ -59,9 +58,11 @@ Noteworthy changes and additions in this release are marked below in bold text. details, see the updated system configuration documentation, as well as a new dedicated NACM configuration guide - New `show nacm` admin-exec command to inspect access control rules +- CLI now supports Ctrl-@ and Ctrl-w/Meta-w to mark and copy test regions - CLI now uses `copy` and `rpc` tools instead of deprecated `sysrepocfg`. The latter now also require the use of `sudo` for `admin` level users - Enhanced `copy` command with XPath filtering support +- Kernel now announces details of new USB devices ### Fixes From 68a638c0d566fb30e5ca4d6104a9cf4e17a0ad41 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 25 Jan 2026 00:08:53 +0100 Subject: [PATCH 29/29] Slight refresh Signed-off-by: Joachim Wiberg --- README.md | 53 +++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 10bd5b107..dd1511d3e 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,12 @@ if something goes wrong. Deploy once, trust forever. **🤝 Friendly** Actually easy to use. Auto-generated CLI from standard YANG models comes -with built-in help for every command — just hit `?` or TAB for -context-aware assistance. Familiar NETCONF/RESTCONF APIs and -[comprehensive documentation][4] mean you're never stuck. Whether -you're learning networking or managing enterprise infrastructure. +with built-in help for every command — just hit ? or +TAB for context-aware assistance. + +Familiar NETCONF & RESTCONF APIs and [comprehensive documentation][4] +mean you're never stuck. Whether you're learning networking or managing +enterprise infrastructure. **🛡️ Secure** Built with security as a foundation, not an afterthought. Minimal @@ -53,27 +55,24 @@ your device, your rules. Consistent tooling from development to production deployment. How about a digital twin using raw Qemu or [GNS3](https://gns3.com/infix)! -## See It In Action +## Quick Example Configure an interface in seconds - the CLI guides you with built-in help: -
Click Here for an example CLI Session - -```bash -admin@infix-12-34-56:/> configure -admin@infix-12-34-56:/config/> edit interface eth0 -admin@infix-12-34-56:/config/interface/eth0/> set ipv4 - address autoconf bind-ni-name enabled - forwarding mtu neighbor -admin@infix-12-34-56:/config/interface/eth0/> set ipv4 address 192.168.2.200 prefix-length 24 -admin@infix-12-34-56:/config/interface/eth0/> show +
admin@infix-12-34-56:/> configure
+admin@infix-12-34-56:/config/> edit interface eth0
+admin@infix-12-34-56:/config/interface/eth0/> set ipv4 TAB
+      address     autoconf      bind-ni-name     dhcp 
+      enabled     forwarding    mtu              neighbor
+admin@infix-12-34-56:/config/interface/eth0/> set ipv4 address 192.168.2.200 prefix-length 24
+admin@infix-12-34-56:/config/interface/eth0/> show
 type ethernet;
 ipv4 {
   address 192.168.2.200 {
     prefix-length 24;
   }
 }
-admin@infix-12-34-56:/config/interface/eth0/> diff
+admin@infix-12-34-56:/config/interface/eth0/> diff
 interfaces {
   interface eth0 {
 +    ipv4 {
@@ -83,25 +82,23 @@ interfaces {
 +    }
   }
 }
-admin@infix-12-34-56:/config/interface/eth0/> leave
-admin@infix-12-34-56:/> show interfaces
-INTERFACE       PROTOCOL   STATE       DATA
+admin@infix-12-34-56:/config/interface/eth0/> leave
+admin@infix-12-34-56:/> show interfaces
+INTERFACE       PROTOCOL   STATE       DATA                                  
 eth0            ethernet   UP          52:54:00:12:34:56
                 ipv4                   192.168.2.200/24 (static)
                 ipv6                   fe80::5054:ff:fe12:3456/64 (link-layer)
 lo              ethernet   UP          00:00:00:00:00:00
                 ipv4                   127.0.0.1/8 (static)
                 ipv6                   ::1/128 (static)
-admin@infix-12-34-56:/> copy running-config startup-config
-```
-
-Notice how TAB completion shows available options, `show` displays
-current config, and `diff` shows exactly what changed before you
-commit your changes with the `leave` command.
+admin@infix-12-34-56:/> copy running startup
+
-
+Notice how TAB completion shows available options, `show` +displays current config, and `diff` shows exactly what changed before +you commit your changes with the `leave` command. -> [Full CLI documentation →][3] +For more information, see [CLI documentation][3]. ## Get Started @@ -111,7 +108,7 @@ containers for any custom functionality you need. ### Supported Platforms -- **Raspberry Pi 4B** - Perfect for home labs, learning, and prototyping +- **Raspberry Pi 2B/3B/4B/CM4** - Perfect for home labs, learning, and prototyping - **Banana Pi-R3** - Your next home router and gateway - **NanoPi R2S** - Compact dual-port router in a tiny package - **x86_64** - Run in VMs or on mini PCs for development and testing