mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-26 18:53:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f372dffe6 |
@@ -12,6 +12,10 @@ on:
|
||||
- bananapi-bpi-r3
|
||||
- friendlyarm-nanopi-r2s
|
||||
default: 'raspberrypi-rpi64'
|
||||
use_latest_release:
|
||||
description: 'Use latest release artifacts instead of workflow artifacts'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
create-image:
|
||||
@@ -50,19 +54,19 @@ jobs:
|
||||
run: |
|
||||
case "${{ inputs.board }}" in
|
||||
raspberrypi-rpi64)
|
||||
echo "BOOTLOADER=rpi64-boot" >> $GITHUB_ENV
|
||||
echo "ARCH=aarch64" >> $GITHUB_ENV
|
||||
echo "BOOTLOADER=rpi64_boot" >> $GITHUB_ENV
|
||||
echo "TARGET=aarch64" >> $GITHUB_ENV
|
||||
echo "BUILD_EMMC=false" >> $GITHUB_ENV
|
||||
;;
|
||||
bananapi-bpi-r3)
|
||||
echo "BOOTLOADER_SD=bpi-r3-sd-boot" >> $GITHUB_ENV
|
||||
echo "BOOTLOADER_EMMC=bpi-r3-emmc-boot" >> $GITHUB_ENV
|
||||
echo "ARCH=aarch64" >> $GITHUB_ENV
|
||||
echo "BOOTLOADER_SD=bpi_r3_sd_boot" >> $GITHUB_ENV
|
||||
echo "BOOTLOADER_EMMC=bpi_r3_emmc_boot" >> $GITHUB_ENV
|
||||
echo "TARGET=aarch64" >> $GITHUB_ENV
|
||||
echo "BUILD_EMMC=true" >> $GITHUB_ENV
|
||||
;;
|
||||
friendlyarm-nanopi-r2s)
|
||||
echo "BOOTLOADER=nanopi-r2s-boot" >> $GITHUB_ENV
|
||||
echo "ARCH=aarch64" >> $GITHUB_ENV
|
||||
echo "BOOTLOADER=nanopi_r2s_boot" >> $GITHUB_ENV
|
||||
echo "TARGET=aarch64" >> $GITHUB_ENV
|
||||
echo "BUILD_EMMC=false" >> $GITHUB_ENV
|
||||
;;
|
||||
*)
|
||||
@@ -70,7 +74,7 @@ jobs:
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
echo "Arch: $ARCH for board: ${{ inputs.board }}"
|
||||
echo "Target: $TARGET for board: ${{ inputs.board }}"
|
||||
if [ "$BUILD_EMMC" = "true" ]; then
|
||||
echo "Building both SD and eMMC images"
|
||||
echo "SD Bootloader: $BOOTLOADER_SD"
|
||||
@@ -81,12 +85,16 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Download bootloader artifacts
|
||||
if: ${{ !inputs.use_latest_release }}
|
||||
run: |
|
||||
# Download bootloader from latest-boot release tag
|
||||
# Download from latest bootloader build workflow on main branch
|
||||
gh run list --workflow=build-boot.yml --branch=main --limit=1 --status=success --json databaseId --jq '.[0].databaseId' > latest_boot_run_id
|
||||
BOOT_RUN_ID=$(cat latest_boot_run_id)
|
||||
|
||||
if [ "$BUILD_EMMC" = "true" ]; then
|
||||
# Download both SD and eMMC bootloaders for boards that support both
|
||||
echo "Downloading SD bootloader: ${BOOTLOADER_SD}"
|
||||
gh release download latest-boot --pattern "*${BOOTLOADER_SD}*" --dir temp_bootloader_sd/
|
||||
gh run download ${BOOT_RUN_ID} --name artifact-${BOOTLOADER_SD} --dir temp_bootloader_sd/
|
||||
mkdir -p output_sd/images
|
||||
cd temp_bootloader_sd/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output_sd/images/
|
||||
@@ -94,7 +102,7 @@ jobs:
|
||||
rm -rf temp_bootloader_sd/
|
||||
|
||||
echo "Downloading eMMC bootloader: ${BOOTLOADER_EMMC}"
|
||||
gh release download latest-boot --pattern "*${BOOTLOADER_EMMC}*" --dir temp_bootloader_emmc/
|
||||
gh run download ${BOOT_RUN_ID} --name artifact-${BOOTLOADER_EMMC} --dir temp_bootloader_emmc/
|
||||
mkdir -p output_emmc/images
|
||||
cd temp_bootloader_emmc/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output_emmc/images/
|
||||
@@ -107,7 +115,7 @@ jobs:
|
||||
ls -la output_emmc/images/
|
||||
else
|
||||
# Single bootloader for boards that only support SD
|
||||
gh release download latest-boot --pattern "*${BOOTLOADER}*" --dir temp_bootloader/
|
||||
gh run download ${BOOT_RUN_ID} --name artifact-${BOOTLOADER} --dir temp_bootloader/
|
||||
|
||||
# Extract bootloader directly to output/images
|
||||
cd temp_bootloader/
|
||||
@@ -122,6 +130,7 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Download Infix artifacts
|
||||
if: ${{ !inputs.use_latest_release }}
|
||||
run: |
|
||||
# Download from latest Kernelkit Trigger workflow for main branch
|
||||
gh run list --workflow=164295764 --branch=main --limit=1 --status=success --json databaseId --jq '.[0].databaseId' > latest_infix_run_id
|
||||
@@ -129,7 +138,7 @@ jobs:
|
||||
|
||||
if [ "$BUILD_EMMC" = "true" ]; then
|
||||
# Copy Infix artifacts to both SD and eMMC output directories
|
||||
gh run download ${INFIX_RUN_ID} --name artifact-${ARCH} --dir temp_infix/
|
||||
gh run download ${INFIX_RUN_ID} --name artifact-${TARGET} --dir temp_infix/
|
||||
|
||||
cd temp_infix/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output_sd/images/
|
||||
@@ -143,7 +152,7 @@ jobs:
|
||||
ls -la output_emmc/images/
|
||||
else
|
||||
# Single output directory for SD-only boards
|
||||
gh run download ${INFIX_RUN_ID} --name artifact-${ARCH} --dir temp_infix/
|
||||
gh run download ${INFIX_RUN_ID} --name artifact-${TARGET} --dir temp_infix/
|
||||
|
||||
# Extract Infix directly to output/images
|
||||
cd temp_infix/
|
||||
@@ -157,6 +166,58 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Download from latest releases
|
||||
if: ${{ inputs.use_latest_release }}
|
||||
run: |
|
||||
if [ "$BUILD_EMMC" = "true" ]; then
|
||||
# Download both SD and eMMC bootloaders
|
||||
gh release download latest-boot --pattern "*${BOOTLOADER_SD}*" --dir temp_bootloader_sd/
|
||||
mkdir -p output_sd/images
|
||||
cd temp_bootloader_sd/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output_sd/images/
|
||||
cd ../
|
||||
rm -rf temp_bootloader_sd/
|
||||
|
||||
gh release download latest-boot --pattern "*${BOOTLOADER_EMMC}*" --dir temp_bootloader_emmc/
|
||||
mkdir -p output_emmc/images
|
||||
cd temp_bootloader_emmc/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output_emmc/images/
|
||||
cd ../
|
||||
rm -rf temp_bootloader_emmc/
|
||||
|
||||
# Download Infix once and extract to both directories
|
||||
gh release download latest --pattern "*${TARGET}*" --dir temp_infix/
|
||||
cd temp_infix/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output_sd/images/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output_emmc/images/
|
||||
cd ../
|
||||
rm -rf temp_infix/
|
||||
|
||||
echo "SD files extracted to output_sd/images:"
|
||||
ls -la output_sd/images/
|
||||
echo "eMMC files extracted to output_emmc/images:"
|
||||
ls -la output_emmc/images/
|
||||
else
|
||||
# Download latest bootloader release
|
||||
gh release download latest-boot --pattern "*${BOOTLOADER}*" --dir temp_bootloader/
|
||||
cd temp_bootloader/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output/images/
|
||||
cd ../
|
||||
rm -rf temp_bootloader/
|
||||
|
||||
# Download latest Infix release
|
||||
gh release download latest --pattern "*${TARGET}*" --dir temp_infix/
|
||||
cd temp_infix/
|
||||
tar -xzf *.tar.gz --strip-components=1 -C ../output/images/
|
||||
cd ../
|
||||
rm -rf temp_infix/
|
||||
|
||||
echo "All files extracted to output/images:"
|
||||
ls -la output/images/
|
||||
fi
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Verify extracted files
|
||||
run: |
|
||||
if [ "$BUILD_EMMC" = "true" ]; then
|
||||
@@ -188,7 +249,7 @@ jobs:
|
||||
export BR2_EXTERNAL_INFIX_PATH=$PWD
|
||||
export RELEASE=""
|
||||
export INFIX_ID="infix"
|
||||
./utils/mkimage.sh -t sdcard ${{ inputs.board }}
|
||||
./utils/mkimage.sh ${{ inputs.board }}
|
||||
fi
|
||||
|
||||
- name: Create eMMC image
|
||||
@@ -286,11 +347,10 @@ jobs:
|
||||
# SD Card & eMMC Image Build Complete! 🚀
|
||||
|
||||
**Board:** ${{ inputs.board }}
|
||||
**Arch:** ${{ env.ARCH }}
|
||||
**Target:** ${{ env.TARGET }}
|
||||
**SD Bootloader:** ${{ env.BOOTLOADER_SD }}
|
||||
**eMMC Bootloader:** ${{ env.BOOTLOADER_EMMC }}
|
||||
**Bootloader Source:** latest-boot release
|
||||
**Infix Source:** Latest workflow run on main
|
||||
**Artifact Source:** ${{ inputs.use_latest_release && 'Latest Release' || 'Latest Workflow Run' }}
|
||||
|
||||
## Created Images
|
||||
$(find output/images/ -name "*.img" -o -name "*.img.bmap" | xargs ls -lh 2>/dev/null | awk '{print "- " $9 " (" $5 ")"}' || echo "- No images found")
|
||||
@@ -303,10 +363,9 @@ jobs:
|
||||
# SD Card Image Build Complete! 🚀
|
||||
|
||||
**Board:** ${{ inputs.board }}
|
||||
**Arch:** ${{ env.ARCH }}
|
||||
**Target:** ${{ env.TARGET }}
|
||||
**Bootloader:** ${{ env.BOOTLOADER }}
|
||||
**Bootloader Source:** latest-boot release
|
||||
**Infix Source:** Latest workflow run on main
|
||||
**Artifact Source:** ${{ inputs.use_latest_release && 'Latest Release' || 'Latest Workflow Run' }}
|
||||
|
||||
## Created Images
|
||||
$(find output/images/ -name "*.img" -o -name "*.img.bmap" | xargs ls -lh 2>/dev/null | awk '{print "- " $9 " (" $5 ")"}' || echo "- No images found")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Check Kernel 6.18 Release
|
||||
name: Check Kernel 6.12 Release
|
||||
|
||||
on:
|
||||
schedule:
|
||||
@@ -17,12 +17,12 @@ jobs:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.KERNEL_UPDATE_TOKEN }}
|
||||
|
||||
- name: Fetch kernel.org and check for 6.18 release
|
||||
- name: Fetch kernel.org and check for 6.12 release
|
||||
id: check
|
||||
run: |
|
||||
set -e -o pipefail
|
||||
# Fetch the kernel.org frontpage and extract 6.18 version
|
||||
CURRENT_VERSION=$(curl -s https://www.kernel.org/ | grep -oP '6\.18\.\d+' | head -n1)
|
||||
# Fetch the kernel.org frontpage and extract 6.12 version
|
||||
CURRENT_VERSION=$(curl -s https://www.kernel.org/ | grep -oP '6\.12\.\d+' | head -n1)
|
||||
|
||||
if [ -z "$CURRENT_VERSION" ]; then
|
||||
echo "Failed to fetch kernel version"
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
fi
|
||||
|
||||
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "Current 6.18 kernel version: $CURRENT_VERSION"
|
||||
echo "Current 6.12 kernel version: $CURRENT_VERSION"
|
||||
|
||||
# Get the version from infix defconfig
|
||||
INFIX_VERSION=$(grep 'BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=' configs/aarch64_defconfig | cut -d'"' -f2)
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
echo "PR already exists for kernel $CURRENT_VERSION, skipping"
|
||||
else
|
||||
echo "new_release=true" >> $GITHUB_OUTPUT
|
||||
echo "🎉 New 6.18 kernel released: $CURRENT_VERSION (infix version: $INFIX_VERSION)"
|
||||
echo "🎉 New 6.12 kernel released: $CURRENT_VERSION (infix version: $INFIX_VERSION)"
|
||||
fi
|
||||
else
|
||||
echo "new_release=false" >> $GITHUB_OUTPUT
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
BRANCH_NAME: ${{ steps.branch.outputs.name }}
|
||||
run: |
|
||||
set -e -o pipefail
|
||||
./utils/kernel-upgrade.sh linux 6.18 "$BRANCH_NAME"
|
||||
./utils/kernel-upgrade.sh linux "$BRANCH_NAME"
|
||||
|
||||
- name: Create pull request
|
||||
if: steps.check.outputs.new_release == 'true'
|
||||
|
||||
@@ -104,7 +104,11 @@ jobs:
|
||||
|
||||
- name: Extract ChangeLog entry ...
|
||||
run: |
|
||||
cat doc/ChangeLog.md | ./utils/extract-changelog.sh > release.md
|
||||
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 release.md
|
||||
|
||||
- uses: ncipollo/release-action@v1
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
*~
|
||||
.claude
|
||||
.gdb_history
|
||||
.claude
|
||||
/.backup
|
||||
/.ccache
|
||||
/dl
|
||||
@@ -11,4 +10,3 @@
|
||||
/test/.log
|
||||
/local.mk
|
||||
/test/spec/Readme.adoc
|
||||
|
||||
|
||||
@@ -16,12 +16,10 @@ 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 <kbd>?</kbd> or
|
||||
<kbd>TAB</kbd> 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
|
||||
@@ -55,24 +53,27 @@ 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)!
|
||||
|
||||
## Quick Example
|
||||
## See It In Action
|
||||
|
||||
Configure an interface in seconds - the CLI guides you with built-in help:
|
||||
|
||||
<pre><code>admin@infix-12-34-56:/> <b>configure</b>
|
||||
admin@infix-12-34-56:/config/> <b>edit interface eth0</b>
|
||||
admin@infix-12-34-56:/config/interface/eth0/> <b>set ipv4</b> <kbd>TAB</kbd>
|
||||
address autoconf bind-ni-name dhcp
|
||||
enabled forwarding mtu neighbor
|
||||
admin@infix-12-34-56:/config/interface/eth0/> <b>set ipv4 address 192.168.2.200 prefix-length 24</b>
|
||||
admin@infix-12-34-56:/config/interface/eth0/> <b>show</b>
|
||||
<details><summary><b>Click Here for an example CLI Session</b></summary>
|
||||
|
||||
```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 <TAB>
|
||||
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
|
||||
type ethernet;
|
||||
ipv4 {
|
||||
address 192.168.2.200 {
|
||||
prefix-length 24;
|
||||
}
|
||||
}
|
||||
admin@infix-12-34-56:/config/interface/eth0/> <b>diff</b>
|
||||
admin@infix-12-34-56:/config/interface/eth0/> diff
|
||||
interfaces {
|
||||
interface eth0 {
|
||||
+ ipv4 {
|
||||
@@ -82,23 +83,25 @@ interfaces {
|
||||
+ }
|
||||
}
|
||||
}
|
||||
admin@infix-12-34-56:/config/interface/eth0/> <b>leave</b>
|
||||
admin@infix-12-34-56:/> <b>show interfaces</b>
|
||||
<u>INTERFACE PROTOCOL STATE DATA </u>
|
||||
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:/> <b>copy running startup</b>
|
||||
</code></pre>
|
||||
admin@infix-12-34-56:/> copy running-config startup-config
|
||||
```
|
||||
|
||||
Notice how <kbd>TAB</kbd> completion shows available options, `show`
|
||||
displays current config, and `diff` shows exactly what changed before
|
||||
you commit your changes with the `leave` command.
|
||||
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.
|
||||
|
||||
For more information, see [CLI documentation][3].
|
||||
</details>
|
||||
|
||||
> [Full CLI documentation →][3]
|
||||
|
||||
## Get Started
|
||||
|
||||
@@ -108,7 +111,7 @@ containers for any custom functionality you need.
|
||||
|
||||
### Supported Platforms
|
||||
|
||||
- **Raspberry Pi 2B/3B/4B/CM4** - Perfect for home labs, learning, and prototyping
|
||||
- **Raspberry Pi 4B** - 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
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
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
|
||||
@@ -31,11 +31,14 @@ CONFIG_SCHED_AUTOGROUP=y
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_PROFILING=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_ARCH_MULTI_V6=y
|
||||
CONFIG_ARCH_MULTI_V7=y
|
||||
CONFIG_ARCH_VIRT=y
|
||||
CONFIG_ARCH_BCM=y
|
||||
CONFIG_ARCH_BCM2835=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_CPU_FREQ=y
|
||||
CONFIG_CPU_FREQ_STAT=y
|
||||
CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE=y
|
||||
@@ -44,6 +47,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_CPUFREQ_DT=y
|
||||
CONFIG_ARM_RASPBERRYPI_CPUFREQ=y
|
||||
CONFIG_AEABI=y
|
||||
CONFIG_VFP=y
|
||||
CONFIG_NEON=y
|
||||
CONFIG_KERNEL_MODE_NEON=y
|
||||
@@ -74,6 +78,7 @@ CONFIG_IP_MROUTE=y
|
||||
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
|
||||
CONFIG_IP_PIMSM_V1=y
|
||||
CONFIG_IP_PIMSM_V2=y
|
||||
CONFIG_SYN_COOKIES=y
|
||||
CONFIG_NET_IPVTI=m
|
||||
CONFIG_NET_FOU_IP_TUNNELS=y
|
||||
CONFIG_IPV6_SIT=m
|
||||
@@ -89,31 +94,12 @@ CONFIG_BRIDGE_NETFILTER=y
|
||||
CONFIG_NETFILTER_NETLINK_QUEUE=y
|
||||
CONFIG_NETFILTER_NETLINK_LOG=y
|
||||
CONFIG_NF_CONNTRACK=y
|
||||
CONFIG_NF_CONNTRACK_ZONES=y
|
||||
CONFIG_NF_CONNTRACK_PROCFS=y
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CONNTRACK_TIMEOUT=y
|
||||
CONFIG_NF_CONNTRACK_TIMESTAMP=y
|
||||
CONFIG_NF_CONNTRACK_AMANDA=y
|
||||
CONFIG_NF_CONNTRACK_FTP=y
|
||||
CONFIG_NF_CONNTRACK_H323=y
|
||||
CONFIG_NF_CONNTRACK_IRC=y
|
||||
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
|
||||
CONFIG_NF_CONNTRACK_SNMP=y
|
||||
CONFIG_NF_CONNTRACK_PPTP=y
|
||||
CONFIG_NF_CONNTRACK_SANE=y
|
||||
CONFIG_NF_CONNTRACK_SIP=y
|
||||
CONFIG_NF_CONNTRACK_TFTP=y
|
||||
CONFIG_NF_CT_NETLINK=y
|
||||
CONFIG_NF_CT_NETLINK_TIMEOUT=y
|
||||
CONFIG_NF_CT_NETLINK_HELPER=y
|
||||
CONFIG_NETFILTER_NETLINK_GLUE_CT=y
|
||||
CONFIG_NF_TABLES=y
|
||||
CONFIG_NF_TABLES_INET=y
|
||||
CONFIG_NF_TABLES_NETDEV=y
|
||||
CONFIG_NFT_NUMGEN=y
|
||||
CONFIG_NFT_CT=m
|
||||
CONFIG_NFT_FLOW_OFFLOAD=y
|
||||
CONFIG_NFT_CONNLIMIT=m
|
||||
CONFIG_NFT_LOG=m
|
||||
CONFIG_NFT_LIMIT=m
|
||||
@@ -122,22 +108,15 @@ CONFIG_NFT_REDIR=m
|
||||
CONFIG_NFT_NAT=m
|
||||
CONFIG_NFT_TUNNEL=m
|
||||
CONFIG_NFT_QUEUE=m
|
||||
CONFIG_NFT_QUOTA=y
|
||||
CONFIG_NFT_REJECT=m
|
||||
CONFIG_NFT_COMPAT=m
|
||||
CONFIG_NFT_HASH=m
|
||||
CONFIG_NFT_FIB_INET=y
|
||||
CONFIG_NFT_XFRM=m
|
||||
CONFIG_NFT_SOCKET=m
|
||||
CONFIG_NFT_OSF=m
|
||||
CONFIG_NFT_TPROXY=y
|
||||
CONFIG_NFT_SYNPROXY=y
|
||||
CONFIG_NFT_DUP_NETDEV=m
|
||||
CONFIG_NFT_FWD_NETDEV=m
|
||||
CONFIG_NFT_FIB_NETDEV=y
|
||||
CONFIG_NFT_REJECT_NETDEV=m
|
||||
CONFIG_NF_FLOW_TABLE_INET=y
|
||||
CONFIG_NF_FLOW_TABLE=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
|
||||
CONFIG_NETFILTER_XT_TARGET_LOG=m
|
||||
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
|
||||
@@ -154,58 +133,29 @@ CONFIG_NETFILTER_XT_MATCH_MAC=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MARK=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
|
||||
CONFIG_IP_SET=y
|
||||
CONFIG_IP_SET_BITMAP_IP=y
|
||||
CONFIG_IP_SET_BITMAP_IPMAC=y
|
||||
CONFIG_IP_SET_BITMAP_PORT=y
|
||||
CONFIG_IP_SET_HASH_IP=y
|
||||
CONFIG_IP_SET_HASH_IPMARK=y
|
||||
CONFIG_IP_SET_HASH_IPPORT=y
|
||||
CONFIG_IP_SET_HASH_IPPORTIP=y
|
||||
CONFIG_IP_SET_HASH_IPPORTNET=y
|
||||
CONFIG_IP_SET_HASH_IPMAC=y
|
||||
CONFIG_IP_SET_HASH_MAC=y
|
||||
CONFIG_IP_SET_HASH_NETPORTNET=y
|
||||
CONFIG_IP_SET_HASH_NET=y
|
||||
CONFIG_IP_SET_HASH_NETNET=y
|
||||
CONFIG_IP_SET_HASH_NETPORT=y
|
||||
CONFIG_IP_SET_HASH_NETIFACE=y
|
||||
CONFIG_IP_SET_LIST_SET=y
|
||||
CONFIG_NFT_DUP_IPV4=y
|
||||
CONFIG_NFT_FIB_IPV4=y
|
||||
CONFIG_NF_TABLES_ARP=y
|
||||
CONFIG_NF_LOG_ARP=y
|
||||
CONFIG_NF_LOG_IPV4=y
|
||||
CONFIG_IP_NF_IPTABLES=m
|
||||
CONFIG_IP_NF_MATCH_AH=m
|
||||
CONFIG_IP_NF_MATCH_ECN=m
|
||||
CONFIG_IP_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP_NF_MATCH_TTL=m
|
||||
CONFIG_IP_NF_FILTER=m
|
||||
CONFIG_IP_NF_TARGET_REJECT=m
|
||||
CONFIG_IP_NF_TARGET_SYNPROXY=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_ARP_MANGLE=m
|
||||
CONFIG_NFT_DUP_IPV6=y
|
||||
CONFIG_NFT_FIB_IPV6=y
|
||||
CONFIG_IP_NF_NAT=m
|
||||
CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP6_NF_IPTABLES=m
|
||||
CONFIG_IP6_NF_MATCH_AH=m
|
||||
CONFIG_IP6_NF_MATCH_EUI64=m
|
||||
CONFIG_IP6_NF_MATCH_FRAG=m
|
||||
CONFIG_IP6_NF_MATCH_OPTS=m
|
||||
CONFIG_IP6_NF_MATCH_HL=m
|
||||
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
|
||||
CONFIG_IP6_NF_MATCH_MH=m
|
||||
CONFIG_IP6_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP6_NF_MATCH_RT=m
|
||||
CONFIG_IP6_NF_MATCH_SRH=m
|
||||
CONFIG_IP6_NF_FILTER=m
|
||||
CONFIG_IP6_NF_TARGET_REJECT=m
|
||||
CONFIG_IP6_NF_TARGET_SYNPROXY=m
|
||||
CONFIG_IP6_NF_RAW=m
|
||||
CONFIG_IP6_NF_NAT=m
|
||||
CONFIG_IP6_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP6_NF_TARGET_NPT=m
|
||||
CONFIG_NF_TABLES_BRIDGE=m
|
||||
CONFIG_NFT_BRIDGE_META=m
|
||||
CONFIG_NFT_BRIDGE_REJECT=m
|
||||
CONFIG_NF_CONNTRACK_BRIDGE=m
|
||||
CONFIG_BRIDGE_NF_EBTABLES=m
|
||||
CONFIG_BRIDGE_EBT_BROUTE=m
|
||||
CONFIG_BRIDGE_EBT_T_FILTER=m
|
||||
CONFIG_BRIDGE_EBT_T_NAT=m
|
||||
CONFIG_BRIDGE_EBT_802_3=m
|
||||
CONFIG_BRIDGE_EBT_ARP=m
|
||||
CONFIG_BRIDGE_EBT_IP=m
|
||||
@@ -244,16 +194,16 @@ CONFIG_NET_MPLS_GSO=y
|
||||
CONFIG_MPLS_ROUTING=m
|
||||
CONFIG_MPLS_IPTUNNEL=m
|
||||
CONFIG_NET_PKTGEN=y
|
||||
CONFIG_CFG80211=m
|
||||
CONFIG_MAC80211=m
|
||||
CONFIG_RFKILL=y
|
||||
# CONFIG_WIRELESS is not set
|
||||
CONFIG_NET_9P=y
|
||||
CONFIG_NET_9P_VIRTIO=y
|
||||
CONFIG_LWTUNNEL=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_PCI_IOV=y
|
||||
CONFIG_PCI_AARDVARK=y
|
||||
CONFIG_PCI_HOST_GENERIC=y
|
||||
CONFIG_PCIE_ARMADA_8K=y
|
||||
CONFIG_UEVENT_HELPER=y
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
CONFIG_DEVTMPFS=y
|
||||
@@ -271,6 +221,7 @@ CONFIG_BLK_DEV_NVME=y
|
||||
CONFIG_SRAM=y
|
||||
CONFIG_EEPROM_AT24=y
|
||||
# CONFIG_SCSI_PROC_FS is not set
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_SCSI_SAS_LIBSAS=y
|
||||
CONFIG_SCSI_SAS_ATA=y
|
||||
@@ -279,6 +230,7 @@ CONFIG_ATA=y
|
||||
CONFIG_SATA_AHCI=y
|
||||
CONFIG_SATA_MOBILE_LPM_POLICY=0
|
||||
CONFIG_SATA_AHCI_PLATFORM=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
CONFIG_PATA_OF_PLATFORM=y
|
||||
CONFIG_MD=y
|
||||
CONFIG_BLK_DEV_DM=y
|
||||
@@ -306,6 +258,8 @@ CONFIG_SMSC911X=y
|
||||
CONFIG_USB_LAN78XX=y
|
||||
CONFIG_USB_USBNET=y
|
||||
CONFIG_USB_NET_SMSC95XX=y
|
||||
CONFIG_BRCMFMAC=m
|
||||
CONFIG_ZD1211RW=m
|
||||
CONFIG_INPUT_MOUSEDEV=m
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
@@ -319,19 +273,22 @@ CONFIG_SERIAL_8250_BCM2835AUX=y
|
||||
CONFIG_SERIAL_AMBA_PL011=y
|
||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||
CONFIG_SERIAL_DEV_BUS=y
|
||||
CONFIG_TTY_PRINTK=y
|
||||
CONFIG_HVC_DRIVER=y
|
||||
CONFIG_VIRTIO_CONSOLE=y
|
||||
CONFIG_I2C_CHARDEV=y
|
||||
CONFIG_I2C_BCM2835=m
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_BCM2835=y
|
||||
CONFIG_SPI_BCM2835AUX=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_SENSORS_RASPBERRYPI_HWMON=m
|
||||
CONFIG_THERMAL=y
|
||||
CONFIG_BCM2711_THERMAL=y
|
||||
CONFIG_BCM2835_THERMAL=m
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_I6300ESB_WDT=y
|
||||
CONFIG_BCM2835_WDT=y
|
||||
CONFIG_I6300ESB_WDT=y
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
@@ -339,12 +296,12 @@ CONFIG_REGULATOR_GPIO=y
|
||||
CONFIG_MEDIA_SUPPORT=y
|
||||
CONFIG_DRM=y
|
||||
CONFIG_DRM_LOAD_EDID_FIRMWARE=y
|
||||
CONFIG_DRM_SIMPLEDRM=y
|
||||
CONFIG_DRM_PANEL_SIMPLE=m
|
||||
CONFIG_DRM_TOSHIBA_TC358762=m
|
||||
CONFIG_DRM_V3D=m
|
||||
CONFIG_DRM_VC4=m
|
||||
CONFIG_DRM_VC4_HDMI_CEC=y
|
||||
CONFIG_DRM_SIMPLEDRM=y
|
||||
CONFIG_FB=y
|
||||
CONFIG_BACKLIGHT_CLASS_DEVICE=y
|
||||
CONFIG_SOUND=y
|
||||
@@ -353,7 +310,6 @@ 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
|
||||
@@ -387,6 +343,7 @@ CONFIG_VIRTIO_INPUT=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
CONFIG_STAGING=y
|
||||
CONFIG_SND_BCM2835=m
|
||||
CONFIG_VIDEO_BCM2835=m
|
||||
CONFIG_CLK_RASPBERRYPI=y
|
||||
CONFIG_MAILBOX=y
|
||||
CONFIG_BCM2835_MBOX=y
|
||||
@@ -395,6 +352,8 @@ CONFIG_RASPBERRYPI_POWER=y
|
||||
CONFIG_PWM=y
|
||||
CONFIG_PWM_BCM2835=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_BTRFS_FS=y
|
||||
CONFIG_BTRFS_FS_POSIX_ACL=y
|
||||
CONFIG_FANOTIFY=y
|
||||
@@ -417,6 +376,8 @@ CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_CRYPTO_CCM=y
|
||||
CONFIG_CRYPTO_GCM=y
|
||||
# CONFIG_XZ_DEC_ARM is not set
|
||||
# CONFIG_XZ_DEC_ARMTHUMB is not set
|
||||
CONFIG_DMA_CMA=y
|
||||
CONFIG_CMA_SIZE_MBYTES=32
|
||||
CONFIG_PRINTK_TIME=y
|
||||
@@ -426,13 +387,9 @@ CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_PANIC_ON_OOPS=y
|
||||
CONFIG_PANIC_TIMEOUT=20
|
||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
|
||||
CONFIG_HARDLOCKUP_DETECTOR=y
|
||||
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
|
||||
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
|
||||
CONFIG_WQ_WATCHDOG=y
|
||||
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
|
||||
CONFIG_TEST_LOCKUP=m
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
# CONFIG_RCU_TRACE is not set
|
||||
CONFIG_FUNCTION_TRACER=y
|
||||
# CONFIG_STRICT_DEVMEM is not set
|
||||
CONFIG_MEMTEST=y
|
||||
|
||||
+13
-90
@@ -41,31 +41,14 @@
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{
|
||||
"id": "netmask"
|
||||
},
|
||||
{
|
||||
"id": "broadcast"
|
||||
},
|
||||
{
|
||||
"id": "router"
|
||||
},
|
||||
{
|
||||
"id": "domain"
|
||||
},
|
||||
{
|
||||
"id": "hostname"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
},
|
||||
{
|
||||
"id": "ntp-server"
|
||||
},
|
||||
{
|
||||
"id": "vendor-class",
|
||||
"value": "Raspberry Pi 2 Model B"
|
||||
}
|
||||
{"id": "netmask"},
|
||||
{"id": "broadcast"},
|
||||
{"id": "router"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": "vendor-class", "value": "Raspberry Pi 2 Model B"}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -88,9 +71,6 @@
|
||||
},
|
||||
"ietf-netconf-acm:nacm": {
|
||||
"enable-nacm": true,
|
||||
"read-default": "permit",
|
||||
"write-default": "permit",
|
||||
"exec-default": "permit",
|
||||
"groups": {
|
||||
"group": [
|
||||
{
|
||||
@@ -98,14 +78,6 @@
|
||||
"user-name": [
|
||||
"admin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "operator",
|
||||
"user-name": []
|
||||
},
|
||||
{
|
||||
"name": "guest",
|
||||
"user-name": []
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -125,37 +97,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
@@ -163,25 +104,11 @@
|
||||
],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-password-access",
|
||||
"name": "deny-password-read",
|
||||
"module-name": "ietf-system",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"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."
|
||||
"action": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -195,11 +122,7 @@
|
||||
"name": "default-ssh",
|
||||
"ssh": {
|
||||
"tcp-server-parameters": {
|
||||
"local-bind": [
|
||||
{
|
||||
"local-address": "::"
|
||||
}
|
||||
]
|
||||
"local-address": "::"
|
||||
},
|
||||
"ssh-server-parameters": {
|
||||
"server-identity": {
|
||||
@@ -245,7 +168,7 @@
|
||||
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
|
||||
},
|
||||
"infix-meta:meta": {
|
||||
"version": "1.7"
|
||||
"version": "1.6"
|
||||
},
|
||||
"infix-services:mdns": {
|
||||
"enabled": true
|
||||
|
||||
@@ -6,7 +6,7 @@ define BANANAPI_BPI_R3_LINUX_CONFIG_FIXUPS
|
||||
$(call KCONFIG_SET_OPT,CONFIG_I2C_GPIO,y)
|
||||
$(call KCONFIG_SET_OPT,CONFIG_MTK_THERMAL,m)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_MTK_UART)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_WATCHDOG)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_MTK_WATCHDOG)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_MEDIATEK_GE_PHY)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_REALTEK_PHY)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_MEDIATEK)
|
||||
|
||||
+34
-169
@@ -17,25 +17,7 @@
|
||||
"state": {
|
||||
"admin-state": "unlocked"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "radio0",
|
||||
"class": "infix-hardware:wifi",
|
||||
"infix-hardware:wifi-radio": {
|
||||
"country-code": "DE",
|
||||
"band": "2.4GHz",
|
||||
"channel": "auto"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "radio1",
|
||||
"class": "infix-hardware:wifi",
|
||||
"infix-hardware:wifi-radio": {
|
||||
"country-code": "DE",
|
||||
"band": "5GHz",
|
||||
"channel": "auto"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"ietf-interfaces:interfaces": {
|
||||
@@ -120,115 +102,54 @@
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{
|
||||
"id": "ntp-server"
|
||||
},
|
||||
{
|
||||
"id": "broadcast"
|
||||
},
|
||||
{
|
||||
"id": "domain"
|
||||
},
|
||||
{
|
||||
"id": "hostname"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
},
|
||||
{
|
||||
"id": "router"
|
||||
},
|
||||
{
|
||||
"id": "netmask"
|
||||
},
|
||||
{
|
||||
"id": "vendor-class",
|
||||
"value": "Banana Pi BPI-R3"
|
||||
}
|
||||
{"id": "ntp-server"},
|
||||
{"id": "broadcast"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "router"},
|
||||
{"id": "netmask"},
|
||||
{"id": "vendor-class", "value": "Banana Pi BPI-R3"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-ip:ipv6": {
|
||||
"infix-dhcpv6-client:dhcp": {
|
||||
"option": [
|
||||
{
|
||||
"id": "ntp-server"
|
||||
},
|
||||
{
|
||||
"id": "client-fqdn"
|
||||
},
|
||||
{
|
||||
"id": "domain-search"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
}
|
||||
{"id": "ntp-server"},
|
||||
{"id": "client-fqdn"},
|
||||
{"id": "domain-search"},
|
||||
{"id": "dns-server"}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wifi0-ap",
|
||||
"type": "infix-if-type:wifi",
|
||||
"infix-interfaces:wifi": {
|
||||
"radio": "radio0",
|
||||
"access-point": {
|
||||
"ssid": "Infix",
|
||||
"security": {
|
||||
"secret": "wifi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"infix-interfaces:bridge-port": {
|
||||
"bridge": "br0"
|
||||
}
|
||||
"name": "wifi0",
|
||||
"type": "infix-if-type:wifi"
|
||||
},
|
||||
{
|
||||
"name": "wifi1-ap",
|
||||
"type": "infix-if-type:wifi",
|
||||
"infix-interfaces:wifi": {
|
||||
"radio": "radio1",
|
||||
"access-point": {
|
||||
"ssid": "Infix5Ghz",
|
||||
"security": {
|
||||
"secret": "wifi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"infix-interfaces:bridge-port": {
|
||||
"bridge": "br0"
|
||||
}
|
||||
"name": "wifi1",
|
||||
"type": "infix-if-type:wifi"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ietf-keystore:keystore": {
|
||||
"asymmetric-keys": {
|
||||
"asymmetric-key": [
|
||||
{
|
||||
"name": "genkey",
|
||||
"public-key-format": "infix-crypto-types:ssh-public-key-format",
|
||||
"public-key": "",
|
||||
"private-key-format": "infix-crypto-types:rsa-private-key-format",
|
||||
"cleartext-private-key": "",
|
||||
"certificates": {}
|
||||
"asymmetric-keys": {
|
||||
"asymmetric-key": [
|
||||
{
|
||||
"name": "genkey",
|
||||
"public-key-format": "infix-crypto-types:ssh-public-key-format",
|
||||
"public-key": "",
|
||||
"private-key-format": "infix-crypto-types:rsa-private-key-format",
|
||||
"cleartext-private-key": "",
|
||||
"certificates": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"symmetric-keys": {
|
||||
"symmetric-key": [
|
||||
{
|
||||
"name": "wifi",
|
||||
"infix-keystore:symmetric-key": "infixinfix",
|
||||
"infix-keystore:key-format": "infix-crypto-types:wifi-preshared-key-format"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-netconf-acm:nacm": {
|
||||
"enable-nacm": true,
|
||||
"read-default": "permit",
|
||||
"write-default": "permit",
|
||||
"exec-default": "permit",
|
||||
"groups": {
|
||||
"group": [
|
||||
{
|
||||
@@ -236,14 +157,6 @@
|
||||
"user-name": [
|
||||
"admin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "operator",
|
||||
"user-name": []
|
||||
},
|
||||
{
|
||||
"name": "guest",
|
||||
"user-name": []
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -263,37 +176,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
@@ -301,25 +183,11 @@
|
||||
],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-password-access",
|
||||
"name": "deny-password-read",
|
||||
"module-name": "ietf-system",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"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."
|
||||
"action": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -333,11 +201,7 @@
|
||||
"name": "default-ssh",
|
||||
"ssh": {
|
||||
"tcp-server-parameters": {
|
||||
"local-bind": [
|
||||
{
|
||||
"local-address": "::"
|
||||
}
|
||||
]
|
||||
"local-address": "::"
|
||||
},
|
||||
"ssh-server-parameters": {
|
||||
"server-identity": {
|
||||
@@ -429,7 +293,7 @@
|
||||
"policy": [
|
||||
{
|
||||
"name": "lan-to-wan",
|
||||
"action": "accept",
|
||||
"action": "accept",
|
||||
"ingress": [
|
||||
"lan"
|
||||
],
|
||||
@@ -441,7 +305,7 @@
|
||||
]
|
||||
},
|
||||
"infix-meta:meta": {
|
||||
"version": "1.7"
|
||||
"version": "1.6"
|
||||
},
|
||||
"infix-services:mdns": {
|
||||
"enabled": true
|
||||
@@ -477,3 +341,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"sfp1": {
|
||||
"comment": "Reports it supports autoneg, but if setting it, dagger crashes",
|
||||
"broken-autoneg": true
|
||||
},
|
||||
"sfp2": {
|
||||
"comment": "Reports it supports autoneg, but if setting it, dagger crashes",
|
||||
"broken-autoneg": true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ config BR2_PACKAGE_FRIENDLYARM_NANOPI_R2S
|
||||
select SDCARD_AUX
|
||||
select BR2_PACKAGE_INPUT_EVENT_DAEMON
|
||||
select BR2_PACKAGE_LINUX_FIRMWARE_RTL_815X
|
||||
select BR2_PACKAGE_INPUT_EVENT_DAEMON
|
||||
help
|
||||
FriendlyElec NanoPi R2S is a compact router board based on
|
||||
the Rockchip RK3328 SoC with dual Gigabit Ethernet ports.
|
||||
|
||||
@@ -4,9 +4,6 @@ define FRIENDLYARM_NANOPI_R2S_LINUX_CONFIG_FIXUPS
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_ROCKCHIP_IOMMU)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_ROCKCHIP_PM_DOMAINS)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_ROCKCHIP_IODOMAIN)
|
||||
# TODO: for some reason this just locks up the device
|
||||
# so we'll have to rely on the softdog :-(
|
||||
# $(call KCONFIG_ENABLE_OPT,CONFIG_DW_WATCHDOG)
|
||||
|
||||
# PHY drivers
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_PHY_ROCKCHIP_EMMC)
|
||||
@@ -54,10 +51,6 @@ define FRIENDLYARM_NANOPI_R2S_LINUX_CONFIG_FIXUPS
|
||||
$(call KCONFIG_SET_OPT,CONFIG_NVMEM_ROCKCHIP_EFUSE,m)
|
||||
$(call KCONFIG_SET_OPT,CONFIG_NVMEM_ROCKCHIP_OTP,m)
|
||||
|
||||
# Input layer
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_INPUT_MISC)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_INPUT_RK805_PWRKEY)
|
||||
|
||||
# Network: STMMAC Ethernet (WAN port - RK3328 GMAC with RTL8211E PHY)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_STMICRO)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_STMMAC_ETH)
|
||||
|
||||
+29
-114
@@ -61,49 +61,24 @@
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{
|
||||
"id": "ntp-server"
|
||||
},
|
||||
{
|
||||
"id": "broadcast"
|
||||
},
|
||||
{
|
||||
"id": "domain"
|
||||
},
|
||||
{
|
||||
"id": "hostname"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
},
|
||||
{
|
||||
"id": "router"
|
||||
},
|
||||
{
|
||||
"id": "netmask"
|
||||
},
|
||||
{
|
||||
"id": "vendor-class",
|
||||
"value": "NanoPi R2S"
|
||||
}
|
||||
{"id": "ntp-server"},
|
||||
{"id": "broadcast"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "router"},
|
||||
{"id": "netmask"},
|
||||
{"id": "vendor-class", "value": "NanoPi R2S"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-ip:ipv6": {
|
||||
"infix-dhcpv6-client:dhcp": {
|
||||
"option": [
|
||||
{
|
||||
"id": "ntp-server"
|
||||
},
|
||||
{
|
||||
"id": "client-fqdn"
|
||||
},
|
||||
{
|
||||
"id": "domain-search"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
}
|
||||
{"id": "ntp-server"},
|
||||
{"id": "client-fqdn"},
|
||||
{"id": "domain-search"},
|
||||
{"id": "dns-server"}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -111,24 +86,21 @@
|
||||
]
|
||||
},
|
||||
"ietf-keystore:keystore": {
|
||||
"asymmetric-keys": {
|
||||
"asymmetric-key": [
|
||||
{
|
||||
"name": "genkey",
|
||||
"public-key-format": "infix-crypto-types:ssh-public-key-format",
|
||||
"public-key": "",
|
||||
"private-key-format": "infix-crypto-types:rsa-private-key-format",
|
||||
"cleartext-private-key": "",
|
||||
"certificates": {}
|
||||
"asymmetric-keys": {
|
||||
"asymmetric-key": [
|
||||
{
|
||||
"name": "genkey",
|
||||
"public-key-format": "infix-crypto-types:ssh-public-key-format",
|
||||
"public-key": "",
|
||||
"private-key-format": "infix-crypto-types:rsa-private-key-format",
|
||||
"cleartext-private-key": "",
|
||||
"certificates": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ietf-netconf-acm:nacm": {
|
||||
"enable-nacm": true,
|
||||
"read-default": "permit",
|
||||
"write-default": "permit",
|
||||
"exec-default": "permit",
|
||||
"groups": {
|
||||
"group": [
|
||||
{
|
||||
@@ -136,14 +108,6 @@
|
||||
"user-name": [
|
||||
"admin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "operator",
|
||||
"user-name": []
|
||||
},
|
||||
{
|
||||
"name": "guest",
|
||||
"user-name": []
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -163,37 +127,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
@@ -201,25 +134,11 @@
|
||||
],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-password-access",
|
||||
"name": "deny-password-read",
|
||||
"module-name": "ietf-system",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"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."
|
||||
"action": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -233,11 +152,7 @@
|
||||
"name": "default-ssh",
|
||||
"ssh": {
|
||||
"tcp-server-parameters": {
|
||||
"local-bind": [
|
||||
{
|
||||
"local-address": "::"
|
||||
}
|
||||
]
|
||||
"local-address": "::"
|
||||
},
|
||||
"ssh-server-parameters": {
|
||||
"server-identity": {
|
||||
@@ -329,7 +244,7 @@
|
||||
"policy": [
|
||||
{
|
||||
"name": "lan-to-wan",
|
||||
"action": "accept",
|
||||
"action": "accept",
|
||||
"ingress": [
|
||||
"lan"
|
||||
],
|
||||
@@ -341,7 +256,7 @@
|
||||
]
|
||||
},
|
||||
"infix-meta:meta": {
|
||||
"version": "1.7"
|
||||
"version": "1.6"
|
||||
},
|
||||
"infix-services:mdns": {
|
||||
"enabled": true
|
||||
|
||||
+2
-5
@@ -20,7 +20,6 @@ cleanup()
|
||||
{
|
||||
rm -f "$LED_FILE"
|
||||
rm -f "$PID_FILE"
|
||||
kill %% 2>/dev/null
|
||||
exit 0
|
||||
}
|
||||
|
||||
@@ -32,13 +31,11 @@ remaining_time=$((1800 - $(awk '{print int($1)}' /proc/uptime)))
|
||||
|
||||
while [ "$remaining_time" -gt 0 ]; do
|
||||
check_wan
|
||||
sleep 1 &
|
||||
wait $!
|
||||
sleep 1
|
||||
remaining_time=$((remaining_time - 1))
|
||||
done
|
||||
|
||||
while :; do
|
||||
check_wan
|
||||
sleep 5 &
|
||||
wait $!
|
||||
sleep 5
|
||||
done
|
||||
@@ -39,6 +39,7 @@ CONFIG_ARM64_ERRATUM_1286807=y
|
||||
CONFIG_ARM64_ERRATUM_1542419=y
|
||||
CONFIG_ARM64_ERRATUM_2441009=y
|
||||
CONFIG_ARM64_VA_BITS_48=y
|
||||
CONFIG_SCHED_MC=y
|
||||
CONFIG_NR_CPUS=64
|
||||
CONFIG_COMPAT=y
|
||||
# CONFIG_SUSPEND is not set
|
||||
@@ -51,6 +52,7 @@ CONFIG_ARM_ARMADA_37XX_CPUFREQ=y
|
||||
CONFIG_ARM_ARMADA_8K_CPUFREQ=y
|
||||
CONFIG_ACPI=y
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_JUMP_LABEL=y
|
||||
# CONFIG_GCC_PLUGINS is not set
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
@@ -77,6 +79,7 @@ CONFIG_IP_MROUTE=y
|
||||
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
|
||||
CONFIG_IP_PIMSM_V1=y
|
||||
CONFIG_IP_PIMSM_V2=y
|
||||
CONFIG_SYN_COOKIES=y
|
||||
CONFIG_NET_IPVTI=m
|
||||
CONFIG_NET_FOU_IP_TUNNELS=y
|
||||
CONFIG_IPV6_SIT=m
|
||||
@@ -92,31 +95,12 @@ CONFIG_BRIDGE_NETFILTER=y
|
||||
CONFIG_NETFILTER_NETLINK_QUEUE=y
|
||||
CONFIG_NETFILTER_NETLINK_LOG=y
|
||||
CONFIG_NF_CONNTRACK=y
|
||||
CONFIG_NF_CONNTRACK_ZONES=y
|
||||
CONFIG_NF_CONNTRACK_PROCFS=y
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CONNTRACK_TIMEOUT=y
|
||||
CONFIG_NF_CONNTRACK_TIMESTAMP=y
|
||||
CONFIG_NF_CONNTRACK_AMANDA=y
|
||||
CONFIG_NF_CONNTRACK_FTP=y
|
||||
CONFIG_NF_CONNTRACK_H323=y
|
||||
CONFIG_NF_CONNTRACK_IRC=y
|
||||
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
|
||||
CONFIG_NF_CONNTRACK_SNMP=y
|
||||
CONFIG_NF_CONNTRACK_PPTP=y
|
||||
CONFIG_NF_CONNTRACK_SANE=y
|
||||
CONFIG_NF_CONNTRACK_SIP=y
|
||||
CONFIG_NF_CONNTRACK_TFTP=y
|
||||
CONFIG_NF_CT_NETLINK=y
|
||||
CONFIG_NF_CT_NETLINK_TIMEOUT=y
|
||||
CONFIG_NF_CT_NETLINK_HELPER=y
|
||||
CONFIG_NETFILTER_NETLINK_GLUE_CT=y
|
||||
CONFIG_NF_TABLES=y
|
||||
CONFIG_NF_TABLES_INET=y
|
||||
CONFIG_NF_TABLES_NETDEV=y
|
||||
CONFIG_NFT_NUMGEN=y
|
||||
CONFIG_NFT_CT=m
|
||||
CONFIG_NFT_FLOW_OFFLOAD=y
|
||||
CONFIG_NFT_CONNLIMIT=m
|
||||
CONFIG_NFT_LOG=m
|
||||
CONFIG_NFT_LIMIT=m
|
||||
@@ -125,23 +109,15 @@ CONFIG_NFT_REDIR=m
|
||||
CONFIG_NFT_NAT=m
|
||||
CONFIG_NFT_TUNNEL=m
|
||||
CONFIG_NFT_QUEUE=m
|
||||
CONFIG_NFT_QUOTA=y
|
||||
CONFIG_NFT_REJECT=m
|
||||
CONFIG_NFT_COMPAT=m
|
||||
CONFIG_NFT_HASH=m
|
||||
CONFIG_NFT_FIB_INET=y
|
||||
CONFIG_NFT_XFRM=m
|
||||
CONFIG_NFT_SOCKET=m
|
||||
CONFIG_NFT_OSF=m
|
||||
CONFIG_NFT_TPROXY=y
|
||||
CONFIG_NFT_SYNPROXY=y
|
||||
CONFIG_NFT_DUP_NETDEV=m
|
||||
CONFIG_NFT_FWD_NETDEV=m
|
||||
CONFIG_NFT_FIB_NETDEV=y
|
||||
CONFIG_NFT_REJECT_NETDEV=m
|
||||
CONFIG_NF_FLOW_TABLE_INET=y
|
||||
CONFIG_NF_FLOW_TABLE=y
|
||||
CONFIG_NETFILTER_XTABLES_LEGACY=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
|
||||
CONFIG_NETFILTER_XT_TARGET_LOG=m
|
||||
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
|
||||
@@ -158,69 +134,29 @@ CONFIG_NETFILTER_XT_MATCH_MAC=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MARK=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
|
||||
CONFIG_IP_SET=y
|
||||
CONFIG_IP_SET_BITMAP_IP=y
|
||||
CONFIG_IP_SET_BITMAP_IPMAC=y
|
||||
CONFIG_IP_SET_BITMAP_PORT=y
|
||||
CONFIG_IP_SET_HASH_IP=y
|
||||
CONFIG_IP_SET_HASH_IPMARK=y
|
||||
CONFIG_IP_SET_HASH_IPPORT=y
|
||||
CONFIG_IP_SET_HASH_IPPORTIP=y
|
||||
CONFIG_IP_SET_HASH_IPPORTNET=y
|
||||
CONFIG_IP_SET_HASH_IPMAC=y
|
||||
CONFIG_IP_SET_HASH_MAC=y
|
||||
CONFIG_IP_SET_HASH_NETPORTNET=y
|
||||
CONFIG_IP_SET_HASH_NET=y
|
||||
CONFIG_IP_SET_HASH_NETNET=y
|
||||
CONFIG_IP_SET_HASH_NETPORT=y
|
||||
CONFIG_IP_SET_HASH_NETIFACE=y
|
||||
CONFIG_IP_SET_LIST_SET=y
|
||||
CONFIG_NFT_DUP_IPV4=y
|
||||
CONFIG_NFT_FIB_IPV4=y
|
||||
CONFIG_NF_TABLES_ARP=y
|
||||
CONFIG_NF_LOG_ARP=y
|
||||
CONFIG_NF_LOG_IPV4=y
|
||||
CONFIG_IP_NF_IPTABLES=m
|
||||
CONFIG_IP_NF_MATCH_AH=m
|
||||
CONFIG_IP_NF_MATCH_ECN=m
|
||||
CONFIG_IP_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP_NF_MATCH_TTL=m
|
||||
CONFIG_IP_NF_FILTER=m
|
||||
CONFIG_IP_NF_TARGET_REJECT=m
|
||||
CONFIG_IP_NF_TARGET_SYNPROXY=m
|
||||
CONFIG_IP_NF_NAT=m
|
||||
CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
CONFIG_IP_NF_ARPFILTER=m
|
||||
CONFIG_IP_NF_ARP_MANGLE=m
|
||||
CONFIG_NFT_DUP_IPV6=y
|
||||
CONFIG_NFT_FIB_IPV6=y
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP6_NF_IPTABLES=m
|
||||
CONFIG_IP6_NF_MATCH_AH=m
|
||||
CONFIG_IP6_NF_MATCH_EUI64=m
|
||||
CONFIG_IP6_NF_MATCH_FRAG=m
|
||||
CONFIG_IP6_NF_MATCH_OPTS=m
|
||||
CONFIG_IP6_NF_MATCH_HL=m
|
||||
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
|
||||
CONFIG_IP6_NF_MATCH_MH=m
|
||||
CONFIG_IP6_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP6_NF_MATCH_RT=m
|
||||
CONFIG_IP6_NF_MATCH_SRH=m
|
||||
CONFIG_IP6_NF_TARGET_HL=m
|
||||
CONFIG_IP6_NF_FILTER=m
|
||||
CONFIG_IP6_NF_TARGET_REJECT=m
|
||||
CONFIG_IP6_NF_TARGET_SYNPROXY=m
|
||||
CONFIG_IP6_NF_RAW=m
|
||||
CONFIG_IP6_NF_NAT=m
|
||||
CONFIG_IP6_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP6_NF_TARGET_NPT=m
|
||||
CONFIG_NF_TABLES_BRIDGE=m
|
||||
CONFIG_NFT_BRIDGE_META=m
|
||||
CONFIG_NFT_BRIDGE_REJECT=m
|
||||
CONFIG_NF_CONNTRACK_BRIDGE=m
|
||||
CONFIG_BRIDGE_NF_EBTABLES=m
|
||||
CONFIG_BRIDGE_EBT_BROUTE=m
|
||||
CONFIG_BRIDGE_EBT_T_FILTER=m
|
||||
CONFIG_BRIDGE_EBT_T_NAT=m
|
||||
CONFIG_BRIDGE_EBT_802_3=m
|
||||
CONFIG_BRIDGE_EBT_ARP=m
|
||||
CONFIG_BRIDGE_EBT_IP=m
|
||||
@@ -308,7 +244,6 @@ CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_BONDING=m
|
||||
CONFIG_DUMMY=m
|
||||
CONFIG_WIREGUARD=m
|
||||
CONFIG_MACVLAN=m
|
||||
CONFIG_MACVTAP=m
|
||||
CONFIG_IPVLAN=m
|
||||
@@ -472,10 +407,10 @@ CONFIG_WATCHDOG=y
|
||||
CONFIG_WATCHDOG_SYSFS=y
|
||||
CONFIG_SOFT_WATCHDOG=y
|
||||
CONFIG_GPIO_WATCHDOG=y
|
||||
CONFIG_ARM_SBSA_WATCHDOG=y
|
||||
CONFIG_ARMADA_37XX_WATCHDOG=y
|
||||
CONFIG_I6300ESB_WDT=y
|
||||
CONFIG_MFD_MAX77620=y
|
||||
CONFIG_MFD_SEC_CORE=y
|
||||
CONFIG_MFD_ROHM_BD718XX=y
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
||||
@@ -484,6 +419,7 @@ CONFIG_REGULATOR_GPIO=y
|
||||
CONFIG_REGULATOR_MAX77620=y
|
||||
CONFIG_REGULATOR_PCA9450=y
|
||||
CONFIG_REGULATOR_QCOM_SPMI=y
|
||||
CONFIG_REGULATOR_S2MPS11=y
|
||||
# CONFIG_HID_GENERIC is not set
|
||||
# CONFIG_HID_A4TECH is not set
|
||||
# CONFIG_HID_APPLE is not set
|
||||
@@ -493,11 +429,11 @@ CONFIG_REGULATOR_QCOM_SPMI=y
|
||||
# CONFIG_HID_CYPRESS is not set
|
||||
# CONFIG_HID_EZKEY is not set
|
||||
# CONFIG_HID_KENSINGTON is not set
|
||||
# CONFIG_HID_LOGITECH is not set
|
||||
# CONFIG_HID_MICROSOFT is not set
|
||||
# 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
|
||||
@@ -515,6 +451,7 @@ CONFIG_USB_CHIPIDEA_UDC=y
|
||||
CONFIG_USB_CHIPIDEA_HOST=y
|
||||
CONFIG_USB_ISP1760=y
|
||||
CONFIG_USB_HSIC_USB3503=m
|
||||
CONFIG_NOP_USB_XCEIV=y
|
||||
CONFIG_USB_ULPI=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_SNP_UDC_PLAT=y
|
||||
@@ -548,6 +485,7 @@ CONFIG_LEDS_TRIGGER_NETDEV=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_MAX77686=y
|
||||
CONFIG_RTC_DRV_PCF8523=y
|
||||
CONFIG_RTC_DRV_S5M=y
|
||||
CONFIG_RTC_DRV_DS3232=y
|
||||
CONFIG_RTC_DRV_EFI=y
|
||||
CONFIG_RTC_DRV_PL031=y
|
||||
@@ -562,6 +500,7 @@ CONFIG_VIRTIO_INPUT=y
|
||||
CONFIG_VIRTIO_MMIO=y
|
||||
# CONFIG_SURFACE_PLATFORMS is not set
|
||||
CONFIG_COMMON_CLK_CS2000_CP=y
|
||||
CONFIG_COMMON_CLK_S2MPS11=y
|
||||
CONFIG_COMMON_CLK_XGENE=y
|
||||
CONFIG_COMMON_CLK_BD718XX=y
|
||||
CONFIG_MAILBOX=y
|
||||
@@ -578,7 +517,7 @@ CONFIG_PHY_SAMSUNG_USB2=y
|
||||
CONFIG_NVMEM_LAYOUT_ONIE_TLV=y
|
||||
CONFIG_MUX_MMIO=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
CONFIG_BTRFS_FS=y
|
||||
CONFIG_BTRFS_FS_POSIX_ACL=y
|
||||
@@ -605,6 +544,8 @@ CONFIG_CRYPTO_CCM=m
|
||||
CONFIG_CRYPTO_ECHAINIV=y
|
||||
CONFIG_CRYPTO_ANSI_CPRNG=y
|
||||
CONFIG_CRYPTO_GHASH_ARM64_CE=y
|
||||
CONFIG_CRYPTO_SHA1_ARM64_CE=y
|
||||
CONFIG_CRYPTO_SHA2_ARM64_CE=y
|
||||
CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
|
||||
CONFIG_DMA_CMA=y
|
||||
CONFIG_CMA_SIZE_MBYTES=0
|
||||
@@ -616,13 +557,8 @@ CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_PANIC_ON_OOPS=y
|
||||
CONFIG_PANIC_TIMEOUT=20
|
||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
|
||||
CONFIG_HARDLOCKUP_DETECTOR=y
|
||||
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
|
||||
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
|
||||
CONFIG_WQ_WATCHDOG=y
|
||||
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
|
||||
CONFIG_TEST_LOCKUP=m
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
# CONFIG_RCU_TRACE is not set
|
||||
CONFIG_FUNCTION_TRACER=y
|
||||
# CONFIG_STRICT_DEVMEM is not set
|
||||
|
||||
@@ -108,7 +108,7 @@ To configure WiFi as a client, first store your WiFi password in the keystore:
|
||||
admin@infix:/> configure
|
||||
admin@infix:/config/> edit keystore symmetric-key mywifi
|
||||
admin@infix:/config/keystore/…/mywifi/> set key-format wifi-preshared-key-format
|
||||
admin@infix:/config/keystore/…/mywifi/> set symmetric-key YourWiFiPassword
|
||||
admin@infix:/config/keystore/…/mywifi/> set cleartext-key YourWiFiPassword
|
||||
admin@infix:/config/keystore/…/mywifi/> leave
|
||||
```
|
||||
|
||||
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Workaround for: https://github.com/kernelkit/infix/issues/1357
|
||||
udevadm control --reload-rules
|
||||
udevadm trigger --subsystem-match=net --action=add
|
||||
+14
-102
@@ -10,13 +10,6 @@
|
||||
"state": {
|
||||
"admin-state": "unlocked"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "radio0",
|
||||
"class": "infix-hardware:wifi",
|
||||
"infix-hardware:wifi-radio": {
|
||||
"country-code": "00"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -45,45 +38,24 @@
|
||||
{
|
||||
"name": "eth0",
|
||||
"type": "infix-if-type:ethernet",
|
||||
"ietf-ip:ipv6": {},
|
||||
"ietf-ip:ipv4": {
|
||||
"infix-dhcp-client:dhcp": {
|
||||
"option": [
|
||||
{
|
||||
"id": "netmask"
|
||||
},
|
||||
{
|
||||
"id": "broadcast"
|
||||
},
|
||||
{
|
||||
"id": "router"
|
||||
},
|
||||
{
|
||||
"id": "domain"
|
||||
},
|
||||
{
|
||||
"id": "hostname"
|
||||
},
|
||||
{
|
||||
"id": "dns-server"
|
||||
},
|
||||
{
|
||||
"id": "ntp-server"
|
||||
},
|
||||
{
|
||||
"id": "vendor-class",
|
||||
"value": "Raspberry Pi 4 Model B"
|
||||
}
|
||||
{"id": "netmask"},
|
||||
{"id": "broadcast"},
|
||||
{"id": "router"},
|
||||
{"id": "domain"},
|
||||
{"id": "hostname"},
|
||||
{"id": "dns-server"},
|
||||
{"id": "ntp-server"},
|
||||
{"id": "vendor-class", "value": "Raspberry Pi 4 Model B"}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wifi0",
|
||||
"type": "infix-if-type:wifi",
|
||||
"infix-interfaces:wifi": {
|
||||
"radio": "radio0"
|
||||
}
|
||||
"type": "infix-if-type:wifi"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -103,9 +75,6 @@
|
||||
},
|
||||
"ietf-netconf-acm:nacm": {
|
||||
"enable-nacm": true,
|
||||
"read-default": "permit",
|
||||
"write-default": "permit",
|
||||
"exec-default": "permit",
|
||||
"groups": {
|
||||
"group": [
|
||||
{
|
||||
@@ -113,14 +82,6 @@
|
||||
"user-name": [
|
||||
"admin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "operator",
|
||||
"user-name": []
|
||||
},
|
||||
{
|
||||
"name": "guest",
|
||||
"user-name": []
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -140,37 +101,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": [
|
||||
@@ -178,25 +108,11 @@
|
||||
],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-password-access",
|
||||
"name": "deny-password-read",
|
||||
"module-name": "ietf-system",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"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."
|
||||
"action": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -210,11 +126,7 @@
|
||||
"name": "default-ssh",
|
||||
"ssh": {
|
||||
"tcp-server-parameters": {
|
||||
"local-bind": [
|
||||
{
|
||||
"local-address": "::"
|
||||
}
|
||||
]
|
||||
"local-address": "::"
|
||||
},
|
||||
"ssh-server-parameters": {
|
||||
"server-identity": {
|
||||
@@ -260,7 +172,7 @@
|
||||
"infix-system:motd-banner": "Li0tLS0tLS0uCnwgIC4gLiAgfCBJbmZpeCBPUyDigJQgSW1tdXRhYmxlLkZyaWVuZGx5LlNlY3VyZQp8LS4gdiAuLXwgaHR0cHM6Ly9rZXJuZWxraXQub3JnCictJy0tLSctJwo="
|
||||
},
|
||||
"infix-meta:meta": {
|
||||
"version": "1.7"
|
||||
"version": "1.6"
|
||||
},
|
||||
"infix-services:mdns": {
|
||||
"enabled": true
|
||||
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Workaround for: https://github.com/kernelkit/infix/issues/1357
|
||||
udevadm control --reload-rules
|
||||
udevadm trigger --subsystem-match=net --action=add
|
||||
@@ -12,15 +12,6 @@
|
||||
boot_targets = "mmc0";
|
||||
ethprime = "eth0";
|
||||
|
||||
/* Memory layout for kernel boot:
|
||||
* 0x00200000: Kernel relocation address
|
||||
* 0x04000000: FDT (64MB, gives enough space for kernels up to ~60MB)
|
||||
* 0x10000000: Ramdisk (Memsize - 256MB)
|
||||
*/
|
||||
kernel_addr_r = "0x00200000";
|
||||
fdt_addr_r = "0x04000000";
|
||||
ramdisk_addr_r = "0x10000000";
|
||||
|
||||
stdout = "serial";
|
||||
stderr = "serial";
|
||||
stdin = "serial";
|
||||
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
ecc_stat()
|
||||
{
|
||||
local chan=
|
||||
local base=
|
||||
|
||||
for chan in 0 1; do
|
||||
base=$((0xf0020360 + 0x200 * chan))
|
||||
|
||||
echo "DRAM Channel $chan ECC Status"
|
||||
echo -n " Log config: "; devmem $((base + 0x0)) 32
|
||||
echo -n " 1b errors: "; devmem $((base + 0x4)) 32
|
||||
echo -n " Info 0: "; devmem $((base + 0x8)) 32
|
||||
echo -n " Info 1: "; devmem $((base + 0xc)) 32
|
||||
echo
|
||||
done
|
||||
}
|
||||
|
||||
[ -n "$1" ] || { echo "usage: $0 OUT-DIR"; exit 1; }
|
||||
work="$1"/marvell-cn913x
|
||||
mkdir -p "${work}"
|
||||
|
||||
ecc_stat >"${work}"/ecc-stat
|
||||
@@ -59,9 +59,3 @@
|
||||
XSWP(a, "e13", 13, &sfp0);
|
||||
};
|
||||
};
|
||||
|
||||
&cp0_spi1 {
|
||||
spi-flash@0 {
|
||||
broken-flash-reset;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1016,7 +1016,12 @@ CONFIG_UDHCPC=y
|
||||
CONFIG_FEATURE_UDHCPC_ARPING=y
|
||||
CONFIG_FEATURE_UDHCPC_SANITIZEOPT=y
|
||||
CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script"
|
||||
# CONFIG_UDHCPC6 is not set
|
||||
CONFIG_UDHCPC6_DEFAULT_SCRIPT="/usr/share/udhcpc/default6.script"
|
||||
CONFIG_UDHCPC6=y
|
||||
CONFIG_FEATURE_UDHCPC6_RFC3646=y
|
||||
CONFIG_FEATURE_UDHCPC6_RFC4704=y
|
||||
CONFIG_FEATURE_UDHCPC6_RFC4833=y
|
||||
CONFIG_FEATURE_UDHCPC6_RFC5970=y
|
||||
|
||||
#
|
||||
# Common options for DHCP applets
|
||||
|
||||
@@ -34,7 +34,7 @@ Depending on how your Linux installation is set up, the following may
|
||||
require being run with superuser privileges, i.e., you may need to
|
||||
repend the command with 'sudo'.
|
||||
|
||||
$ ./qemu/run.sh
|
||||
$ ./qemu.sh
|
||||
|
||||
You should now see the Infix init system booting up. When the final
|
||||
"Please press Enter to activate this console." is shown, press Enter
|
||||
@@ -75,13 +75,13 @@ interface, which requires the following extra package:
|
||||
|
||||
We can now enter the configuration:
|
||||
|
||||
$ ./qemu/run.sh -c
|
||||
$ ./qemu.sh -c
|
||||
|
||||
Go down to *Networking*, select *TAP*, now you can change the *Number of
|
||||
TAPs*, e.g. to 10. Exit and save the configuration, then you can start
|
||||
Qemu again:
|
||||
|
||||
$ ./qemu/run.sh
|
||||
./qemu.sh
|
||||
|
||||
> Make sure to do a factory reset from the CLI, otherwise you will be
|
||||
> stuck with that single interface from before.
|
||||
|
||||
@@ -10,18 +10,15 @@
|
||||
#
|
||||
# and then call this script with:
|
||||
#
|
||||
# ./run.sh -c
|
||||
# ./qemu.sh -c
|
||||
#
|
||||
# To bring up a menuconfig dialog. Select `Exit` and save the changes.
|
||||
# For more help, see:_
|
||||
#
|
||||
# ./run.sh -h
|
||||
# ./qemu.sh -h
|
||||
#
|
||||
# shellcheck disable=SC3037
|
||||
|
||||
# Add /sbin to PATH for mkfs.ext4 and such (not default in debian)
|
||||
export PATH="/sbin:/usr/sbin:$PATH"
|
||||
|
||||
qdir=$(dirname "$(readlink -f "$0")")
|
||||
imgdir=$(readlink -f "${qdir}/..")
|
||||
prognm=$(basename "$0")
|
||||
@@ -43,7 +40,7 @@ usage()
|
||||
echo " Also, qemu.cfg has QEMU_APPEND which can affect this."
|
||||
echo
|
||||
echo "Example:"
|
||||
echo " $prognm -- finit.debug"
|
||||
echo " qemu.sh -- finit.debug"
|
||||
echo "___________________________________________________________________"
|
||||
echo "Note: 'kconfig-frontends' package (Debian/Ubuntu) must be installed"
|
||||
echo " for -c to work: sudo apt install kconfig-frontents"
|
||||
@@ -177,8 +174,6 @@ rw_args()
|
||||
{
|
||||
[ "$CONFIG_QEMU_RW" ] || return
|
||||
|
||||
command -v mkfs.ext4 >/dev/null || die "$prognm: cannot find mkfs.ext4"
|
||||
|
||||
if ! [ -f "aux.ext4" ]; then
|
||||
dd if=/dev/zero of="aux.ext4" bs=1M count=1 >/dev/null 2>&1
|
||||
mkfs.ext4 -L aux "aux.ext4" >/dev/null 2>&1
|
||||
|
||||
@@ -40,12 +40,11 @@ log()
|
||||
less +G -r "$fn"
|
||||
}
|
||||
|
||||
follow ()
|
||||
follow()
|
||||
{
|
||||
local fn="/var/log/syslog"
|
||||
[ -n "$1" ] && fn="/var/log/$1"
|
||||
|
||||
tail -F -n +1 "$fn"
|
||||
less +F -r "$fn"
|
||||
}
|
||||
|
||||
_logfile_completions()
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# --log-level debug
|
||||
ZEBRA_ARGS="-A 127.0.0.1 -u frr -g frr --log syslog --log-level err"
|
||||
ZEBRA_ARGS="-A 127.0.0.1 -u frr -g frr --log syslog "
|
||||
|
||||
@@ -5,5 +5,4 @@
|
||||
# 'podman load', must not have a timeout.
|
||||
sysv log:prio:local1,tag:%i kill:30 pid:!/run/container:%i.pid \
|
||||
pre:0,/usr/sbin/container cleanup:0,/usr/sbin/container \
|
||||
cgroup.system,delegate \
|
||||
[2345] <!> :%i container -n %i -- container %i
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
service <!> name:hostapd :%i \
|
||||
[2345] hostapd -P/var/run/hostapd-%i.pid /etc/hostapd-%i.conf \
|
||||
-- Wi-Fi Access Point @%i
|
||||
@@ -1,3 +1,3 @@
|
||||
service name:rousette notify:none log:null <pid/confd> env:/etc/default/confd \
|
||||
service name:rousette notify:none log <pid/confd> env:/etc/default/confd \
|
||||
[12345] rousette --syslog -t $CONFD_TIMEOUT \
|
||||
-- RESTCONF server
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
service name:wpa_supplicant :%i \
|
||||
[2345] wpa_supplicant -s -i %i -c /etc/wpa_supplicant-%i.conf -P/var/run/wpa_supplicant-%i.pid \
|
||||
-- Wi-Fi Station @%i
|
||||
[2345] wpa_supplicant -s -i %i -c /etc/wpa_supplicant-%i.conf -P/var/run/wpa_supplicant-%i.pid \
|
||||
-- WPA supplicant @%i
|
||||
|
||||
task name:wifi-scanner :%i [2345] <pid/wpa_supplicant:%i> /usr/libexec/infix/wifi-scanner %i -- Start scanning for SSID @ %i
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
# Virtual filesystems
|
||||
tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
|
||||
tmpfs /media tmpfs mode=1755,nosuid,nodev 0 0
|
||||
debugfs /sys/kernel/debug debugfs nofail 0 0
|
||||
cfgfs /config configfs nofail,noauto 0 0
|
||||
devtmpfs /dev devtmpfs defaults 0 0
|
||||
mkdir#-p /dev/pts helper none 0 0
|
||||
devpts /dev/pts devpts mode=620,ptmxmode=0666 0 0
|
||||
mkdir#-p /dev/shm helper none 0 0
|
||||
tmpfs /dev/shm tmpfs mode=0777 0 0
|
||||
proc /proc proc defaults 0 0
|
||||
tmpfs /tmp tmpfs mode=1777,nosuid,nodev 0 0
|
||||
tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
|
||||
tmpfs /media tmpfs mode=1755,nosuid,nodev 0 0
|
||||
sysfs /sys sysfs defaults 0 0
|
||||
debugfs /sys/kernel/debug debugfs nofail 0 0
|
||||
cfgfs /config configfs nofail,noauto 0 0
|
||||
|
||||
# The chosen backing storage for the overlays placed on /cfg, /etc,
|
||||
# /home, /root, and /var, are determined dynamically by /usr/libexec/infix/mnt
|
||||
# depending on the available devices.
|
||||
mnttmp /mnt/tmp tmpfs defaults 0 0
|
||||
LABEL=aux /mnt/aux auto noatime,nodiratime,noauto 0 0
|
||||
LABEL=var /mnt/var ext4 noatime,nodiratime,noauto 0 0
|
||||
LABEL=cfg /mnt/cfg ext4 noatime,nodiratime,noauto 0 0
|
||||
LABEL=aux /mnt/aux auto noatime,nodiratime,noauto,errors=remount-ro 0 0
|
||||
LABEL=var /mnt/var ext4 noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
|
||||
LABEL=cfg /mnt/cfg ext4 noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
|
||||
hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0
|
||||
/usr/libexec/infix/mnt# /cfg helper none 0 0
|
||||
|
||||
@@ -19,14 +19,6 @@ http {
|
||||
|
||||
include /etc/nginx/enabled/*.conf;
|
||||
|
||||
# Skip 2xx and 3xx
|
||||
# Skip 400 (e.g., rrousette syntax errors)
|
||||
map $status $loggable {
|
||||
~^[23] 0;
|
||||
400 0;
|
||||
default 1;
|
||||
}
|
||||
|
||||
access_log syslog:server=unix:/dev/log,nohostname,facility=local7,severity=warn combined if=$loggable;
|
||||
error_log syslog:server=unix:/dev/log,nohostname,facility=local7 warn;
|
||||
access_log syslog:server=unix:/dev/log,nohostname,facility=local7,severity=info;
|
||||
error_log syslog:server=unix:/dev/log,nohostname,facility=local7 info;
|
||||
}
|
||||
|
||||
@@ -4,14 +4,14 @@ alias ll='ls -alF'
|
||||
alias ls='ls --color=auto'
|
||||
|
||||
export LANG=C.UTF-8
|
||||
export EDITOR=/usr/bin/editor
|
||||
export VISUAL=/usr/bin/editor
|
||||
export EDITOR=/usr/bin/edit
|
||||
export VISUAL=/usr/bin/edit
|
||||
export LESS="-P %f (press h for help or q to quit)"
|
||||
export LESSOPEN="|/usr/bin/lesspipe.sh %s"
|
||||
alias vim='vi'
|
||||
alias view='vi -R'
|
||||
alias emacs='mg'
|
||||
alias sensible-editor=editor
|
||||
alias sensible-editor=edit
|
||||
alias sensible-pager=pager
|
||||
alias hd="hexdump -C"
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Memory and OOM tuning for embedded network devices
|
||||
# Optimized for systems with 512MB-4GB RAM
|
||||
# Target: Fast and deterministic OOM behavior
|
||||
|
||||
# OOM Behavior
|
||||
# Panic on OOM for fast system reset and recovery
|
||||
vm.panic_on_oom=1
|
||||
|
||||
# Dirty Page Writeback
|
||||
# Limit dirty pages to 10% of RAM before blocking writers
|
||||
# Start background writeback at 5% to prevent accumulation
|
||||
vm.dirty_ratio=10
|
||||
vm.dirty_background_ratio=5
|
||||
|
||||
# Writeback Timing
|
||||
# Expire dirty pages after 10 seconds (1000 centiseconds)
|
||||
# Ensures quick flushing on limited-memory systems
|
||||
vm.dirty_expire_centisecs=1000
|
||||
|
||||
# Memory Watermarks
|
||||
# Increase distance between low/high watermarks for earlier reclaim
|
||||
# Maintains larger free memory buffer proactively (default: 10)
|
||||
vm.watermark_scale_factor=150
|
||||
@@ -1,3 +0,0 @@
|
||||
# Rename WiFi PHY devices from phy0 to radio0 to avoid name clashes
|
||||
SUBSYSTEM=="ieee80211", ACTION=="add", KERNEL=="phy*", \
|
||||
RUN+="/bin/sh -c '/usr/sbin/iw phy %k set name radio%n'"
|
||||
@@ -1,7 +0,0 @@
|
||||
# Remove kernel-created WiFi interfaces
|
||||
# All WiFi interfaces are now virtual interfaces created by confd
|
||||
SUBSYSTEM=="net", ACTION=="add", KERNEL=="wlan*", \
|
||||
TEST=="/sys/class/net/$name/phy80211/name", \
|
||||
PROGRAM="/bin/cat /sys/class/net/%k/phy80211/name", \
|
||||
TEST!="/run/wifi-cleaned-%c", \
|
||||
RUN+="/bin/sh -c '/usr/sbin/iw dev %k del && touch /run/wifi-cleaned-%c'"
|
||||
@@ -0,0 +1 @@
|
||||
SUBSYSTEM=="net", ACTION=="add", TEST=="/sys/class/net/$name/wireless", NAME="wifi%n"
|
||||
@@ -90,9 +90,9 @@ reset-reason {
|
||||
|
||||
# Monitors file descriptor leaks based on /proc/sys/fs/file-nr
|
||||
filenr {
|
||||
enabled = true
|
||||
interval = 3600
|
||||
logmark = true
|
||||
# enabled = true
|
||||
interval = 300
|
||||
logmark = false
|
||||
warning = 0.9
|
||||
critical = 1.0
|
||||
# script = "/path/to/alt-reboot-action.sh"
|
||||
@@ -102,42 +102,33 @@ filenr {
|
||||
# The script is called with fsmon as the first argument and there
|
||||
# are two environment variables FSMON_NAME, for the monitored path,
|
||||
# and FSMON_TYPE indicating either 'blocks' or 'inodes'.
|
||||
fsmon /var {
|
||||
enabled = true
|
||||
interval = 3600
|
||||
logmark = true
|
||||
warning = 0.95
|
||||
critical = 1.0
|
||||
# script = "/path/to/alt-reboot-action.sh"
|
||||
}
|
||||
|
||||
fsmon /tmp {
|
||||
enabled = true
|
||||
interval = 3600
|
||||
logmark = true
|
||||
warning = 0.95
|
||||
critical = 1.0
|
||||
# script = "/path/to/alt-reboot-action.sh"
|
||||
}
|
||||
|
||||
# Monitors load average based on sysinfo() from /proc/loadavg
|
||||
# The level is composed from the average of the 1 and 5 min marks.
|
||||
#loadavg {
|
||||
#fsmon /var {
|
||||
# enabled = true
|
||||
# interval = 300
|
||||
# logmark = true
|
||||
# warning = 1.0
|
||||
# critical = 2.0
|
||||
# logmark = false
|
||||
# warning = 0.95
|
||||
# critical = 1.0
|
||||
# script = "/path/to/alt-reboot-action.sh"
|
||||
#}
|
||||
|
||||
# Monitors load average based on sysinfo() from /proc/loadavg
|
||||
# The level is composed from the average of the 1 and 5 min marks.
|
||||
loadavg {
|
||||
# enabled = true
|
||||
interval = 300
|
||||
logmark = false
|
||||
warning = 1.0
|
||||
critical = 2.0
|
||||
# script = "/path/to/alt-reboot-action.sh"
|
||||
}
|
||||
|
||||
# Monitors free RAM based on data from /proc/meminfo
|
||||
meminfo {
|
||||
enabled = true
|
||||
interval = 3600
|
||||
logmark = true
|
||||
# enabled = true
|
||||
interval = 300
|
||||
logmark = false
|
||||
warning = 0.9
|
||||
critical = 0.97
|
||||
critical = 0.95
|
||||
# script = "/path/to/alt-reboot-action.sh"
|
||||
}
|
||||
|
||||
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
# User-friendly wrapper for sysrepocfg
|
||||
# TODO: add import/export, copy, ...
|
||||
|
||||
# Edit YANG binary types using sysrepo, base64, and duct tape.
|
||||
edit()
|
||||
{
|
||||
xpath=$1
|
||||
if [ -z "$xpath" ]; then
|
||||
echo "Usage: cfg edit \"/full/xpath/to/binary/leaf\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if tmp=$(sysrepocfg -G "$xpath"); then
|
||||
file=$(mktemp)
|
||||
|
||||
echo "$tmp" | base64 -d > "$file"
|
||||
if /usr/bin/editor "$file"; then
|
||||
tmp=$(base64 -w0 < "$file")
|
||||
sysrepocfg -S "$xpath" -u "$tmp"
|
||||
fi
|
||||
|
||||
rm -f "$file"
|
||||
else
|
||||
echo "Failed to retrieve value for $xpath"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "Usage:"
|
||||
echo " cfg CMD [ARG]"
|
||||
echo
|
||||
echo "Command:"
|
||||
echo " edit XPATH Edit YANG binary type"
|
||||
echo " help This help text"
|
||||
echo
|
||||
echo "As a backwards compatible fallback, this script forwards"
|
||||
echo "all other commands as options to sysrepocfg."
|
||||
echo
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
cmd=$1; shift
|
||||
case $cmd in
|
||||
edit)
|
||||
edit "$1"
|
||||
;;
|
||||
help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
set -- "$cmd" "$@"
|
||||
exec sysrepocfg -f json "$@"
|
||||
;;
|
||||
esac
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
/etc/alternatives/editor
|
||||
@@ -91,7 +91,7 @@ EOF
|
||||
|
||||
is_dhcp_running()
|
||||
{
|
||||
copy operational -x /infix-dhcp-server:dhcp-server | jq -r '
|
||||
sysrepocfg -X -f json -m infix-dhcp-server | jq -r '
|
||||
."infix-dhcp-server:dhcp-server".enabled as $global |
|
||||
if ."infix-dhcp-server:dhcp-server".subnet? then
|
||||
(."infix-dhcp-server:dhcp-server".subnet[] |
|
||||
@@ -110,15 +110,15 @@ dhcp()
|
||||
|
||||
case $1 in
|
||||
detail)
|
||||
copy operational -x /infix-dhcp-server:dhcp-server | \
|
||||
sysrepocfg -f json -X -d operational -m infix-dhcp-server | \
|
||||
jq -C .
|
||||
;;
|
||||
stat*)
|
||||
copy operational -x /infix-dhcp-server:dhcp-server | \
|
||||
sysrepocfg -f json -X -d operational -m infix-dhcp-server | \
|
||||
/usr/libexec/statd/cli-pretty "show-dhcp-server" -s
|
||||
;;
|
||||
*)
|
||||
copy operational -x /infix-dhcp-server:dhcp-server | \
|
||||
sysrepocfg -f json -X -d operational -m infix-dhcp-server | \
|
||||
/usr/libexec/statd/cli-pretty "show-dhcp-server"
|
||||
;;
|
||||
esac
|
||||
@@ -182,13 +182,13 @@ ifaces()
|
||||
else
|
||||
if [ $# -gt 0 ]; then
|
||||
for iface in $*; do
|
||||
copy operational -x \
|
||||
sysrepocfg -f json -X -d operational -x \
|
||||
"/ietf-interfaces:interfaces/interface[name='$iface']" | \
|
||||
/usr/libexec/statd/cli-pretty "show-interfaces" -n "$iface"
|
||||
done
|
||||
return
|
||||
fi
|
||||
copy operational -x /ietf-interfaces:interfaces | \
|
||||
sysrepocfg -f json -X -d operational -m ietf-interfaces | \
|
||||
/usr/libexec/statd/cli-pretty "show-interfaces"
|
||||
fi
|
||||
}
|
||||
@@ -227,7 +227,7 @@ rstp()
|
||||
|
||||
stp()
|
||||
{
|
||||
copy operational -x /ietf-interfaces:interfaces | \
|
||||
sysrepocfg -f json -X -d operational -m ietf-interfaces | \
|
||||
/usr/libexec/statd/cli-pretty "show-bridge-stp"
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ routes()
|
||||
else
|
||||
arg="-i ipv4"
|
||||
fi
|
||||
copy operational -x /ietf-routing:routing/ribs | \
|
||||
sysrepocfg -f json -X -d operational -x "/ietf-routing:routing/ribs" | \
|
||||
/usr/libexec/statd/cli-pretty "show-routing-table" $arg
|
||||
}
|
||||
|
||||
|
||||
@@ -1,600 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
iw command wrapper that returns structured JSON data
|
||||
|
||||
Usage:
|
||||
iw.py list - List all PHY devices
|
||||
iw.py dev - List all interfaces grouped by PHY
|
||||
iw.py info <device> - Get PHY or interface information
|
||||
iw.py survey <interface> - Get channel survey data
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import re
|
||||
def decode_iw_ssid(ssid):
|
||||
"""Decode iw escaped SSID (\\xHH) to UTF-8, stripping non-printable chars."""
|
||||
try:
|
||||
ssid = ssid.encode().decode('unicode_escape').encode('latin-1').decode('utf-8')
|
||||
except (UnicodeDecodeError, UnicodeEncodeError):
|
||||
return ssid
|
||||
return ''.join(c for c in ssid if c.isprintable())
|
||||
|
||||
|
||||
def run_iw(*args):
|
||||
"""Run iw command and return output"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['iw'] + list(args),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return result.stdout
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def normalize_phy_name(name):
|
||||
"""
|
||||
Convert radioN to phyN or vice versa based on what exists in sysfs.
|
||||
Returns the actual phy name that exists.
|
||||
"""
|
||||
import os
|
||||
|
||||
# Try the name as-is first
|
||||
if os.path.exists(f'/sys/class/ieee80211/{name}'):
|
||||
return name
|
||||
|
||||
# Try converting radioN <-> phyN
|
||||
if name.startswith('radio'):
|
||||
phy_name = 'phy' + name[5:]
|
||||
if os.path.exists(f'/sys/class/ieee80211/{phy_name}'):
|
||||
return phy_name
|
||||
elif name.startswith('phy'):
|
||||
radio_name = 'radio' + name[3:]
|
||||
if os.path.exists(f'/sys/class/ieee80211/{radio_name}'):
|
||||
return radio_name
|
||||
|
||||
# Return original if nothing found
|
||||
return name
|
||||
|
||||
|
||||
def parse_phy_info(phy_name):
|
||||
"""
|
||||
Parse 'iw phy <name> info' output or 'iw <name> info' output
|
||||
Returns: {bands, driver, manufacturer, max_txpower, num_virtual_interfaces, interface_combinations}
|
||||
"""
|
||||
# Normalize the phy name
|
||||
actual_phy = normalize_phy_name(phy_name)
|
||||
|
||||
# Try 'iw phy <name> info' first
|
||||
output = run_iw('phy', actual_phy, 'info')
|
||||
|
||||
# If that fails, try 'iw <name> info' (some systems support this)
|
||||
if not output:
|
||||
output = run_iw(actual_phy, 'info')
|
||||
|
||||
if not output:
|
||||
return {}
|
||||
|
||||
result = {
|
||||
'name': phy_name,
|
||||
'bands': [],
|
||||
'driver': None,
|
||||
'manufacturer': None,
|
||||
'max_txpower': None,
|
||||
'num_virtual_interfaces': 0,
|
||||
'interface_combinations': []
|
||||
}
|
||||
|
||||
current_band = None
|
||||
band_num = 0
|
||||
in_combinations = False
|
||||
max_power = None
|
||||
|
||||
for line in output.splitlines():
|
||||
stripped = line.strip()
|
||||
|
||||
# Detect band sections
|
||||
if stripped.startswith('Band '):
|
||||
if current_band and current_band.get('frequencies'):
|
||||
result['bands'].append(current_band)
|
||||
band_num += 1
|
||||
current_band = {
|
||||
'band': band_num,
|
||||
'frequencies': [],
|
||||
'name': None,
|
||||
'ht_capable': False,
|
||||
'vht_capable': False,
|
||||
'he_capable': False
|
||||
}
|
||||
in_combinations = False
|
||||
|
||||
# Parse frequencies (handle both "2412 MHz" and "2412.0 MHz" formats)
|
||||
elif current_band and not in_combinations:
|
||||
freq_match = re.match(r'\* ([0-9.]+) MHz.*?\(([0-9.]+) dBm\)', stripped)
|
||||
if freq_match:
|
||||
freq = int(float(freq_match.group(1))) # Convert "2412.0" to 2412
|
||||
power = float(freq_match.group(2))
|
||||
|
||||
current_band['frequencies'].append(freq)
|
||||
|
||||
# Track max power
|
||||
if max_power is None or power > max_power:
|
||||
max_power = power
|
||||
|
||||
# Check capabilities
|
||||
if 'HT ' in stripped or 'High Throughput' in stripped:
|
||||
current_band['ht_capable'] = True
|
||||
if 'VHT' in stripped or 'Very High Throughput' in stripped:
|
||||
current_band['vht_capable'] = True
|
||||
if 'HE ' in stripped or 'High Efficiency' in stripped:
|
||||
current_band['he_capable'] = True
|
||||
|
||||
# Detect interface combinations section
|
||||
if 'valid interface combinations:' in stripped.lower():
|
||||
in_combinations = True
|
||||
continue
|
||||
|
||||
# Parse interface combinations
|
||||
if in_combinations:
|
||||
if stripped.startswith('*'):
|
||||
# Parse combination line
|
||||
comb_info = {'limits': []}
|
||||
|
||||
# Parse limits: #{ type } <= max
|
||||
limit_matches = re.findall(r'#\{\s*([^}]+)\s*\}\s*<=\s*(\d+)', stripped)
|
||||
for types_str, max_val in limit_matches:
|
||||
types = [t.strip() for t in types_str.split(',')]
|
||||
comb_info['limits'].append({
|
||||
'max': int(max_val),
|
||||
'types': types
|
||||
})
|
||||
|
||||
# Parse total
|
||||
total_match = re.search(r'total\s*<=\s*(\d+)', stripped)
|
||||
if total_match:
|
||||
comb_info['max_total'] = int(total_match.group(1))
|
||||
|
||||
# Parse channels
|
||||
channels_match = re.search(r'#channels\s*<=\s*(\d+)', stripped)
|
||||
if channels_match:
|
||||
comb_info['num_channels'] = int(channels_match.group(1))
|
||||
|
||||
if comb_info.get('limits') or comb_info.get('max_total'):
|
||||
result['interface_combinations'].append(comb_info)
|
||||
|
||||
elif not stripped.startswith('#') and ':' in stripped and not stripped.startswith('*'):
|
||||
# End of combinations section
|
||||
in_combinations = False
|
||||
|
||||
# Add last band
|
||||
if current_band and current_band.get('frequencies'):
|
||||
result['bands'].append(current_band)
|
||||
|
||||
# Determine band names and assign band numbers
|
||||
for band in result['bands']:
|
||||
if band['frequencies']:
|
||||
freq = band['frequencies'][0]
|
||||
if 2400 <= freq <= 2500:
|
||||
band['name'] = '2.4GHz'
|
||||
band['band'] = 1
|
||||
elif 5150 <= freq <= 5900:
|
||||
band['name'] = '5GHz'
|
||||
band['band'] = 2
|
||||
elif 5955 <= freq <= 7115:
|
||||
band['name'] = '6GHz'
|
||||
band['band'] = 3
|
||||
|
||||
# Set max TX power
|
||||
if max_power is not None:
|
||||
result['max_txpower'] = int(max_power)
|
||||
|
||||
# Get driver and manufacturer from sysfs
|
||||
try:
|
||||
driver_link = subprocess.run(
|
||||
['readlink', '-f', f'/sys/class/ieee80211/{actual_phy}/device/driver'],
|
||||
capture_output=True, text=True, timeout=1
|
||||
).stdout.strip()
|
||||
|
||||
if driver_link:
|
||||
driver_name = driver_link.split('/')[-1]
|
||||
result['driver'] = driver_name
|
||||
|
||||
# Map driver to manufacturer
|
||||
driver_lower = driver_name.lower()
|
||||
if 'mt' in driver_lower or 'mediatek' in driver_lower:
|
||||
result['manufacturer'] = 'MediaTek Inc.'
|
||||
elif 'rtw' in driver_lower or 'realtek' in driver_lower:
|
||||
result['manufacturer'] = 'Realtek Semiconductor Corp.'
|
||||
elif 'ath' in driver_lower or 'qca' in driver_lower:
|
||||
result['manufacturer'] = 'Qualcomm Atheros'
|
||||
elif 'iwl' in driver_lower or 'intel' in driver_lower:
|
||||
result['manufacturer'] = 'Intel Corporation'
|
||||
elif 'brcm' in driver_lower or 'broadcom' in driver_lower:
|
||||
result['manufacturer'] = 'Broadcom Inc.'
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Count virtual interfaces
|
||||
dev_output = run_iw('dev')
|
||||
if dev_output:
|
||||
# Extract phy number from actual phy name
|
||||
phy_num = None
|
||||
if actual_phy.startswith('radio'):
|
||||
phy_num = actual_phy[5:]
|
||||
elif actual_phy.startswith('phy'):
|
||||
phy_num = actual_phy[3:]
|
||||
|
||||
if phy_num:
|
||||
count = 0
|
||||
current_phy = None
|
||||
for line in dev_output.splitlines():
|
||||
if line.startswith('phy#'):
|
||||
current_phy = line.replace('phy#', '').strip()
|
||||
elif current_phy == phy_num and 'Interface' in line:
|
||||
count += 1
|
||||
result['num_virtual_interfaces'] = count
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def parse_interface_info(ifname):
|
||||
"""
|
||||
Parse 'iw dev <name> info' output
|
||||
Returns: {ifname, iftype, mac, ssid, frequency, channel, txpower, channel_width}
|
||||
"""
|
||||
output = run_iw('dev', ifname, 'info')
|
||||
if not output:
|
||||
return {}
|
||||
|
||||
result = {'ifname': ifname}
|
||||
|
||||
for line in output.splitlines():
|
||||
stripped = line.strip()
|
||||
|
||||
# Interface type
|
||||
if stripped.startswith('type '):
|
||||
result['iftype'] = stripped.split()[1]
|
||||
|
||||
# MAC address
|
||||
elif stripped.startswith('addr '):
|
||||
result['mac'] = stripped.split()[1]
|
||||
|
||||
# SSID
|
||||
elif stripped.startswith('ssid '):
|
||||
result['ssid'] = decode_iw_ssid(' '.join(stripped.split()[1:]))
|
||||
|
||||
# Channel/frequency
|
||||
elif stripped.startswith('channel '):
|
||||
parts = stripped.split()
|
||||
if len(parts) >= 2:
|
||||
result['channel'] = int(parts[1])
|
||||
if 'MHz' in stripped:
|
||||
freq_match = re.search(r'\((\d+) MHz', stripped)
|
||||
if freq_match:
|
||||
result['frequency'] = int(freq_match.group(1))
|
||||
# Channel width
|
||||
if 'width:' in stripped:
|
||||
width_match = re.search(r'width:\s*(\d+)\s*MHz', stripped)
|
||||
if width_match:
|
||||
result['channel_width'] = f"{width_match.group(1)} MHz"
|
||||
|
||||
# TX power
|
||||
elif stripped.startswith('txpower '):
|
||||
power_match = re.search(r'([0-9.]+) dBm', stripped)
|
||||
if power_match:
|
||||
result['txpower'] = float(power_match.group(1))
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def parse_stations(ifname):
|
||||
"""
|
||||
Parse 'iw dev <name> station dump' output
|
||||
Returns: list of connected stations with stats
|
||||
"""
|
||||
output = run_iw('dev', ifname, 'station', 'dump')
|
||||
if not output:
|
||||
return []
|
||||
|
||||
stations = []
|
||||
current = None
|
||||
|
||||
for line in output.splitlines():
|
||||
stripped = line.strip()
|
||||
|
||||
# New station entry: "Station aa:bb:cc:dd:ee:ff (on wifiX)"
|
||||
if stripped.startswith('Station '):
|
||||
if current:
|
||||
stations.append(current)
|
||||
parts = stripped.split()
|
||||
if len(parts) >= 2:
|
||||
current = {'mac-address': parts[1].lower()}
|
||||
else:
|
||||
current = None
|
||||
continue
|
||||
|
||||
if not current or ':' not in stripped:
|
||||
continue
|
||||
|
||||
key, _, value = stripped.partition(':')
|
||||
key = key.strip()
|
||||
value = value.strip()
|
||||
|
||||
try:
|
||||
if key == 'signal':
|
||||
# Format: "-42 dBm" or "-42 [-44, -45] dBm"
|
||||
current['signal-strength'] = int(value.split()[0])
|
||||
elif key == 'connected time':
|
||||
# Format: "123 seconds"
|
||||
current['connected-time'] = int(value.split()[0])
|
||||
elif key == 'rx bytes':
|
||||
current['rx-bytes'] = value # counter64: string-encoded
|
||||
elif key == 'tx bytes':
|
||||
current['tx-bytes'] = value # counter64: string-encoded
|
||||
elif key == 'rx packets':
|
||||
current['rx-packets'] = value # counter64: string-encoded
|
||||
elif key == 'tx packets':
|
||||
current['tx-packets'] = value # counter64: string-encoded
|
||||
elif key == 'tx bitrate':
|
||||
# Format: "866.7 MBit/s ..." - convert to 100kbit/s units
|
||||
speed_mbps = float(value.split()[0])
|
||||
current['tx-speed'] = int(speed_mbps * 10)
|
||||
elif key == 'rx bitrate':
|
||||
speed_mbps = float(value.split()[0])
|
||||
current['rx-speed'] = int(speed_mbps * 10)
|
||||
elif key == 'inactive time':
|
||||
# Format: "1234 ms"
|
||||
current['inactive-time'] = int(value.split()[0])
|
||||
except (ValueError, IndexError):
|
||||
continue
|
||||
|
||||
if current:
|
||||
stations.append(current)
|
||||
|
||||
return stations
|
||||
|
||||
|
||||
def parse_survey(ifname):
|
||||
"""
|
||||
Parse 'iw dev <name> survey dump' output
|
||||
Returns: list of {frequency, in_use, noise, active_time, busy_time, receive_time, transmit_time}
|
||||
"""
|
||||
output = run_iw('dev', ifname, 'survey', 'dump')
|
||||
if not output:
|
||||
return []
|
||||
|
||||
channels = []
|
||||
current_channel = None
|
||||
|
||||
for line in output.splitlines():
|
||||
stripped = line.strip()
|
||||
|
||||
# New survey entry
|
||||
if stripped.startswith('Survey data from'):
|
||||
if current_channel:
|
||||
channels.append(current_channel)
|
||||
current_channel = None
|
||||
|
||||
# Frequency
|
||||
elif stripped.startswith('frequency:'):
|
||||
parts = stripped.split()
|
||||
if len(parts) >= 2:
|
||||
freq = int(parts[1])
|
||||
in_use = '[in use]' in stripped
|
||||
current_channel = {
|
||||
'frequency': freq,
|
||||
'in_use': in_use
|
||||
}
|
||||
|
||||
# Channel metrics
|
||||
elif current_channel:
|
||||
if stripped.startswith('noise:'):
|
||||
noise_match = re.search(r'(-?\d+) dBm', stripped)
|
||||
if noise_match:
|
||||
current_channel['noise'] = int(noise_match.group(1))
|
||||
|
||||
elif stripped.startswith('channel active time:'):
|
||||
time_match = re.search(r'(\d+) ms', stripped)
|
||||
if time_match:
|
||||
current_channel['active_time'] = int(time_match.group(1))
|
||||
|
||||
elif stripped.startswith('channel busy time:'):
|
||||
time_match = re.search(r'(\d+) ms', stripped)
|
||||
if time_match:
|
||||
current_channel['busy_time'] = int(time_match.group(1))
|
||||
|
||||
elif stripped.startswith('channel receive time:'):
|
||||
time_match = re.search(r'(\d+) ms', stripped)
|
||||
if time_match:
|
||||
current_channel['receive_time'] = int(time_match.group(1))
|
||||
|
||||
elif stripped.startswith('channel transmit time:'):
|
||||
time_match = re.search(r'(\d+) ms', stripped)
|
||||
if time_match:
|
||||
current_channel['transmit_time'] = int(time_match.group(1))
|
||||
|
||||
# Add last channel
|
||||
if current_channel:
|
||||
channels.append(current_channel)
|
||||
|
||||
return channels
|
||||
|
||||
|
||||
def parse_list():
|
||||
"""
|
||||
Parse 'iw list' output
|
||||
Returns: list of PHY names
|
||||
"""
|
||||
output = run_iw('list')
|
||||
if not output:
|
||||
return []
|
||||
|
||||
phys = []
|
||||
for line in output.splitlines():
|
||||
match = re.match(r'Wiphy (phy\d+|radio\d+)', line)
|
||||
if match:
|
||||
phys.append(match.group(1))
|
||||
|
||||
return phys
|
||||
|
||||
|
||||
def parse_dev():
|
||||
"""
|
||||
Parse 'iw dev' output
|
||||
Returns: dict mapping PHY numbers to list of interfaces
|
||||
"""
|
||||
output = run_iw('dev')
|
||||
if not output:
|
||||
return {}
|
||||
|
||||
result = {}
|
||||
current_phy = None
|
||||
|
||||
for line in output.splitlines():
|
||||
# PHY line: "phy#0" or "phy#1"
|
||||
if line.startswith('phy#'):
|
||||
current_phy = line.replace('phy#', '').strip()
|
||||
if current_phy not in result:
|
||||
result[current_phy] = []
|
||||
# Interface line: " Interface wlan0"
|
||||
elif current_phy and 'Interface' in line:
|
||||
ifname = line.split('Interface')[1].strip()
|
||||
result[current_phy].append(ifname)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def parse_link(ifname):
|
||||
"""
|
||||
Parse 'iw dev <name> link' output for station mode
|
||||
Returns: {connected, bssid, ssid, frequency, signal, tx_bitrate, rx_bitrate}
|
||||
"""
|
||||
output = run_iw('dev', ifname, 'link')
|
||||
if not output:
|
||||
return {'connected': False}
|
||||
|
||||
if 'Not connected' in output:
|
||||
return {'connected': False}
|
||||
|
||||
result = {'connected': True}
|
||||
|
||||
for line in output.splitlines():
|
||||
stripped = line.strip()
|
||||
|
||||
# Connected to aa:bb:cc:dd:ee:ff
|
||||
if stripped.startswith('Connected to '):
|
||||
parts = stripped.split()
|
||||
if len(parts) >= 3:
|
||||
result['bssid'] = parts[2].lower()
|
||||
|
||||
# SSID: NetworkName
|
||||
elif stripped.startswith('SSID: '):
|
||||
result['ssid'] = decode_iw_ssid(stripped[6:])
|
||||
|
||||
# freq: 5180
|
||||
elif stripped.startswith('freq: '):
|
||||
try:
|
||||
result['frequency'] = int(stripped[6:])
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# signal: -42 dBm
|
||||
elif stripped.startswith('signal: '):
|
||||
try:
|
||||
result['signal-strength'] = int(stripped.split()[1])
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
# tx bitrate: 866.7 MBit/s ...
|
||||
elif stripped.startswith('tx bitrate: '):
|
||||
try:
|
||||
speed = float(stripped.split()[2])
|
||||
result['tx-speed'] = int(speed * 10) # 100kbit/s units
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
# rx bitrate: 780.0 MBit/s ...
|
||||
elif stripped.startswith('rx bitrate: '):
|
||||
try:
|
||||
speed = float(stripped.split()[2])
|
||||
result['rx-speed'] = int(speed * 10)
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print(json.dumps({
|
||||
'error': 'Usage: iw.py <command> [device]',
|
||||
'commands': {
|
||||
'list': 'List all PHY devices',
|
||||
'dev': 'List all interfaces grouped by PHY',
|
||||
'info': 'Get PHY or interface information (requires device)',
|
||||
'survey': 'Get channel survey data (requires interface)',
|
||||
'station': 'Get connected stations in AP mode (requires interface)',
|
||||
'link': 'Get link info in station mode (requires interface)'
|
||||
},
|
||||
'examples': [
|
||||
'iw.py list',
|
||||
'iw.py dev',
|
||||
'iw.py info radio0',
|
||||
'iw.py info wlan0',
|
||||
'iw.py station wifi0',
|
||||
'iw.py link wlan0',
|
||||
'iw.py survey wlan0'
|
||||
]
|
||||
}, indent=2))
|
||||
sys.exit(1)
|
||||
|
||||
command = sys.argv[1]
|
||||
|
||||
try:
|
||||
if command == 'list':
|
||||
data = parse_list()
|
||||
elif command == 'dev':
|
||||
data = parse_dev()
|
||||
elif command == 'info':
|
||||
if len(sys.argv) < 3:
|
||||
data = {'error': 'info command requires device argument'}
|
||||
else:
|
||||
device = sys.argv[2]
|
||||
# Auto-detect if device is a PHY (phy*/radio*) or interface
|
||||
if device.startswith('phy') or device.startswith('radio'):
|
||||
data = parse_phy_info(device)
|
||||
else:
|
||||
data = parse_interface_info(device)
|
||||
elif command == 'station':
|
||||
if len(sys.argv) < 3:
|
||||
data = {'error': 'station command requires interface argument'}
|
||||
else:
|
||||
data = parse_stations(sys.argv[2])
|
||||
elif command == 'link':
|
||||
if len(sys.argv) < 3:
|
||||
data = {'error': 'link command requires interface argument'}
|
||||
else:
|
||||
data = parse_link(sys.argv[2])
|
||||
elif command == 'survey':
|
||||
if len(sys.argv) < 3:
|
||||
data = {'error': 'survey command requires interface argument'}
|
||||
else:
|
||||
data = parse_survey(sys.argv[2])
|
||||
else:
|
||||
data = {'error': f'Unknown command: {command}'}
|
||||
|
||||
print(json.dumps(data, indent=2, ensure_ascii=False))
|
||||
|
||||
except Exception as e:
|
||||
print(json.dumps({'error': str(e)}))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,724 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
WiFi Channel Visualization Tool
|
||||
Shows graphical representation of WiFi channel overlap and utilization
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
|
||||
|
||||
class Colors:
|
||||
"""ANSI color codes for terminal output"""
|
||||
RESET = '\033[0m'
|
||||
BOLD = '\033[1m'
|
||||
RED = '\033[91m'
|
||||
GREEN = '\033[92m'
|
||||
YELLOW = '\033[93m'
|
||||
BLUE = '\033[94m'
|
||||
MAGENTA = '\033[95m'
|
||||
CYAN = '\033[96m'
|
||||
GRAY = '\033[90m'
|
||||
BG_RED = '\033[101m'
|
||||
BG_GREEN = '\033[102m'
|
||||
BG_YELLOW = '\033[103m'
|
||||
BG_BLUE = '\033[104m'
|
||||
BG_GRAY = '\033[100m'
|
||||
|
||||
|
||||
def freq_to_channel(freq):
|
||||
"""Convert frequency (MHz) to WiFi channel number"""
|
||||
# 2.4 GHz band
|
||||
if 2412 <= freq <= 2484:
|
||||
if freq == 2484:
|
||||
return 14
|
||||
return (freq - 2412) // 5 + 1
|
||||
# 5 GHz band
|
||||
elif 5170 <= freq <= 5825:
|
||||
return (freq - 5000) // 5
|
||||
# 6 GHz band
|
||||
elif 5955 <= freq <= 7115:
|
||||
return (freq - 5950) // 5
|
||||
return None
|
||||
|
||||
|
||||
def get_channel_frequency(channel, band='2.4'):
|
||||
"""Get center frequency for a channel"""
|
||||
if band == '2.4':
|
||||
if channel == 14:
|
||||
return 2484
|
||||
return 2412 + (channel - 1) * 5
|
||||
elif band == '5':
|
||||
return 5000 + channel * 5
|
||||
return None
|
||||
|
||||
|
||||
def get_busy_percentage(channel_data):
|
||||
"""Calculate channel busy percentage"""
|
||||
active = channel_data.get('active-time', 0)
|
||||
busy = channel_data.get('busy-time', 0)
|
||||
if active > 0:
|
||||
return (busy / active) * 100
|
||||
return 0
|
||||
|
||||
|
||||
def get_utilization_color(busy_pct):
|
||||
"""Get color based on channel utilization"""
|
||||
if busy_pct >= 50:
|
||||
return Colors.RED
|
||||
elif busy_pct >= 25:
|
||||
return Colors.YELLOW
|
||||
elif busy_pct >= 10:
|
||||
return Colors.CYAN
|
||||
else:
|
||||
return Colors.GREEN
|
||||
|
||||
|
||||
def draw_channel_graph_2_4ghz(survey_data):
|
||||
"""Draw channel overlap graph for 2.4 GHz band"""
|
||||
# Parse survey data
|
||||
channels = {}
|
||||
in_use_channel = None
|
||||
|
||||
for ch_data in survey_data:
|
||||
freq = ch_data.get('frequency')
|
||||
ch_num = freq_to_channel(freq)
|
||||
if ch_num and 1 <= ch_num <= 14:
|
||||
busy_pct = get_busy_percentage(ch_data)
|
||||
channels[ch_num] = {
|
||||
'freq': freq,
|
||||
'noise': ch_data.get('noise', -100),
|
||||
'busy': busy_pct,
|
||||
'in_use': ch_data.get('in-use', False),
|
||||
'active_time': ch_data.get('active-time', 0),
|
||||
'busy_time': ch_data.get('busy-time', 0)
|
||||
}
|
||||
if ch_data.get('in-use'):
|
||||
in_use_channel = ch_num
|
||||
|
||||
if not channels:
|
||||
print("No 2.4 GHz channel data available")
|
||||
return
|
||||
|
||||
print(f"\n{Colors.BOLD}2.4 GHz WiFi Channel Overlap Visualization{Colors.RESET}")
|
||||
print("=" * 80)
|
||||
print(f"Channel width: 20 MHz | Channel spacing: 5 MHz")
|
||||
print(f"Non-overlapping channels: 1, 6, 11 (shown in {Colors.GREEN}green{Colors.RESET})")
|
||||
print()
|
||||
|
||||
# Draw frequency scale
|
||||
print("Frequency (MHz):")
|
||||
print("2400 2420 2440 2460 2480")
|
||||
print("|-----------|-----------|-----------|-----------|")
|
||||
|
||||
# Draw each channel as a bar showing its 20 MHz width
|
||||
# Each channel occupies ~4 adjacent channels worth of space
|
||||
for ch in range(1, 14):
|
||||
if ch not in channels:
|
||||
continue
|
||||
|
||||
data = channels[ch]
|
||||
busy_pct = data['busy']
|
||||
is_in_use = data['in_use']
|
||||
noise = data['noise']
|
||||
|
||||
# Determine color based on status
|
||||
if is_in_use:
|
||||
color = Colors.BG_BLUE
|
||||
marker = '█'
|
||||
elif busy_pct >= 50:
|
||||
color = Colors.RED
|
||||
marker = '▓'
|
||||
elif busy_pct >= 25:
|
||||
color = Colors.YELLOW
|
||||
marker = '▒'
|
||||
elif busy_pct > 0:
|
||||
color = Colors.CYAN
|
||||
marker = '░'
|
||||
else:
|
||||
color = Colors.GRAY
|
||||
marker = '·'
|
||||
|
||||
# Non-overlapping channels get green color
|
||||
if ch in [1, 6, 11] and not is_in_use and busy_pct < 10:
|
||||
color = Colors.GREEN
|
||||
|
||||
# Calculate position (each channel is offset by 5 MHz = 1 position)
|
||||
# Channel 1 is at 2412 MHz, base is 2400
|
||||
offset = ((data['freq'] - 2400) // 5)
|
||||
|
||||
# Draw channel bar (20 MHz = 4 positions wide)
|
||||
line = ' ' * 80
|
||||
line_arr = list(line)
|
||||
|
||||
# Mark the channel span (20 MHz width)
|
||||
for i in range(4):
|
||||
pos = offset + i - 2 # Center the 20 MHz around channel
|
||||
if 0 <= pos < len(line_arr):
|
||||
line_arr[pos] = marker
|
||||
|
||||
# Add channel label
|
||||
label_pos = offset
|
||||
if 0 <= label_pos < len(line_arr) - 5:
|
||||
# Clear space for label
|
||||
for i in range(5):
|
||||
if label_pos + i < len(line_arr):
|
||||
line_arr[label_pos + i] = ' '
|
||||
|
||||
line = ''.join(line_arr)
|
||||
|
||||
# Status indicators
|
||||
status = ""
|
||||
if is_in_use:
|
||||
status = f" {Colors.BOLD}[IN USE]{Colors.RESET}"
|
||||
|
||||
busy_color = get_utilization_color(busy_pct)
|
||||
|
||||
print(f"{color}Ch{ch:2d}{Colors.RESET} {color}{line}{Colors.RESET} "
|
||||
f"{busy_color}{busy_pct:5.1f}%{Colors.RESET} "
|
||||
f"{noise:4d}dBm{status}")
|
||||
|
||||
print("\n" + "=" * 80)
|
||||
print(f"\n{Colors.BOLD}Legend:{Colors.RESET}")
|
||||
print(f" {Colors.BG_BLUE}██{Colors.RESET} In use (your network)")
|
||||
print(f" {Colors.RED}▓▓{Colors.RESET} High usage (>50%)")
|
||||
print(f" {Colors.YELLOW}▒▒{Colors.RESET} Medium usage (25-50%)")
|
||||
print(f" {Colors.CYAN}░░{Colors.RESET} Low usage (1-25%)")
|
||||
print(f" {Colors.GRAY}··{Colors.RESET} Idle (<1%)")
|
||||
print()
|
||||
|
||||
|
||||
def draw_channel_list(survey_data):
|
||||
"""Draw a simple channel list with utilization bars"""
|
||||
print(f"\n{Colors.BOLD}Channel Utilization{Colors.RESET}")
|
||||
print("=" * 80)
|
||||
print(f"{'Ch':<4} {'Freq':<6} {'Noise':<8} {'Busy%':<8} {'Utilization Bar':<40}")
|
||||
print("-" * 80)
|
||||
|
||||
for ch_data in sorted(survey_data, key=lambda x: x.get('frequency', 0)):
|
||||
freq = ch_data.get('frequency')
|
||||
ch_num = freq_to_channel(freq)
|
||||
if not ch_num:
|
||||
continue
|
||||
|
||||
noise = ch_data.get('noise', -100)
|
||||
busy_pct = get_busy_percentage(ch_data)
|
||||
is_in_use = ch_data.get('in-use', False)
|
||||
|
||||
# Create utilization bar (40 chars wide = 100%)
|
||||
bar_length = int(busy_pct * 40 / 100)
|
||||
bar_color = get_utilization_color(busy_pct)
|
||||
|
||||
if is_in_use:
|
||||
bar = f"{Colors.BG_BLUE}{'█' * bar_length}{Colors.RESET}"
|
||||
marker = f" {Colors.BOLD}◀ IN USE{Colors.RESET}"
|
||||
else:
|
||||
bar = f"{bar_color}{'█' * bar_length}{Colors.RESET}"
|
||||
marker = ""
|
||||
|
||||
empty = '░' * (40 - bar_length)
|
||||
|
||||
print(f"{ch_num:<4} {freq:<6} {noise:<8} {busy_pct:5.1f}% {bar}{Colors.GRAY}{empty}{Colors.RESET}{marker}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def draw_overlap_pie(survey_data):
|
||||
"""Draw a pie-style visualization of channel group utilization"""
|
||||
# Parse channel data into 3 non-overlapping groups
|
||||
# Group 1: channels 1-5 (centered on ch 1)
|
||||
# Group 2: channels 4-8 (centered on ch 6)
|
||||
# Group 3: channels 9-13 (centered on ch 11)
|
||||
|
||||
channels = {}
|
||||
in_use_channel = None
|
||||
|
||||
for ch_data in survey_data:
|
||||
freq = ch_data.get('frequency')
|
||||
ch_num = freq_to_channel(freq)
|
||||
if ch_num and 1 <= ch_num <= 13:
|
||||
busy_pct = get_busy_percentage(ch_data)
|
||||
channels[ch_num] = {
|
||||
'busy': busy_pct,
|
||||
'noise': ch_data.get('noise', -100),
|
||||
'in_use': ch_data.get('in-use', False)
|
||||
}
|
||||
if ch_data.get('in-use'):
|
||||
in_use_channel = ch_num
|
||||
|
||||
if not channels:
|
||||
return
|
||||
|
||||
# Calculate group utilization (average of channels in each group)
|
||||
groups = [
|
||||
{'name': 'Ch 1', 'channels': [1, 2, 3, 4, 5], 'center': 1},
|
||||
{'name': 'Ch 6', 'channels': [4, 5, 6, 7, 8], 'center': 6},
|
||||
{'name': 'Ch 11', 'channels': [9, 10, 11, 12, 13], 'center': 11},
|
||||
]
|
||||
|
||||
for group in groups:
|
||||
busy_values = [channels.get(ch, {}).get('busy', 0) for ch in group['channels'] if ch in channels]
|
||||
group['avg_busy'] = sum(busy_values) / len(busy_values) if busy_values else 0
|
||||
group['center_busy'] = channels.get(group['center'], {}).get('busy', 0)
|
||||
group['in_use'] = in_use_channel in group['channels'] if in_use_channel else False
|
||||
|
||||
total_busy = sum(g['avg_busy'] for g in groups)
|
||||
|
||||
print(f"\n{Colors.BOLD}Channel Group Utilization (2.4 GHz){Colors.RESET}")
|
||||
print("=" * 60)
|
||||
print("Non-overlapping channel groups with their overlap zones:\n")
|
||||
|
||||
# Draw ASCII donut/pie
|
||||
pie_width = 50
|
||||
|
||||
# Calculate proportions
|
||||
if total_busy > 0:
|
||||
for group in groups:
|
||||
group['proportion'] = group['avg_busy'] / total_busy
|
||||
group['width'] = max(1, int(group['proportion'] * pie_width))
|
||||
else:
|
||||
for group in groups:
|
||||
group['proportion'] = 1/3
|
||||
group['width'] = pie_width // 3
|
||||
|
||||
# Adjust to exactly fill pie_width
|
||||
total_width = sum(g['width'] for g in groups)
|
||||
if total_width < pie_width:
|
||||
groups[0]['width'] += pie_width - total_width
|
||||
|
||||
# Draw the pie bar
|
||||
pie_chars = ['█', '▓', '░']
|
||||
colors = [Colors.GREEN, Colors.YELLOW, Colors.CYAN]
|
||||
|
||||
pie_line = ""
|
||||
for i, group in enumerate(groups):
|
||||
if group['in_use']:
|
||||
color = Colors.BG_BLUE
|
||||
elif group['avg_busy'] >= 50:
|
||||
color = Colors.RED
|
||||
elif group['avg_busy'] >= 25:
|
||||
color = Colors.YELLOW
|
||||
else:
|
||||
color = Colors.GREEN
|
||||
|
||||
char = pie_chars[i % len(pie_chars)]
|
||||
pie_line += f"{color}{char * group['width']}{Colors.RESET}"
|
||||
|
||||
# Draw centered pie
|
||||
print(f" ┌{'─' * pie_width}┐")
|
||||
print(f" │{pie_line}│")
|
||||
print(f" └{'─' * pie_width}┘")
|
||||
|
||||
# Legend with percentages
|
||||
print()
|
||||
for i, group in enumerate(groups):
|
||||
char = pie_chars[i % len(pie_chars)]
|
||||
|
||||
if group['in_use']:
|
||||
color = Colors.BG_BLUE
|
||||
marker = " ◀ IN USE"
|
||||
elif group['avg_busy'] >= 50:
|
||||
color = Colors.RED
|
||||
marker = ""
|
||||
elif group['avg_busy'] >= 25:
|
||||
color = Colors.YELLOW
|
||||
marker = ""
|
||||
else:
|
||||
color = Colors.GREEN
|
||||
marker = ""
|
||||
|
||||
pct_of_total = group['proportion'] * 100
|
||||
print(f" {color}{char * 3}{Colors.RESET} {group['name']:>5}: "
|
||||
f"{group['center_busy']:5.1f}% busy (center), "
|
||||
f"{group['avg_busy']:5.1f}% avg in overlap zone, "
|
||||
f"{pct_of_total:4.1f}% of total{marker}")
|
||||
|
||||
# Draw overlap diagram
|
||||
print(f"\n{Colors.BOLD}Channel Overlap Diagram:{Colors.RESET}")
|
||||
print(" Ch: 1 2 3 4 5 6 7 8 9 10 11 12 13")
|
||||
print(" ╔═══════════════════╗")
|
||||
print(" G1: ║ 1 ─ 2 ─ 3 ─ 4 ─ 5 ║ (centered on ch 1)")
|
||||
print(" ╚═══════╦═══════════╝")
|
||||
print(" ╔═══════════════════╗")
|
||||
print(" G2: ║ 4 ─ 5 ─ 6 ─ 7 ─ 8 ║ (centered on ch 6)")
|
||||
print(" ╚═══════════╦═══════╝")
|
||||
print(" ╔═══════════════════════╗")
|
||||
print(" G3: ║ 9 ─10 ─11 ─12 ─13 ║ (centered on ch 11)")
|
||||
print(" ╚═══════════════════════╝")
|
||||
print()
|
||||
|
||||
|
||||
def generate_svg(survey_data, output_file=None):
|
||||
"""Generate SVG image(s) showing channel overlap and utilization for both bands"""
|
||||
# Separate channels by band
|
||||
channels_2_4 = {}
|
||||
channels_5 = {}
|
||||
in_use_2_4 = None
|
||||
in_use_5 = None
|
||||
|
||||
for ch_data in survey_data:
|
||||
freq = ch_data.get('frequency')
|
||||
ch_num = freq_to_channel(freq)
|
||||
if not ch_num:
|
||||
continue
|
||||
|
||||
busy_pct = get_busy_percentage(ch_data)
|
||||
ch_info = {
|
||||
'freq': freq,
|
||||
'busy': busy_pct,
|
||||
'noise': ch_data.get('noise', -100),
|
||||
'in_use': ch_data.get('in-use', False)
|
||||
}
|
||||
|
||||
if 2400 <= freq <= 2500:
|
||||
channels_2_4[ch_num] = ch_info
|
||||
if ch_info['in_use']:
|
||||
in_use_2_4 = ch_num
|
||||
elif 5100 <= freq <= 5900:
|
||||
channels_5[ch_num] = ch_info
|
||||
if ch_info['in_use']:
|
||||
in_use_5 = ch_num
|
||||
|
||||
def busy_to_color(busy_pct, is_in_use=False):
|
||||
if is_in_use:
|
||||
return "#3b82f6" # Blue
|
||||
elif busy_pct >= 50:
|
||||
return "#ef4444" # Red
|
||||
elif busy_pct >= 25:
|
||||
return "#f59e0b" # Yellow/Orange
|
||||
elif busy_pct >= 10:
|
||||
return "#06b6d4" # Cyan
|
||||
else:
|
||||
return "#22c55e" # Green
|
||||
|
||||
def generate_band_svg(channels, band, freq_min, freq_max, title, non_overlap_channels=None):
|
||||
if not channels:
|
||||
return None
|
||||
|
||||
width = 900
|
||||
height = 400
|
||||
margin_left = 60
|
||||
margin_right = 40
|
||||
margin_top = 60
|
||||
margin_bottom = 80
|
||||
chart_width = width - margin_left - margin_right
|
||||
chart_height = height - margin_top - margin_bottom
|
||||
|
||||
def freq_to_x(freq):
|
||||
return margin_left + (freq - freq_min) / (freq_max - freq_min) * chart_width
|
||||
|
||||
def busy_to_height(busy_pct):
|
||||
return (busy_pct / 100) * chart_height
|
||||
|
||||
svg_parts = []
|
||||
|
||||
# SVG header
|
||||
svg_parts.append(f'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {width} {height}">
|
||||
<defs>
|
||||
<style>
|
||||
.title {{ font: bold 18px sans-serif; fill: #333; }}
|
||||
.label {{ font: 12px sans-serif; fill: #666; }}
|
||||
.axis {{ font: 10px sans-serif; fill: #333; }}
|
||||
.channel-label {{ font: bold 10px sans-serif; fill: #333; }}
|
||||
.legend {{ font: 12px sans-serif; fill: #333; }}
|
||||
</style>
|
||||
</defs>
|
||||
|
||||
<!-- Background -->
|
||||
<rect width="{width}" height="{height}" fill="#fafafa"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="{width/2}" y="30" text-anchor="middle" class="title">{title}</text>
|
||||
|
||||
<!-- Chart area -->
|
||||
<rect x="{margin_left}" y="{margin_top}" width="{chart_width}" height="{chart_height}" fill="#fff" stroke="#ddd"/>
|
||||
''')
|
||||
|
||||
# Draw grid lines
|
||||
for pct in [25, 50, 75, 100]:
|
||||
y = margin_top + chart_height - busy_to_height(pct)
|
||||
svg_parts.append(f' <line x1="{margin_left}" y1="{y}" x2="{margin_left + chart_width}" y2="{y}" stroke="#eee" stroke-dasharray="4,4"/>')
|
||||
svg_parts.append(f' <text x="{margin_left - 5}" y="{y + 4}" text-anchor="end" class="axis">{pct}%</text>')
|
||||
|
||||
# Y-axis label
|
||||
svg_parts.append(f' <text x="15" y="{margin_top + chart_height/2}" text-anchor="middle" transform="rotate(-90, 15, {margin_top + chart_height/2})" class="label">Channel Busy %</text>')
|
||||
|
||||
# Draw channels as bars
|
||||
for ch_num, data in sorted(channels.items()):
|
||||
center_freq = data['freq']
|
||||
busy_pct = data['busy']
|
||||
is_in_use = data['in_use']
|
||||
|
||||
# 20 MHz width: ±10 MHz from center
|
||||
x1 = freq_to_x(center_freq - 10)
|
||||
x2 = freq_to_x(center_freq + 10)
|
||||
bar_width = x2 - x1
|
||||
bar_height = busy_to_height(busy_pct)
|
||||
bar_y = margin_top + chart_height - bar_height
|
||||
|
||||
color = busy_to_color(busy_pct, is_in_use)
|
||||
opacity = 0.6 if not is_in_use else 0.8
|
||||
|
||||
# Draw the channel bar
|
||||
svg_parts.append(f' <rect x="{x1}" y="{bar_y}" width="{bar_width}" height="{bar_height}" fill="{color}" opacity="{opacity}" stroke="{color}" stroke-width="1"/>')
|
||||
|
||||
# Channel label at bottom
|
||||
label_x = freq_to_x(center_freq)
|
||||
svg_parts.append(f' <text x="{label_x}" y="{margin_top + chart_height + 15}" text-anchor="middle" class="channel-label">{ch_num}</text>')
|
||||
|
||||
# Frequency label (only for some channels to avoid clutter)
|
||||
if band == '2.4' or ch_num in [36, 52, 100, 149, 165]:
|
||||
svg_parts.append(f' <text x="{label_x}" y="{margin_top + chart_height + 28}" text-anchor="middle" class="axis">{center_freq}</text>')
|
||||
|
||||
# Busy percentage on top of bar (if tall enough)
|
||||
if bar_height > 20:
|
||||
svg_parts.append(f' <text x="{label_x}" y="{bar_y + 15}" text-anchor="middle" class="channel-label" fill="white">{busy_pct:.0f}%</text>')
|
||||
|
||||
# X-axis labels
|
||||
svg_parts.append(f' <text x="{margin_left + chart_width/2}" y="{height - 15}" text-anchor="middle" class="label">Channel (Center Frequency MHz)</text>')
|
||||
|
||||
# Legend
|
||||
legend_y = margin_top + 10
|
||||
legend_x = margin_left + chart_width - 150
|
||||
legend_items = [
|
||||
("#3b82f6", "In Use"),
|
||||
("#ef4444", "High (>50%)"),
|
||||
("#f59e0b", "Medium (25-50%)"),
|
||||
("#06b6d4", "Low (10-25%)"),
|
||||
("#22c55e", "Idle (<10%)"),
|
||||
]
|
||||
|
||||
svg_parts.append(f' <rect x="{legend_x - 10}" y="{legend_y - 5}" width="160" height="{len(legend_items) * 18 + 10}" fill="white" stroke="#ddd" rx="4"/>')
|
||||
|
||||
for i, (color, label) in enumerate(legend_items):
|
||||
y = legend_y + 10 + i * 18
|
||||
svg_parts.append(f' <rect x="{legend_x}" y="{y - 8}" width="12" height="12" fill="{color}" opacity="0.7"/>')
|
||||
svg_parts.append(f' <text x="{legend_x + 18}" y="{y + 2}" class="legend">{label}</text>')
|
||||
|
||||
# Non-overlapping channels note (for 2.4 GHz)
|
||||
if non_overlap_channels:
|
||||
svg_parts.append(f' <text x="{margin_left + 5}" y="{margin_top + chart_height + 50}" class="label">Non-overlapping: Ch {", ".join(map(str, non_overlap_channels))}</text>')
|
||||
for ch in non_overlap_channels:
|
||||
if ch in channels:
|
||||
center_freq = channels[ch]['freq']
|
||||
x = freq_to_x(center_freq)
|
||||
svg_parts.append(f' <circle cx="{x}" cy="{margin_top + chart_height + 40}" r="8" fill="none" stroke="#22c55e" stroke-width="2"/>')
|
||||
svg_parts.append(f' <text x="{x}" y="{margin_top + chart_height + 44}" text-anchor="middle" class="channel-label" fill="#22c55e">{ch}</text>')
|
||||
else:
|
||||
svg_parts.append(f' <text x="{margin_left + 5}" y="{margin_top + chart_height + 50}" class="label">All channels non-overlapping (20 MHz spacing)</text>')
|
||||
|
||||
svg_parts.append('</svg>')
|
||||
return '\n'.join(svg_parts)
|
||||
|
||||
# Generate SVGs for each band
|
||||
svg_2_4 = generate_band_svg(channels_2_4, '2.4', 2400, 2485,
|
||||
"2.4 GHz WiFi Channel Overlap & Utilization",
|
||||
[1, 6, 11])
|
||||
svg_5 = generate_band_svg(channels_5, '5', 5150, 5850,
|
||||
"5 GHz WiFi Channel Utilization",
|
||||
None)
|
||||
|
||||
# Combine or output separately
|
||||
if svg_2_4 and svg_5:
|
||||
# Combine into one SVG with both bands stacked
|
||||
combined = f'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 820">
|
||||
<g transform="translate(0, 0)">
|
||||
{svg_2_4.replace('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 400">', '').replace('</svg>', '')}
|
||||
</g>
|
||||
<g transform="translate(0, 410)">
|
||||
{svg_5.replace('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 400">', '').replace('</svg>', '')}
|
||||
</g>
|
||||
</svg>'''
|
||||
svg_content = combined
|
||||
elif svg_2_4:
|
||||
svg_content = svg_2_4
|
||||
elif svg_5:
|
||||
svg_content = svg_5
|
||||
else:
|
||||
return None
|
||||
|
||||
if output_file:
|
||||
with open(output_file, 'w') as f:
|
||||
f.write(svg_content)
|
||||
print(f"SVG written to: {output_file}")
|
||||
else:
|
||||
print(svg_content)
|
||||
|
||||
return svg_content
|
||||
|
||||
|
||||
def draw_recommendations(survey_data, json_output=False):
|
||||
"""Analyze channels and provide recommendations"""
|
||||
# Parse channel data
|
||||
channels = {}
|
||||
in_use_channel = None
|
||||
|
||||
for ch_data in survey_data:
|
||||
freq = ch_data.get('frequency')
|
||||
ch_num = freq_to_channel(freq)
|
||||
if ch_num:
|
||||
busy_pct = get_busy_percentage(ch_data)
|
||||
channels[ch_num] = {
|
||||
'busy': busy_pct,
|
||||
'noise': ch_data.get('noise', -100),
|
||||
'in_use': ch_data.get('in-use', False)
|
||||
}
|
||||
if ch_data.get('in-use'):
|
||||
in_use_channel = ch_num
|
||||
|
||||
# Find least congested non-overlapping channels
|
||||
best_channels = []
|
||||
for ch in [1, 6, 11]:
|
||||
if ch in channels:
|
||||
best_channels.append((ch, channels[ch]['busy']))
|
||||
|
||||
best_channels.sort(key=lambda x: x[1])
|
||||
|
||||
# JSON output
|
||||
if json_output:
|
||||
output = {
|
||||
"recommended_channels": [
|
||||
{"channel": ch, "busy_percent": round(busy, 1)}
|
||||
for ch, busy in best_channels
|
||||
]
|
||||
}
|
||||
if in_use_channel:
|
||||
output["current_channel"] = in_use_channel
|
||||
output["current_busy_percent"] = round(channels.get(in_use_channel, {}).get('busy', 0), 1)
|
||||
|
||||
print(json.dumps(output, indent=2))
|
||||
return
|
||||
|
||||
# Text output
|
||||
print(f"\n{Colors.BOLD}Channel Recommendations{Colors.RESET}")
|
||||
print("=" * 80)
|
||||
|
||||
if in_use_channel:
|
||||
print(f"Current channel: {Colors.BOLD}{in_use_channel}{Colors.RESET}")
|
||||
current_busy = channels.get(in_use_channel, {}).get('busy', 0)
|
||||
if current_busy > 50:
|
||||
print(f" {Colors.RED}⚠{Colors.RESET} High congestion detected ({current_busy:.1f}% busy)")
|
||||
elif current_busy > 25:
|
||||
print(f" {Colors.YELLOW}⚠{Colors.RESET} Moderate congestion ({current_busy:.1f}% busy)")
|
||||
else:
|
||||
print(f" {Colors.GREEN}✓{Colors.RESET} Good channel utilization ({current_busy:.1f}% busy)")
|
||||
|
||||
print(f"\nRecommended non-overlapping channels (2.4 GHz):")
|
||||
for i, (ch, busy) in enumerate(best_channels[:3], 1):
|
||||
color = get_utilization_color(busy)
|
||||
marker = "★" if i == 1 else " "
|
||||
print(f" {marker} Channel {ch:2d}: {color}{busy:5.1f}% busy{Colors.RESET}")
|
||||
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Visualize WiFi channel overlap and utilization',
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog='''
|
||||
Examples:
|
||||
# Read from yanger output (show all sections)
|
||||
yanger -x "ixll -A ssh host sudo" ietf-hardware | %(prog)s
|
||||
|
||||
# Read from file
|
||||
%(prog)s survey_data.json
|
||||
|
||||
# Show only list view
|
||||
%(prog)s --list survey_data.json
|
||||
|
||||
# Show only specific sections
|
||||
%(prog)s --overlap survey_data.json
|
||||
%(prog)s --pie survey_data.json
|
||||
%(prog)s --utilization survey_data.json
|
||||
%(prog)s --recommendations survey_data.json
|
||||
%(prog)s --overlap --pie survey_data.json
|
||||
|
||||
# Output recommendations as JSON
|
||||
%(prog)s --recommendations --json survey_data.json
|
||||
|
||||
# Generate SVG image
|
||||
%(prog)s --svg /tmp/wifi-channels.svg survey_data.json
|
||||
%(prog)s --svg - survey_data.json > output.svg
|
||||
'''
|
||||
)
|
||||
parser.add_argument('file', nargs='?', help='JSON file with hardware data (default: stdin)')
|
||||
parser.add_argument('--list', action='store_true', help='Show simple list view instead of overlap graph')
|
||||
parser.add_argument('--no-color', action='store_true', help='Disable colors')
|
||||
parser.add_argument('--json', action='store_true', help='Output recommendations in JSON format')
|
||||
parser.add_argument('--svg', metavar='FILE', help='Generate SVG image to FILE (use - for stdout)')
|
||||
|
||||
# Section filters
|
||||
parser.add_argument('--overlap', action='store_true', help='Show only channel overlap visualization (2.4 GHz)')
|
||||
parser.add_argument('--pie', action='store_true', help='Show only channel group pie chart (2.4 GHz)')
|
||||
parser.add_argument('--utilization', action='store_true', help='Show only channel utilization list')
|
||||
parser.add_argument('--recommendations', action='store_true', help='Show only channel recommendations')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Disable colors if requested
|
||||
if args.no_color:
|
||||
for attr in dir(Colors):
|
||||
if not attr.startswith('_'):
|
||||
setattr(Colors, attr, '')
|
||||
|
||||
# Read input
|
||||
if args.file:
|
||||
with open(args.file, 'r') as f:
|
||||
data = json.load(f)
|
||||
else:
|
||||
data = json.load(sys.stdin)
|
||||
|
||||
# Extract survey data from hardware components
|
||||
survey_data = []
|
||||
hardware = data.get('ietf-hardware:hardware', {})
|
||||
components = hardware.get('component', [])
|
||||
|
||||
for component in components:
|
||||
if component.get('class') == 'infix-hardware:wifi':
|
||||
wifi_radio = component.get('infix-hardware:wifi-radio', {})
|
||||
survey = wifi_radio.get('survey', {})
|
||||
channels = survey.get('channel', [])
|
||||
if channels:
|
||||
survey_data.extend(channels)
|
||||
|
||||
if not survey_data:
|
||||
print("No WiFi survey data found in input", file=sys.stderr)
|
||||
print("Expected format: yanger ietf-hardware output with wifi-radio survey data", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Generate SVG if requested (exclusive mode)
|
||||
if args.svg:
|
||||
output_file = None if args.svg == '-' else args.svg
|
||||
generate_svg(survey_data, output_file)
|
||||
return
|
||||
|
||||
# Determine which sections to show
|
||||
# If no section flags are set, show all sections
|
||||
show_all = not (args.overlap or args.pie or args.utilization or args.recommendations)
|
||||
|
||||
show_overlap = show_all or args.overlap
|
||||
show_pie = show_all or args.pie
|
||||
show_utilization = show_all or args.utilization
|
||||
show_recommendations_section = show_all or args.recommendations
|
||||
|
||||
# Draw visualization
|
||||
freqs = [ch.get('frequency', 0) for ch in survey_data]
|
||||
has_2_4ghz = any(2400 <= f <= 2500 for f in freqs)
|
||||
|
||||
if show_overlap and has_2_4ghz and not args.list:
|
||||
draw_channel_graph_2_4ghz(survey_data)
|
||||
|
||||
if show_pie and has_2_4ghz:
|
||||
draw_overlap_pie(survey_data)
|
||||
|
||||
if show_utilization:
|
||||
draw_channel_list(survey_data)
|
||||
|
||||
if show_recommendations_section:
|
||||
draw_recommendations(survey_data, json_output=args.json)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "usage: $0 <ifname>"
|
||||
exit 1
|
||||
fi
|
||||
ifname=$1
|
||||
|
||||
TIMEOUT=300
|
||||
status=$(wpa_cli -i $ifname scan)
|
||||
while [ "$status" != "OK" ]; do
|
||||
status=$(wpa_cli -i $ifname scan)
|
||||
TIMEOUT=$((TIMEOUT-1))
|
||||
[ $TIMEOUT -eq 0 ] && logger -t wifi-scanner "Failed to start scanning $ifname" && exit 1
|
||||
sleep 0.5
|
||||
done
|
||||
@@ -1,242 +0,0 @@
|
||||
#!/bin/sh
|
||||
# DHCPv6 client state update script for odhcp6c
|
||||
# This script expects a system with resolvconf (openresolv) and iproute2
|
||||
|
||||
[ -z "$1" ] && echo "Error: should be called from odhcp6c" && exit 1
|
||||
|
||||
interface="$1"
|
||||
state="$2"
|
||||
RESOLV_CONF="/run/resolvconf/interfaces/${interface}-ipv6.conf"
|
||||
NTPFILE="/run/chrony/dhcp-sources.d/${interface}-ipv6.sources"
|
||||
|
||||
[ -n "$metric" ] || metric=5
|
||||
|
||||
log()
|
||||
{
|
||||
logger -I $$ -t odhcp6c -p user.notice "${interface}: $*"
|
||||
}
|
||||
|
||||
dbg()
|
||||
{
|
||||
logger -I $$ -t odhcp6c -p user.debug "${interface}: $*"
|
||||
}
|
||||
|
||||
err()
|
||||
{
|
||||
logger -I $$ -t odhcp6c -p user.err "${interface}: $*"
|
||||
}
|
||||
|
||||
teardown_interface()
|
||||
{
|
||||
ip -6 route flush dev "$interface"
|
||||
ip -6 address flush dev "$interface" scope global
|
||||
}
|
||||
|
||||
setup_interface()
|
||||
{
|
||||
# Merge RA addresses with DHCP addresses
|
||||
for entry in $RA_ADDRESSES; do
|
||||
duplicate=0
|
||||
addr="${entry%%/*}"
|
||||
for dentry in $ADDRESSES; do
|
||||
daddr="${dentry%%/*}"
|
||||
[ "$addr" = "$daddr" ] && duplicate=1
|
||||
done
|
||||
[ "$duplicate" = "0" ] && ADDRESSES="$ADDRESSES $entry"
|
||||
done
|
||||
|
||||
# Add addresses
|
||||
for entry in $ADDRESSES; do
|
||||
addr="${entry%%,*}"
|
||||
entry="${entry#*,}"
|
||||
preferred="${entry%%,*}"
|
||||
entry="${entry#*,}"
|
||||
valid="${entry%%,*}"
|
||||
|
||||
ip -6 address add "$addr" dev "$interface" preferred_lft "$preferred" valid_lft "$valid" proto dhcp
|
||||
log "assigned address $addr (preferred=$preferred, valid=$valid)"
|
||||
done
|
||||
|
||||
# Add routes from RA
|
||||
for entry in $RA_ROUTES; do
|
||||
addr="${entry%%,*}"
|
||||
entry="${entry#*,}"
|
||||
gw="${entry%%,*}"
|
||||
entry="${entry#*,}"
|
||||
valid="${entry%%,*}"
|
||||
entry="${entry#*,}"
|
||||
metric="${entry%%,*}"
|
||||
|
||||
if [ -n "$gw" ]; then
|
||||
ip -6 route add "$addr" via "$gw" metric "$metric" dev "$interface" from "::/128"
|
||||
else
|
||||
ip -6 route add "$addr" metric "$metric" dev "$interface"
|
||||
fi
|
||||
|
||||
# Add routes for delegated prefixes
|
||||
for prefix in $PREFIXES; do
|
||||
paddr="${prefix%%,*}"
|
||||
[ -n "$gw" ] && ip -6 route add "$addr" via "$gw" metric "$metric" dev "$interface" from "$paddr"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
handle_prefixes()
|
||||
{
|
||||
# $PREFIXES format: "prefix/len,preferred,valid[,class=N][,excluded=...] ..."
|
||||
for entry in $PREFIXES; do
|
||||
addr="${entry%%,*}"
|
||||
entry="${entry#*,}"
|
||||
preferred="${entry%%,*}"
|
||||
entry="${entry#*,}"
|
||||
valid="${entry%%,*}"
|
||||
|
||||
log "received delegated prefix $addr (preferred=$preferred, valid=$valid)"
|
||||
|
||||
# Add unreachable route to prevent routing loops
|
||||
ip -6 route add unreachable "$addr" 2>/dev/null
|
||||
|
||||
# Future: Distribute to downstream interfaces
|
||||
done
|
||||
}
|
||||
|
||||
handle_dns()
|
||||
{
|
||||
truncate -s 0 "$RESOLV_CONF"
|
||||
|
||||
# Combine DHCPv6 DNS ($RDNSS) and RA DNS ($RA_DNS), deduplicating
|
||||
all_dns=""
|
||||
for server in $RDNSS $RA_DNS; do
|
||||
# Simple deduplication: only add if not already in list
|
||||
case " $all_dns " in
|
||||
*" $server "*) ;;
|
||||
*) all_dns="$all_dns $server" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Domain search list (DHCPv6 option 24)
|
||||
if [ -n "$DOMAINS" ]; then
|
||||
dbg "adding search domains: $DOMAINS"
|
||||
echo "search $DOMAINS # $interface" >> "$RESOLV_CONF"
|
||||
fi
|
||||
|
||||
# DNS servers
|
||||
for server in $all_dns; do
|
||||
[ -z "$server" ] && continue
|
||||
dbg "adding dns $server"
|
||||
echo "nameserver $server # $interface" >> "$RESOLV_CONF"
|
||||
done
|
||||
|
||||
if [ -n "$all_dns" ]; then
|
||||
resolvconf -u
|
||||
fi
|
||||
}
|
||||
|
||||
handle_ntp()
|
||||
{
|
||||
# DHCPv6 option 56 (NTP server) is provided as $OPTION_56 in hex format
|
||||
# Format: sub-option-code (2 bytes) + length (2 bytes) + data
|
||||
# Sub-option 1 = NTP server address (16 bytes IPv6)
|
||||
#
|
||||
# This is complex to parse in shell. For now, we attempt basic parsing
|
||||
# and fall back to logging a warning if the format is unexpected.
|
||||
|
||||
if [ -n "$OPTION_56" ]; then
|
||||
# Remove all non-hex characters (spaces, colons, etc.) and convert to lowercase
|
||||
hex=$(echo "$OPTION_56" | tr -d '[:space:]:-' | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
truncate -s 0 "$NTPFILE"
|
||||
ntp_found=0
|
||||
|
||||
# Parse option 56: iterate through sub-options
|
||||
# Each sub-option: 2 bytes code + 2 bytes length + data
|
||||
pos=0
|
||||
while [ $pos -lt ${#hex} ]; do
|
||||
# Need at least 4 hex chars (2 bytes) for sub-option code
|
||||
[ $((${#hex} - pos)) -lt 4 ] && break
|
||||
|
||||
# Extract sub-option code (2 bytes = 4 hex chars)
|
||||
subopt_code=$(echo "$hex" | cut -c $((pos+1))-$((pos+4)))
|
||||
pos=$((pos + 4))
|
||||
|
||||
# Need 4 more hex chars for length
|
||||
[ $((${#hex} - pos)) -lt 4 ] && break
|
||||
|
||||
# Extract length (2 bytes = 4 hex chars)
|
||||
subopt_len_hex=$(echo "$hex" | cut -c $((pos+1))-$((pos+4)))
|
||||
subopt_len=$(printf "%d" "0x$subopt_len_hex")
|
||||
pos=$((pos + 4))
|
||||
|
||||
# Sub-option 1 = NTP server address (should be 16 bytes for IPv6)
|
||||
if [ "$subopt_code" = "0001" ] && [ "$subopt_len" -eq 16 ]; then
|
||||
# Extract 16 bytes (32 hex chars) for IPv6 address
|
||||
addr_hex=$(echo "$hex" | cut -c $((pos+1))-$((pos+32)))
|
||||
|
||||
# Convert hex to IPv6 address format
|
||||
# Format: 0123456789abcdef0123456789abcdef -> 0123:4567:89ab:cdef:0123:4567:89ab:cdef
|
||||
ipv6=$(echo "$addr_hex" | sed 's/\(....\)\(....\)\(....\)\(....\)\(....\)\(....\)\(....\)\(....\)/\1:\2:\3:\4:\5:\6:\7:\8/')
|
||||
|
||||
dbg "got NTP server $ipv6"
|
||||
echo "server $ipv6 iburst" >> "$NTPFILE"
|
||||
ntp_found=1
|
||||
fi
|
||||
|
||||
# Skip this sub-option's data
|
||||
pos=$((pos + subopt_len * 2))
|
||||
done
|
||||
|
||||
if [ "$ntp_found" -eq 1 ]; then
|
||||
chronyc reload sources >/dev/null 2>&1
|
||||
else
|
||||
dbg "option 56 received but no NTP server addresses found (consider using option 31/SNTP)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
log "state: $state"
|
||||
|
||||
(
|
||||
flock 9
|
||||
case "$state" in
|
||||
started)
|
||||
# Initial state - clean up any stale config
|
||||
teardown_interface
|
||||
;;
|
||||
|
||||
bound)
|
||||
# Fresh lease - tear down and set up from scratch
|
||||
teardown_interface
|
||||
setup_interface
|
||||
handle_prefixes
|
||||
handle_dns
|
||||
handle_ntp
|
||||
;;
|
||||
|
||||
informed|updated|rebound|ra-updated)
|
||||
# Update existing configuration
|
||||
setup_interface
|
||||
[ -n "$PREFIXES" ] && handle_prefixes
|
||||
handle_dns
|
||||
handle_ntp
|
||||
;;
|
||||
|
||||
unbound|stopped)
|
||||
# Lost server or client stopped
|
||||
teardown_interface
|
||||
rm -f "$RESOLV_CONF"
|
||||
rm -f "$NTPFILE"
|
||||
resolvconf -u
|
||||
chronyc reload sources >/dev/null 2>&1
|
||||
;;
|
||||
esac
|
||||
) 9>/tmp/odhcp6c.lock.${interface}
|
||||
rm -f /tmp/odhcp6c.lock.${interface}
|
||||
|
||||
# Run hooks
|
||||
HOOK_DIR="/usr/libexec/odhcp6c.d"
|
||||
for hook in "${HOOK_DIR}/"*; do
|
||||
[ -f "${hook}" -a -x "${hook}" ] || continue
|
||||
"${hook}" "$interface" "$state"
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -411,20 +411,10 @@ create()
|
||||
logging="--log-driver syslog"
|
||||
fi
|
||||
|
||||
# Build resource limit arguments
|
||||
resource=""
|
||||
if [ -n "$memory" ]; then
|
||||
resource="$resource --memory=$memory"
|
||||
fi
|
||||
if [ -n "$cpu_limit" ]; then
|
||||
resource="$resource --cpu-quota=$cpu_limit"
|
||||
fi
|
||||
|
||||
# When we get here we've already fetched, or pulled, the image
|
||||
args="$args --read-only --replace --quiet $caps"
|
||||
args="$args --cgroups=enabled --cgroupns=host --cgroup-parent=system/container@$name"
|
||||
args="$args --read-only --replace --quiet --cgroup-parent=containers $caps"
|
||||
args="$args --restart=$restart --systemd=false --tz=local $privileged"
|
||||
args="$args $vol $mount $hostname $entrypoint $env $port $logging $resource"
|
||||
args="$args $vol $mount $hostname $entrypoint $env $port $logging"
|
||||
pidfile=/run/container:${name}.pid
|
||||
|
||||
[ -n "$quiet" ] || log "---------------------------------------"
|
||||
@@ -726,8 +716,6 @@ options:
|
||||
--log-path PATH Path for k8s-file log pipe
|
||||
-m, --mount HOST:DEST Bind mount a read-only file inside a container
|
||||
--manual Do not start container automatically after creation
|
||||
--memory BYTES Memory limit in bytes (supports K/M/G suffix)
|
||||
--cpu-limit LIMIT CPU limit in millicores (1000m = 100% of 1 core)
|
||||
-n, --name NAME Alternative way of supplying name to start/stop/restart
|
||||
--privileged Give container extended privileges
|
||||
-p, --publish PORT Publish ports when creating container
|
||||
@@ -848,14 +836,6 @@ while [ "$1" != "" ]; do
|
||||
--manual)
|
||||
manual=true
|
||||
;;
|
||||
--memory)
|
||||
shift
|
||||
memory="$1"
|
||||
;;
|
||||
--cpu-limit)
|
||||
shift
|
||||
cpu_limit="$1"
|
||||
;;
|
||||
-n | --name)
|
||||
shift
|
||||
name="$1"
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
#!/bin/sh
|
||||
# This script expects a system with resolvconf (openresolv) and iproute2
|
||||
|
||||
[ -z "$1" ] && echo "Error: should be called from udhcpc6" && exit 1
|
||||
|
||||
ACTION="$1"
|
||||
RESOLV_CONF="/run/resolvconf/interfaces/${interface}-ipv6.conf"
|
||||
NTPFILE="/run/chrony/dhcp-sources.d/${interface}-ipv6.sources"
|
||||
|
||||
[ -n "$metric" ] || metric=5
|
||||
|
||||
if [ -z "${IF_WAIT_DELAY}" ]; then
|
||||
IF_WAIT_DELAY=10
|
||||
fi
|
||||
|
||||
log()
|
||||
{
|
||||
logger -I $$ -t udhcpc6 -p user.notice "${interface}: $*"
|
||||
}
|
||||
|
||||
dbg()
|
||||
{
|
||||
logger -I $$ -t udhcpc6 -p user.debug "${interface}: $*"
|
||||
}
|
||||
|
||||
err()
|
||||
{
|
||||
logger -I $$ -t udhcpc6 -p user.err "${interface}: $*"
|
||||
}
|
||||
|
||||
clr_dhcpv6_addresses()
|
||||
{
|
||||
addrs=$(ip -j addr show dev $interface \
|
||||
| jq -c '.[0].addr_info[] | select(.family == "inet6") | select(.protocol == "dhcp")')
|
||||
|
||||
for addr in $addrs; do
|
||||
ip="$(echo "$addr" | jq -r '."local"')"
|
||||
prefix="$(echo "$addr" | jq -r '."prefixlen"')"
|
||||
log "removing $ip/$prefix"
|
||||
ip addr del "$ip/$prefix" dev "$interface"
|
||||
done
|
||||
}
|
||||
|
||||
log "action $ACTION"
|
||||
case "$ACTION" in
|
||||
deconfig)
|
||||
clr_dhcpv6_addresses
|
||||
|
||||
# drop info from this interface
|
||||
rm -f "$RESOLV_CONF"
|
||||
rm -f "$NTPFILE"
|
||||
;;
|
||||
|
||||
leasefail|nak)
|
||||
# DHCPv6 lease failed - log it
|
||||
err "DHCPv6 lease failed"
|
||||
;;
|
||||
|
||||
renew|bound)
|
||||
# Add IPv6 address if provided (stateful DHCPv6)
|
||||
if [ -n "$ipv6" ]; then
|
||||
if /bin/ip addr add dev $interface $ipv6 proto dhcp; then
|
||||
log "assigned address $ipv6"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Handle delegated prefix (prefix delegation)
|
||||
if [ -n "$ipv6prefix" ]; then
|
||||
log "received delegated prefix $ipv6prefix"
|
||||
# Prefix delegation handling could be added here
|
||||
# For now, just log it - actual routing/distribution
|
||||
# would need additional configuration
|
||||
fi
|
||||
|
||||
# drop info from this interface
|
||||
truncate -s 0 "$RESOLV_CONF"
|
||||
|
||||
# DHCPv6 domain search list (option 24)
|
||||
if [ -n "$search" ]; then
|
||||
dbg "adding search $search"
|
||||
echo "search $search # $interface" >> $RESOLV_CONF
|
||||
fi
|
||||
|
||||
# DHCPv6 DNS servers (option 23)
|
||||
if [ -n "$dns" ]; then
|
||||
for i in $dns ; do
|
||||
dbg "adding dns $i"
|
||||
echo "nameserver $i # $interface" >> $RESOLV_CONF
|
||||
done
|
||||
resolvconf -u
|
||||
fi
|
||||
|
||||
# NTP servers (option 56)
|
||||
if [ -n "$ntpsrv" ]; then
|
||||
truncate -s 0 "$NTPFILE"
|
||||
for srv in $ntpsrv; do
|
||||
dbg "got NTP server $srv"
|
||||
echo "server $srv iburst" >> "$NTPFILE"
|
||||
done
|
||||
chronyc reload sources >/dev/null
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
HOOK_DIR="$0.d"
|
||||
for hook in "${HOOK_DIR}/"*; do
|
||||
[ -f "${hook}" -a -x "${hook}" ] || continue
|
||||
"${hook}" "$ACTION"
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -358,7 +358,6 @@ 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
|
||||
@@ -473,16 +472,8 @@ CONFIG_DEBUG_FS=y
|
||||
# CONFIG_SLUB_DEBUG is not set
|
||||
CONFIG_DEBUG_RODATA_TEST=y
|
||||
CONFIG_DEBUG_WX=y
|
||||
CONFIG_PANIC_ON_OOPS=y
|
||||
CONFIG_PANIC_TIMEOUT=20
|
||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
|
||||
CONFIG_HARDLOCKUP_DETECTOR=y
|
||||
CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY=y
|
||||
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
|
||||
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
|
||||
CONFIG_SOFTLOCKUP_DETECTOR=y
|
||||
CONFIG_WQ_WATCHDOG=y
|
||||
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
|
||||
CONFIG_TEST_LOCKUP=m
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_STACKTRACE=y
|
||||
CONFIG_RCU_CPU_STALL_TIMEOUT=60
|
||||
|
||||
@@ -53,6 +53,7 @@ CONFIG_IP_MROUTE=y
|
||||
CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
|
||||
CONFIG_IP_PIMSM_V1=y
|
||||
CONFIG_IP_PIMSM_V2=y
|
||||
CONFIG_SYN_COOKIES=y
|
||||
CONFIG_NET_IPVTI=m
|
||||
CONFIG_NET_FOU_IP_TUNNELS=y
|
||||
CONFIG_IPV6_SIT=m
|
||||
@@ -68,31 +69,12 @@ CONFIG_BRIDGE_NETFILTER=y
|
||||
CONFIG_NETFILTER_NETLINK_QUEUE=y
|
||||
CONFIG_NETFILTER_NETLINK_LOG=y
|
||||
CONFIG_NF_CONNTRACK=y
|
||||
CONFIG_NF_CONNTRACK_ZONES=y
|
||||
CONFIG_NF_CONNTRACK_PROCFS=y
|
||||
CONFIG_NF_CONNTRACK_EVENTS=y
|
||||
CONFIG_NF_CONNTRACK_TIMEOUT=y
|
||||
CONFIG_NF_CONNTRACK_TIMESTAMP=y
|
||||
CONFIG_NF_CONNTRACK_AMANDA=y
|
||||
CONFIG_NF_CONNTRACK_FTP=y
|
||||
CONFIG_NF_CONNTRACK_H323=y
|
||||
CONFIG_NF_CONNTRACK_IRC=y
|
||||
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
|
||||
CONFIG_NF_CONNTRACK_SNMP=y
|
||||
CONFIG_NF_CONNTRACK_PPTP=y
|
||||
CONFIG_NF_CONNTRACK_SANE=y
|
||||
CONFIG_NF_CONNTRACK_SIP=y
|
||||
CONFIG_NF_CONNTRACK_TFTP=y
|
||||
CONFIG_NF_CT_NETLINK=y
|
||||
CONFIG_NF_CT_NETLINK_TIMEOUT=y
|
||||
CONFIG_NF_CT_NETLINK_HELPER=y
|
||||
CONFIG_NETFILTER_NETLINK_GLUE_CT=y
|
||||
CONFIG_NF_TABLES=y
|
||||
CONFIG_NF_TABLES_INET=y
|
||||
CONFIG_NF_TABLES_NETDEV=y
|
||||
CONFIG_NFT_NUMGEN=y
|
||||
CONFIG_NFT_CT=m
|
||||
CONFIG_NFT_FLOW_OFFLOAD=y
|
||||
CONFIG_NFT_CONNLIMIT=m
|
||||
CONFIG_NFT_LOG=m
|
||||
CONFIG_NFT_LIMIT=m
|
||||
@@ -101,23 +83,15 @@ CONFIG_NFT_REDIR=m
|
||||
CONFIG_NFT_NAT=m
|
||||
CONFIG_NFT_TUNNEL=m
|
||||
CONFIG_NFT_QUEUE=m
|
||||
CONFIG_NFT_QUOTA=y
|
||||
CONFIG_NFT_REJECT=m
|
||||
CONFIG_NFT_COMPAT=m
|
||||
CONFIG_NFT_HASH=m
|
||||
CONFIG_NFT_FIB_INET=y
|
||||
CONFIG_NFT_XFRM=m
|
||||
CONFIG_NFT_SOCKET=m
|
||||
CONFIG_NFT_OSF=m
|
||||
CONFIG_NFT_TPROXY=y
|
||||
CONFIG_NFT_SYNPROXY=y
|
||||
CONFIG_NFT_DUP_NETDEV=m
|
||||
CONFIG_NFT_FWD_NETDEV=m
|
||||
CONFIG_NFT_FIB_NETDEV=y
|
||||
CONFIG_NFT_REJECT_NETDEV=m
|
||||
CONFIG_NF_FLOW_TABLE_INET=y
|
||||
CONFIG_NF_FLOW_TABLE=y
|
||||
CONFIG_NETFILTER_XTABLES_LEGACY=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
|
||||
CONFIG_NETFILTER_XT_TARGET_LOG=m
|
||||
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
|
||||
@@ -134,69 +108,29 @@ CONFIG_NETFILTER_XT_MATCH_MAC=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MARK=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
|
||||
CONFIG_IP_SET=y
|
||||
CONFIG_IP_SET_BITMAP_IP=y
|
||||
CONFIG_IP_SET_BITMAP_IPMAC=y
|
||||
CONFIG_IP_SET_BITMAP_PORT=y
|
||||
CONFIG_IP_SET_HASH_IP=y
|
||||
CONFIG_IP_SET_HASH_IPMARK=y
|
||||
CONFIG_IP_SET_HASH_IPPORT=y
|
||||
CONFIG_IP_SET_HASH_IPPORTIP=y
|
||||
CONFIG_IP_SET_HASH_IPPORTNET=y
|
||||
CONFIG_IP_SET_HASH_IPMAC=y
|
||||
CONFIG_IP_SET_HASH_MAC=y
|
||||
CONFIG_IP_SET_HASH_NETPORTNET=y
|
||||
CONFIG_IP_SET_HASH_NET=y
|
||||
CONFIG_IP_SET_HASH_NETNET=y
|
||||
CONFIG_IP_SET_HASH_NETPORT=y
|
||||
CONFIG_IP_SET_HASH_NETIFACE=y
|
||||
CONFIG_IP_SET_LIST_SET=y
|
||||
CONFIG_NFT_DUP_IPV4=y
|
||||
CONFIG_NFT_FIB_IPV4=y
|
||||
CONFIG_NF_TABLES_ARP=y
|
||||
CONFIG_NF_LOG_ARP=y
|
||||
CONFIG_NF_LOG_IPV4=y
|
||||
CONFIG_IP_NF_IPTABLES=m
|
||||
CONFIG_IP_NF_MATCH_AH=m
|
||||
CONFIG_IP_NF_MATCH_ECN=m
|
||||
CONFIG_IP_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP_NF_MATCH_TTL=m
|
||||
CONFIG_IP_NF_FILTER=m
|
||||
CONFIG_IP_NF_TARGET_REJECT=m
|
||||
CONFIG_IP_NF_TARGET_SYNPROXY=m
|
||||
CONFIG_IP_NF_NAT=m
|
||||
CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
CONFIG_IP_NF_ARPFILTER=m
|
||||
CONFIG_IP_NF_ARP_MANGLE=m
|
||||
CONFIG_NFT_DUP_IPV6=y
|
||||
CONFIG_NFT_FIB_IPV6=y
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP6_NF_IPTABLES=m
|
||||
CONFIG_IP6_NF_MATCH_AH=m
|
||||
CONFIG_IP6_NF_MATCH_EUI64=m
|
||||
CONFIG_IP6_NF_MATCH_FRAG=m
|
||||
CONFIG_IP6_NF_MATCH_OPTS=m
|
||||
CONFIG_IP6_NF_MATCH_HL=m
|
||||
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
|
||||
CONFIG_IP6_NF_MATCH_MH=m
|
||||
CONFIG_IP6_NF_MATCH_RPFILTER=m
|
||||
CONFIG_IP6_NF_MATCH_RT=m
|
||||
CONFIG_IP6_NF_MATCH_SRH=m
|
||||
CONFIG_IP6_NF_TARGET_HL=m
|
||||
CONFIG_IP6_NF_FILTER=m
|
||||
CONFIG_IP6_NF_TARGET_REJECT=m
|
||||
CONFIG_IP6_NF_TARGET_SYNPROXY=m
|
||||
CONFIG_IP6_NF_RAW=m
|
||||
CONFIG_IP6_NF_NAT=m
|
||||
CONFIG_IP6_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP6_NF_TARGET_NPT=m
|
||||
CONFIG_NF_TABLES_BRIDGE=m
|
||||
CONFIG_NFT_BRIDGE_META=m
|
||||
CONFIG_NFT_BRIDGE_REJECT=m
|
||||
CONFIG_NF_CONNTRACK_BRIDGE=m
|
||||
CONFIG_BRIDGE_NF_EBTABLES=m
|
||||
CONFIG_BRIDGE_EBT_BROUTE=m
|
||||
CONFIG_BRIDGE_EBT_T_FILTER=m
|
||||
CONFIG_BRIDGE_EBT_T_NAT=m
|
||||
CONFIG_BRIDGE_EBT_802_3=m
|
||||
CONFIG_BRIDGE_EBT_ARP=m
|
||||
CONFIG_BRIDGE_EBT_IP=m
|
||||
@@ -257,7 +191,6 @@ CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_BONDING=m
|
||||
CONFIG_DUMMY=m
|
||||
CONFIG_WIREGUARD=m
|
||||
CONFIG_MACVLAN=m
|
||||
CONFIG_MACVTAP=m
|
||||
CONFIG_IPVLAN=m
|
||||
@@ -287,7 +220,6 @@ 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
|
||||
@@ -331,13 +263,7 @@ CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_PANIC_ON_OOPS=y
|
||||
CONFIG_PANIC_TIMEOUT=20
|
||||
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
|
||||
CONFIG_HARDLOCKUP_DETECTOR=y
|
||||
CONFIG_HARDLOCKUP_DETECTOR_PREFER_BUDDY=y
|
||||
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
|
||||
CONFIG_WQ_WATCHDOG=y
|
||||
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
|
||||
CONFIG_TEST_LOCKUP=m
|
||||
CONFIG_FUNCTION_TRACER=y
|
||||
CONFIG_UNWINDER_FRAME_POINTER=y
|
||||
|
||||
+1
-1
Submodule buildroot updated: 8fdb85060c...5baee16c62
@@ -29,13 +29,12 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.7"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.58"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch32/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
|
||||
BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_INFIX_PATH}/board/common/busybox_defconfig"
|
||||
BR2_PACKAGE_ODHCP6C=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_PACKAGE_STRESS_NG=y
|
||||
BR2_PACKAGE_JQ=y
|
||||
@@ -60,7 +59,7 @@ BR2_PACKAGE_LIBINPUT=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sysrepo"
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sys-cli"
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
BR2_PACKAGE_AVAHI_DAEMON=y
|
||||
@@ -83,7 +82,6 @@ BR2_PACKAGE_OPENSSH=y
|
||||
BR2_PACKAGE_SOCAT=y
|
||||
BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_WHOIS=y
|
||||
BR2_PACKAGE_WIREGUARD_TOOLS=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_SUDO=y
|
||||
BR2_PACKAGE_GETENT=y
|
||||
@@ -97,12 +95,6 @@ BR2_PACKAGE_RAUC_JSON=y
|
||||
BR2_PACKAGE_SYSKLOGD=y
|
||||
BR2_PACKAGE_SYSKLOGD_LOGGER=y
|
||||
BR2_PACKAGE_WATCHDOGD=y
|
||||
BR2_PACKAGE_WATCHDOGD_GENERIC=y
|
||||
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
|
||||
BR2_PACKAGE_WATCHDOGD_FILENR=y
|
||||
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
|
||||
BR2_PACKAGE_WATCHDOGD_FSMON=y
|
||||
BR2_PACKAGE_WATCHDOGD_TEMPMON
|
||||
BR2_PACKAGE_LESS=y
|
||||
BR2_PACKAGE_MG=y
|
||||
BR2_PACKAGE_NANO=y
|
||||
@@ -141,6 +133,7 @@ BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
BR2_PACKAGE_ONIEPROM=y
|
||||
BR2_PACKAGE_SHOW=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
|
||||
IMAGE_ITB_AUX=y
|
||||
|
||||
@@ -29,13 +29,12 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.7"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.58"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch32/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
|
||||
BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_INFIX_PATH}/board/common/busybox_defconfig"
|
||||
BR2_PACKAGE_ODHCP6C=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_PACKAGE_STRESS_NG=y
|
||||
BR2_PACKAGE_JQ=y
|
||||
@@ -60,7 +59,7 @@ BR2_PACKAGE_LIBINPUT=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sysrepo"
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sys-cli"
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
BR2_PACKAGE_AVAHI_DAEMON=y
|
||||
@@ -83,7 +82,6 @@ BR2_PACKAGE_OPENSSH=y
|
||||
BR2_PACKAGE_SOCAT=y
|
||||
BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_WHOIS=y
|
||||
BR2_PACKAGE_WIREGUARD_TOOLS=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_SUDO=y
|
||||
BR2_PACKAGE_GETENT=y
|
||||
@@ -97,12 +95,6 @@ BR2_PACKAGE_RAUC_JSON=y
|
||||
BR2_PACKAGE_SYSKLOGD=y
|
||||
BR2_PACKAGE_SYSKLOGD_LOGGER=y
|
||||
BR2_PACKAGE_WATCHDOGD=y
|
||||
BR2_PACKAGE_WATCHDOGD_GENERIC=y
|
||||
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
|
||||
BR2_PACKAGE_WATCHDOGD_FILENR=y
|
||||
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
|
||||
BR2_PACKAGE_WATCHDOGD_FSMON=y
|
||||
BR2_PACKAGE_WATCHDOGD_TEMPMON
|
||||
BR2_PACKAGE_LESS=y
|
||||
BR2_PACKAGE_MG=y
|
||||
BR2_PACKAGE_NANO=y
|
||||
@@ -141,6 +133,7 @@ BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
BR2_PACKAGE_ONIEPROM=y
|
||||
BR2_PACKAGE_SHOW=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
|
||||
IMAGE_ITB_AUX=y
|
||||
|
||||
@@ -27,17 +27,17 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.7"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.61"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_INFIX_PATH}/board/common/busybox_defconfig"
|
||||
BR2_PACKAGE_ODHCP6C=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_PACKAGE_STRESS_NG=y
|
||||
BR2_PACKAGE_JQ=y
|
||||
BR2_PACKAGE_E2FSPROGS=y
|
||||
BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
|
||||
BR2_PACKAGE_LINUX_FIRMWARE_INSIDE_SECURE_MINIFW=y
|
||||
BR2_PACKAGE_LINUX_FIRMWARE_RTL_8169=y
|
||||
BR2_PACKAGE_DBUS_CXX=y
|
||||
BR2_PACKAGE_DBUS_GLIB=y
|
||||
@@ -63,7 +63,7 @@ BR2_PACKAGE_LIBINPUT=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sysrepo"
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sys-cli"
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
BR2_PACKAGE_LIBPAM_RADIUS_AUTH=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
@@ -102,7 +102,6 @@ BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_TRACEROUTE=y
|
||||
BR2_PACKAGE_ULOGD=y
|
||||
BR2_PACKAGE_WHOIS=y
|
||||
BR2_PACKAGE_WIREGUARD_TOOLS=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_NEOFETCH=y
|
||||
BR2_PACKAGE_SUDO=y
|
||||
@@ -120,12 +119,6 @@ BR2_PACKAGE_RAUC_JSON=y
|
||||
BR2_PACKAGE_SYSKLOGD=y
|
||||
BR2_PACKAGE_SYSKLOGD_LOGGER=y
|
||||
BR2_PACKAGE_WATCHDOGD=y
|
||||
BR2_PACKAGE_WATCHDOGD_GENERIC=y
|
||||
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
|
||||
BR2_PACKAGE_WATCHDOGD_FILENR=y
|
||||
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
|
||||
BR2_PACKAGE_WATCHDOGD_FSMON=y
|
||||
BR2_PACKAGE_WATCHDOGD_TEMPMON
|
||||
BR2_PACKAGE_LESS=y
|
||||
BR2_PACKAGE_MG=y
|
||||
BR2_PACKAGE_NANO=y
|
||||
@@ -149,8 +142,7 @@ BR2_PACKAGE_MARVELL_CN9130_CRB=y
|
||||
BR2_PACKAGE_MARVELL_ESPRESSOBIN=y
|
||||
BR2_PACKAGE_RASPBERRYPI_RPI64=y
|
||||
BR2_PACKAGE_STYX_DCP_SC_28P=y
|
||||
BR2_PACKAGE_FEATURE_WIFI_MEDIATEK=y
|
||||
BR2_PACKAGE_FEATURE_WIFI_REALTEK=y
|
||||
BR2_PACKAGE_FEATURE_WIFI_DONGLE_REALTEK=y
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CONFD_TEST_MODE=y
|
||||
BR2_PACKAGE_CURIOS_HTTPD=y
|
||||
@@ -179,6 +171,7 @@ BR2_PACKAGE_PODMAN=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_VFS=y
|
||||
BR2_PACKAGE_SHOW=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
|
||||
|
||||
@@ -26,17 +26,19 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.7"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.61"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/aarch64/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_INFIX_PATH}/board/common/busybox_defconfig"
|
||||
BR2_PACKAGE_ODHCP6C=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_PACKAGE_STRESS_NG=y
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sysrepo"
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sys-cli"
|
||||
BR2_PACKAGE_JQ=y
|
||||
BR2_PACKAGE_E2FSPROGS=y
|
||||
BR2_PACKAGE_E2FSPROGS_RESIZE2FS=y
|
||||
BR2_PACKAGE_LINUX_FIRMWARE_INSIDE_SECURE_MINIFW=y
|
||||
BR2_PACKAGE_LINUX_FIRMWARE_RTL_8169=y
|
||||
BR2_PACKAGE_DBUS_CXX=y
|
||||
BR2_PACKAGE_DBUS_GLIB=y
|
||||
BR2_PACKAGE_DBUS_TRIGGERD=y
|
||||
@@ -83,7 +85,6 @@ BR2_PACKAGE_OPENSSH=y
|
||||
BR2_PACKAGE_SOCAT=y
|
||||
BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_WHOIS=y
|
||||
BR2_PACKAGE_WIREGUARD_TOOLS=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_SUDO=y
|
||||
BR2_PACKAGE_KMOD_TOOLS=y
|
||||
@@ -96,12 +97,6 @@ BR2_PACKAGE_RAUC_JSON=y
|
||||
BR2_PACKAGE_SYSKLOGD=y
|
||||
BR2_PACKAGE_SYSKLOGD_LOGGER=y
|
||||
BR2_PACKAGE_WATCHDOGD=y
|
||||
BR2_PACKAGE_WATCHDOGD_GENERIC=y
|
||||
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
|
||||
BR2_PACKAGE_WATCHDOGD_FILENR=y
|
||||
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
|
||||
BR2_PACKAGE_WATCHDOGD_FSMON=y
|
||||
BR2_PACKAGE_WATCHDOGD_TEMPMON
|
||||
BR2_PACKAGE_LESS=y
|
||||
BR2_PACKAGE_MG=y
|
||||
BR2_PACKAGE_NANO=y
|
||||
@@ -128,6 +123,7 @@ BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_CONFD_TEST_MODE=y
|
||||
BR2_PACKAGE_GENCERT=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_SHOW=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
|
||||
|
||||
@@ -37,7 +37,6 @@ BR2_LINUX_KERNEL_DTB_KEEP_DIRNAME=y
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
|
||||
BR2_PACKAGE_BUSYBOX_CONFIG="$(BR2_EXTERNAL_INFIX_PATH)/board/common/busybox_defconfig"
|
||||
BR2_PACKAGE_ODHCP6C=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_PACKAGE_STRESS_NG=y
|
||||
BR2_PACKAGE_JQ=y
|
||||
@@ -76,7 +75,7 @@ BR2_PACKAGE_LIBINPUT=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sysrepo"
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sys-cli"
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
BR2_PACKAGE_LIBPAM_RADIUS_AUTH=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
@@ -132,12 +131,6 @@ BR2_PACKAGE_RAUC_JSON=y
|
||||
BR2_PACKAGE_SYSKLOGD=y
|
||||
BR2_PACKAGE_SYSKLOGD_LOGGER=y
|
||||
BR2_PACKAGE_WATCHDOGD=y
|
||||
BR2_PACKAGE_WATCHDOGD_GENERIC=y
|
||||
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
|
||||
BR2_PACKAGE_WATCHDOGD_FILENR=y
|
||||
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
|
||||
BR2_PACKAGE_WATCHDOGD_FSMON=y
|
||||
BR2_PACKAGE_WATCHDOGD_TEMPMON
|
||||
BR2_PACKAGE_LESS=y
|
||||
BR2_PACKAGE_MG=y
|
||||
BR2_PACKAGE_NANO=y
|
||||
@@ -203,6 +196,7 @@ BR2_PACKAGE_PODMAN=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_VFS=y
|
||||
BR2_PACKAGE_SHOW=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
|
||||
|
||||
@@ -26,13 +26,12 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.7"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.61"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y
|
||||
BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_INFIX_PATH}/board/common/busybox_defconfig"
|
||||
BR2_PACKAGE_ODHCP6C=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_PACKAGE_STRESS_NG=y
|
||||
BR2_PACKAGE_JQ=y
|
||||
@@ -51,6 +50,7 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_SUPPORT=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_FIT_SIGNATURE_SUPPORT=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y
|
||||
BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON_GUNICORN=y
|
||||
BR2_PACKAGE_LIBSSH_OPENSSL=y
|
||||
BR2_PACKAGE_LIBSSH2=y
|
||||
@@ -59,7 +59,7 @@ BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_LIBCURL_CURL=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sysrepo"
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sys-cli"
|
||||
BR2_PACKAGE_LINUX_PAM=y
|
||||
BR2_PACKAGE_LIBPAM_RADIUS_AUTH=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
@@ -70,6 +70,7 @@ BR2_PACKAGE_CONNTRACK_TOOLS=y
|
||||
BR2_PACKAGE_DNSMASQ=y
|
||||
BR2_PACKAGE_ETHTOOL=y
|
||||
BR2_PACKAGE_FPING=y
|
||||
BR2_PACKAGE_FIREWALL=y
|
||||
BR2_PACKAGE_FRR=y
|
||||
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
|
||||
BR2_PACKAGE_IPERF3=y
|
||||
@@ -82,6 +83,7 @@ BR2_PACKAGE_MTR=y
|
||||
BR2_PACKAGE_NETCALC=y
|
||||
BR2_PACKAGE_NETCAT_OPENBSD=y
|
||||
BR2_PACKAGE_NETSNMP=y
|
||||
BR2_PACKAGE_NFTABLES=y
|
||||
BR2_PACKAGE_NGINX=y
|
||||
BR2_PACKAGE_NGINX_HTTP_SSL_MODULE=y
|
||||
BR2_PACKAGE_NGINX_HTTP_V2_MODULE=y
|
||||
@@ -96,7 +98,6 @@ BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_TRACEROUTE=y
|
||||
BR2_PACKAGE_ULOGD=y
|
||||
BR2_PACKAGE_WHOIS=y
|
||||
BR2_PACKAGE_WIREGUARD_TOOLS=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_NEOFETCH=y
|
||||
BR2_PACKAGE_SUDO=y
|
||||
@@ -114,12 +115,6 @@ BR2_PACKAGE_RAUC_JSON=y
|
||||
BR2_PACKAGE_SYSKLOGD=y
|
||||
BR2_PACKAGE_SYSKLOGD_LOGGER=y
|
||||
BR2_PACKAGE_WATCHDOGD=y
|
||||
BR2_PACKAGE_WATCHDOGD_GENERIC=y
|
||||
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
|
||||
BR2_PACKAGE_WATCHDOGD_FILENR=y
|
||||
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
|
||||
BR2_PACKAGE_WATCHDOGD_FSMON=y
|
||||
BR2_PACKAGE_WATCHDOGD_TEMPMON
|
||||
BR2_PACKAGE_LESS=y
|
||||
BR2_PACKAGE_MG=y
|
||||
BR2_PACKAGE_NANO=y
|
||||
@@ -160,7 +155,6 @@ BR2_PACKAGE_FINIT_RTC_DATE="2024-11-04 10:54:00"
|
||||
BR2_PACKAGE_FINIT_RTC_FILE="/var/lib/misc/rtc"
|
||||
BR2_PACKAGE_FINIT_PLUGIN_TTY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y
|
||||
BR2_PACKAGE_FIREWALL=y
|
||||
BR2_PACKAGE_IITO=y
|
||||
BR2_PACKAGE_KEYACK=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
@@ -174,6 +168,7 @@ BR2_PACKAGE_PODMAN=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_BTRFS=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_DEVICEMAPPER=y
|
||||
BR2_PACKAGE_PODMAN_DRIVER_VFS=y
|
||||
BR2_PACKAGE_SHOW=y
|
||||
BR2_PACKAGE_TETRIS=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
|
||||
|
||||
@@ -26,16 +26,15 @@ BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNA
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.7"
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.61"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/linux_defconfig"
|
||||
BR2_LINUX_KERNEL_INSTALL_TARGET=y
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y
|
||||
BR2_PACKAGE_BUSYBOX_CONFIG="${BR2_EXTERNAL_INFIX_PATH}/board/common/busybox_defconfig"
|
||||
BR2_PACKAGE_ODHCP6C=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_PACKAGE_STRESS_NG=y
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sysrepo"
|
||||
BR2_PACKAGE_SYSREPO_GROUP="sys-cli"
|
||||
BR2_PACKAGE_JQ=y
|
||||
BR2_PACKAGE_E2FSPROGS=y
|
||||
BR2_PACKAGE_DBUS_CXX=y
|
||||
@@ -81,7 +80,6 @@ BR2_PACKAGE_OPENSSH=y
|
||||
BR2_PACKAGE_SOCAT=y
|
||||
BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_WHOIS=y
|
||||
BR2_PACKAGE_WIREGUARD_TOOLS=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_SUDO=y
|
||||
BR2_PACKAGE_GETENT=y
|
||||
@@ -95,12 +93,6 @@ BR2_PACKAGE_RAUC_JSON=y
|
||||
BR2_PACKAGE_SYSKLOGD=y
|
||||
BR2_PACKAGE_SYSKLOGD_LOGGER=y
|
||||
BR2_PACKAGE_WATCHDOGD=y
|
||||
BR2_PACKAGE_WATCHDOGD_GENERIC=y
|
||||
BR2_PACKAGE_WATCHDOGD_LOADAVG=y
|
||||
BR2_PACKAGE_WATCHDOGD_FILENR=y
|
||||
BR2_PACKAGE_WATCHDOGD_MEMINFO=y
|
||||
BR2_PACKAGE_WATCHDOGD_FSMON=y
|
||||
BR2_PACKAGE_WATCHDOGD_TEMPMON=y
|
||||
BR2_PACKAGE_LESS=y
|
||||
BR2_PACKAGE_MG=y
|
||||
BR2_PACKAGE_NANO=y
|
||||
@@ -143,6 +135,7 @@ BR2_PACKAGE_LOWDOWN=y
|
||||
BR2_PACKAGE_MCD=y
|
||||
BR2_PACKAGE_MDNS_ALIAS=y
|
||||
BR2_PACKAGE_ONIEPROM=y
|
||||
BR2_PACKAGE_SHOW=y
|
||||
BR2_PACKAGE_ROUSETTE=y
|
||||
BR2_PACKAGE_RAUC_INSTALLATION_STATUS=y
|
||||
IMAGE_ITB_AUX=y
|
||||
|
||||
+5
-63
@@ -6,80 +6,22 @@ All notable changes to the project are documented in this file.
|
||||
[v26.01.0][UNRELEASED]
|
||||
-------------------------
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This release includes **breaking changes** to WiFi configuration that will
|
||||
> result in existing configuration being disabled:
|
||||
>
|
||||
> - WiFi station/client configuration has been restructured. The `wifi` container
|
||||
> now requires a `radio` reference, and station configuration has moved under a
|
||||
> `wifi/station` container. Existing WiFi configurations must be manually updated
|
||||
> - WiFi radios are now configured via `ietf-hardware` instead of the interfaces module
|
||||
>
|
||||
> Also, **Raspberry Pi users must upgrade the bootloader** before upgrading to
|
||||
> this release. We recommend backing up your `startup-config.cfg` and reflash
|
||||
> the SD card with a new [sd card image][].
|
||||
|
||||
### Changes
|
||||
|
||||
Noteworthy changes and additions in this release are marked below in bold text.
|
||||
|
||||
- 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
|
||||
- Upgrade netopeer2 (NETCONF) to 2.7.0
|
||||
- Add **RIPv2 routing support**, issue #582
|
||||
- Add **NTP server support**, issue #904
|
||||
- Migrate DHCPv6 client to odhcp6c for improved Router Advertisement
|
||||
integration. Adds support for hybrid RA+DHCPv6 deployments where SLAAC
|
||||
assigns addresses and DHCPv6 provides DNS (common ISP scenario)
|
||||
- Upgrade Linux kernel to 6.12.61 (LTS)
|
||||
- Add RIPv2 routing support, issue #582
|
||||
- Add support for configurable OSPF debug logging, issue #1281. Debug options
|
||||
can now be enabled per category (bfd, packet, ism, nsm, default-information,
|
||||
nssa). All debug options are disabled by default to prevent log flooding in
|
||||
production environments. See the documentation for usage examples
|
||||
- Add support for configurable container resource limits, memory and CPU.
|
||||
Resource usage is available through the operational datastore, where the
|
||||
currently active resource limits in the container runtime are also available
|
||||
- Add support for "routing interfaces", issue #647. Lists interfaces with IP
|
||||
forwarding. Inspect from CLI using `show interface`, look for `⇅` flag
|
||||
- Add operational data journal to statd with hierarchical time-based retention
|
||||
policy, keeping snapshots from every 5 minutes (recent) to yearly (historical)
|
||||
- Add support data collection script, useful when troubleshooting issues on
|
||||
deployed systems. Gathers system information, logs, and more. Issue #1287
|
||||
- Add **WiFi Access Point (AP) mode with multi-SSID support and WPA2/WPA3**
|
||||
security. **BREAKING:** WiFi architecture refactored with radios configured
|
||||
via `ietf-hardware` and interfaces requiring `radio` reference. Station
|
||||
config moved to `wifi/station` container. Existing Wi-Fi interfaces will be
|
||||
removed during upgrade (for the rest of the configuration to apply) and you
|
||||
need to reconfigure them again. See the [WiFi][] documentation for details
|
||||
- Add support for **WireGuard VPN tunnels**.
|
||||
- New default NACM privilege levels (user levels) in `factory-config`:
|
||||
`operator` (network & container manager) and `guest` (read-only). For
|
||||
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
|
||||
- Add memory tuning configuration for embedded network devices with aggressive
|
||||
dirty page writeback and OOM panic for deterministic recovery
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix #1082: Wi-Fi interfaces always scanned, introduce a `scan-mode` to the
|
||||
Wi-Fi concept in Infix
|
||||
- Fix #1314: Raspberry Pi 4B with 1 or 8 GiB RAM does not boot. This was due
|
||||
newer EEPROM firmware in newer boards require a newer rpi-firmware package
|
||||
- Fix #1345: firewall not updating when interfaces become bridge/lag ports
|
||||
- Fix #1346: firewall complains in syslog, missing `/etc/firewalld/firewalld.conf`
|
||||
- Fix default password hash in `do password encrypt` command. New hash is the
|
||||
same as the more commonly used `change password` command, *yescrypt*
|
||||
- Prevent MOTD from showing on non-shell user login attempts
|
||||
- Fix mDNS reflector.
|
||||
|
||||
[wifi]: https://kernelkit.org/infix/latest/wifi/
|
||||
[sd card image]: https://github.com/kernelkit/infix/releases/download/latest-boot/infix-rpi64-sdcard.img
|
||||
|
||||
N/A
|
||||
|
||||
[v25.11.0][] - 2025-12-02
|
||||
-------------------------
|
||||
|
||||
-284
@@ -1,284 +0,0 @@
|
||||
# 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface br0</b>
|
||||
admin@example:/config/interface/br0/> <b>up</b>
|
||||
admin@example:/config/> <b>set interface eth0 bridge-port bridge br0</b>
|
||||
admin@example:/config/> <b>set interface eth1 bridge-port bridge br0</b>
|
||||
admin@example:/config/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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).
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface br0</b>
|
||||
admin@example:/config/interface/br0/> <b>up</b>
|
||||
admin@example:/config/> <b>set interface eth0 bridge-port bridge br0</b>
|
||||
admin@example:/config/> <b>set interface eth0 bridge-port pvid 10</b>
|
||||
admin@example:/config/> <b>set interface eth1 bridge-port bridge br0</b>
|
||||
admin@example:/config/> <b>set interface eth1 bridge-port pvid 20</b>
|
||||
admin@example:/config/> <b>edit interface br0</b>
|
||||
admin@example:/config/interface/br0/> <b>set bridge vlans vlan 10 untagged eth0</b>
|
||||
admin@example:/config/interface/br0/> <b>set bridge vlans vlan 20 untagged eth1</b>
|
||||
</code></pre>
|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/br0/> <b>set bridge vlans vlan 10 tagged br0</b>
|
||||
admin@example:/config/interface/br0/> <b>set bridge vlans vlan 20 tagged br0</b>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface br0</b>
|
||||
admin@example:/config/interface/br0/> <b>set bridge multicast snooping</b>
|
||||
admin@example:/config/interface/br0/> <b>set ipv4 address 192.168.2.1 prefix-length 24</b>
|
||||
admin@example:/config/interface/br0/> <b>leave</b>
|
||||
admin@example:/> <b>copy running-config startup-config</b>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ip multicast</b>
|
||||
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
|
||||
|
||||
<span class="header">Interface VID Querier State Interval Timeout Ver</span>
|
||||
br0 192.168.2.1 Up 125 None 3
|
||||
|
||||
<span class="header">Bridge VID Multicast Group Ports </span>
|
||||
br0 224.1.1.1 e3, e2
|
||||
br0 ff02::6a br0
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface br1</b>
|
||||
admin@example:/config/interface/br1/> <b>set bridge vlans vlan 1 multicast snooping</b>
|
||||
admin@example:/config/interface/br1/> <b>set bridge vlans vlan 2 multicast snooping</b>
|
||||
admin@example:/config/interface/br1/> <b>leave</b>
|
||||
admin@example:/> <b>copy running-config startup-config</b>
|
||||
</code></pre>
|
||||
|
||||
Let us see what we get:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ip multicast</b>
|
||||
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
|
||||
|
||||
<span class="header">Interface VID Querier State Interval Timeout Ver</span>
|
||||
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
|
||||
|
||||
<span class="header">Bridge VID Multicast Group Ports </span>
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
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`:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface br0 bridge</b>
|
||||
admin@example:/config/interface/br0/bridge/> <b>set ieee-group-forward</b> # 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/> <b>set ieee-group-forward</b>
|
||||
</code></pre>
|
||||
|
||||
The following example configures bridge *br0* to forward LLDP packets.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/br0/bridge/> <b>set ieee-group-forward lldp</b>
|
||||
admin@example:/config/interface/br0/bridge/>
|
||||
</code></pre>
|
||||
|
||||
[^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.
|
||||
@@ -16,21 +16,16 @@ 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 | | Kill region if mark set, else kill word backward |
|
||||
| | Meta-Backspace | Delete (cut) word to the left |
|
||||
| Ctrl-w | 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?
|
||||
|
||||
|
||||
+242
-311
@@ -92,18 +92,17 @@ your container image and application to run.
|
||||
|
||||
Classic Hello World:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>container run docker://hello-world</b>
|
||||
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
|
||||
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.
|
||||
</code></pre>
|
||||
Hello from Docker!
|
||||
This message shows that your installation appears to be working correctly.
|
||||
|
||||
### Example: Web Server
|
||||
|
||||
@@ -111,24 +110,22 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface docker0</b>
|
||||
admin@example:/config/interface/docker0/> <b>set container-network</b>
|
||||
admin@example:/config/interface/docker0/> <b>end</b>
|
||||
admin@example:/config/> <b>edit container web</b>
|
||||
admin@example:/config/container/web/> <b>set image docker://nginx:alpine</b>
|
||||
admin@example:/config/container/web/> <b>set network publish 8080:80</b>
|
||||
admin@example:/config/container/web/> <b>set network interface docker0</b>
|
||||
admin@example:/config/container/web/> <b>set volume cache target /var/cache</b>
|
||||
admin@example:/config/container/web/> <b>leave</b>
|
||||
admin@example:/> <b>show container</b>
|
||||
</code></pre>
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:~$ <b>curl http://localhost:8080</b>
|
||||
</code></pre>
|
||||
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
|
||||
@@ -145,32 +142,31 @@ how to upgrade to a newer base image.
|
||||
|
||||
The CLI help shows:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/system/> <b>help image</b>
|
||||
<b>NAME</b>
|
||||
image <string>
|
||||
admin@example:/config/container/system/> help image
|
||||
NAME
|
||||
image <string>
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
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.
|
||||
</code></pre>
|
||||
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,
|
||||
@@ -202,28 +198,26 @@ mind.
|
||||
|
||||
**Shell OCI Example:**
|
||||
|
||||
<pre class="cli"><code>admin@example:~$ <b>cd /var/tmp/</b>
|
||||
admin@example:/var/tmp$ <b>sudo wget https://github.com/kernelkit/curiOS/releases/download/edge/curios-oci-amd64.tar.gz</b>
|
||||
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$ <b>ll</b>
|
||||
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/
|
||||
</code></pre>
|
||||
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 ...
|
||||
|
||||
<pre class="cli"><code>admin@example:/var/tmp$ <b>cli</b>
|
||||
admin@example:/> <b>container load /var/tmp/curios-oci-amd64.tar.gz name curios:edge</b>
|
||||
</code></pre>
|
||||
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
|
||||
@@ -233,33 +227,31 @@ admin@example:/> <b>container load /var/tmp/curios-oci-amd64.tar.gz name curios:
|
||||
... or by giving the container configuration the full path to the OCI
|
||||
archive, which helps greatly with container upgrades (see below):
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/system/> <b>set image oci-archive:/var/tmp/curios-oci-amd64.tar.gz</b>
|
||||
</code></pre>
|
||||
admin@example:/config/container/system/> set image oci-archive:/var/tmp/curios-oci-amd64.tar.gz
|
||||
|
||||
**Checksum Example:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit container sys</b>
|
||||
admin@example:/config/container/sys/> <b>set hostname sys</b>
|
||||
admin@example:/config/container/sys/> <b>set image ftp://192.168.122.1/curios-oci-amd64-v24.05.0.tar.gz</b>
|
||||
admin@example:/config/container/sys/> <b>set checksum</b>
|
||||
md5 sha256 sha512
|
||||
admin@example:/config/container/sys/> <b>set checksum sha256 4f01077036527498ed910f1a3e80645ae3eff629d10043cf80ebc6850c99c629</b>
|
||||
admin@example:/config/container/sys/> <b>leave</b>
|
||||
admin@example:/> <b>copy running-config startup-config</b>
|
||||
admin@example:/> <b>show container</b>
|
||||
<span class="header">NAME STATUS NETWORK MEMORY (KiB) CPU%</span>
|
||||
sys Up 5 seconds 72/512 0.02
|
||||
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:/> <b>show log</b>
|
||||
...
|
||||
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
|
||||
</code></pre>
|
||||
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
|
||||
@@ -367,11 +359,12 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit container web</b>
|
||||
admin@example:/config/container/web/> <b>set image docker://nginx:1.25.3</b>
|
||||
admin@example:/config/container/web/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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:**
|
||||
|
||||
@@ -382,27 +375,29 @@ admin@example:/config/container/web/> <b>leave</b>
|
||||
|
||||
**Example:** Upgrading from one version to another:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit container system</b>
|
||||
admin@example:/config/container/system/> <b>show image</b>
|
||||
```
|
||||
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/> <b>set image ghcr.io/kernelkit/curios:v24.12.0</b>
|
||||
admin@example:/config/container/system/> <b>leave</b>
|
||||
admin@example:/> <b>show log</b>
|
||||
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
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
### Method 2: Upgrading Mutable Tags
|
||||
|
||||
For images using mutable tags like `:latest` or `:edge`, use the
|
||||
`container upgrade` command:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>container upgrade NAME</b>
|
||||
</code></pre>
|
||||
```
|
||||
admin@example:/> container upgrade NAME
|
||||
```
|
||||
|
||||
This command:
|
||||
|
||||
@@ -413,7 +408,8 @@ This command:
|
||||
|
||||
**Example using registry:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>container upgrade system</b>
|
||||
```
|
||||
admin@example:/> container upgrade system
|
||||
system
|
||||
Trying to pull ghcr.io/kernelkit/curios:edge...
|
||||
Getting image source signatures
|
||||
@@ -424,7 +420,7 @@ Storing signatures
|
||||
0cb6059c0f4111650ddbc7dbc4880c64ab8180d4bdbb7269c08034defc348f17
|
||||
system: not running.
|
||||
59618cc3c84bef341c1f5251a62be1592e459cc990f0b8864bc0f5be70e60719
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
**Example using local OCI archive:**
|
||||
|
||||
@@ -433,10 +429,11 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>container upgrade system</b>
|
||||
```
|
||||
admin@example:/> container upgrade system
|
||||
Upgrading container system with local archive: oci-archive:/var/tmp/curios-oci-amd64.tar.gz ...
|
||||
7ab4a07ee0c6039837419b7afda4da1527a70f0c60c0f0ac21cafee05ba24b52
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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
|
||||
@@ -475,16 +472,15 @@ occasions where they are too restricted and users start looking for the
|
||||
|
||||
For example, a system container from which `ping` does not work:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/system/> <b>edit capabilities</b>
|
||||
admin@example:/config/container/system/capabilities/> <b>set add net_raw</b>
|
||||
admin@example:/config/container/system/capabilities/> <b>end</b>
|
||||
admin@infix-00-00-00:/config/container/system/> <b>show</b>
|
||||
...
|
||||
capabilities {
|
||||
add net_raw;
|
||||
}
|
||||
...
|
||||
</code></pre>
|
||||
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
|
||||
@@ -492,48 +488,6 @@ time and analysis of your container application to figure out which
|
||||
capabilities you need.
|
||||
|
||||
|
||||
Resource Limits
|
||||
---------------
|
||||
|
||||
Containers can be configured with resource limits to control their memory
|
||||
and CPU usage. This helps prevent containers from consuming excessive system
|
||||
resources and ensures fair resource allocation across multiple containers.
|
||||
|
||||
### Configuring Resource Limits
|
||||
|
||||
Resource limits are set per container and include:
|
||||
|
||||
- **Memory:** Maximum memory usage in kibibytes (KiB)
|
||||
- **CPU:** Maximum CPU usage in millicores (1000 millicores = 1 CPU core)
|
||||
|
||||
Example configuration limiting a container to 512 MiB of memory and 1.5 CPU cores:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit container web</b>
|
||||
admin@example:/config/container/web/> <b>edit resource-limit</b>
|
||||
admin@example:/config/container/web/resource-limit/> <b>set memory 524288</b>
|
||||
admin@example:/config/container/web/resource-limit/> <b>set cpu 1500</b>
|
||||
admin@example:/config/container/web/resource-limit/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
Common CPU limit examples:
|
||||
|
||||
- `500` = 0.5 cores (50% of one core)
|
||||
- `1000` = 1.0 cores (one full core)
|
||||
- `2000` = 2.0 cores (two full cores)
|
||||
|
||||
### Monitoring Resource Usage
|
||||
|
||||
Runtime resource usage statistics are available in the operational datastore:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show container web</b>
|
||||
...
|
||||
</code></pre>
|
||||
|
||||
Use `show container usage` to see resource consumption across all containers,
|
||||
including memory, CPU, block I/O, network I/O, and process counts.
|
||||
|
||||
|
||||
Networking and Containers
|
||||
-------------------------
|
||||
|
||||
@@ -569,11 +523,10 @@ container use seem to be so simple.
|
||||
|
||||
All interface configuration is done in configure context.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config> <b>edit interface docker0</b>
|
||||
admin@example:/config/interface/docker0/> <b>set container-network</b>
|
||||
admin@example:/config/interface/docker0/> <b>leave</b>
|
||||
</code></pre>
|
||||
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.
|
||||
@@ -581,9 +534,8 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/docker0/> <b>set type bridge</b>
|
||||
admin@example:/config/interface/docker0/> <b>set container-network type bridge</b>
|
||||
</code></pre>
|
||||
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
|
||||
@@ -609,17 +561,16 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/docker0/> <b>edit container-network</b>
|
||||
admin@example:/config/…/container-network/> <b>set type bridge</b>
|
||||
admin@example:/config/…/container-network/> <b>edit subnet 192.168.0.0/16</b>
|
||||
admin@example:/config/…/subnet/192.168.0.0/16/> <b>set gateway 192.168.255.254</b>
|
||||
admin@example:/config/…/subnet/192.168.0.0/16/> <b>end</b>
|
||||
admin@example:/config/…/container-network/> <b>edit route 10.0.10.0/24</b>
|
||||
admin@example:/config/…/route/10.0.10.0/24/> <b>set gateway 192.168.10.254</b>
|
||||
admin@example:/config/…/route/10.0.10.0/24/> <b>end</b>
|
||||
admin@example:/config/…/container-network/> <b>end</b>
|
||||
admin@example:/config/interface/docker0/> <b>leave</b>
|
||||
</code></pre>
|
||||
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
|
||||
|
||||
Other network settings, like DNS and domain, use built-in defaults, but
|
||||
can be overridden from each container. Other common settings per
|
||||
@@ -631,25 +582,24 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/ntpd/> <b>edit network interface docker0</b>
|
||||
admin@example:/config/…/network/interface/docker0/>
|
||||
admin@example:/config/…/network/interface/docker0/> <b>set option</b>
|
||||
<string> Options for masquerading container bridges.
|
||||
admin@example:/config/…/network/interface/docker0/> <b>help option</b>
|
||||
NAME
|
||||
option <string>
|
||||
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
|
||||
<string> Options for masquerading container bridges.
|
||||
admin@example:/config/container/ntpd/network/interface/docker0/> help option
|
||||
NAME
|
||||
option <string>
|
||||
|
||||
DESCRIPTION
|
||||
Options for masquerading container bridges.
|
||||
|
||||
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/> <b>set option ip=172.17.0.2</b>
|
||||
admin@example:/config/…/network/interface/docker0/> <b>set option interface_name=wan</b>
|
||||
admin@example:/config/…/network/interface/docker0/> <b>leave</b>
|
||||
</code></pre>
|
||||
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
|
||||
|
||||
|
||||
### Container Host Interface
|
||||
@@ -684,15 +634,14 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface veth0</b>
|
||||
admin@example:/config/interface/veth0/> <b>set veth peer ntpd</b>
|
||||
admin@example:/config/interface/veth0/> <b>set ipv4 address 192.168.0.1 prefix-length 24</b>
|
||||
admin@example:/config/interface/veth0/> <b>end</b>
|
||||
admin@example:/config/> <b>edit interface ntpd</b>
|
||||
admin@example:/config/interface/ntpd/> <b>set ipv4 address 192.168.0.2 prefix-length 24</b>
|
||||
admin@example:/config/interface/ntpd/> <b>set custom-phys-address static 00:c0:ff:ee:00:01</b>
|
||||
admin@example:/config/interface/ntpd/> <b>set container-network</b>
|
||||
</code></pre>
|
||||
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.
|
||||
@@ -701,9 +650,8 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/ntpd/> <b>set network interface ntpd</b>
|
||||
admin@example:/config/container/ntpd/> <b>leave</b>
|
||||
</code></pre>
|
||||
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
|
||||
@@ -724,10 +672,9 @@ pair to give our container two interfaces:
|
||||
|
||||
We start by adding the second VETH pair:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface veth1a</b>
|
||||
admin@example:/config/interface/veth1a/> <b>set veth peer veth1</b>
|
||||
admin@example:/config/interface/veth1a/> <b>set ipv4 address 192.168.1.2 prefix-length 24</b>
|
||||
</code></pre>
|
||||
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.
|
||||
@@ -736,21 +683,20 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/veth1a/> <b>set container-network route 0.0.0.0/0 gateway 192.168.1.1</b>
|
||||
admin@example:/config/interface/veth1a/> <b>show</b>
|
||||
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/> <b>end</b>
|
||||
admin@example:/config/> <b>set interface veth1 bridge-port bridge br1</b>
|
||||
</code></pre>
|
||||
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,
|
||||
@@ -776,12 +722,11 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/system/> <b>edit mount leds</b>
|
||||
admin@example:/config/container/system/mount/leds> <b>set source /sys/class/leds</b>
|
||||
admin@example:/config/container/system/mount/leds> <b>set target /sys/class/leds</b>
|
||||
admin@example:/config/container/system/mount/leds> <b>end</b>
|
||||
admin@example:/config/container/system/>
|
||||
</code></pre>
|
||||
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
|
||||
@@ -797,8 +742,7 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/ntpd/> <b>set volume varlib target /var/lib</b>
|
||||
</code></pre>
|
||||
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,
|
||||
@@ -828,15 +772,14 @@ where:
|
||||
To clean up unused volumes and reclaim disk space, use the admin-exec
|
||||
command:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>container prune</b>
|
||||
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
|
||||
</code></pre>
|
||||
Total reclaimed space: 45.2MB
|
||||
|
||||
The `container prune` command safely removes:
|
||||
|
||||
@@ -847,16 +790,14 @@ The `container prune` command safely removes:
|
||||
> [!TIP]
|
||||
> You can monitor container resource usage with the command:
|
||||
>
|
||||
> <pre class="cli"><code>admin@example:/> <b>show container usage</b>
|
||||
> </code></pre>
|
||||
> 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:
|
||||
>
|
||||
> <pre class="cli"><code>admin@example:/> <b>show container volumes</b>
|
||||
> </code></pre>
|
||||
> admin@example:/> show container volumes
|
||||
|
||||
### Content Mounts
|
||||
|
||||
@@ -866,13 +807,12 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/ntpd/> <b>edit mount ntpd.conf</b>
|
||||
admin@example:/config/container/ntpd/mount/ntpd.conf> <b>text-editor content</b>
|
||||
... interactive editor starts up ...
|
||||
admin@example:/config/container/ntpd/mount/ntpd.conf> <b>set target /etc/ntpd.conf</b>
|
||||
admin@example:/config/container/ntpd/mount/ntpd.conf> <b>end</b>
|
||||
admin@example:/config/container/ntpd/>
|
||||
</code></pre>
|
||||
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
|
||||
@@ -896,13 +836,12 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config> <b>edit container system</b>
|
||||
admin@example:/config/container/system/> <b>set image ghcr.io/kernelkit/curios:edge</b>
|
||||
admin@example:/config/container/system/> <b>set network interface docker0</b>
|
||||
admin@example:/config/container/system/> <b>set publish 222:22</b>
|
||||
admin@example:/config/container/system/> <b>leave</b>
|
||||
</code></pre>
|
||||
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
|
||||
@@ -917,29 +856,26 @@ container configuration context for the full syntax.)
|
||||
|
||||
Available containers can be accessed from admin-exec:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show container</b>
|
||||
<span class="header">NAME STATUS NETWORK MEMORY (KiB) CPU%</span>
|
||||
system Up 16 hours docker0 136/512 0.02
|
||||
</code></pre>
|
||||
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
|
||||
|
||||
This is a system container, so you can "attach" to it by starting a
|
||||
shell (or logging in with SSH):
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>container shell system</b>
|
||||
root@439af2917b44:/#
|
||||
</code></pre>
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>root@439af2917b44:/# <b>exit</b>
|
||||
admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit container system</b>
|
||||
admin@example:/config/container/system/> <b>set hostname sys101</b>
|
||||
admin@example:/config/container/system/> <b>leave</b>
|
||||
admin@example:/> <b>container shell system</b>
|
||||
root@sys101:/#
|
||||
</code></pre>
|
||||
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:
|
||||
@@ -964,17 +900,16 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config> <b>edit container nftables</b>
|
||||
admin@example:/config/container/nftables/> <b>set image ghcr.io/kernelkit/curios-nftables:edge</b>
|
||||
admin@example:/config/container/nftables/> <b>set network host</b>
|
||||
admin@example:/config/container/nftables/> <b>set privileged</b>
|
||||
admin@example:/config/container/nftables/> <b>edit mount nftables.conf</b>
|
||||
admin@example:/config/…/mount/nftables.conf/> <b>set target /etc/nftables.conf</b>
|
||||
admin@example:/config/…/mount/nftables.conf/> <b>text-editor content</b>
|
||||
... interactive editor starts up where you can paste your rules ...
|
||||
admin@example:/config/…/mount/nftables.conf/> <b>leave</b>
|
||||
</code></pre>
|
||||
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
|
||||
|
||||
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
|
||||
@@ -993,20 +928,19 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config> <b>edit container ntpd</b>
|
||||
admin@example:/config/container/ntpd/> <b>set image ghcr.io/kernelkit/curios-ntpd:edge</b>
|
||||
admin@example:/config/container/ntpd/> <b>set network interface ntpd</b> # From veth0 above
|
||||
admin@example:/config/container/ntpd/> <b>edit mount ntp.conf</b>
|
||||
admin@example:/config/container/ntpd/mount/ntp.conf/> <b>set target /etc/ntp.conf</b>
|
||||
admin@example:/config/container/ntpd/mount/ntp.conf/> <b>text-editor content</b>
|
||||
... interactive editor starts up where you can paste your rules ...
|
||||
admin@example:/config/container/ntpd/mount/ntp.conf/> <b>end</b>
|
||||
admin@example:/config/container/ntpd/> <b>edit volume varlib</b>
|
||||
admin@example:/config/container/ntpd/volume/varlib/> <b>set target /var/lib</b>
|
||||
admin@example:/config/container/ntpd/volume/varlib/> <b>leave</b>
|
||||
admin@example:/> <b>copy running-config startup-config</b>
|
||||
</code></pre>
|
||||
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
|
||||
@@ -1041,28 +975,25 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/system/> <b>set privileged</b>
|
||||
</code></pre>
|
||||
admin@example:/config/container/system/> set privileged
|
||||
|
||||
Second, mount the host's `/proc/1` directory to somewhere inside your
|
||||
container. Here we pick `/1`:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/container/system/> <b>edit mount host</b>
|
||||
admin@example:/config/container/system/mount/host/> <b>set source /proc/1</b>
|
||||
admin@example:/config/container/system/mount/host/> <b>set target /1</b>
|
||||
admin@example:/config/container/system/mount/host/> <b>leave</b>
|
||||
</code></pre>
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>root@sys101:/# <b>hostname</b>
|
||||
sys101
|
||||
root@sys101:/# <b>nsenter -m/1/ns/mnt -u/1/ns/uts -i/1/ns/ipc -n/1/ns/net hostname</b>
|
||||
example
|
||||
</code></pre>
|
||||
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
|
||||
|
||||
+54
-46
@@ -19,18 +19,20 @@ servers[^1].
|
||||
The following example configures a DHCP server for subnet 192.168.2.0/24
|
||||
with an address pool:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit dhcp-server subnet 192.168.2.0/24</b>
|
||||
admin@example:/config/dhcp-server/…/192.168.2.0/24/> <b>set pool start-address 192.168.2.100 end-address 192.168.2.200</b>
|
||||
admin@example:/config/dhcp-server/…/192.168.2.0/24/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show running-config</b>
|
||||
```
|
||||
admin@example:/> show running-config
|
||||
"infix-dhcp-server:dhcp-server": {
|
||||
"subnet": [
|
||||
{
|
||||
@@ -52,7 +54,7 @@ interface.
|
||||
}
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Remember to set up an interface in this subnet, avoid using addresses
|
||||
@@ -66,21 +68,23 @@ interface.
|
||||
To reserve specific IP addresses for clients based on their MAC address,
|
||||
hostname, or client ID:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/dhcp-server/…/192.168.2.0/24/> <b>edit host 192.168.2.10</b>
|
||||
admin@example:/config/dhcp-server/…/192.168.2.10/> <b>set match mac-address 00:11:22:33:44:55</b>
|
||||
admin@example:/config/dhcp-server/…/192.168.2.10/> <b>set hostname printer</b>
|
||||
admin@example:/config/dhcp-server/…/192.168.2.10/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/dhcp-server/…/192.168.1.0/24/> <b>edit host 192.168.1.50</b>
|
||||
admin@example:/config/dhcp-server/…/192.168.1.50/> <b>edit match</b>
|
||||
admin@example:/config/dhcp-server/…/match/> <b>set client-id hex c0:ff:ee</b>
|
||||
admin@example:/config/dhcp-server/…/match/> <b>leave</b>
|
||||
admin@example:/config/dhcp-server/…/192.168.1.50/> <b>set lease-time infinite</b>
|
||||
admin@example:/config/dhcp-server/…/192.168.1.50/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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
|
||||
@@ -96,30 +100,32 @@ ASCII string "c0:ff:ee", eight bytes, is used.
|
||||
|
||||
Configure additional DHCP options globally, per subnet, or per host:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/dhcp-server/> <b>edit subnet 192.168.2.0/24</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> <b>edit option dns-server</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/dns-server/> <b>set address 8.8.8.8</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/dns-server/> <b>leave</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> <b>edit option ntp-server</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/ntp-server/> <b>set address 192.168.2.1</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/option/ntp-server/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
```
|
||||
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/> <b>edit option dns-server</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/option/dns-server/> <b>set address auto</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/option/dns-server/> <b>leave</b>
|
||||
</code></pre>
|
||||
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.
|
||||
@@ -129,27 +135,29 @@ as their DNS server address.
|
||||
|
||||
Configure DHCP for multiple networks:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit dhcp-server</b>
|
||||
admin@example:/config/dhcp-server/> <b>edit subnet 192.168.1.0/24</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> <b>set pool start-address 192.168.1.100 end-address 192.168.1.200</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.1.0/24/> <b>leave</b>
|
||||
admin@example:/config/dhcp-server/> <b>edit subnet 192.168.2.0/24</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> <b>set pool start-address 192.168.2.100 end-address 192.168.2.200</b>
|
||||
admin@example:/config/dhcp-server/subnet/192.168.2.0/24/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show dhcp-server</b>
|
||||
<span class="header">IP ADDRESS MAC HOSTNAME CLIENT ID EXPIRES</span>
|
||||
```
|
||||
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:/> <b>show dhcp-server statistics</b>
|
||||
admin@example:/> show dhcp-server statistics
|
||||
DHCP offers sent : 6
|
||||
DHCP ACK messages sent : 5
|
||||
DHCP NAK messages sent : 0
|
||||
@@ -158,7 +166,7 @@ DHCP discover messages received : 6
|
||||
DHCP request messages received : 5
|
||||
DHCP release messages received : 6
|
||||
DHCP inform messages received : 6
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
|
||||
[^1]: This requires the system DNS resolver to be configured.
|
||||
|
||||
-208
@@ -1,208 +0,0 @@
|
||||
# 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.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0.20</b>
|
||||
admin@example:/config/interface/eth0.20/> <b>show</b>
|
||||
type vlan;
|
||||
vlan {
|
||||
tag-type c-vlan;
|
||||
id 20;
|
||||
lower-layer-if eth0;
|
||||
}
|
||||
admin@example:/config/interface/eth0.20/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
The example below assumes bridge br0 is already created, see [VLAN
|
||||
Filtering Bridge](bridging.md#vlan-filtering-bridge).
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface vlan10</b>
|
||||
admin@example:/config/interface/vlan10/> <b>set vlan id 10</b>
|
||||
admin@example:/config/interface/vlan10/> <b>set vlan lower-layer-if br0</b>
|
||||
admin@example:/config/interface/vlan10/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
The speed and duplex status for the links can be listed as shown
|
||||
below, assuming the link operational status is 'up'.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interface eth1</b>
|
||||
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:/> <b>show interface eth4</b>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
### 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth3 ethernet</b>
|
||||
admin@example:/config/interface/eth3/ethernet/> <b>set speed 0.1</b>
|
||||
admin@example:/config/interface/eth3/ethernet/> <b>set duplex half</b>
|
||||
admin@example:/config/interface/eth3/ethernet/> <b>set auto-negotiation enable false</b>
|
||||
admin@example:/config/interface/eth3/ethernet/> <b>show</b>
|
||||
auto-negotiation {
|
||||
enable false;
|
||||
}
|
||||
duplex half;
|
||||
speed 0.1;
|
||||
admin@example:/config/interface/eth3/ethernet/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interface eth1</b>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface veth0a</b>
|
||||
admin@example:/config/interface/veth0a/> <b>set veth peer veth0b</b>
|
||||
admin@example:/config/interface/veth0a/> <b>end</b>
|
||||
admin@example:/config/> <b>diff</b>
|
||||
interfaces {
|
||||
+ interface veth0a {
|
||||
+ type veth;
|
||||
+ veth {
|
||||
+ peer veth0b;
|
||||
+ }
|
||||
+ }
|
||||
+ interface veth0b {
|
||||
+ type veth;
|
||||
+ veth {
|
||||
+ peer veth0a;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
admin@example:/config/>
|
||||
</code></pre>
|
||||
|
||||
> [!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.
|
||||
@@ -24,14 +24,3 @@
|
||||
/* 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;
|
||||
}
|
||||
|
||||
+20
-24
@@ -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](ip.md#ipv4-forwarding)
|
||||
> to work, you must also enable [IP forwarding](networking.md#ipv4-forwarding)
|
||||
> on the relevant interfaces.
|
||||
|
||||
### Intra-Zone Traffic
|
||||
@@ -151,16 +151,15 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/firewall/policy/lan-to-dmz/> <b>help masquerade</b>
|
||||
<code><pre>admin@example:/config/firewall/policy/lan-to-dmz/> <b>help masquerade</b>
|
||||
<b>NAME</b>
|
||||
masquerade <true/false><br/>
|
||||
<b>DESCRIPTION</b>
|
||||
Enable masquerading (SNAT) for traffic matching this policy.<br/>
|
||||
Matching traffic will have their source IP address changed on egress,
|
||||
using the IP address of the interface the traffic egresses.<br/>
|
||||
using the IP address of the interface the traffic egresses.";<br/>
|
||||
admin@example:/config/firewall/policy/lan-to-dmz/>
|
||||
</code></pre>
|
||||
</pre></code>
|
||||
|
||||
### Symbolic Names
|
||||
|
||||
@@ -230,8 +229,7 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
<code><pre>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit firewall</b>
|
||||
admin@example:/config/firewall/> <b>show</b>
|
||||
default public;
|
||||
@@ -242,21 +240,21 @@ zone public {
|
||||
service ssh;
|
||||
}
|
||||
admin@example:/config/firewall/> <b>leave</b>
|
||||
</code></pre>
|
||||
</pre></code>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code><b>$</b> ping 192.168.122.161
|
||||
<code><pre>
|
||||
<b>$</b> ping 192.168.122.161
|
||||
From 192.168.122.161 icmp_seq=1 <u>Packet filtered</u>
|
||||
</code></pre>
|
||||
</pre></code>
|
||||
|
||||
If we run `tcpdump` it shows us why:
|
||||
|
||||
<pre class="cli"><code><b>$</b> tcpdump -lni eth0
|
||||
<code><pre>
|
||||
<b>$</b> 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 <u>host 192.168.122.161 unreachable - admin prohibited filter</u>, length 92
|
||||
</code></pre>
|
||||
</pre></code>
|
||||
|
||||
The key here is that, yes the device responds, but not with `ICMP reply` but
|
||||
`ICMP unreachable`, and a little helpful message.
|
||||
@@ -287,8 +285,7 @@ Zone matrix and firewall overview from <kbd>show firewall</kbd>.
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
<code><pre>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit firewall</b>
|
||||
admin@example:/config/firewall/> <b>set default wan</b>
|
||||
admin@example:/config/firewall/> <b>edit zone lan</b>
|
||||
@@ -311,15 +308,14 @@ admin@example:/config/firewall/…/loc-to-wan/> <b>set egress wan</b>
|
||||
admin@example:/config/firewall/…/loc-to-wan/> <b>set action accept</b>
|
||||
admin@example:/config/firewall/…/loc-to-wan/> <b>set masquerade</b>
|
||||
admin@example:/config/firewall/…/loc-to-wan/> <b>leave</b>
|
||||
</code></pre>
|
||||
</pre></code>
|
||||
|
||||
### 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
<code><pre>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit firewall zone dmz</b>
|
||||
admin@example:/config/firewall/…/dmz/> <b>set description "Semi-trusted public services"</b>
|
||||
admin@example:/config/firewall/…/dmz/> <b>set action drop</b>
|
||||
@@ -343,7 +339,7 @@ admin@example:/config/firewall/> <b>edit zone wan port-forward 8080 tcp</b>
|
||||
admin@example:/config/firewall/…/tcp/> <b>set to addr 192.168.2.10</b>
|
||||
admin@example:/config/firewall/…/tcp/> <b>set to port 80</b>
|
||||
admin@example:/config/firewall/…/tcp/> <b>leave</b>
|
||||
</code></pre>
|
||||
</pre></code>
|
||||
|
||||
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
|
||||
@@ -353,12 +349,12 @@ external web traffic to the DMZ server.
|
||||
|
||||
Different log levels are available to monitor and debug firewall behavior.
|
||||
Configure logging using the CLI:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
<code><pre>
|
||||
admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit firewall</b>
|
||||
admin@example:/config/firewall/> <b>set logging all</b>
|
||||
admin@example:/config/firewall/> <b>leave</b>
|
||||
</code></pre>
|
||||
</pre></code>
|
||||
|
||||
Firewall logs help you understand traffic patterns and security events. The
|
||||
CLI admin-exec command <kbd>show firewall</kbd> shows the last 10 log messages in the
|
||||
@@ -461,4 +457,4 @@ You can check the current lockdown state:
|
||||
}
|
||||
```
|
||||
|
||||
[1]: bridging.md
|
||||
[1]: networking.md#bridging
|
||||
|
||||
+17
-27
@@ -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,38 +24,26 @@ 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
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show hardware</b>
|
||||
<span class="header">HARDWARE COMPONENTS </span>
|
||||
──────────────────────────────────────────────────────────────
|
||||
<span class="title">Board Information </span>
|
||||
Model : FriendlyElec NanoPi R2S
|
||||
Manufacturer : FriendlyElec
|
||||
Serial Number : 9d1fbfdab6d171ce
|
||||
Base MAC Address : 4a:dc:d8:20:0d:85
|
||||
──────────────────────────────────────────────────────────────
|
||||
<span class="title">USB Ports </span>
|
||||
<span class="header">NAME STATE OPER </span>
|
||||
USB unlocked enabled
|
||||
──────────────────────────────────────────────────────────────
|
||||
<span class="title">Sensors </span>
|
||||
<span class="header">NAME VALUE STATUS </span>
|
||||
soc 44.1 °C ok
|
||||
soc 44.5 °C ok
|
||||
</code></pre>
|
||||
```
|
||||
admin@example:/> show hardware
|
||||
USB PORTS
|
||||
NAME STATE
|
||||
USB unlocked
|
||||
```
|
||||
|
||||
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
|
||||
@@ -68,11 +56,12 @@ Linux to use.
|
||||
> command `show hardware` in admin-exec context. (Use `do` prefix in
|
||||
> configure context.)
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>set hardware component USB state admin-state unlocked</b>
|
||||
admin@example:/config/> <b>leave</b>
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> set hardware component USB state admin-state unlocked
|
||||
admin@example:/config/> leave
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
### Using a USB Stick
|
||||
|
||||
@@ -92,7 +81,8 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:~$ <b>sudo umount /media/log</b>
|
||||
</code></pre>
|
||||
```
|
||||
admin@example:~$ sudo umount /media/log
|
||||
```
|
||||
|
||||
[1]: https://www.rfc-editor.org/rfc/rfc8348.html
|
||||
|
||||
-143
@@ -1,143 +0,0 @@
|
||||
# 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface br0</b>
|
||||
admin@example:/config/interface/br0/> <b>set type bridge</b>
|
||||
</code></pre>
|
||||
|
||||
Available types can be listed from the CLI:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/br0/> <b>set type ?</b>
|
||||
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.
|
||||
</code></pre>
|
||||
|
||||
|
||||
## Enable/Disable
|
||||
|
||||
An interface can be administratively disabled using the `enabled` setting.
|
||||
By default, interfaces are enabled (`true`).
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface eth0</b>
|
||||
admin@example:/config/interface/eth0/> <b>set enabled false</b>
|
||||
admin@example:/config/interface/eth0/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
The operational status can be inspected to see both administrative and
|
||||
actual link state:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interfaces</b>
|
||||
INTERFACE PROTOCOL STATE DATA
|
||||
eth0 ethernet <b>DISABLED</b> 02:00:00:00:00:00
|
||||
eth1 ethernet UP 02:00:00:00:00:01
|
||||
...
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface eth0</b>
|
||||
admin@example:/config/interface/eth0/> <b>set description "Uplink to core switch"</b>
|
||||
admin@example:/config/interface/eth0/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
The description is visible in the operational datastore and in `show`
|
||||
commands:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interface eth0</b>
|
||||
name : eth0
|
||||
description : Uplink to core switch
|
||||
index : 2
|
||||
...
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface veth0a</b>
|
||||
admin@example:/config/interface/veth0a/> <b>set custom-phys-address static 00:ab:00:11:22:33</b>
|
||||
|
||||
=> 00:ab:00:11:22:33
|
||||
</code></pre>
|
||||
|
||||
### Chassis MAC
|
||||
|
||||
Chassis MAC, sometimes also referred to as base MAC. In these two
|
||||
examples it is `00:53:00:c0:ff:ee`.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface veth0a</b>
|
||||
admin@example:/config/interface/veth0a/> <b>set custom-phys-address chassis</b>
|
||||
|
||||
=> 00:53:00:c0:ff:ee
|
||||
</code></pre>
|
||||
|
||||
### Chassis MAC, with offset
|
||||
|
||||
When constructing a derived address it is recommended to set the locally
|
||||
administered bit. Same chassis MAC as before.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface veth0a</b>
|
||||
admin@example:/config/interface/veth0a/> <b>set custom-phys-address chassis offset 02:00:00:00:00:02</b>
|
||||
|
||||
=> 02:53:00:c0:ff:f0
|
||||
</code></pre>
|
||||
|
||||
|
||||
[^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`.
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 250 KiB |
@@ -1,983 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 700 500"
|
||||
version="1.1"
|
||||
id="svg220"
|
||||
sodipodi:docname="vpn-hub-spoke.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview222"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.8885714"
|
||||
inkscape:cx="350.00001"
|
||||
inkscape:cy="225.56733"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1014"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg220" />
|
||||
<defs
|
||||
id="defs40">
|
||||
<linearGradient
|
||||
id="bgGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="100%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#fafbfc;stop-opacity:1"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#f3f4f6;stop-opacity:1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="siteGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#3b82f6;stop-opacity:1"
|
||||
id="stop7" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#2563eb;stop-opacity:1"
|
||||
id="stop9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="routerGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#ef4444;stop-opacity:1"
|
||||
id="stop12" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#dc2626;stop-opacity:1"
|
||||
id="stop14" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="hubGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#f59e0b;stop-opacity:1"
|
||||
id="stop17" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#d97706;stop-opacity:1"
|
||||
id="stop19" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
id="shadow"
|
||||
x="-0.054666667"
|
||||
y="-0.082"
|
||||
width="1.1093333"
|
||||
height="1.184">
|
||||
<feGaussianBlur
|
||||
in="SourceAlpha"
|
||||
stdDeviation="3"
|
||||
id="feGaussianBlur22" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="2"
|
||||
result="offsetblur"
|
||||
id="feOffset24" />
|
||||
<feComponentTransfer
|
||||
id="feComponentTransfer28">
|
||||
<feFuncA
|
||||
type="linear"
|
||||
slope="0.2"
|
||||
id="feFuncA26" />
|
||||
</feComponentTransfer>
|
||||
<feMerge
|
||||
id="feMerge34">
|
||||
<feMergeNode
|
||||
id="feMergeNode30" />
|
||||
<feMergeNode
|
||||
in="SourceGraphic"
|
||||
id="feMergeNode32" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<marker
|
||||
id="arrow"
|
||||
markerWidth="8"
|
||||
markerHeight="8"
|
||||
refX="7"
|
||||
refY="4"
|
||||
orient="auto">
|
||||
<path
|
||||
d="M 0,0 V 8 L 8,4 Z"
|
||||
fill="#10b981"
|
||||
id="path37" />
|
||||
</marker>
|
||||
<radialGradient
|
||||
id="cloudGrad"
|
||||
cx="220.99805"
|
||||
cy="209.29596"
|
||||
gradientTransform="matrix(1.3416408,0,0,0.74535599,215.52724,137.78745)"
|
||||
fx="220.99805"
|
||||
fy="209.29596"
|
||||
r="51.988579"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
id="stop22" />
|
||||
<stop
|
||||
offset="70%"
|
||||
style="stop-color:#dbeafe;stop-opacity:1"
|
||||
id="stop24" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#93c5fd;stop-opacity:1"
|
||||
id="stop26" />
|
||||
</radialGradient>
|
||||
<filter
|
||||
id="shadow-7"
|
||||
x="-0.061678832"
|
||||
y="-0.11266667"
|
||||
width="1.1233577"
|
||||
height="1.252">
|
||||
<feGaussianBlur
|
||||
in="SourceAlpha"
|
||||
stdDeviation="3"
|
||||
id="feGaussianBlur29" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="2"
|
||||
result="offsetblur"
|
||||
id="feOffset31" />
|
||||
<feComponentTransfer
|
||||
id="feComponentTransfer35">
|
||||
<feFuncA
|
||||
type="linear"
|
||||
slope="0.2"
|
||||
id="feFuncA33" />
|
||||
</feComponentTransfer>
|
||||
<feMerge
|
||||
id="feMerge41">
|
||||
<feMergeNode
|
||||
id="feMergeNode37" />
|
||||
<feMergeNode
|
||||
in="SourceGraphic"
|
||||
id="feMergeNode39" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<style
|
||||
id="style26">
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#bgGrad stop:first-child { stop-color: #1f2937; }
|
||||
#bgGrad stop:last-child { stop-color: #111827; }
|
||||
#siteGrad stop:first-child { stop-color: #2563eb; }
|
||||
#siteGrad stop:last-child { stop-color: #1e40af; }
|
||||
#routerGrad stop:first-child { stop-color: #dc2626; }
|
||||
#routerGrad stop:last-child { stop-color: #b91c1c; }
|
||||
#hubGrad stop:first-child { stop-color: #f59e0b; }
|
||||
#hubGrad stop:last-child { stop-color: #d97706; }
|
||||
rect[fill="#fff"], rect[fill="#ffffff"] { fill: #374151; }
|
||||
rect[stroke="#e5e7eb"] { stroke: #4b5563; }
|
||||
text[fill="#6b7280"] { fill: #d1d5db; }
|
||||
circle[fill="#60a5fa"] { fill: #3b82f6; }
|
||||
line[stroke="#94a3b8"] { stroke: #6b7280; }
|
||||
rect[fill="#fbbf24"] { fill: #f59e0b; }
|
||||
rect[fill="#fca5a5"] { fill: #fca5a5; }
|
||||
}
|
||||
</style>
|
||||
<!-- Physical Internet connections (solid lines) -->
|
||||
<!-- VPN Tunnels -->
|
||||
<line
|
||||
x1="149.87024"
|
||||
y1="94.852066"
|
||||
x2="262.66898"
|
||||
y2="194.88768"
|
||||
stroke="#10b981"
|
||||
stroke-width="2.6"
|
||||
stroke-dasharray="10,6"
|
||||
marker-end="url(#arrow)"
|
||||
id="line44" />
|
||||
<g
|
||||
transform="translate(155,83)"
|
||||
id="g52">
|
||||
<rect
|
||||
width="8"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="#10b981"
|
||||
id="rect46"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 1.5,0 v -2.5 a 2.5,2.5 0 0 1 5,0 V 0"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.2"
|
||||
id="path48" />
|
||||
<circle
|
||||
cx="4"
|
||||
cy="6"
|
||||
r="1.2"
|
||||
fill="#ffffff"
|
||||
id="circle50" />
|
||||
</g>
|
||||
<line
|
||||
x1="550.13788"
|
||||
y1="94.850327"
|
||||
x2="437.03882"
|
||||
y2="193.65047"
|
||||
stroke="#10b981"
|
||||
stroke-width="2.6"
|
||||
stroke-dasharray="10,6"
|
||||
marker-end="url(#arrow)"
|
||||
id="line54" />
|
||||
<g
|
||||
transform="translate(537,83)"
|
||||
id="g62">
|
||||
<rect
|
||||
width="8"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="#10b981"
|
||||
id="rect56"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 1.5,0 v -2.5 a 2.5,2.5 0 0 1 5,0 V 0"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.2"
|
||||
id="path58" />
|
||||
<circle
|
||||
cx="4"
|
||||
cy="6"
|
||||
r="1.2"
|
||||
fill="#ffffff"
|
||||
id="circle60" />
|
||||
</g>
|
||||
<line
|
||||
x1="348.10764"
|
||||
y1="399.8786"
|
||||
x2="348.10764"
|
||||
y2="311.25961"
|
||||
stroke="#10b981"
|
||||
stroke-width="2.6"
|
||||
stroke-dasharray="10, 6"
|
||||
marker-end="url(#arrow)"
|
||||
id="line64" />
|
||||
<g
|
||||
transform="translate(346,383)"
|
||||
id="g72">
|
||||
<rect
|
||||
width="8"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="#10b981"
|
||||
id="rect66"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 1.5,0 v -2.5 a 2.5,2.5 0 0 1 5,0 V 0"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.2"
|
||||
id="path68" />
|
||||
<circle
|
||||
cx="4"
|
||||
cy="6"
|
||||
r="1.2"
|
||||
fill="#ffffff"
|
||||
id="circle70" />
|
||||
</g>
|
||||
<!-- Hub (Center) -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g114">
|
||||
<rect
|
||||
x="260"
|
||||
y="195"
|
||||
width="180"
|
||||
height="110"
|
||||
rx="12"
|
||||
fill="#fff"
|
||||
stroke="#e5e7eb"
|
||||
stroke-width="2"
|
||||
id="rect82" />
|
||||
<!-- Header -->
|
||||
<rect
|
||||
x="260"
|
||||
y="195"
|
||||
width="180"
|
||||
height="38"
|
||||
rx="12"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect84" />
|
||||
<rect
|
||||
x="260"
|
||||
y="220"
|
||||
width="180"
|
||||
height="13"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect86" />
|
||||
<text
|
||||
x="350"
|
||||
y="220"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="15"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text88">Headquarters</text>
|
||||
<!-- Hub Router -->
|
||||
<rect
|
||||
x="278"
|
||||
y="243"
|
||||
width="144"
|
||||
height="38"
|
||||
rx="8"
|
||||
fill="url(#hubGrad)"
|
||||
id="rect90" />
|
||||
<rect
|
||||
x="280"
|
||||
y="245"
|
||||
width="140"
|
||||
height="18"
|
||||
rx="6"
|
||||
fill="#fbbf24"
|
||||
opacity="0.3"
|
||||
id="rect92" />
|
||||
<text
|
||||
x="350"
|
||||
y="267"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="13"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text94">HUB</text>
|
||||
<!-- Local Network -->
|
||||
<line
|
||||
x1="260"
|
||||
y1="250"
|
||||
x2="180"
|
||||
y2="250"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line96" />
|
||||
<line
|
||||
x1="180"
|
||||
y1="220"
|
||||
x2="180"
|
||||
y2="280"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line98" />
|
||||
<circle
|
||||
cx="172"
|
||||
cy="225"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle100" />
|
||||
<line
|
||||
x1="180"
|
||||
y1="225"
|
||||
x2="174"
|
||||
y2="225"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line102" />
|
||||
<circle
|
||||
cx="172"
|
||||
cy="250"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle104" />
|
||||
<line
|
||||
x1="180"
|
||||
y1="250"
|
||||
x2="174"
|
||||
y2="250"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line106" />
|
||||
<circle
|
||||
cx="172"
|
||||
cy="275"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle108" />
|
||||
<line
|
||||
x1="180"
|
||||
y1="275"
|
||||
x2="174"
|
||||
y2="275"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line110" />
|
||||
<text
|
||||
x="130"
|
||||
y="252"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="8"
|
||||
font-weight="600"
|
||||
fill="#6b7280"
|
||||
id="text112">192.168.0.0/24</text>
|
||||
</g>
|
||||
<!-- Spoke A (Top Left) -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g148">
|
||||
<rect
|
||||
x="40"
|
||||
y="30"
|
||||
width="150"
|
||||
height="100"
|
||||
rx="12"
|
||||
fill="#fff"
|
||||
stroke="#e5e7eb"
|
||||
stroke-width="2"
|
||||
id="rect116" />
|
||||
<!-- Header -->
|
||||
<rect
|
||||
x="40"
|
||||
y="30"
|
||||
width="150"
|
||||
height="32"
|
||||
rx="12"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect118" />
|
||||
<rect
|
||||
x="40"
|
||||
y="51"
|
||||
width="150"
|
||||
height="11"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect120" />
|
||||
<text
|
||||
x="115"
|
||||
y="51"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text122">Branch A</text>
|
||||
<!-- Router -->
|
||||
<rect
|
||||
x="55"
|
||||
y="70"
|
||||
width="120"
|
||||
height="30"
|
||||
rx="6"
|
||||
fill="url(#routerGrad)"
|
||||
id="rect124" />
|
||||
<rect
|
||||
x="57"
|
||||
y="72"
|
||||
width="116"
|
||||
height="14"
|
||||
rx="4"
|
||||
fill="#fca5a5"
|
||||
opacity="0.3"
|
||||
id="rect126" />
|
||||
<text
|
||||
x="115"
|
||||
y="89"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#fff"
|
||||
id="text128">Spoke</text>
|
||||
<!-- Local Network -->
|
||||
<line
|
||||
x1="115"
|
||||
y1="100"
|
||||
x2="115"
|
||||
y2="107"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line130" />
|
||||
<line
|
||||
x1="90"
|
||||
y1="107"
|
||||
x2="140"
|
||||
y2="107"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line132" />
|
||||
<circle
|
||||
cx="95"
|
||||
cy="115"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle134" />
|
||||
<line
|
||||
x1="95"
|
||||
y1="107"
|
||||
x2="95"
|
||||
y2="113"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line136" />
|
||||
<circle
|
||||
cx="115"
|
||||
cy="115"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle138" />
|
||||
<line
|
||||
x1="115"
|
||||
y1="107"
|
||||
x2="115"
|
||||
y2="113"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line140" />
|
||||
<circle
|
||||
cx="135"
|
||||
cy="115"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle142" />
|
||||
<line
|
||||
x1="135"
|
||||
y1="107"
|
||||
x2="135"
|
||||
y2="113"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line144" />
|
||||
<text
|
||||
x="115"
|
||||
y="128"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="7"
|
||||
font-weight="600"
|
||||
fill="#6b7280"
|
||||
id="text146">192.168.1.0/24</text>
|
||||
</g>
|
||||
<!-- Spoke B (Top Right) -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g182">
|
||||
<rect
|
||||
x="510"
|
||||
y="30"
|
||||
width="150"
|
||||
height="100"
|
||||
rx="12"
|
||||
fill="#fff"
|
||||
stroke="#e5e7eb"
|
||||
stroke-width="2"
|
||||
id="rect150" />
|
||||
<!-- Header -->
|
||||
<rect
|
||||
x="510"
|
||||
y="30"
|
||||
width="150"
|
||||
height="32"
|
||||
rx="12"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect152" />
|
||||
<rect
|
||||
x="510"
|
||||
y="51"
|
||||
width="150"
|
||||
height="11"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect154" />
|
||||
<text
|
||||
x="585"
|
||||
y="51"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text156">Branch B</text>
|
||||
<!-- Router -->
|
||||
<rect
|
||||
x="525"
|
||||
y="70"
|
||||
width="120"
|
||||
height="30"
|
||||
rx="6"
|
||||
fill="url(#routerGrad)"
|
||||
id="rect158" />
|
||||
<rect
|
||||
x="527"
|
||||
y="72"
|
||||
width="116"
|
||||
height="14"
|
||||
rx="4"
|
||||
fill="#fca5a5"
|
||||
opacity="0.3"
|
||||
id="rect160" />
|
||||
<text
|
||||
x="585"
|
||||
y="89"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#fff"
|
||||
id="text162">Spoke</text>
|
||||
<!-- Local Network -->
|
||||
<line
|
||||
x1="585"
|
||||
y1="100"
|
||||
x2="585"
|
||||
y2="107"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line164" />
|
||||
<line
|
||||
x1="560"
|
||||
y1="107"
|
||||
x2="610"
|
||||
y2="107"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line166" />
|
||||
<circle
|
||||
cx="565"
|
||||
cy="115"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle168" />
|
||||
<line
|
||||
x1="565"
|
||||
y1="107"
|
||||
x2="565"
|
||||
y2="113"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line170" />
|
||||
<circle
|
||||
cx="585"
|
||||
cy="115"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle172" />
|
||||
<line
|
||||
x1="585"
|
||||
y1="107"
|
||||
x2="585"
|
||||
y2="113"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line174" />
|
||||
<circle
|
||||
cx="605"
|
||||
cy="115"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle176" />
|
||||
<line
|
||||
x1="605"
|
||||
y1="107"
|
||||
x2="605"
|
||||
y2="113"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line178" />
|
||||
<text
|
||||
x="585"
|
||||
y="125"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="7"
|
||||
font-weight="600"
|
||||
fill="#6b7280"
|
||||
id="text180">192.168.2.0/24</text>
|
||||
</g>
|
||||
<!-- Spoke C (Bottom) -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g216">
|
||||
<rect
|
||||
x="275"
|
||||
y="370"
|
||||
width="150"
|
||||
height="100"
|
||||
rx="12"
|
||||
fill="#fff"
|
||||
stroke="#e5e7eb"
|
||||
stroke-width="2"
|
||||
id="rect184" />
|
||||
<!-- Header -->
|
||||
<rect
|
||||
x="275"
|
||||
y="370"
|
||||
width="150"
|
||||
height="32"
|
||||
rx="12"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect186" />
|
||||
<rect
|
||||
x="275"
|
||||
y="391"
|
||||
width="150"
|
||||
height="11"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect188" />
|
||||
<text
|
||||
x="350"
|
||||
y="391"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="14"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text190">Branch C</text>
|
||||
<!-- Router -->
|
||||
<rect
|
||||
x="290"
|
||||
y="410"
|
||||
width="120"
|
||||
height="30"
|
||||
rx="6"
|
||||
fill="url(#routerGrad)"
|
||||
id="rect192" />
|
||||
<rect
|
||||
x="292"
|
||||
y="412"
|
||||
width="116"
|
||||
height="14"
|
||||
rx="4"
|
||||
fill="#fca5a5"
|
||||
opacity="0.3"
|
||||
id="rect194" />
|
||||
<text
|
||||
x="350"
|
||||
y="429"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#fff"
|
||||
id="text196">Spoke</text>
|
||||
<!-- Local Network -->
|
||||
<line
|
||||
x1="350"
|
||||
y1="440"
|
||||
x2="350"
|
||||
y2="447"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line198" />
|
||||
<line
|
||||
x1="325"
|
||||
y1="447"
|
||||
x2="375"
|
||||
y2="447"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line200" />
|
||||
<circle
|
||||
cx="330"
|
||||
cy="455"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle202" />
|
||||
<line
|
||||
x1="330"
|
||||
y1="447"
|
||||
x2="330"
|
||||
y2="453"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line204" />
|
||||
<circle
|
||||
cx="350"
|
||||
cy="455"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle206" />
|
||||
<line
|
||||
x1="350"
|
||||
y1="447"
|
||||
x2="350"
|
||||
y2="453"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line208" />
|
||||
<circle
|
||||
cx="370"
|
||||
cy="455"
|
||||
r="4"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle210" />
|
||||
<line
|
||||
x1="370"
|
||||
y1="447"
|
||||
x2="370"
|
||||
y2="453"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line212" />
|
||||
<text
|
||||
x="350"
|
||||
y="465"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="7"
|
||||
font-weight="600"
|
||||
fill="#6b7280"
|
||||
id="text214">192.168.3.0/24</text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.98466939,0,0,1.0000859,498.17175,113.77759)"
|
||||
id="g97">
|
||||
<rect
|
||||
width="10"
|
||||
height="12"
|
||||
rx="2"
|
||||
fill="#10b981"
|
||||
id="rect91"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 2,0 v -3 a 3,3 0 0 1 6,0 v 3"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.5"
|
||||
id="path93" />
|
||||
<circle
|
||||
cx="5"
|
||||
cy="7"
|
||||
r="1.5"
|
||||
fill="#ffffff"
|
||||
id="circle95" />
|
||||
</g>
|
||||
<text
|
||||
x="446.42084"
|
||||
y="148.79063"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', sans-serif"
|
||||
font-size="10.9158px"
|
||||
font-weight="600"
|
||||
fill="#059669"
|
||||
id="text99"
|
||||
transform="scale(0.99226244,1.0077979)"
|
||||
style="stroke-width:0.992348">Encrypted VPN</text>
|
||||
<g
|
||||
transform="matrix(0.98466939,0,0,1.0000859,193.71492,114.69643)"
|
||||
id="g97-3">
|
||||
<rect
|
||||
width="10"
|
||||
height="12"
|
||||
rx="2"
|
||||
fill="#10b981"
|
||||
id="rect91-6"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 2,0 v -3 a 3,3 0 0 1 6,0 v 3"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.5"
|
||||
id="path93-7" />
|
||||
<circle
|
||||
cx="5"
|
||||
cy="7"
|
||||
r="1.5"
|
||||
fill="#ffffff"
|
||||
id="circle95-5" />
|
||||
</g>
|
||||
<text
|
||||
x="254.16939"
|
||||
y="144.61209"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', sans-serif"
|
||||
font-size="10.9158px"
|
||||
font-weight="600"
|
||||
fill="#059669"
|
||||
id="text99-3"
|
||||
transform="scale(0.99226244,1.0077979)"
|
||||
style="stroke-width:0.992348">Encrypted VPN</text>
|
||||
<g
|
||||
transform="matrix(0.98466939,0,0,1.0000859,333.47081,353.92815)"
|
||||
id="g97-5">
|
||||
<rect
|
||||
width="10"
|
||||
height="12"
|
||||
rx="2"
|
||||
fill="#10b981"
|
||||
id="rect91-62"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 2,0 v -3 a 3,3 0 0 1 6,0 v 3"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.5"
|
||||
id="path93-9" />
|
||||
<circle
|
||||
cx="5"
|
||||
cy="7"
|
||||
r="1.5"
|
||||
fill="#ffffff"
|
||||
id="circle95-1" />
|
||||
</g>
|
||||
<text
|
||||
x="393.52994"
|
||||
y="352.21753"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', sans-serif"
|
||||
font-size="10.9158px"
|
||||
font-weight="600"
|
||||
fill="#059669"
|
||||
id="text99-2"
|
||||
transform="scale(0.99226244,1.0077979)"
|
||||
style="stroke-width:0.992348">Encrypted VPN</text>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 21 KiB |
@@ -1,689 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 700 350"
|
||||
version="1.1"
|
||||
id="svg171"
|
||||
sodipodi:docname="vpn-roadwarrior.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview173"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.8885714"
|
||||
inkscape:cx="350.00001"
|
||||
inkscape:cy="174.73525"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1374"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg171" />
|
||||
<defs
|
||||
id="defs47">
|
||||
<linearGradient
|
||||
id="bgGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="100%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#fafbfc;stop-opacity:1"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#f3f4f6;stop-opacity:1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="corpGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#3b82f6;stop-opacity:1"
|
||||
id="stop7" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#2563eb;stop-opacity:1"
|
||||
id="stop9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="routerGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#ef4444;stop-opacity:1"
|
||||
id="stop12" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#dc2626;stop-opacity:1"
|
||||
id="stop14" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="deviceGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#8b5cf6;stop-opacity:1"
|
||||
id="stop17" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#7c3aed;stop-opacity:1"
|
||||
id="stop19" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="cloudGrad"
|
||||
cx="220.99805"
|
||||
cy="209.29596"
|
||||
gradientTransform="scale(1.3416408,0.74535599)"
|
||||
fx="220.99805"
|
||||
fy="209.29596"
|
||||
r="51.98858"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
id="stop22" />
|
||||
<stop
|
||||
offset="70%"
|
||||
style="stop-color:#dbeafe;stop-opacity:1"
|
||||
id="stop24" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#93c5fd;stop-opacity:1"
|
||||
id="stop26" />
|
||||
</radialGradient>
|
||||
<filter
|
||||
id="shadow"
|
||||
x="-0.164"
|
||||
y="-0.11699244"
|
||||
width="1.328"
|
||||
height="1.2563258">
|
||||
<feGaussianBlur
|
||||
in="SourceAlpha"
|
||||
stdDeviation="3"
|
||||
id="feGaussianBlur29" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="2"
|
||||
result="offsetblur"
|
||||
id="feOffset31" />
|
||||
<feComponentTransfer
|
||||
id="feComponentTransfer35">
|
||||
<feFuncA
|
||||
type="linear"
|
||||
slope="0.2"
|
||||
id="feFuncA33" />
|
||||
</feComponentTransfer>
|
||||
<feMerge
|
||||
id="feMerge41">
|
||||
<feMergeNode
|
||||
id="feMergeNode37" />
|
||||
<feMergeNode
|
||||
in="SourceGraphic"
|
||||
id="feMergeNode39" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<marker
|
||||
id="arrow"
|
||||
markerWidth="8"
|
||||
markerHeight="8"
|
||||
refX="7"
|
||||
refY="4"
|
||||
orient="auto">
|
||||
<path
|
||||
d="M 0,0 V 8 L 8,4 Z"
|
||||
fill="#10b981"
|
||||
id="path44" />
|
||||
</marker>
|
||||
</defs>
|
||||
<style
|
||||
id="style30">
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#bgGrad stop:first-child { stop-color: #1f2937; }
|
||||
#bgGrad stop:last-child { stop-color: #111827; }
|
||||
#corpGrad stop:first-child { stop-color: #2563eb; }
|
||||
#corpGrad stop:last-child { stop-color: #1e40af; }
|
||||
#routerGrad stop:first-child { stop-color: #dc2626; }
|
||||
#routerGrad stop:last-child { stop-color: #b91c1c; }
|
||||
#deviceGrad stop:first-child { stop-color: #4c1d95; }
|
||||
#deviceGrad stop:last-child { stop-color: #3b0764; }
|
||||
#cloudGrad stop:first-child { stop-color: #374151; }
|
||||
#cloudGrad stop:nth-child(2) { stop-color: #1e3a8a; }
|
||||
#cloudGrad stop:last-child { stop-color: #1e40af; }
|
||||
rect[fill="#fff"], rect[fill="#ffffff"] { fill: #374151; }
|
||||
rect[stroke="#e5e7eb"] { stroke: #4b5563; }
|
||||
text[fill="#6b7280"] { fill: #d1d5db; }
|
||||
text[fill="#1e40af"] { fill: #60a5fa; }
|
||||
ellipse[fill="#ffffff"] { fill: #4b5563; }
|
||||
circle[fill="#60a5fa"] { fill: #3b82f6; }
|
||||
line[stroke="#94a3b8"] { stroke: #6b7280; }
|
||||
rect[fill="#1e40af"] { fill: #1e3a8a; }
|
||||
rect[fill="#c4b5fd"] { fill: #8b5cf6; }
|
||||
rect[fill="#ede9fe"] { fill: #2e1065; }
|
||||
text[fill="#5b21b6"] { fill: #9333ea; }
|
||||
circle[stroke="#6d28d9"] { stroke: #4c1d95; }
|
||||
rect[stroke="#6d28d9"] { stroke: #4c1d95; }
|
||||
text[fill="#ef4444"] { fill: #fca5a5; }
|
||||
}
|
||||
</style>
|
||||
<!-- Internet Cloud -->
|
||||
<!-- Physical Internet connections (solid lines) -->
|
||||
<line
|
||||
x1="110"
|
||||
y1="65"
|
||||
x2="230"
|
||||
y2="160"
|
||||
stroke="#6b7280"
|
||||
stroke-width="2"
|
||||
id="inet-laptop" />
|
||||
<text
|
||||
x="137.55841"
|
||||
y="109.12807"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', sans-serif"
|
||||
font-size="9px"
|
||||
font-weight="500"
|
||||
fill="#ef4444"
|
||||
id="text-inet-laptop">Unsecure</text>
|
||||
<line
|
||||
x1="79.384186"
|
||||
y1="185.51099"
|
||||
x2="229.7012"
|
||||
y2="183.32214"
|
||||
stroke="#6b7280"
|
||||
stroke-width="2"
|
||||
id="inet-phone" />
|
||||
<text
|
||||
x="145"
|
||||
y="194"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', sans-serif"
|
||||
font-size="9px"
|
||||
font-weight="500"
|
||||
fill="#ef4444"
|
||||
id="text-inet-phone">Unsecure</text>
|
||||
<line
|
||||
x1="105"
|
||||
y1="292"
|
||||
x2="230"
|
||||
y2="190"
|
||||
stroke="#6b7280"
|
||||
stroke-width="2"
|
||||
id="inet-tablet" />
|
||||
<text
|
||||
x="143.19562"
|
||||
y="243.69884"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', sans-serif"
|
||||
font-size="9px"
|
||||
font-weight="500"
|
||||
fill="#ef4444"
|
||||
id="text-inet-tablet">Unsecure</text>
|
||||
<line
|
||||
x1="513.08228"
|
||||
y1="155.4146"
|
||||
x2="344.54852"
|
||||
y2="156.5854"
|
||||
stroke="#6b7280"
|
||||
stroke-width="1.98644"
|
||||
id="inet-corporate" />
|
||||
<text
|
||||
x="430"
|
||||
y="150"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="9"
|
||||
font-weight="500"
|
||||
fill="#ef4444"
|
||||
id="text-inet-corporate">Unsecure</text>
|
||||
<!-- VPN Tunnels: Three lines from clients that merge into one line to server -->
|
||||
<g
|
||||
transform="matrix(0.98466939,0,0,1.0000859,119.62684,52.989786)"
|
||||
id="g73">
|
||||
<rect
|
||||
width="8"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="#10b981"
|
||||
id="rect67"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 1.5,0 v -2.5 a 2.5,2.5 0 0 1 5,0 V 0"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.2"
|
||||
id="path69" />
|
||||
<circle
|
||||
cx="4"
|
||||
cy="6"
|
||||
r="1.2"
|
||||
fill="#ffffff"
|
||||
id="circle71" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.98466939,0,0,1.0000859,87.933449,161.99967)"
|
||||
id="g81">
|
||||
<rect
|
||||
width="8"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="#10b981"
|
||||
id="rect75"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 1.5,0 v -2.5 a 2.5,2.5 0 0 1 5,0 V 0"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.2"
|
||||
id="path77" />
|
||||
<circle
|
||||
cx="4"
|
||||
cy="6"
|
||||
r="1.2"
|
||||
fill="#ffffff"
|
||||
id="circle79" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.98466939,0,0,1.0000859,113.62684,307.00955)"
|
||||
id="g89">
|
||||
<rect
|
||||
width="8"
|
||||
height="10"
|
||||
rx="1.5"
|
||||
fill="#10b981"
|
||||
id="rect83"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 1.5,0 v -2.5 a 2.5,2.5 0 0 1 5,0 V 0"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.2"
|
||||
id="path85" />
|
||||
<circle
|
||||
cx="4"
|
||||
cy="6"
|
||||
r="1.2"
|
||||
fill="#ffffff"
|
||||
id="circle87" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.98466939,0,0,1.0000859,457.18096,186.99924)"
|
||||
id="g97">
|
||||
<rect
|
||||
width="10"
|
||||
height="12"
|
||||
rx="2"
|
||||
fill="#10b981"
|
||||
id="rect91"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 2,0 v -3 a 3,3 0 0 1 6,0 v 3"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.5"
|
||||
id="path93" />
|
||||
<circle
|
||||
cx="5"
|
||||
cy="7"
|
||||
r="1.5"
|
||||
fill="#ffffff"
|
||||
id="circle95" />
|
||||
</g>
|
||||
<text
|
||||
x="413.23505"
|
||||
y="186.04326"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', sans-serif"
|
||||
font-size="10.9158px"
|
||||
font-weight="600"
|
||||
fill="#059669"
|
||||
id="text99"
|
||||
transform="scale(0.99226244,1.0077979)"
|
||||
style="stroke-width:0.992348">Encrypted VPN</text>
|
||||
<!-- Laptop Device -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g115">
|
||||
<rect
|
||||
x="20"
|
||||
y="30"
|
||||
width="90"
|
||||
height="60"
|
||||
rx="6"
|
||||
fill="url(#deviceGrad)"
|
||||
stroke="#6d28d9"
|
||||
stroke-width="2"
|
||||
id="rect103" />
|
||||
<rect
|
||||
x="26"
|
||||
y="36"
|
||||
width="78"
|
||||
height="46"
|
||||
rx="3"
|
||||
fill="#ede9fe"
|
||||
id="rect105" />
|
||||
<rect
|
||||
x="49"
|
||||
y="82"
|
||||
width="32"
|
||||
height="4"
|
||||
rx="2"
|
||||
fill="url(#deviceGrad)"
|
||||
id="rect107" />
|
||||
<rect
|
||||
x="35"
|
||||
y="86"
|
||||
width="60"
|
||||
height="3"
|
||||
rx="1.5"
|
||||
fill="url(#deviceGrad)"
|
||||
id="rect109" />
|
||||
<text
|
||||
x="65"
|
||||
y="63"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#5b21b6"
|
||||
id="text111">Laptop</text>
|
||||
<text
|
||||
x="65"
|
||||
y="100"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="9"
|
||||
font-weight="500"
|
||||
fill="#6b7280"
|
||||
id="text113">Remote Worker</text>
|
||||
</g>
|
||||
<!-- Mobile Phone Device -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g127">
|
||||
<rect
|
||||
x="30"
|
||||
y="145"
|
||||
width="50"
|
||||
height="80"
|
||||
rx="6"
|
||||
fill="url(#deviceGrad)"
|
||||
stroke="#6d28d9"
|
||||
stroke-width="2"
|
||||
id="rect117" />
|
||||
<rect
|
||||
x="36"
|
||||
y="153"
|
||||
width="38"
|
||||
height="56"
|
||||
rx="3"
|
||||
fill="#ede9fe"
|
||||
id="rect119" />
|
||||
<circle
|
||||
cx="55"
|
||||
cy="218"
|
||||
r="4"
|
||||
fill="#ede9fe"
|
||||
stroke="#6d28d9"
|
||||
stroke-width="1.5"
|
||||
id="circle121" />
|
||||
<text
|
||||
x="55"
|
||||
y="188"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="10"
|
||||
font-weight="600"
|
||||
fill="#5b21b6"
|
||||
id="text123">Mobile</text>
|
||||
<text
|
||||
x="55"
|
||||
y="240"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="9"
|
||||
font-weight="500"
|
||||
fill="#6b7280"
|
||||
id="text125">On-the-go</text>
|
||||
</g>
|
||||
<!-- Tablet Device -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g139">
|
||||
<rect
|
||||
x="25"
|
||||
y="265"
|
||||
width="80"
|
||||
height="55"
|
||||
rx="5"
|
||||
fill="url(#deviceGrad)"
|
||||
stroke="#6d28d9"
|
||||
stroke-width="2"
|
||||
id="rect129" />
|
||||
<rect
|
||||
x="31"
|
||||
y="271"
|
||||
width="68"
|
||||
height="40"
|
||||
rx="3"
|
||||
fill="#ede9fe"
|
||||
id="rect131" />
|
||||
<circle
|
||||
cx="65"
|
||||
cy="313"
|
||||
r="3.5"
|
||||
fill="#ede9fe"
|
||||
stroke="#6d28d9"
|
||||
stroke-width="1.5"
|
||||
id="circle133" />
|
||||
<text
|
||||
x="65"
|
||||
y="295"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="10"
|
||||
font-weight="600"
|
||||
fill="#5b21b6"
|
||||
id="text135">Tablet</text>
|
||||
<text
|
||||
x="65"
|
||||
y="335"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="9"
|
||||
font-weight="500"
|
||||
fill="#6b7280"
|
||||
id="text137">Traveling</text>
|
||||
</g>
|
||||
<!-- Corporate Network -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g167">
|
||||
<rect
|
||||
x="510"
|
||||
y="80"
|
||||
width="170"
|
||||
height="190"
|
||||
rx="12"
|
||||
fill="#fff"
|
||||
stroke="#e5e7eb"
|
||||
stroke-width="2"
|
||||
id="rect141" />
|
||||
<!-- Header -->
|
||||
<rect
|
||||
x="510"
|
||||
y="80"
|
||||
width="170"
|
||||
height="45"
|
||||
rx="12"
|
||||
fill="url(#corpGrad)"
|
||||
id="rect143" />
|
||||
<rect
|
||||
x="510"
|
||||
y="105"
|
||||
width="170"
|
||||
height="20"
|
||||
fill="url(#corpGrad)"
|
||||
id="rect145" />
|
||||
<text
|
||||
x="595"
|
||||
y="108"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="16"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text147">Corporate</text>
|
||||
<rect
|
||||
x="545"
|
||||
y="115"
|
||||
width="100"
|
||||
height="18"
|
||||
rx="9"
|
||||
fill="#1e40af"
|
||||
id="rect149" />
|
||||
<text
|
||||
x="595"
|
||||
y="127"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#fff"
|
||||
id="text151">192.168.0.0/24</text>
|
||||
<!-- VPN Gateway -->
|
||||
<rect
|
||||
x="530"
|
||||
y="140"
|
||||
width="130"
|
||||
height="42"
|
||||
rx="8"
|
||||
fill="url(#routerGrad)"
|
||||
id="rect153" />
|
||||
<rect
|
||||
x="532"
|
||||
y="142"
|
||||
width="126"
|
||||
height="20"
|
||||
rx="6"
|
||||
fill="#fca5a5"
|
||||
opacity="0.3"
|
||||
id="rect155" />
|
||||
<text
|
||||
x="595"
|
||||
y="165"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="13"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text157">VPN Gateway</text>
|
||||
<!-- Resources -->
|
||||
<rect
|
||||
x="530"
|
||||
y="195"
|
||||
width="130"
|
||||
height="60"
|
||||
rx="8"
|
||||
fill="#dbeafe"
|
||||
stroke="#3b82f6"
|
||||
stroke-width="1.5"
|
||||
id="rect159" />
|
||||
<text
|
||||
x="595"
|
||||
y="218"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="600"
|
||||
fill="#1e40af"
|
||||
id="text161">Servers</text>
|
||||
<text
|
||||
x="595"
|
||||
y="232"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="600"
|
||||
fill="#1e40af"
|
||||
id="text163">Files</text>
|
||||
<text
|
||||
x="595"
|
||||
y="246"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="12"
|
||||
font-weight="600"
|
||||
fill="#1e40af"
|
||||
id="text165">Applications</text>
|
||||
</g>
|
||||
<path
|
||||
d="m 230,175 c 0,-13 8,-23 20,-23 2,-9 10,-15 20,-15 7,0 13,3 17,8 5,-7 13,-11 23,-11 16,0 30,11 32,26 13,1 23,12 23,25 0,13 -11,24 -25,24 h -88 c -13,0 -24,-11 -24,-24 0,-7 3,-13 7,-17 z"
|
||||
fill="url(#cloudGrad)"
|
||||
stroke="#3b82f6"
|
||||
stroke-width="2.5"
|
||||
stroke-linejoin="round"
|
||||
id="path51"
|
||||
style="fill:url(#cloudGrad);filter:url(#shadow)" />
|
||||
<line
|
||||
x1="114.70349"
|
||||
y1="64.990814"
|
||||
x2="316.56073"
|
||||
y2="175.00027"
|
||||
stroke="#10b981"
|
||||
stroke-width="2.6"
|
||||
stroke-dasharray="10,6"
|
||||
id="line59" />
|
||||
<line
|
||||
x1="83.621422"
|
||||
y1="175.41223"
|
||||
x2="316.59158"
|
||||
y2="175.58884"
|
||||
stroke="#10b981"
|
||||
stroke-width="2.6"
|
||||
stroke-dasharray="10, 6"
|
||||
id="line61" />
|
||||
<line
|
||||
x1="108.29816"
|
||||
y1="302.53445"
|
||||
x2="316.5495"
|
||||
y2="175.04326"
|
||||
stroke="#10b981"
|
||||
stroke-width="2.6"
|
||||
stroke-dasharray="10, 6"
|
||||
id="line63" />
|
||||
<line
|
||||
x1="316.56073"
|
||||
y1="175.00027"
|
||||
x2="503.64789"
|
||||
y2="175.00027"
|
||||
stroke="#10b981"
|
||||
stroke-width="2.6"
|
||||
stroke-dasharray="12,8"
|
||||
marker-end="url(#arrow)"
|
||||
id="line65" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,595 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 800 300"
|
||||
version="1.1"
|
||||
id="svg178"
|
||||
sodipodi:docname="vpn-site-to-site.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview180"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.6525"
|
||||
inkscape:cx="400"
|
||||
inkscape:cy="150.07564"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1374"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg178" />
|
||||
<defs
|
||||
id="defs42">
|
||||
<linearGradient
|
||||
id="bgGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="100%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#fafbfc;stop-opacity:1"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#f3f4f6;stop-opacity:1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="siteGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#3b82f6;stop-opacity:1"
|
||||
id="stop7" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#2563eb;stop-opacity:1"
|
||||
id="stop9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="routerGrad"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#ef4444;stop-opacity:1"
|
||||
id="stop12" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#dc2626;stop-opacity:1"
|
||||
id="stop14" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="cloudGrad"
|
||||
cx="288.08009"
|
||||
cy="175.75494"
|
||||
gradientTransform="matrix(1.3416408,0,0,0.74535599,-11.528571,2.8295566)"
|
||||
fx="288.08009"
|
||||
fy="175.75494"
|
||||
r="51.98858"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
id="stop17" />
|
||||
<stop
|
||||
offset="70%"
|
||||
style="stop-color:#dbeafe;stop-opacity:1"
|
||||
id="stop19" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#93c5fd;stop-opacity:1"
|
||||
id="stop21" />
|
||||
</radialGradient>
|
||||
<filter
|
||||
id="shadow"
|
||||
x="-0.061678832"
|
||||
y="-0.11266667"
|
||||
width="1.1233577"
|
||||
height="1.252">
|
||||
<feGaussianBlur
|
||||
in="SourceAlpha"
|
||||
stdDeviation="3"
|
||||
id="feGaussianBlur24" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="2"
|
||||
result="offsetblur"
|
||||
id="feOffset26" />
|
||||
<feComponentTransfer
|
||||
id="feComponentTransfer30">
|
||||
<feFuncA
|
||||
type="linear"
|
||||
slope="0.2"
|
||||
id="feFuncA28" />
|
||||
</feComponentTransfer>
|
||||
<feMerge
|
||||
id="feMerge36">
|
||||
<feMergeNode
|
||||
id="feMergeNode32" />
|
||||
<feMergeNode
|
||||
in="SourceGraphic"
|
||||
id="feMergeNode34" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<marker
|
||||
id="arrow"
|
||||
markerWidth="8"
|
||||
markerHeight="8"
|
||||
refX="7"
|
||||
refY="4"
|
||||
orient="auto">
|
||||
<path
|
||||
d="M 0,0 V 8 L 8,4 Z"
|
||||
fill="#10b981"
|
||||
id="path39" />
|
||||
</marker>
|
||||
</defs>
|
||||
<style
|
||||
id="style27">
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#bgGrad stop:first-child { stop-color: #1f2937; }
|
||||
#bgGrad stop:last-child { stop-color: #111827; }
|
||||
#siteGrad stop:first-child { stop-color: #2563eb; }
|
||||
#siteGrad stop:last-child { stop-color: #1e40af; }
|
||||
#routerGrad stop:first-child { stop-color: #dc2626; }
|
||||
#routerGrad stop:last-child { stop-color: #b91c1c; }
|
||||
#cloudGrad stop:first-child { stop-color: #374151; }
|
||||
#cloudGrad stop:nth-child(2) { stop-color: #1e3a8a; }
|
||||
#cloudGrad stop:last-child { stop-color: #1e40af; }
|
||||
rect[fill="#fff"], rect[fill="#ffffff"] { fill: #374151; }
|
||||
rect[stroke="#e5e7eb"] { stroke: #4b5563; }
|
||||
text[fill="#6b7280"] { fill: #d1d5db; }
|
||||
text[fill="#1e40af"] { fill: #60a5fa; }
|
||||
ellipse[fill="#ffffff"] { fill: #4b5563; }
|
||||
circle[fill="#60a5fa"] { fill: #3b82f6; }
|
||||
line[stroke="#94a3b8"] { stroke: #6b7280; }
|
||||
rect[fill="#1e40af"] { fill: #1e3a8a; }
|
||||
text[fill="#ef4444"] { fill: #fca5a5; }
|
||||
}
|
||||
</style>
|
||||
<!-- Internet Cloud -->
|
||||
<!-- Physical Internet connections (solid lines) -->
|
||||
<line
|
||||
x1="169.96941"
|
||||
y1="150.66559"
|
||||
x2="308.03061"
|
||||
y2="148.83441"
|
||||
stroke="#6b7280"
|
||||
stroke-width="2"
|
||||
id="inet-left" />
|
||||
<text
|
||||
x="240"
|
||||
y="145"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="10"
|
||||
font-weight="500"
|
||||
fill="#ef4444"
|
||||
id="text-inet-left">Unsecure</text>
|
||||
<line
|
||||
x1="630.02637"
|
||||
y1="143.69931"
|
||||
x2="437.97366"
|
||||
y2="143.80069"
|
||||
stroke="#6b7280"
|
||||
stroke-width="2"
|
||||
id="inet-right" />
|
||||
<text
|
||||
x="535"
|
||||
y="138"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="10"
|
||||
font-weight="500"
|
||||
fill="#ef4444"
|
||||
id="text-inet-right">Unsecure</text>
|
||||
<!-- VPN Tunnel through cloud -->
|
||||
<g
|
||||
transform="translate(191.99738,184.62118)"
|
||||
id="g62">
|
||||
<rect
|
||||
width="10"
|
||||
height="12"
|
||||
rx="2"
|
||||
fill="#10b981"
|
||||
id="rect56"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 2,0 v -3 a 3,3 0 0 1 6,0 v 3"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.5"
|
||||
id="path58" />
|
||||
<circle
|
||||
cx="5"
|
||||
cy="7"
|
||||
r="1.5"
|
||||
fill="#ffffff"
|
||||
id="circle60" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(564.75904,184.3387)"
|
||||
id="g70">
|
||||
<rect
|
||||
width="10"
|
||||
height="12"
|
||||
rx="2"
|
||||
fill="#10b981"
|
||||
id="rect64"
|
||||
x="0"
|
||||
y="0" />
|
||||
<path
|
||||
d="m 2,0 v -3 a 3,3 0 0 1 6,0 v 3"
|
||||
fill="none"
|
||||
stroke="#10b981"
|
||||
stroke-width="1.5"
|
||||
id="path66" />
|
||||
<circle
|
||||
cx="5"
|
||||
cy="7"
|
||||
r="1.5"
|
||||
fill="#ffffff"
|
||||
id="circle68" />
|
||||
</g>
|
||||
<text
|
||||
x="513.77582"
|
||||
y="161.37065"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', sans-serif"
|
||||
font-size="12px"
|
||||
font-weight="600"
|
||||
fill="#059669"
|
||||
id="text72">Encrypted VPN Tunnel</text>
|
||||
<!-- Site A (Left) -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g124">
|
||||
<rect
|
||||
x="20"
|
||||
y="60"
|
||||
width="170"
|
||||
height="180"
|
||||
rx="12"
|
||||
fill="#fff"
|
||||
stroke="#e5e7eb"
|
||||
stroke-width="2"
|
||||
id="rect76" />
|
||||
<!-- Header -->
|
||||
<rect
|
||||
x="20"
|
||||
y="60"
|
||||
width="170"
|
||||
height="45"
|
||||
rx="12"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect78" />
|
||||
<rect
|
||||
x="20"
|
||||
y="85"
|
||||
width="170"
|
||||
height="20"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect80" />
|
||||
<text
|
||||
x="105"
|
||||
y="88"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="16"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text82">Main Office</text>
|
||||
<rect
|
||||
x="55"
|
||||
y="95"
|
||||
width="100"
|
||||
height="18"
|
||||
rx="9"
|
||||
fill="#1e40af"
|
||||
id="rect84" />
|
||||
<text
|
||||
x="105"
|
||||
y="107"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#fff"
|
||||
id="text86">192.168.1.0/24</text>
|
||||
<!-- Router -->
|
||||
<rect
|
||||
x="40"
|
||||
y="125"
|
||||
width="130"
|
||||
height="45"
|
||||
rx="8"
|
||||
fill="url(#routerGrad)"
|
||||
id="rect88" />
|
||||
<rect
|
||||
x="42"
|
||||
y="127"
|
||||
width="126"
|
||||
height="20"
|
||||
rx="6"
|
||||
fill="#fca5a5"
|
||||
opacity="0.3"
|
||||
id="rect90" />
|
||||
<text
|
||||
x="105"
|
||||
y="152"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="13"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text92">VPN Gateway</text>
|
||||
<!-- Local Network -->
|
||||
<line
|
||||
x1="105"
|
||||
y1="170"
|
||||
x2="105"
|
||||
y2="195"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line94" />
|
||||
<line
|
||||
x1="65"
|
||||
y1="195"
|
||||
x2="145"
|
||||
y2="195"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line96" />
|
||||
<circle
|
||||
cx="70"
|
||||
cy="204"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle98" />
|
||||
<line
|
||||
x1="70"
|
||||
y1="195"
|
||||
x2="70"
|
||||
y2="202"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line100" />
|
||||
<circle
|
||||
cx="105"
|
||||
cy="204"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle102" />
|
||||
<line
|
||||
x1="105"
|
||||
y1="195"
|
||||
x2="105"
|
||||
y2="202"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line104" />
|
||||
<circle
|
||||
cx="140"
|
||||
cy="204"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle106" />
|
||||
<line
|
||||
x1="140"
|
||||
y1="195"
|
||||
x2="140"
|
||||
y2="202"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line108" />
|
||||
<text
|
||||
x="105"
|
||||
y="218"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="8"
|
||||
font-weight="600"
|
||||
fill="#6b7280"
|
||||
id="text122">192.168.1.0/24</text>
|
||||
</g>
|
||||
<!-- Site B (Right) -->
|
||||
<g
|
||||
filter="url(#shadow)"
|
||||
id="g174">
|
||||
<rect
|
||||
x="610"
|
||||
y="60"
|
||||
width="170"
|
||||
height="180"
|
||||
rx="12"
|
||||
fill="#fff"
|
||||
stroke="#e5e7eb"
|
||||
stroke-width="2"
|
||||
id="rect126" />
|
||||
<!-- Header -->
|
||||
<rect
|
||||
x="610"
|
||||
y="60"
|
||||
width="170"
|
||||
height="45"
|
||||
rx="12"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect128" />
|
||||
<rect
|
||||
x="610"
|
||||
y="85"
|
||||
width="170"
|
||||
height="20"
|
||||
fill="url(#siteGrad)"
|
||||
id="rect130" />
|
||||
<text
|
||||
x="695"
|
||||
y="88"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="16"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text132">Branch Office</text>
|
||||
<rect
|
||||
x="645"
|
||||
y="95"
|
||||
width="100"
|
||||
height="18"
|
||||
rx="9"
|
||||
fill="#1e40af"
|
||||
id="rect134" />
|
||||
<text
|
||||
x="695"
|
||||
y="107"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#fff"
|
||||
id="text136">192.168.2.0/24</text>
|
||||
<!-- Router -->
|
||||
<rect
|
||||
x="630"
|
||||
y="125"
|
||||
width="130"
|
||||
height="45"
|
||||
rx="8"
|
||||
fill="url(#routerGrad)"
|
||||
id="rect138" />
|
||||
<rect
|
||||
x="632"
|
||||
y="127"
|
||||
width="126"
|
||||
height="20"
|
||||
rx="6"
|
||||
fill="#fca5a5"
|
||||
opacity="0.3"
|
||||
id="rect140" />
|
||||
<text
|
||||
x="695"
|
||||
y="152"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, sans-serif"
|
||||
font-size="13"
|
||||
font-weight="700"
|
||||
fill="#fff"
|
||||
id="text142">VPN Gateway</text>
|
||||
<!-- Local Network -->
|
||||
<line
|
||||
x1="695"
|
||||
y1="170"
|
||||
x2="695"
|
||||
y2="195"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line144" />
|
||||
<line
|
||||
x1="655"
|
||||
y1="195"
|
||||
x2="735"
|
||||
y2="195"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1.5"
|
||||
id="line146" />
|
||||
<circle
|
||||
cx="660"
|
||||
cy="204"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle148" />
|
||||
<line
|
||||
x1="660"
|
||||
y1="195"
|
||||
x2="660"
|
||||
y2="202"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line150" />
|
||||
<circle
|
||||
cx="695"
|
||||
cy="204"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle152" />
|
||||
<line
|
||||
x1="695"
|
||||
y1="195"
|
||||
x2="695"
|
||||
y2="202"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line154" />
|
||||
<circle
|
||||
cx="730"
|
||||
cy="204"
|
||||
r="5"
|
||||
fill="#60a5fa"
|
||||
stroke="#2563eb"
|
||||
stroke-width="1"
|
||||
id="circle156" />
|
||||
<line
|
||||
x1="730"
|
||||
y1="195"
|
||||
x2="730"
|
||||
y2="202"
|
||||
stroke="#94a3b8"
|
||||
stroke-width="1"
|
||||
id="line158" />
|
||||
<text
|
||||
x="695"
|
||||
y="218"
|
||||
text-anchor="middle"
|
||||
font-family="'SF Mono', 'Monaco', monospace"
|
||||
font-size="8"
|
||||
font-weight="600"
|
||||
fill="#6b7280"
|
||||
id="text172">192.168.2.0/24</text>
|
||||
</g>
|
||||
<path
|
||||
d="m 308.47143,152.82956 c 0,-13 8,-23 20,-23 2,-9 10,-15 20,-15 7,0 13,3 17,8 5,-7 13,-11 23,-11 16,0 30,11 32,26 13,1 23,12 23,25 0,13 -11,24 -25,24 h -88 c -13,0 -24,-11 -24,-24 0,-7 3,-13 7,-17 z"
|
||||
fill="url(#cloudGrad)"
|
||||
stroke="#3b82f6"
|
||||
stroke-width="2.5"
|
||||
stroke-linejoin="round"
|
||||
id="path46"
|
||||
style="fill:url(#cloudGrad);filter:url(#shadow)" />
|
||||
<line
|
||||
x1="188.49466"
|
||||
y1="166.37616"
|
||||
x2="604.93829"
|
||||
y2="166.37616"
|
||||
stroke="#10b981"
|
||||
stroke-width="2.6"
|
||||
stroke-dasharray="12, 8"
|
||||
marker-end="url(#arrow)"
|
||||
id="line54" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,785 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 900 400"
|
||||
version="1.1"
|
||||
id="svg180"
|
||||
sodipodi:docname="wireguard-allowed-ips.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview182"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.3653333"
|
||||
inkscape:cx="297.36329"
|
||||
inkscape:cy="375.00001"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1374"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg180" />
|
||||
<defs
|
||||
id="defs57">
|
||||
<!-- Premium Gradients -->
|
||||
<linearGradient
|
||||
id="bgGradient"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="821.58384"
|
||||
y2="821.58384"
|
||||
gradientTransform="matrix(1.0954451,0,0,0.46357119,-0.66009153,-0.49920384)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#f8f9fa;stop-opacity:1"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#e9ecef;stop-opacity:1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="peerGradient"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#748ffc;stop-opacity:1"
|
||||
id="stop7" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#5c7cfa;stop-opacity:1"
|
||||
id="stop9" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="networkGradient"
|
||||
x1="0%"
|
||||
y1="0%"
|
||||
x2="0%"
|
||||
y2="100%">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#51cf66;stop-opacity:1"
|
||||
id="stop12" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#40c057;stop-opacity:1"
|
||||
id="stop14" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="tunnelGradient"
|
||||
gradientTransform="scale(9.797959,0.10206207)"
|
||||
x1="21.433035"
|
||||
y1="2767.9234"
|
||||
x2="70.42283"
|
||||
y2="2767.9234"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0%"
|
||||
style="stop-color:#5c7cfa;stop-opacity:0.8"
|
||||
id="stop17" />
|
||||
<stop
|
||||
offset="50%"
|
||||
style="stop-color:#4c6ef5;stop-opacity:1"
|
||||
id="stop19" />
|
||||
<stop
|
||||
offset="100%"
|
||||
style="stop-color:#5c7cfa;stop-opacity:0.8"
|
||||
id="stop21" />
|
||||
</linearGradient>
|
||||
<!-- Premium Filters -->
|
||||
<filter
|
||||
id="cardShadow"
|
||||
x="-0.075714286"
|
||||
y="-0.35333333"
|
||||
width="1.1514286"
|
||||
height="1.84">
|
||||
<feGaussianBlur
|
||||
in="SourceAlpha"
|
||||
stdDeviation="4"
|
||||
id="feGaussianBlur24" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="4"
|
||||
result="offsetblur"
|
||||
id="feOffset26" />
|
||||
<feComponentTransfer
|
||||
id="feComponentTransfer30">
|
||||
<feFuncA
|
||||
type="linear"
|
||||
slope="0.15"
|
||||
id="feFuncA28" />
|
||||
</feComponentTransfer>
|
||||
<feMerge
|
||||
id="feMerge36">
|
||||
<feMergeNode
|
||||
id="feMergeNode32" />
|
||||
<feMergeNode
|
||||
in="SourceGraphic"
|
||||
id="feMergeNode34" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<filter
|
||||
id="glow"
|
||||
x="-0.015"
|
||||
y="-inf"
|
||||
width="1.03"
|
||||
height="inf">
|
||||
<feGaussianBlur
|
||||
stdDeviation="3"
|
||||
result="coloredBlur"
|
||||
id="feGaussianBlur39" />
|
||||
<feMerge
|
||||
id="feMerge45">
|
||||
<feMergeNode
|
||||
in="coloredBlur"
|
||||
id="feMergeNode41" />
|
||||
<feMergeNode
|
||||
in="SourceGraphic"
|
||||
id="feMergeNode43" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<marker
|
||||
id="arrowRight"
|
||||
markerWidth="12"
|
||||
markerHeight="12"
|
||||
refX="9"
|
||||
refY="6"
|
||||
orient="auto"
|
||||
markerUnits="strokeWidth">
|
||||
<path
|
||||
d="M 2,2 L 10,6 L 2,10 Z"
|
||||
fill="#4c6ef5"
|
||||
id="path48" />
|
||||
</marker>
|
||||
<marker
|
||||
id="arrowLeft"
|
||||
markerWidth="12"
|
||||
markerHeight="12"
|
||||
refX="3"
|
||||
refY="6"
|
||||
orient="auto"
|
||||
markerUnits="strokeWidth">
|
||||
<path
|
||||
d="M 10,2 L 2,6 L 10,10 Z"
|
||||
fill="#4c6ef5"
|
||||
id="path51" />
|
||||
</marker>
|
||||
<marker
|
||||
id="keyArrow"
|
||||
markerWidth="10"
|
||||
markerHeight="10"
|
||||
refX="8"
|
||||
refY="5"
|
||||
orient="auto"
|
||||
markerUnits="strokeWidth">
|
||||
<path
|
||||
d="M 1,1 L 9,5 L 1,9 Z"
|
||||
fill="#ff6b6b"
|
||||
id="path54" />
|
||||
</marker>
|
||||
<marker
|
||||
id="arrowRight-3"
|
||||
markerWidth="12"
|
||||
markerHeight="12"
|
||||
refX="9"
|
||||
refY="6"
|
||||
orient="auto"
|
||||
markerUnits="strokeWidth">
|
||||
<path
|
||||
d="m 2,2 8,4 -8,4 z"
|
||||
fill="#4c6ef5"
|
||||
id="path48-6" />
|
||||
</marker>
|
||||
</defs>
|
||||
<style>
|
||||
@media (prefers-color-scheme: dark) {
|
||||
/* Gradients */
|
||||
#bgGradient stop:first-child { stop-color: #1f2937; }
|
||||
#bgGradient stop:last-child { stop-color: #111827; }
|
||||
#peerGradient stop:first-child { stop-color: #3b82f6; }
|
||||
#peerGradient stop:last-child { stop-color: #2563eb; }
|
||||
#networkGradient stop:first-child { stop-color: #10b981; }
|
||||
#networkGradient stop:last-child { stop-color: #059669; }
|
||||
#tunnelGradient stop:first-child { stop-color: #3b82f6; stop-opacity: 0.8; }
|
||||
#tunnelGradient stop:nth-child(2) { stop-color: #2563eb; stop-opacity: 1; }
|
||||
#tunnelGradient stop:last-child { stop-color: #3b82f6; stop-opacity: 0.8; }
|
||||
|
||||
/* White backgrounds to dark */
|
||||
rect[fill="white"] { fill: #374151; }
|
||||
|
||||
/* Borders */
|
||||
rect[stroke="#dee2e6"] { stroke: #4b5563; }
|
||||
rect[stroke="#4263eb"] { stroke: #3b82f6; }
|
||||
rect[stroke="#4dabf7"] { stroke: #60a5fa; }
|
||||
rect[stroke="#fa5252"] { stroke: #ef4444; }
|
||||
rect[stroke="#fab005"] { stroke: #f59e0b; }
|
||||
|
||||
/* Background colors */
|
||||
rect[fill="#e7f5ff"] { fill: #1e3a8a; }
|
||||
rect[fill="#fff5f5"] { fill: #7f1d1d; }
|
||||
rect[fill="#fff3bf"] { fill: #78350f; }
|
||||
rect[fill="#ffffff"] { fill: #374151; }
|
||||
|
||||
/* Text colors */
|
||||
text[fill="#364fc7"] { fill: #60a5fa; }
|
||||
text[fill="#2b8a3e"] { fill: #10b981; }
|
||||
text[fill="#868e96"] { fill: #9ca3af; }
|
||||
text[fill="#1971c2"] { fill: #60a5fa; }
|
||||
text[fill="#c92a2a"] { fill: #f87171; }
|
||||
text[fill="#2f9e44"] { fill: #34d399; }
|
||||
text[fill="#495057"] { fill: #d1d5db; }
|
||||
text[fill="#e67700"] { fill: #fbbf24; }
|
||||
text[fill="#fa5252"] { fill: #f87171; }
|
||||
text[fill="#4263eb"] { fill: #60a5fa; }
|
||||
|
||||
/* Arrows and strokes */
|
||||
line[stroke="#4c6ef5"] { stroke: #60a5fa; }
|
||||
path[stroke="#ff6b6b"] { stroke: #f87171; }
|
||||
#arrowRight path { fill: #60a5fa; }
|
||||
#arrowLeft path { fill: #60a5fa; }
|
||||
#arrowRight-3 path { fill: #60a5fa; }
|
||||
#keyArrow path { fill: #f87171; }
|
||||
}
|
||||
</style>
|
||||
<line
|
||||
id="traffic-arrow-right-5"
|
||||
x1="690.22913"
|
||||
y1="168.51242"
|
||||
x2="584.96887"
|
||||
y2="264.0126"
|
||||
stroke="#4c6ef5"
|
||||
stroke-width="2.5"
|
||||
stroke-dasharray="6, 4"
|
||||
marker-end="url(#arrowRight-3)"
|
||||
style="display:inline;marker-end:url(#arrowRight-3);fill:none"
|
||||
inkscape:label="traffic-arrow-right-5" />
|
||||
<!-- Title -->
|
||||
<text
|
||||
id="title"
|
||||
x="450"
|
||||
y="30"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="22"
|
||||
font-weight="800"
|
||||
fill="#364fc7">Understanding WireGuard: Keys & allowed-ips</text>
|
||||
<!-- Peer A (Left Side) -->
|
||||
<g
|
||||
id="peer-a">
|
||||
<!-- Network behind Peer A -->
|
||||
<g
|
||||
id="network-a"
|
||||
filter="url(#cardShadow)">
|
||||
<rect
|
||||
id="network-a-bg"
|
||||
x="30"
|
||||
y="80"
|
||||
width="180"
|
||||
height="90"
|
||||
rx="12"
|
||||
fill="white"
|
||||
stroke="#dee2e6"
|
||||
stroke-width="2" />
|
||||
<rect
|
||||
id="network-a-header-bg"
|
||||
x="30"
|
||||
y="80"
|
||||
width="180"
|
||||
height="30"
|
||||
rx="12"
|
||||
fill="url(#networkGradient)" />
|
||||
<rect
|
||||
id="network-a-header-extension"
|
||||
x="30"
|
||||
y="98"
|
||||
width="180"
|
||||
height="12"
|
||||
fill="url(#networkGradient)" />
|
||||
<text
|
||||
id="network-a-title"
|
||||
x="120"
|
||||
y="98"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="13"
|
||||
font-weight="700"
|
||||
fill="white">Network A</text>
|
||||
<text
|
||||
id="network-a-cidr"
|
||||
x="120"
|
||||
y="130"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="16"
|
||||
font-weight="600"
|
||||
fill="#2b8a3e">192.168.1.0/24</text>
|
||||
<text
|
||||
id="network-a-devices"
|
||||
x="120"
|
||||
y="155"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="10"
|
||||
fill="#868e96">Devices: .1, .2, .3...</text>
|
||||
</g>
|
||||
<!-- WireGuard Peer A -->
|
||||
<g
|
||||
id="wg-peer-a"
|
||||
filter="url(#cardShadow)">
|
||||
<rect
|
||||
id="wg-peer-a-bg"
|
||||
x="30"
|
||||
y="200"
|
||||
width="180"
|
||||
height="170"
|
||||
rx="12"
|
||||
fill="white"
|
||||
stroke="#4263eb"
|
||||
stroke-width="3" />
|
||||
<rect
|
||||
id="wg-peer-a-header-bg"
|
||||
x="30"
|
||||
y="200"
|
||||
width="180"
|
||||
height="35"
|
||||
rx="12"
|
||||
fill="url(#peerGradient)" />
|
||||
<rect
|
||||
id="wg-peer-a-header-extension"
|
||||
x="30"
|
||||
y="221"
|
||||
width="180"
|
||||
height="14"
|
||||
fill="url(#peerGradient)" />
|
||||
<text
|
||||
id="wg-peer-a-title"
|
||||
x="120"
|
||||
y="221"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="15"
|
||||
font-weight="700"
|
||||
fill="white">WireGuard Peer A</text>
|
||||
<!-- Interface IP -->
|
||||
<rect
|
||||
id="wg-peer-a-interface-bg"
|
||||
x="50"
|
||||
y="245"
|
||||
width="140"
|
||||
height="22"
|
||||
rx="6"
|
||||
fill="#e7f5ff"
|
||||
stroke="#4dabf7"
|
||||
stroke-width="1" />
|
||||
<text
|
||||
id="wg-peer-a-interface-text"
|
||||
x="120"
|
||||
y="260"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#1971c2">wg0: 10.0.0.1/24</text>
|
||||
<!-- Own Keys -->
|
||||
<rect
|
||||
id="wg-peer-a-keys-bg"
|
||||
x="40"
|
||||
y="275"
|
||||
width="160"
|
||||
height="30"
|
||||
rx="6"
|
||||
fill="#fff5f5"
|
||||
stroke="#fa5252"
|
||||
stroke-width="1.5" />
|
||||
<text
|
||||
id="wg-peer-a-private-key"
|
||||
x="120"
|
||||
y="288"
|
||||
text-anchor="middle"
|
||||
font-family="Consolas, Monaco, 'Courier New', monospace"
|
||||
font-size="9px"
|
||||
font-weight="600"
|
||||
fill="#c92a2a">PrivateKey: aaa...=</text>
|
||||
<text
|
||||
id="wg-peer-a-public-key"
|
||||
x="120"
|
||||
y="300"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="9"
|
||||
font-weight="600"
|
||||
fill="#2f9e44">PublicKey: AAA...=</text>
|
||||
<!-- Peer B Config -->
|
||||
<text
|
||||
id="wg-peer-a-peer-config-label"
|
||||
x="120"
|
||||
y="320"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="10"
|
||||
font-weight="700"
|
||||
fill="#495057">[Peer] # Peer B</text>
|
||||
<rect
|
||||
id="wg-peer-a-peer-config-bg"
|
||||
x="40"
|
||||
y="325"
|
||||
width="160"
|
||||
height="38"
|
||||
rx="6"
|
||||
fill="#fff3bf"
|
||||
stroke="#fab005"
|
||||
stroke-width="1.5" />
|
||||
<text
|
||||
id="wg-peer-a-peer-pubkey"
|
||||
x="120"
|
||||
y="338"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="9"
|
||||
font-weight="700"
|
||||
fill="#e67700">PublicKey = BBB...=</text>
|
||||
<text
|
||||
id="wg-peer-a-peer-allowed-ips-1"
|
||||
x="120"
|
||||
y="350"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="9"
|
||||
font-weight="700"
|
||||
fill="#e67700">allowed-ips = 10.0.0.2/32,</text>
|
||||
<text
|
||||
id="wg-peer-a-peer-allowed-ips-2"
|
||||
x="120"
|
||||
y="360"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="9"
|
||||
font-weight="700"
|
||||
fill="#e67700"> 192.168.2.0/24</text>
|
||||
</g>
|
||||
</g>
|
||||
<!-- Peer B (Right Side) -->
|
||||
<g
|
||||
id="peer-b">
|
||||
<!-- Network behind Peer B -->
|
||||
<g
|
||||
id="network-b"
|
||||
filter="url(#cardShadow)">
|
||||
<rect
|
||||
id="network-b-bg"
|
||||
x="690"
|
||||
y="80"
|
||||
width="180"
|
||||
height="90"
|
||||
rx="12"
|
||||
fill="white"
|
||||
stroke="#dee2e6"
|
||||
stroke-width="2" />
|
||||
<rect
|
||||
id="network-b-header-bg"
|
||||
x="690"
|
||||
y="80"
|
||||
width="180"
|
||||
height="30"
|
||||
rx="12"
|
||||
fill="url(#networkGradient)" />
|
||||
<rect
|
||||
id="network-b-header-extension"
|
||||
x="690"
|
||||
y="98"
|
||||
width="180"
|
||||
height="12"
|
||||
fill="url(#networkGradient)" />
|
||||
<text
|
||||
id="network-b-title"
|
||||
x="780"
|
||||
y="98"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="13"
|
||||
font-weight="700"
|
||||
fill="white">Network B</text>
|
||||
<text
|
||||
id="network-b-cidr"
|
||||
x="780"
|
||||
y="130"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="16"
|
||||
font-weight="600"
|
||||
fill="#2b8a3e">192.168.2.0/24</text>
|
||||
<text
|
||||
id="network-b-devices"
|
||||
x="780"
|
||||
y="155"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="10"
|
||||
fill="#868e96">Devices: .1, .2, .3...</text>
|
||||
</g>
|
||||
<!-- WireGuard Peer B -->
|
||||
<g
|
||||
id="wg-peer-b"
|
||||
filter="url(#cardShadow)">
|
||||
<rect
|
||||
id="wg-peer-b-bg"
|
||||
x="690"
|
||||
y="200"
|
||||
width="180"
|
||||
height="170"
|
||||
rx="12"
|
||||
fill="white"
|
||||
stroke="#4263eb"
|
||||
stroke-width="3" />
|
||||
<rect
|
||||
id="wg-peer-b-header-bg"
|
||||
x="690"
|
||||
y="200"
|
||||
width="180"
|
||||
height="35"
|
||||
rx="12"
|
||||
fill="url(#peerGradient)" />
|
||||
<rect
|
||||
id="wg-peer-b-header-extension"
|
||||
x="690"
|
||||
y="221"
|
||||
width="180"
|
||||
height="14"
|
||||
fill="url(#peerGradient)" />
|
||||
<text
|
||||
id="wg-peer-b-title"
|
||||
x="780"
|
||||
y="221"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="15"
|
||||
font-weight="700"
|
||||
fill="white">WireGuard Peer B</text>
|
||||
<!-- Interface IP -->
|
||||
<rect
|
||||
id="wg-peer-b-interface-bg"
|
||||
x="710"
|
||||
y="245"
|
||||
width="140"
|
||||
height="22"
|
||||
rx="6"
|
||||
fill="#e7f5ff"
|
||||
stroke="#4dabf7"
|
||||
stroke-width="1" />
|
||||
<text
|
||||
id="wg-peer-b-interface-text"
|
||||
x="780"
|
||||
y="260"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="11"
|
||||
font-weight="600"
|
||||
fill="#1971c2">wg0: 10.0.0.2/24</text>
|
||||
<!-- Own Keys -->
|
||||
<rect
|
||||
id="wg-peer-b-keys-bg"
|
||||
x="700"
|
||||
y="275"
|
||||
width="160"
|
||||
height="30"
|
||||
rx="6"
|
||||
fill="#fff5f5"
|
||||
stroke="#fa5252"
|
||||
stroke-width="1.5" />
|
||||
<text
|
||||
id="wg-peer-b-private-key"
|
||||
x="780"
|
||||
y="288"
|
||||
text-anchor="middle"
|
||||
font-family="Consolas, Monaco, 'Courier New', monospace"
|
||||
font-size="9px"
|
||||
font-weight="600"
|
||||
fill="#c92a2a">PrivateKey: bbb...=</text>
|
||||
<text
|
||||
id="wg-peer-b-public-key"
|
||||
x="780"
|
||||
y="300"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="9"
|
||||
font-weight="600"
|
||||
fill="#2f9e44">PublicKey: BBB...=</text>
|
||||
<!-- Peer A Config -->
|
||||
<text
|
||||
id="wg-peer-b-peer-config-label"
|
||||
x="780"
|
||||
y="320"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="10"
|
||||
font-weight="700"
|
||||
fill="#495057">[Peer] # Peer A</text>
|
||||
<rect
|
||||
id="wg-peer-b-peer-config-bg"
|
||||
x="700"
|
||||
y="325"
|
||||
width="160"
|
||||
height="38"
|
||||
rx="6"
|
||||
fill="#fff3bf"
|
||||
stroke="#fab005"
|
||||
stroke-width="1.5" />
|
||||
<text
|
||||
id="wg-peer-b-peer-pubkey"
|
||||
x="780"
|
||||
y="338"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="9"
|
||||
font-weight="700"
|
||||
fill="#e67700">PublicKey = AAA...=</text>
|
||||
<text
|
||||
id="wg-peer-b-peer-allowed-ips-1"
|
||||
x="780"
|
||||
y="350"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="9"
|
||||
font-weight="700"
|
||||
fill="#e67700">allowed-ips = 10.0.0.1/32,</text>
|
||||
<text
|
||||
id="wg-peer-b-peer-allowed-ips-2"
|
||||
x="780"
|
||||
y="360"
|
||||
text-anchor="middle"
|
||||
font-family="'Consolas', 'Monaco', 'Courier New', monospace"
|
||||
font-size="9"
|
||||
font-weight="700"
|
||||
fill="#e67700"> 192.168.1.0/24</text>
|
||||
</g>
|
||||
</g>
|
||||
<!-- Key Exchange Arrows -->
|
||||
<path
|
||||
id="key-arrow-a-to-b"
|
||||
d="m 178.05495,298.67711 q 309.54082,10.30088 544.04144,39.14333"
|
||||
stroke="#ff6b6b"
|
||||
stroke-width="2.45742"
|
||||
stroke-dasharray="6, 4"
|
||||
fill="none"
|
||||
marker-end="url(#keyArrow)" />
|
||||
<text
|
||||
id="key-label-a"
|
||||
x="362.67459"
|
||||
y="320.16849"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="10px"
|
||||
font-weight="600"
|
||||
fill="#fa5252">A's public key (AAA...=)</text>
|
||||
<path
|
||||
id="key-arrow-b-to-a"
|
||||
d="M 729.1812,299.9818 Q 415.736,360.0266 178.27753,338.01017"
|
||||
stroke="#ff6b6b"
|
||||
stroke-width="2.4374"
|
||||
stroke-dasharray="6, 4"
|
||||
fill="none"
|
||||
marker-end="url(#keyArrow)" />
|
||||
<text
|
||||
id="key-label-b"
|
||||
x="375.15118"
|
||||
y="360.33688"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="10px"
|
||||
font-weight="600"
|
||||
fill="#fa5252">B's public key (BBB...=)</text>
|
||||
<!-- WireGuard Tunnel -->
|
||||
<g
|
||||
id="tunnel"
|
||||
transform="translate(0.0587404,0.39164733)">
|
||||
<line
|
||||
id="tunnel-glow"
|
||||
x1="210"
|
||||
y1="285"
|
||||
x2="690"
|
||||
y2="285"
|
||||
stroke="#4c6ef5"
|
||||
stroke-width="10"
|
||||
opacity="0.2"
|
||||
filter="url(#glow)" />
|
||||
<line
|
||||
id="tunnel-line"
|
||||
x1="210"
|
||||
y1="285"
|
||||
x2="690"
|
||||
y2="285"
|
||||
stroke="url(#tunnelGradient)"
|
||||
stroke-width="5"
|
||||
style="stroke:url(#tunnelGradient)" />
|
||||
<!-- Tunnel label -->
|
||||
<rect
|
||||
id="tunnel-label-bg"
|
||||
x="380"
|
||||
y="270"
|
||||
width="140"
|
||||
height="30"
|
||||
rx="8"
|
||||
fill="#ffffff"
|
||||
stroke="#4263eb"
|
||||
stroke-width="2"
|
||||
filter="url(#cardShadow)" />
|
||||
<text
|
||||
id="tunnel-label-text"
|
||||
x="450"
|
||||
y="290"
|
||||
text-anchor="middle"
|
||||
font-family="system-ui, '-apple-system', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="12px"
|
||||
font-weight="700"
|
||||
fill="#4263eb">WireGuard Tunnel</text>
|
||||
</g>
|
||||
<!-- Explanation Box -->
|
||||
<!-- Traffic Flow Example -->
|
||||
<g
|
||||
id="traffic-left"
|
||||
transform="matrix(1.0191745,0,0,1.0648706,-3.9974789,-10.979528)">
|
||||
<line
|
||||
id="traffic-arrow-left"
|
||||
x1="210"
|
||||
y1="170"
|
||||
x2="320"
|
||||
y2="260"
|
||||
stroke="#4c6ef5"
|
||||
stroke-width="2.5"
|
||||
stroke-dasharray="6, 4"
|
||||
marker-end="url(#arrowRight)" />
|
||||
<text
|
||||
id="traffic-label-left"
|
||||
x="290"
|
||||
y="215"
|
||||
font-family="system-ui, '-apple-system', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="9px"
|
||||
font-weight="600"
|
||||
fill="#4263eb">to 192.168.2.x</text>
|
||||
</g>
|
||||
<text
|
||||
id="traffic-label-right"
|
||||
x="583.14978"
|
||||
y="201.57195"
|
||||
font-family="system-ui, '-apple-system', 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
|
||||
font-size="9px"
|
||||
font-weight="600"
|
||||
fill="#4263eb">to 192.168.1.x</text>
|
||||
<path
|
||||
style="fill:none"
|
||||
d="m 585.61735,261.45164 c -1.59298,2.54412 -1.30788,10.31284 2.71904,6.28562"
|
||||
id="path1111" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 21 KiB |
@@ -1,445 +0,0 @@
|
||||
# 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.)
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
|
||||

|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
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
|
||||
|
||||

|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv4</b>
|
||||
admin@example:/config/interface/eth0/ipv4/> <b>set address 10.0.1.1 prefix-length 24</b>
|
||||
admin@example:/config/interface/eth0/ipv4/> <b>set autoconf</b>
|
||||
admin@example:/config/interface/eth0/ipv4/> <b>diff</b>
|
||||
+interfaces {
|
||||
+ interface eth0 {
|
||||
+ ipv4 {
|
||||
+ address 10.0.1.1 {
|
||||
+ prefix-length 24;
|
||||
+ }
|
||||
+ autoconf;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
admin@example:/config/interface/eth0/ipv4/> <b>leave</b>
|
||||
admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/eth0/ipv4/> <b>edit autoconf</b>
|
||||
admin@example:/config/interface/eth0/ipv4/autoconf/> <b>set request-address 169.254.1.2</b>
|
||||
admin@example:/config/interface/eth0/ipv4/autoconf/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### Use of DHCP for IPv4 address assignment
|
||||
|
||||

|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv4</b>
|
||||
admin@example:/config/interface/eth0/ipv4/> <b>set dhcp</b>
|
||||
admin@example:/config/interface/eth0/ipv4/> <b>leave</b>
|
||||
admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv4 dhcp</b>
|
||||
admin@example:/config/interface/eth0/ipv4/dhcp/> <b>set option hostname value myhost</b>
|
||||
admin@example:/config/interface/eth0/ipv4/dhcp/> <b>show</b>
|
||||
option hostname {
|
||||
value myhost;
|
||||
}
|
||||
admin@example:/config/interface/eth0/ipv4/dhcp/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
> [!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
|
||||
|
||||

|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv6</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>set dhcp</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>leave</b>
|
||||
admin@example:/> <b>show interface</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv6 dhcp</b>
|
||||
admin@example:/config/interface/eth0/ipv6/dhcp/> <b>set option ia-pd</b>
|
||||
admin@example:/config/interface/eth0/ipv6/dhcp/> <b>set option dns-server</b>
|
||||
admin@example:/config/interface/eth0/ipv6/dhcp/> <b>show</b>
|
||||
option dns-server;
|
||||
option ia-pd;
|
||||
admin@example:/config/interface/eth0/ipv6/dhcp/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
For stateless DHCPv6 (used with SLAAC to get only configuration information):
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv6 dhcp</b>
|
||||
admin@example:/config/interface/eth0/ipv6/dhcp/> <b>set information-only true</b>
|
||||
admin@example:/config/interface/eth0/ipv6/dhcp/> <b>show</b>
|
||||
information-only true;
|
||||
option dns-server;
|
||||
option domain-search;
|
||||
admin@example:/config/interface/eth0/ipv6/dhcp/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv6</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>set enabled false</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>leave</b>
|
||||
admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
### Static IPv6 address
|
||||
|
||||

|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv6</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>set address 2001:db8::1 prefix-length 64</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>leave</b>
|
||||
admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### Stateless Auto-configuration of Global IPv6 Address
|
||||
|
||||

|
||||
|
||||
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]).
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
Disabling auto-configuration of global IPv6 addresses can be done as shown
|
||||
below.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv6</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>set autoconf create-global-addresses false</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>leave</b>
|
||||
admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### Random Link Identifiers for IPv6 Stateless Autoconfiguration
|
||||
|
||||

|
||||
|
||||
By default, the auto-configured link-local and global IPv6 addresses
|
||||
are formed from a link-identifier based on the MAC address.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
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]).
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface eth0 ipv6</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>set autoconf create-temporary-addresses true</b>
|
||||
admin@example:/config/interface/eth0/ipv6/> <b>leave</b>
|
||||
admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface eth0</b>
|
||||
admin@example:/config/interface/eth0/> <b>set ipv4 forwarding</b>
|
||||
admin@example:/config/interface/eth0/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 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 |
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface eth0</b>
|
||||
admin@example:/config/interface/eth0/> <b>set ipv6 forwarding</b>
|
||||
admin@example:/config/interface/eth0/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
[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.
|
||||
-245
@@ -1,245 +0,0 @@
|
||||
# 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface lag0</b>
|
||||
admin@example:/config/interface/lag0/> <b>set lag mode static</b>
|
||||
admin@example:/config/interface/lag0/> <b>end</b>
|
||||
admin@example:/config/> <b>set interface eth7 lag-port lag lag0</b>
|
||||
admin@example:/config/> <b>set interface eth8 lag-port lag lag0</b>
|
||||
admin@example:/config/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface lag0</b>
|
||||
admin@example:/config/interface/lag0/> <b>set lag mode lacp</b>
|
||||
admin@example:/config/interface/lag0/> <b>set lag lacp mode passive</b>
|
||||
admin@example:/config/interface/lag0/> <b>set lag lacp rate fast</b>
|
||||
admin@example:/config/interface/lag0/> <b>set lag lacp system-priority 100</b>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/lag0/lag/link-monitor/> <b>edit debounce</b>
|
||||
admin@example:/config/interface/lag0/lag/link-monitor/debounce/> <b>set up 500</b>
|
||||
admin@example:/config/interface/lag0/lag/link-monitor/debounce/> <b>set down 200</b>
|
||||
</code></pre>
|
||||
|
||||
## 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
Same aggregate, but in LACP mode:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
|
||||
## Operational Status, Detail
|
||||
|
||||
In addition to basic status shown in the interface overview, detailed
|
||||
LAG status can be inspected:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interface lag0</b>
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
Same aggregate, but in LACP mode:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interface lag0</b>
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interface eth7</b>
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface lag0</b>
|
||||
admin@example:/config/interface/lag0/> <b>set lag mode lacp</b>
|
||||
</code></pre>
|
||||
|
||||
Enable fast LACP for quicker fail-over:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/lag0/> <b>set lag lacp rate fast</b>
|
||||
</code></pre>
|
||||
|
||||
Add uplink ports
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/lag0/> <b>end</b>
|
||||
admin@example:/config/> <b>set interface eth7 lag-port lag lag0</b>
|
||||
admin@example:/config/> <b>set interface eth8 lag-port lag lag0</b>
|
||||
</code></pre>
|
||||
|
||||
Enable protection against "link flapping".
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/lag0/> <b>edit lag link-monitor</b>
|
||||
admin@example:/config/interface/lag0/lag/link-monitor/> <b>edit debounce</b>
|
||||
admin@example:/config/interface/lag0/lag/link-monitor/debounce/> <b>set up 500</b>
|
||||
admin@example:/config/interface/lag0/lag/link-monitor/debounce/> <b>set down 200</b>
|
||||
admin@example:/config/interface/lag0/lag/link-monitor/debounce/> <b>top</b>
|
||||
</code></pre>
|
||||
|
||||
Add to bridge for switching
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/lag0/lag/link-monitor/debounce/> <b>end</b>
|
||||
admin@example:/config/> <b>set interface lag0 bridge-port bridge br0</b>
|
||||
admin@example:/config/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
[^1]: `(source MAC XOR destination MAC XOR EtherType) MODULO num_links`
|
||||
+48
-40
@@ -9,20 +9,22 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit ssh</b>
|
||||
admin@example:/config/ssh/> <b>set enabled</b>
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit ssh
|
||||
admin@example:/config/ssh/> set enabled
|
||||
admin@example:/config/ssh/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit ssh</b>
|
||||
admin@example:/config/ssh/> <b>show</b>
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit ssh
|
||||
admin@example:/config/ssh/> show
|
||||
enabled true;
|
||||
hostkey genkey;
|
||||
listen ipv4 {
|
||||
@@ -33,12 +35,12 @@ listen ipv6 {
|
||||
address ::;
|
||||
port 22;
|
||||
}
|
||||
admin@example:/config/ssh/> <b>no listen ipv6</b>
|
||||
admin@example:/config/ssh/> <b>edit listen ipv4</b>
|
||||
admin@example:/config/ssh/listen/ipv4/> <b>set address 192.168.1.1</b>
|
||||
admin@example:/config/ssh/listen/ipv4/> <b>set port 12345</b>
|
||||
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/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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
|
||||
@@ -60,10 +62,9 @@ created by OpenSSL.
|
||||
After the key has been stored in the keystore and given the name
|
||||
_mykey_ it can be added to SSH configuration:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit ssh</b>
|
||||
admin@example:/config/ssh/> <b>set hostkey mykey</b>
|
||||
</code></pre>
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit ssh
|
||||
admin@example:/config/ssh/> set hostkey mykey
|
||||
|
||||
## Console Port
|
||||
|
||||
@@ -77,8 +78,9 @@ connected to the console port of the device. The serial port is
|
||||
typically setup to run at 115200 baud, 8N1.
|
||||
|
||||
|
||||
<pre class="cli"><code>Infix OS — Immutable.Friendly.Secure v24.11.1 (ttyS0)
|
||||
example login: <b>admin</b>
|
||||
```
|
||||
Infix OS — Immutable.Friendly.Secure v24.11.1 (ttyS0)
|
||||
example login: admin
|
||||
Password:
|
||||
.-------.
|
||||
| . . | Infix OS — Immutable.Friendly.Secure
|
||||
@@ -88,24 +90,26 @@ Password:
|
||||
Run the command 'cli' for interactive OAM
|
||||
|
||||
admin@example:~$
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
The `resize` command can be used to update terminal settings to the
|
||||
size of your terminal window.
|
||||
|
||||
<pre class="cli"><code>admin@example:~$ <b>resize</b>
|
||||
```
|
||||
admin@example:~$ resize
|
||||
COLUMNS=115;LINES=59;export COLUMNS LINES;
|
||||
admin@example:~$
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
CLI can be entered from shell in the same way as for SSH.
|
||||
|
||||
<pre class="cli"><code>admin@example:~$ <b>cli</b>
|
||||
```
|
||||
admin@example:~$ cli
|
||||
|
||||
See the 'help' command for an introduction to the system
|
||||
|
||||
admin@example:/> <b>show interfaces</b>
|
||||
<span class="header">INTERFACE PROTOCOL STATE DATA </span>
|
||||
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)
|
||||
@@ -113,7 +117,7 @@ e1 ethernet LOWER-DOWN 00:53:00:06:03:01
|
||||
e2 ethernet LOWER-DOWN 00:53:00:06:03:02
|
||||
...
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
## Web, Web-console and RESTCONF
|
||||
|
||||
@@ -128,25 +132,27 @@ There is also a *Netbrowse* Web service presenting information about
|
||||
the unit's neighbors, collected via mDNS (see
|
||||
[Discovery](discovery.md) for more details).
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit web</b>
|
||||
admin@example:/config/web/> <b>help</b>
|
||||
```
|
||||
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/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
### Enable/disable Web Service and Server
|
||||
|
||||
The Web service can be enabled as shown below.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit web</b>
|
||||
admin@example:/config/web/> <b>set enabled</b>
|
||||
admin@example:/config/web/>
|
||||
</code></pre>
|
||||
```
|
||||
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,
|
||||
@@ -166,10 +172,11 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/web/> <b>edit console</b>
|
||||
admin@example:/config/web/console/> <b>no enabled</b>
|
||||
```
|
||||
admin@example:/config/web/> edit console
|
||||
admin@example:/config/web/console/> no enabled
|
||||
admin@example:/config/web/console/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
### Enable/disable RESTCONF Service
|
||||
|
||||
@@ -181,10 +188,11 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/web/> <b>edit restconf</b>
|
||||
admin@example:/config/web/restconf/> <b>no enabled</b>
|
||||
```
|
||||
admin@example:/config/web/> edit restconf
|
||||
admin@example:/config/web/restconf/> no enabled
|
||||
admin@example:/config/web/restconf/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
## System Upgrade
|
||||
|
||||
|
||||
-640
@@ -1,640 +0,0 @@
|
||||
# Network Access Control Model (NACM)
|
||||
|
||||
NETCONF Access Control Model ([RFC 8341][1]) provides fine-grained access
|
||||
control for YANG data models. NACM controls who can read, write, and
|
||||
execute operations on specific parts of the configuration and operational
|
||||
state.
|
||||
|
||||
This document provides technical details about how NACM works, how rules
|
||||
are evaluated, and best practices for creating custom access control
|
||||
policies.
|
||||
|
||||
> [!TIP]
|
||||
> For a practical introduction to user management and the built-in user
|
||||
> levels (admin, operator, guest), see the [Multiple Users][2] section
|
||||
> in the System Configuration guide.
|
||||
|
||||
|
||||
## TL;DR - The Factory Defaults Work
|
||||
|
||||
**You don't need to understand NACM to use the system securely.**
|
||||
|
||||
The factory configuration implements a "permit by default, deny sensitive
|
||||
items" policy that provides:
|
||||
|
||||
- **Immediate usability** - Operators can configure the entire system
|
||||
without custom NACM rules
|
||||
- **Automatic security** - Passwords, cryptographic keys, and dangerous
|
||||
operations are protected out-of-the-box
|
||||
- **Future-proof design** - New features work immediately without NACM
|
||||
updates
|
||||
|
||||
The three built-in user levels (admin, operator, guest) cover most use
|
||||
cases. Only read on if you need to create custom access control policies.
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
NACM provides three types of access control:
|
||||
|
||||
- **Data node access** - Control read/write access to configuration and state
|
||||
- **Operation access** - Control execution of RPCs (remote procedure calls)
|
||||
- **Notification access** - Control subscription to event notifications (not covered here)
|
||||
|
||||
Access is controlled through:
|
||||
|
||||
1. **Global defaults** - Default permissions for read/write/exec
|
||||
2. **YANG-level annotations** - Security markers in YANG modules (see below)
|
||||
3. **NACM rules** - Explicit permit/deny rules organized in rule-lists
|
||||
|
||||
|
||||
## Rule Evaluation
|
||||
|
||||
NACM rules are evaluated in a specific order:
|
||||
|
||||
1. **Rule-lists are processed sequentially** in the order they appear in the configuration
|
||||
2. **Within each rule-list**, rules are evaluated sequentially
|
||||
3. **First matching rule wins** - no further rules are evaluated
|
||||
4. **If no rule matches**, global defaults apply (read-default, write-default, exec-default)
|
||||
5. **YANG annotations override everything** - `nacm:default-deny-all` in a YANG module requires an explicit permit rule regardless of global defaults
|
||||
|
||||
### Example Rule Evaluation
|
||||
|
||||
Given this configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"read-default": "permit",
|
||||
"write-default": "permit",
|
||||
"rule-list": [
|
||||
{
|
||||
"name": "operator-acl",
|
||||
"group": ["operator"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "permit-system-rpcs",
|
||||
"module-name": "ietf-system",
|
||||
"access-operations": "exec",
|
||||
"action": "permit"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "default-deny-all",
|
||||
"group": ["*"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-passwords",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"action": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
When operator user "jacky" tries to:
|
||||
|
||||
- **Read password**: Matches "deny-passwords" → **DENIED**
|
||||
- **Write interface config**: No match, uses write-default → **PERMITTED** (write-default=permit)
|
||||
- **Write hostname**: No match, uses write-default → **PERMITTED** (write-default=permit)
|
||||
- **Reboot system**: Matches "permit-system-rpcs" → **PERMITTED** (overrides `nacm:default-deny-all`)
|
||||
|
||||
## Global Defaults
|
||||
|
||||
NACM has three global defaults that apply when no rule matches:
|
||||
|
||||
```json
|
||||
{
|
||||
"read-default": "permit",
|
||||
"write-default": "permit",
|
||||
"exec-default": "permit"
|
||||
}
|
||||
```
|
||||
|
||||
**Factory configuration defaults:**
|
||||
|
||||
- `read-default: "permit"` - Users can read configuration and state by default
|
||||
- `write-default: "permit"` - Users can modify configuration by default
|
||||
- `exec-default: "permit"` - Users can execute RPCs by default
|
||||
|
||||
This permit-by-default approach, combined with targeted denials for
|
||||
sensitive items (passwords, cryptographic keys), provides a balance
|
||||
between usability and security. It also makes the system "future proof" -
|
||||
when new YANG modules are added, operators can immediately configure them
|
||||
without updating NACM rules.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> YANG modules with `nacm:default-deny-all` or `nacm:default-deny-write`
|
||||
> annotations override these global defaults. You must create explicit
|
||||
> permit rules for those operations.
|
||||
|
||||
## Module-Name vs Path
|
||||
|
||||
NACM rules can match operations using either `module-name` or `path`.
|
||||
The following sub-sections provide detailed information and examples of
|
||||
both.
|
||||
|
||||
### Module-Name Matching
|
||||
|
||||
Matches all nodes **defined** in a specific YANG module:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "permit-keystore",
|
||||
"module-name": "ietf-keystore",
|
||||
"access-operations": "*",
|
||||
"action": "permit"
|
||||
}
|
||||
```
|
||||
|
||||
This permits all operations on data **defined** in ietf-keystore, but does
|
||||
NOT cover augments from other modules.
|
||||
|
||||
**Example:** The `/interfaces/interface/ipv4/address` path:
|
||||
|
||||
- Interface is defined in `ietf-interfaces`
|
||||
- IPv4 config is defined in `ietf-ip` (augments ietf-interfaces)
|
||||
- A rule with `module-name: "ietf-interfaces"` does NOT cover ipv4/address
|
||||
|
||||
### Path Matching
|
||||
|
||||
Matches a specific data tree path and **all nodes under it**, including
|
||||
augments from other modules:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "permit-network-config",
|
||||
"path": "/ietf-interfaces:interfaces/interface",
|
||||
"access-operations": "*",
|
||||
"action": "permit"
|
||||
}
|
||||
```
|
||||
|
||||
This permits operations on `/interfaces/interface` **and all child nodes**,
|
||||
including augments like:
|
||||
|
||||
- `/interfaces/interface/ipv4` (from ietf-ip)
|
||||
- `/interfaces/interface/ipv6` (from ietf-ip)
|
||||
- `/interfaces/interface/bridge-port` (from infix-interfaces)
|
||||
|
||||
**Path syntax:**
|
||||
|
||||
- When used **with** module-name: Path is module-relative (no prefix)
|
||||
|
||||
```json
|
||||
"module-name": "ietf-system",
|
||||
"path": "/system/authentication/user/password"
|
||||
```
|
||||
|
||||
- When used **without** module-name: Path must include module prefix
|
||||
|
||||
```json
|
||||
"path": "/ietf-system:system/authentication/user/password"
|
||||
```
|
||||
|
||||
> [!TIP] Use path-based rules
|
||||
> When you want to permit/deny access to a configuration subtree
|
||||
> including all augments, e.g., all IP settings below
|
||||
> `/ietf-interfaces:interfaces/`. This is more flexible and requires
|
||||
> less maintenance as new features are added.
|
||||
|
||||
## YANG-Level Annotations
|
||||
|
||||
Many YANG modules include NACM annotations that provide baseline security:
|
||||
|
||||
### nacm:default-deny-all
|
||||
|
||||
Requires an explicit permit rule, regardless of global defaults:
|
||||
|
||||
```yang
|
||||
rpc system-restart {
|
||||
nacm:default-deny-all;
|
||||
description "Restart the system";
|
||||
}
|
||||
```
|
||||
|
||||
Even with `exec-default: "permit"`, users need an explicit permit rule to
|
||||
execute system-restart.
|
||||
|
||||
### nacm:default-deny-write
|
||||
|
||||
Write operations require an explicit permit rule:
|
||||
|
||||
```yang
|
||||
container authentication {
|
||||
nacm:default-deny-write;
|
||||
description "User authentication configuration";
|
||||
}
|
||||
```
|
||||
|
||||
Even with `write-default: "permit"`, users need an explicit permit rule to
|
||||
modify authentication settings.
|
||||
|
||||
### Protected Operations
|
||||
|
||||
The following are protected by YANG annotations and require explicit permits:
|
||||
|
||||
**RPC Operations:**
|
||||
|
||||
- `ietf-system:system-restart` ([ietf-system][3])
|
||||
- `ietf-system:system-shutdown` ([ietf-system][3])
|
||||
- `ietf-system:set-current-datetime` ([ietf-system][3])
|
||||
- `infix-factory-default:factory-default`
|
||||
- `ietf-factory-default:factory-reset` ([RFC 8808][4])
|
||||
- `infix-system-software:install-bundle`
|
||||
- `infix-system-software:set-boot-order`
|
||||
|
||||
**Data Containers:**
|
||||
|
||||
- `/system/authentication` (`nacm:default-deny-write`, [ietf-system][3])
|
||||
- `/nacm` (`nacm:default-deny-all`, [RFC 8341][1])
|
||||
- Routing protocol key chains ([ietf-key-chain][5])
|
||||
- RADIUS shared secrets ([ietf-system][3])
|
||||
- TLS client/server credentials ([ietf-tls-client][6])
|
||||
|
||||
This provides defense-in-depth - even if NACM rules are misconfigured, these
|
||||
critical operations remain protected.
|
||||
|
||||
## Access Operations
|
||||
|
||||
NACM supports the following access operations:
|
||||
|
||||
- `create` - Create new data nodes
|
||||
- `read` - Read existing data nodes
|
||||
- `update` - Modify existing data nodes
|
||||
- `delete` - Delete data nodes
|
||||
- `exec` - Execute RPC operations
|
||||
- `*` - All operations (wildcard)
|
||||
|
||||
**Common combinations:**
|
||||
|
||||
- `"create update delete"` - All write operations
|
||||
- `"*"` - Everything (read, write, execute)
|
||||
- `"read"` - Read-only access
|
||||
|
||||
## Rule-List Groups
|
||||
|
||||
Each rule-list applies to one or more user groups:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "operator-acl",
|
||||
"group": ["operator"],
|
||||
"rule": [...]
|
||||
}
|
||||
```
|
||||
|
||||
**Special group names:**
|
||||
|
||||
- `"*"` - Matches all users (including those not in any NACM group)
|
||||
|
||||
**Evaluation:**
|
||||
A user can be in multiple NACM groups. All rule-lists matching the user's
|
||||
groups are evaluated in order until a matching rule is found.
|
||||
|
||||
## Example: Factory Configuration
|
||||
|
||||
The factory configuration uses a "permit by default, deny sensitive items"
|
||||
approach. This design is "future proof" - when new YANG modules are added,
|
||||
operators can immediately configure them without updating NACM rules.
|
||||
|
||||
```json
|
||||
{
|
||||
"ietf-netconf-acm:nacm": {
|
||||
"enable-nacm": true,
|
||||
"read-default": "permit",
|
||||
"write-default": "permit",
|
||||
"exec-default": "permit",
|
||||
"groups": {
|
||||
"group": [
|
||||
{"name": "admin", "user-name": ["admin"]},
|
||||
{"name": "operator", "user-name": []},
|
||||
{"name": "guest", "user-name": []}
|
||||
]
|
||||
},
|
||||
"rule-list": [
|
||||
{
|
||||
"name": "admin-acl",
|
||||
"group": ["admin"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "permit-all",
|
||||
"module-name": "*",
|
||||
"access-operations": "*",
|
||||
"action": "permit",
|
||||
"comment": "Admin has full unrestricted access"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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 can only read, not modify or execute"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "default-deny-all",
|
||||
"group": ["*"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-password-access",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key design decisions:**
|
||||
|
||||
1. **Permit by default** - `write-default: permit` allows operators to configure any module
|
||||
2. **Minimal operator rules** - Only one rule to permit system RPCs (reboot, set time)
|
||||
3. **Future proof** - New YANG modules automatically configurable by operators
|
||||
4. **Targeted denials** - Only sensitive items (passwords, keys) are explicitly denied
|
||||
5. **Global denials** - Password/keystore/truststore denied for everyone via group "*"
|
||||
6. **YANG annotations** - Sensitive operations (factory-reset, software upgrades) still protected by `nacm:default-deny-all` in YANG modules
|
||||
|
||||
**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 |
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Permit-by-Default
|
||||
|
||||
The factory default approach - allow everything except sensitive items:
|
||||
|
||||
```json
|
||||
{
|
||||
"write-default": "permit",
|
||||
"exec-default": "permit",
|
||||
"rule-list": [
|
||||
{
|
||||
"name": "admin-acl",
|
||||
"group": ["admin"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "permit-all",
|
||||
"module-name": "*",
|
||||
"access-operations": "*",
|
||||
"action": "permit"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "global-denials",
|
||||
"group": ["*"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-passwords",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"action": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This approach is "future proof" - new YANG modules are automatically
|
||||
accessible without rule updates. Admins bypass the global denials
|
||||
because their `permit-all` rule is evaluated first.
|
||||
|
||||
### Deny-by-Default
|
||||
|
||||
More restrictive approach - deny everything except what is explicitly
|
||||
allowed:
|
||||
|
||||
```json
|
||||
{
|
||||
"write-default": "deny",
|
||||
"exec-default": "deny",
|
||||
"rule-list": [
|
||||
{
|
||||
"group": ["limited-user"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "permit-interface-config",
|
||||
"path": "/ietf-interfaces:interfaces/interface",
|
||||
"access-operations": "create update delete",
|
||||
"action": "permit"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> This requires updating NACM rules whenever new features are added.
|
||||
|
||||
### Global Restrictions
|
||||
|
||||
Deny access to sensitive data for all users (except admins with permit-all):
|
||||
|
||||
```json
|
||||
{
|
||||
"rule-list": [
|
||||
{
|
||||
"group": ["*"],
|
||||
"rule": [
|
||||
{
|
||||
"name": "deny-passwords",
|
||||
"path": "/ietf-system:system/authentication/user/password",
|
||||
"access-operations": "*",
|
||||
"action": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Debugging NACM
|
||||
|
||||
### Viewing Effective Permissions
|
||||
|
||||
Check what NACM groups a user belongs to:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show nacm</b>
|
||||
enabled : yes
|
||||
default read access : permit
|
||||
default write access : permit
|
||||
default exec access : permit
|
||||
denied operations : 0
|
||||
denied data writes : 0
|
||||
denied notifications : 0
|
||||
|
||||
┌──────────┬─────────┬─────────┬─────────┐
|
||||
│ GROUP │ READ │ WRITE │ EXEC │
|
||||
├──────────┼─────────┼─────────┼─────────┤
|
||||
│ admin │ ✓ │ ✓ │ ✓ │
|
||||
│ operator │ ⚠ │ ⚠ │ ⚠ │
|
||||
│ guest │ ⚠ │ ✗ │ ✗ │
|
||||
└──────────┴─────────┴─────────┴─────────┘
|
||||
✓ Full ⚠ Restricted ✗ Denied
|
||||
|
||||
<span class="header">USER SHELL LOGIN </span>
|
||||
admin bash password+key
|
||||
jacky bash password
|
||||
monitor false key
|
||||
|
||||
<span class="header">GROUP USERS </span>
|
||||
admin admin
|
||||
operator jacky
|
||||
guest monitor
|
||||
</code></pre>
|
||||
|
||||
For details about a group's restrictions, use `show nacm group <name>`:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show nacm group operator</b>
|
||||
members : jacky
|
||||
read permission : restricted
|
||||
write permission : restricted
|
||||
exec permission : restricted
|
||||
applicable rules : 4
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">permit-system-rpcs</span>
|
||||
action : permit
|
||||
operations : exec
|
||||
target : ietf-system (rpc: *)
|
||||
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">deny-password-access (via '*')</span>
|
||||
action : deny
|
||||
operations : *
|
||||
target : /ietf-system:system/authentication/user/password
|
||||
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">deny-keystore-access (via '*')</span>
|
||||
action : deny
|
||||
operations : *
|
||||
target : ietf-keystore
|
||||
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">deny-truststore-access (via '*')</span>
|
||||
action : deny
|
||||
operations : *
|
||||
target : ietf-truststore
|
||||
</code></pre>
|
||||
|
||||
### Testing Access
|
||||
|
||||
The easiest way to test NACM permissions is to log in as the user and try
|
||||
the operation:
|
||||
|
||||
<pre class="cli"><code>$ ssh jacky@host
|
||||
jacky@example:/> <b>configure</b>
|
||||
jacky@example:/config/> <b>edit system authentication user admin</b>
|
||||
jacky@example:/config/system/authentication/user/admin/> <b>set authorized-key foo</b>
|
||||
Error: Access to the data model "ietf-system" is denied because "jacky" NACM authorization failed.
|
||||
Error: Failed applying changes (2).
|
||||
</code></pre>
|
||||
|
||||
### NACM Statistics
|
||||
|
||||
NACM tracks denied operations. If you suspect permission issues, check
|
||||
the statistics:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show nacm</b>
|
||||
...
|
||||
denied operations : 5
|
||||
denied data writes : 12
|
||||
...
|
||||
</code></pre>
|
||||
|
||||
Increasing counters indicate permission denials are occurring.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Leverage permit-by-default** - The factory configuration uses
|
||||
`write-default: "permit"` with targeted denials. This is "future proof" -
|
||||
new features work immediately without NACM updates.
|
||||
|
||||
2. **Protect sensitive items globally** - Use `group: ["*"]` rule-list to
|
||||
deny access to passwords, cryptographic keys, and similar sensitive data.
|
||||
Admin's permit-all rule (evaluated first) bypasses these denials.
|
||||
|
||||
3. **Leverage YANG annotations** - Many sensitive operations are already
|
||||
protected by `nacm:default-deny-all` in YANG modules (factory-reset,
|
||||
software upgrades, etc.). Only add explicit permit rules when needed.
|
||||
|
||||
4. **Order matters** - Rule-lists are evaluated in order. Place admin's
|
||||
permit-all rule first so it bypasses global denials.
|
||||
|
||||
5. **Use path-based denials** - For protecting specific data (like password
|
||||
hashes), use path rules. For protecting entire modules (like keystore),
|
||||
use module-name rules.
|
||||
|
||||
6. **Test thoroughly** - Always test user permissions after changes. NACM
|
||||
errors can be subtle (nodes may be silently omitted from read operations).
|
||||
|
||||
7. **Keep it simple** - The factory configuration uses only 6 rules for
|
||||
three user levels. Fewer rules are easier to understand and maintain.
|
||||
|
||||
8. **Document rules** - Use the "comment" field to explain why specific
|
||||
permissions are granted or denied.
|
||||
|
||||
## References
|
||||
|
||||
- [RFC 8341: Network Configuration Access Control Model (NACM)][1]
|
||||
- [RFC 7317: A YANG Data Model for System Management (ietf-system)][3]
|
||||
- [RFC 8808: A YANG Data Model for Factory Default Settings (ietf-factory-default)][4]
|
||||
- [RFC 8177: YANG Key Chain (ietf-key-chain)][5]
|
||||
- [System Configuration - Multiple Users][2]
|
||||
|
||||
[1]: https://www.rfc-editor.org/rfc/rfc8341
|
||||
[2]: system.md#multiple-users
|
||||
[3]: https://www.rfc-editor.org/rfc/rfc7317
|
||||
[4]: https://www.rfc-editor.org/rfc/rfc8808
|
||||
[5]: https://www.rfc-editor.org/rfc/rfc8177
|
||||
[6]: https://datatracker.ietf.org/doc/html/draft-ietf-netconf-tls-client-server
|
||||
+1717
-10
File diff suppressed because it is too large
Load Diff
-192
@@ -1,192 +0,0 @@
|
||||
# NTP Server
|
||||
|
||||
The NTP (Network Time Protocol) server provides accurate time synchronization
|
||||
for network clients. It supports both standalone operation with a local
|
||||
reference clock and hybrid mode where it synchronizes with upstream servers
|
||||
while serving time to downstream clients.
|
||||
|
||||
> [!NOTE]
|
||||
> The NTP server is mutually exclusive with the NTP client in system
|
||||
> configuration context.
|
||||
|
||||
## Standalone Mode
|
||||
|
||||
Configure a standalone NTP server using only a local reference clock:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit ntp</b>
|
||||
admin@example:/config/ntp/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit ntp</b>
|
||||
admin@example:/config/ntp/> <b>set refclock-master master-stratum 10</b>
|
||||
admin@example:/config/ntp/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
## Server Mode
|
||||
|
||||
Synchronize from upstream NTP servers while serving time to clients:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit ntp</b>
|
||||
admin@example:/config/ntp/> <b>edit unicast-configuration 0.pool.ntp.org type uc-server</b>
|
||||
admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> <b>set iburst true</b>
|
||||
admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> <b>end</b>
|
||||
admin@example:/config/ntp/> <b>edit unicast-configuration 1.pool.ntp.org type uc-server</b>
|
||||
admin@example:/config/ntp/…/1.pool.ntp.org/type/uc-server/> <b>set iburst true</b>
|
||||
admin@example:/config/ntp/…/1.pool.ntp.org/type/uc-server/> <b>end</b>
|
||||
admin@example:/config/ntp/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
The `unicast-configuration` uses a composite key with both address and type.
|
||||
Both hostnames and IP addresses are supported. The `iburst` option enables
|
||||
fast initial synchronization.
|
||||
|
||||
## Peer Mode
|
||||
|
||||
In peer mode, two NTP servers synchronize with each other bidirectionally.
|
||||
Each server acts as both client and server to the other:
|
||||
|
||||
**First peer:**
|
||||
|
||||
<pre class="cli"><code>admin@peer1:/config/> <b>edit ntp</b>
|
||||
admin@peer1:/config/ntp/> <b>edit unicast-configuration 192.168.1.2 type uc-peer</b>
|
||||
admin@peer1:/config/ntp/…/192.168.1.2/type/uc-peer/> <b>end</b>
|
||||
admin@peer1:/config/ntp/> <b>set refclock-master master-stratum 8</b>
|
||||
admin@peer1:/config/ntp/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
**Second peer:**
|
||||
|
||||
<pre class="cli"><code>admin@peer2:/config/> <b>edit ntp</b>
|
||||
admin@peer2:/config/ntp/> <b>edit unicast-configuration 192.168.1.1 type uc-peer</b>
|
||||
admin@peer2:/config/ntp/…/192.168.1.1/type/uc-peer/> <b>end</b>
|
||||
admin@peer2:/config/ntp/> <b>set refclock-master master-stratum 8</b>
|
||||
admin@peer2:/config/ntp/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
This configuration provides mutual synchronization between peers. If one peer
|
||||
fails, the other continues to serve time to clients.
|
||||
|
||||
> [!NOTE]
|
||||
> The `iburst` and `burst` options are not supported in peer mode.
|
||||
|
||||
### Peer Selection in Symmetric Mode
|
||||
|
||||
When both peers have the same stratum (as in the example above where both are
|
||||
stratum 8), NTP's clock selection algorithm uses the **Reference ID** as the
|
||||
tie-breaker. The Reference ID is typically derived from the peer's IP address
|
||||
when using a local reference clock.
|
||||
|
||||
This means the peer with the **numerically lower IP address** will be selected
|
||||
as the sync source by the other peer. In the example above:
|
||||
|
||||
- peer1 (192.168.1.1) has a lower Reference ID
|
||||
- peer2 (192.168.1.2) will select peer1 as sync source
|
||||
|
||||
This behavior is deterministic and ensures stable clock selection. If you need
|
||||
a specific peer to be selected, configure it with a lower stratum level than
|
||||
the other peer.
|
||||
|
||||
## Timing Configuration
|
||||
|
||||
### Poll Intervals
|
||||
|
||||
Control how often the NTP server polls upstream sources:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/ntp/> <b>edit unicast-configuration 0.pool.ntp.org type uc-server</b>
|
||||
admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> <b>set minpoll 4</b>
|
||||
admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> <b>set maxpoll 10</b>
|
||||
admin@example:/config/ntp/…/0.pool.ntp.org/type/uc-server/> <b>end</b>
|
||||
</code></pre>
|
||||
|
||||
Poll intervals are specified as powers of 2:
|
||||
- `minpoll 4` = poll every 2^4 = 16 seconds (minimum polling rate)
|
||||
- `maxpoll 10` = poll every 2^10 = 1024 seconds (maximum polling rate)
|
||||
- Defaults: minpoll 6 (64 seconds), maxpoll 10 (1024 seconds)
|
||||
|
||||
Use shorter intervals (minpoll 2-4) for faster convergence in test environments
|
||||
or peer configurations. Use defaults for production servers.
|
||||
|
||||
### Fast Initial Synchronization
|
||||
|
||||
The `makestep` directive is automatically configured with safe defaults (1.0
|
||||
seconds threshold, 3 updates limit) when creating an NTP server. This is
|
||||
critical for embedded systems without RTC that boot with epoch time.
|
||||
|
||||
To customize the values:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/ntp/> <b>edit makestep</b>
|
||||
admin@example:/config/ntp/makestep/> <b>set threshold 2.0</b>
|
||||
admin@example:/config/ntp/makestep/> <b>set limit 1</b>
|
||||
admin@example:/config/ntp/makestep/> <b>end</b>
|
||||
</code></pre>
|
||||
|
||||
- **threshold** - If clock offset exceeds this (in seconds), step immediately
|
||||
instead of slewing slowly
|
||||
- **limit** - Number of updates during which stepping is allowed. After this,
|
||||
only gradual slewing is used for security
|
||||
|
||||
With these defaults, a device booting at epoch time (1970-01-01) will sync to
|
||||
correct time within seconds instead of hours.
|
||||
|
||||
## Monitoring
|
||||
|
||||
For a quick overview:
|
||||
|
||||
To view the sources being used by the NTP client, run:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ntp</b>
|
||||
Mode : Client
|
||||
Stratum : 3
|
||||
Ref time (UTC) : Sat Jan 24 23:41:42 2026
|
||||
|
||||
<span class="header">ADDRESS MODE STATE STRATUM POLL</span>
|
||||
147.78.228.41 server outlier 2 64s
|
||||
192.168.0.1 server unusable 0 128s
|
||||
176.126.86.247 server selected 2 64s
|
||||
</code></pre>
|
||||
|
||||
Check NTP source status:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ntp source</b>
|
||||
<span class="header">MS Name/IP address Stratum Poll Reach LastRx Last sample</span>
|
||||
^+ 147.78.228.41 2 6 007 15 -431us +/- 33.573ms
|
||||
^* 176.126.86.247 2 6 007 14 -389us +/- 4.307ms
|
||||
</code></pre>
|
||||
|
||||
For detailed information about a specific source:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ntp source 176.126.86.247</b>
|
||||
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)
|
||||
</code></pre>
|
||||
|
||||
## NTP Stratum Levels
|
||||
|
||||
NTP uses a hierarchical system called **stratum** to indicate distance from
|
||||
authoritative time sources:
|
||||
|
||||
- **Stratum 0**: Reference clocks (atomic clocks)
|
||||
- **Stratum 1**: Servers directly connected to stratum 0 (e.g., GPS receivers)
|
||||
- **Stratum 2-15**: Servers that sync from lower stratum (each hop adds one)
|
||||
- **Stratum 16**: Unsynchronized (invalid)
|
||||
|
||||
The default stratum (16) is not suitable for distributing time in isolated
|
||||
networks, so when setting up an NTP server remember to adjust this value.
|
||||
Use, e.g., `10`, this is a safe, low-priority value that ensures clients will
|
||||
prefer upstream-synchronized servers (stratum 1-9) while still having a
|
||||
fallback time source in isolated networks.
|
||||
+9
-8
@@ -91,14 +91,15 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface e1.10</b>
|
||||
admin@example:/config/interface/e1.10/> <b>set vlan ingress-qos priority from-pcp</b>
|
||||
admin@example:/config/interface/e1.10/> <b>up</b>
|
||||
admin@example:/config/> <b>edit interface e1.20</b>
|
||||
admin@example:/config/interface/e1.20/> <b>set vlan egress-qos pcp from-priority</b>
|
||||
admin@example:/config/interface/e1.20/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
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
|
||||
|
||||
|
||||
-453
@@ -1,453 +0,0 @@
|
||||
# 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit routing control-plane-protocol static name default ipv4</b>
|
||||
admin@example:/config/routing/…/ipv4/> <b>set route 192.168.200.0/24 next-hop next-hop-address 192.168.1.1</b>
|
||||
admin@example:/config/routing/…/ipv4/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit routing control-plane-protocol static name default ipv4</b>
|
||||
admin@example:/config/routing/…/ipv4/> <b>set route 10.0.0.0/16 next-hop next-hop-address 192.168.1.1 route-preference 254</b>
|
||||
admin@example:/config/routing/…/ipv4/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
> [!TIP]
|
||||
> Remember to enable [IPv4 forwarding](ip.md#ipv4-forwarding) for the
|
||||
> interfaces you want to route between.
|
||||
|
||||
|
||||
## IPv6 Static routes
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit routing control-plane-protocol static name default ipv6</b>
|
||||
admin@example:/config/routing/…/ipv6/> <b>set route 2001:db8:3c4d:200::/64 next-hop next-hop-address 2001:db8:3c4d:1::1</b>
|
||||
admin@example:/config/routing/…/ipv6/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
## OSPFv2 Routing
|
||||
|
||||
The system supports OSPF dynamic routing for IPv4, i.e., OSPFv2. To
|
||||
enable OSPF and set one active interface in area 0:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit routing control-plane-protocol ospfv2 name default ospf</b>
|
||||
admin@example:/config/routing/…/ospf/> <b>set area 0.0.0.0 interface e0 enabled</b>
|
||||
admin@example:/config/routing/…/ospf/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
> [!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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit routing control-plane-protocol ospfv2 name default ospf</b>
|
||||
admin@example:/config/routing/…/ospf/> <b>set area 0.0.0.1 area-type nssa-area</b>
|
||||
admin@example:/config/routing/…/ospf/> <b>set area 0.0.0.1 summary true</b>
|
||||
admin@example:/config/routing/…/ospf/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### Bidirectional Forwarding Detection (BFD)
|
||||
|
||||
It is possible to enable BFD per OSPF interface to speed up detection of
|
||||
link loss.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit routing control-plane-protocol ospfv2 name default ospf</b>
|
||||
admin@example:/config/routing/…/ospf/> <b>set area 0.0.0.0 interface e0 bfd enabled true</b>
|
||||
admin@example:/config/routing/…/ospf/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/routing/…/> <b>edit ospf area 0.0.0.0</b>
|
||||
admin@example:/config/routing/…/ospf/area/0.0.0.0/> <b>edit interface e0</b>
|
||||
admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> <b>set ?</b>
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
For example, setting the OSPF *interface type* to *point-to-point* for
|
||||
an Ethernet interface can be done as follows.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/> <b>set interface-type point-to-point</b>
|
||||
admin@example:/config/routing/…/ospf/area/0.0.0.0/interface/e0/>
|
||||
</code></pre>
|
||||
|
||||
### OSPF global settings
|
||||
|
||||
In addition to *area* and *interface* specific settings, OSPF provides
|
||||
global settings for route redistribution and OSPF router identifier.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit routing control-plane-protocol ospfv2 name default ospf</b>
|
||||
admin@example:/config/routing/…/ospf/> <b>set ?</b>
|
||||
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
|
||||
</code></pre>
|
||||
|
||||
- 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`.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ospf neighbor</b>
|
||||
<span class="header">Neighbor ID Pri State Up Time Dead Time Address Interface RXmtL RqstL DBsmL</span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit routing control-plane-protocol ospfv2 name default ospf debug</b>
|
||||
admin@example:/config/routing/…/ospf/debug/> <b>set bfd true</b>
|
||||
admin@example:/config/routing/…/ospf/debug/> <b>set nsm true</b>
|
||||
admin@example:/config/routing/…/ospf/debug/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show running-config routing control-plane-protocol</b>
|
||||
</code></pre>
|
||||
|
||||
To disable all debug logging, simply delete the debug settings or set
|
||||
all options back to `false`:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>delete routing control-plane-protocol ospfv2 name default ospf debug</b>
|
||||
admin@example:/config/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
## RIP Routing
|
||||
|
||||
The system supports RIP dynamic routing for IPv4, i.e., RIPv2. To enable
|
||||
RIP and set active interfaces:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit routing control-plane-protocol ripv2 name default rip</b>
|
||||
admin@example:/config/routing/…/rip/> <b>set interfaces interface e0</b>
|
||||
admin@example:/config/routing/…/rip/> <b>set interfaces interface e1</b>
|
||||
admin@example:/config/routing/…/rip/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
> [!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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/routing/…/rip/> <b>edit interfaces interface e0</b>
|
||||
admin@example:/config/routing/…/rip/interfaces/interface/e0/> <b>set send-version 1</b>
|
||||
admin@example:/config/routing/…/rip/interfaces/interface/e0/> <b>set receive-version 1-2</b>
|
||||
admin@example:/config/routing/…/rip/interfaces/interface/e0/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
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):
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/routing/…/rip/> <b>edit interfaces interface e0</b>
|
||||
admin@example:/config/routing/…/rip/interfaces/interface/e0/> <b>set passive</b>
|
||||
admin@example:/config/routing/…/rip/interfaces/interface/e0/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### RIP global settings
|
||||
|
||||
RIP supports redistribution of connected and static routes:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/routing/…/rip/> <b>set redistribute connected</b>
|
||||
admin@example:/config/routing/…/rip/> <b>set redistribute static</b>
|
||||
admin@example:/config/routing/…/rip/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### Debug RIPv2
|
||||
|
||||
The CLI provides various RIP status commands:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ip rip</b>
|
||||
Default version control: send version 2, receive version 2
|
||||
<span class="header"> Interface Send Recv Key-chain </span>
|
||||
e0 2 2
|
||||
e1 2 2
|
||||
|
||||
Routing for Networks:
|
||||
e0
|
||||
e1
|
||||
|
||||
Routing Information Sources:
|
||||
<span class="header"> Gateway BadPackets BadRoutes Distance Last Update</span>
|
||||
10.0.1.2 0 0 120 00:00:16
|
||||
Distance: (default is 120)
|
||||
|
||||
admin@example:/> <b>show ip rip neighbor</b>
|
||||
<span class="header">ADDRESS BAD-PACKETS BAD-ROUTES </span>
|
||||
10.0.1.2 0 0
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit routing control-plane-protocol ripv2 name default rip debug</b>
|
||||
admin@example:/config/routing/…/rip/debug/> <b>set events true</b>
|
||||
admin@example:/config/routing/…/rip/debug/> <b>set packet true</b>
|
||||
admin@example:/config/routing/…/rip/debug/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show running-config routing control-plane-protocol</b>
|
||||
</code></pre>
|
||||
|
||||
To disable all debug logging, simply delete the debug settings or set
|
||||
all options back to `false`:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>delete routing control-plane-protocol ripv2 name default rip debug</b>
|
||||
admin@example:/config/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
## 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*).
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ip route</b>
|
||||
<span class="header"> DESTINATION PREF NEXT-HOP PROTO UPTIME</span>
|
||||
>* 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:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### IPv6 routing table
|
||||
|
||||
This CLI example show the IPv6 routing table.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ipv6 route</b>
|
||||
<span class="header"> DESTINATION PREF NEXT-HOP PROTO UPTIME</span>
|
||||
>* ::/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:/>
|
||||
</code></pre>
|
||||
|
||||
|
||||
### 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/
|
||||
@@ -350,5 +350,5 @@ the created configuration.
|
||||
|
||||
[1]: scripting-sysrepocfg.md#backup-configuration
|
||||
[2]: scripting-sysrepocfg.md#restore-configuration
|
||||
[8]: bridging.md
|
||||
[9]: bridging.md#vlan-filtering-bridge
|
||||
[8]: networking.md#bridging
|
||||
[9]: networking.md#vlan-filtering-bridge
|
||||
|
||||
+53
-306
@@ -18,116 +18,77 @@ To simplify RESTCONF operations, create a `curl.sh` wrapper script:
|
||||
#!/bin/sh
|
||||
# RESTCONF CLI wrapper for curl
|
||||
|
||||
# Show usage and exit
|
||||
usage()
|
||||
{
|
||||
cat <<-EOF >&2
|
||||
Usage: $0 [-h HOST] [-d DATASTORE] [-u USER:PASS] METHOD PATH [CURL_ARGS...]
|
||||
|
||||
Options:
|
||||
-h HOST Target host (default: infix.local)
|
||||
-d DS Datastore: running, operational, startup (default: running)
|
||||
-u CREDS Credentials as user:pass (default: admin:admin)
|
||||
|
||||
Methods: GET, POST, PUT, PATCH, DELETE
|
||||
EOF
|
||||
exit "$1"
|
||||
}
|
||||
|
||||
# Default values
|
||||
HOST=${HOST:-infix.local}
|
||||
DATASTORE=running
|
||||
AUTH=admin:admin
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<EOF >&2
|
||||
Usage: $0 [-v] [-h HOST] [-d DATASTORE] [-u USER:PASS] METHOD XPATH [CURL_ARGS...]
|
||||
|
||||
Options:
|
||||
-h HOST Target host (default: infix.local)
|
||||
-d DS Datastore: running, operational, startup (default: running)
|
||||
-u CREDS Credentials as user:pass (default: admin:admin)
|
||||
-v Verbose mode, use it to display variables and curl command
|
||||
|
||||
Methods: GET, POST, PUT, PATCH, DELETE
|
||||
EOF
|
||||
exit "$1"
|
||||
}
|
||||
|
||||
check()
|
||||
{
|
||||
hint="Note: URL may be missing a module prefix (e.g., ietf-system:system)"
|
||||
resp="$1"
|
||||
url="$2"
|
||||
|
||||
if ! command -v jq >/dev/null 2>&1; then
|
||||
printf "%s\n" "$resp"
|
||||
return
|
||||
fi
|
||||
|
||||
case "$resp" in
|
||||
*"Syntax error"*)
|
||||
path_only="${url#*//}"
|
||||
|
||||
# Check for common URL error(s), e.g., missing module prefix
|
||||
case "$path_only" in
|
||||
*":"*)
|
||||
printf "%s\n" "$resp" | jq .
|
||||
;;
|
||||
*)
|
||||
printf "%s\n" "$resp" | jq --arg hint "$hint" \
|
||||
'.["ietf-restconf:errors"].error[] |= . + {comment: $hint}'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
printf "%s\n" "$resp" | jq .
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
while getopts "h:d:u:v" opt; do
|
||||
case $opt in
|
||||
h) HOST="$OPTARG" ;;
|
||||
d) DATASTORE="$OPTARG" ;;
|
||||
u) AUTH="$OPTARG" ;;
|
||||
v) VERBOSE=1 ;;
|
||||
*) usage 1 ;;
|
||||
esac
|
||||
# Parse options
|
||||
while getopts "h:d:u:" opt; do
|
||||
case $opt in
|
||||
h) HOST="$OPTARG" ;;
|
||||
d) DATASTORE="$OPTARG" ;;
|
||||
u) AUTH="$OPTARG" ;;
|
||||
*) usage 1 ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
# Validate required arguments
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "Error: METHOD and XPATH are required" >&2
|
||||
usage 1
|
||||
echo "Error: METHOD and PATH are required" >&2
|
||||
usage 1
|
||||
fi
|
||||
|
||||
METHOD=$1
|
||||
XPATH=$2
|
||||
PATH=$2
|
||||
shift 2
|
||||
|
||||
# Ensure XPATH starts with /
|
||||
case "$XPATH" in
|
||||
/*) ;;
|
||||
*) XPATH="/$XPATH" ;;
|
||||
# Ensure PATH starts with /
|
||||
case "$PATH" in
|
||||
/*) ;;
|
||||
*) PATH="/$PATH" ;;
|
||||
esac
|
||||
|
||||
# Build URL based on datastore
|
||||
case "$DATASTORE" in
|
||||
running|startup)
|
||||
URL="https://${HOST}/restconf/data${XPATH}"
|
||||
;;
|
||||
operational)
|
||||
URL="https://${HOST}/restconf/data${XPATH}"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid datastore '$DATASTORE'. Use: running, operational, or startup" >&2
|
||||
exit 1
|
||||
;;
|
||||
running|startup)
|
||||
URL="https://${HOST}/restconf/data${PATH}"
|
||||
;;
|
||||
operational)
|
||||
URL="https://${HOST}/restconf/data${PATH}"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid datastore '$DATASTORE'. Use: running, operational, or startup" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$VERBOSE" ]; then
|
||||
echo "DS : $DATASTORE"
|
||||
echo "OP : $METHOD"
|
||||
echo "XPATH : $XPATH"
|
||||
echo "AUTH : $AUTH"
|
||||
echo "=> URL : $URL"
|
||||
set -x
|
||||
fi
|
||||
|
||||
RESP=$(/usr/bin/curl --silent \
|
||||
--insecure \
|
||||
--user "${AUTH}" \
|
||||
--request "${METHOD}" \
|
||||
--header "Content-Type: application/yang-data+json" \
|
||||
--header "Accept: application/yang-data+json" \
|
||||
"$@" \
|
||||
"${URL}")
|
||||
|
||||
check "$RESP" "$URL"
|
||||
# Execute curl with all remaining arguments passed through
|
||||
exec /usr/bin/curl \
|
||||
--insecure \
|
||||
--user "${AUTH}" \
|
||||
--request "${METHOD}" \
|
||||
--header "Content-Type: application/yang-data+json" \
|
||||
--header "Accept: application/yang-data+json" \
|
||||
"$@" \
|
||||
"${URL}"
|
||||
```
|
||||
|
||||
Make it executable:
|
||||
@@ -151,158 +112,6 @@ command-line options or environment variables:
|
||||
The examples below show both raw `curl` commands and the equivalent using
|
||||
`curl.sh` where applicable.
|
||||
|
||||
## HTTP Methods in RESTCONF
|
||||
|
||||
RESTCONF uses standard HTTP methods to perform different operations on
|
||||
configuration and operational data. Understanding when to use each method is
|
||||
crucial for correct and safe operations.
|
||||
|
||||
### GET - Read Data
|
||||
|
||||
Retrieve configuration or operational data without making changes.
|
||||
|
||||
**When to use:**
|
||||
|
||||
- Reading current configuration
|
||||
- Querying operational state (interface statistics, routing tables, etc.)
|
||||
- Discovering what exists before making changes
|
||||
|
||||
**Characteristics:**
|
||||
|
||||
- Safe operation (no side effects)
|
||||
- Can be repeated without consequences
|
||||
- Works on both configuration and operational datastores
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
~$ ./curl.sh -h example.local GET /ietf-interfaces:interfaces
|
||||
```
|
||||
|
||||
### PUT - Replace Resource
|
||||
|
||||
> [!DANGER] Heads-up!
|
||||
> PUT replaces everything - missing fields will be deleted!
|
||||
|
||||
Replace an entire resource with new content.
|
||||
|
||||
**When to use:**
|
||||
|
||||
- Replacing entire datastore (backup/restore scenarios)
|
||||
- Complete reconfiguration of a container
|
||||
- When you want to ensure the resource matches exactly what you provide
|
||||
|
||||
**Characteristics:**
|
||||
|
||||
- Replaces all content at the target path
|
||||
- Any existing data not in the PUT request is **removed**
|
||||
- Requires complete, valid configuration
|
||||
- Dangerous if you don't include all necessary fields
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
~$ ./curl.sh -h example.local PUT /ietf-system:system \
|
||||
-d '{"ietf-system:system":{"hostname":"newhost","contact":"admin@example.com"}}'
|
||||
```
|
||||
|
||||
### PATCH - Merge/Update Resource
|
||||
|
||||
Partially update a resource by merging changes with existing data.
|
||||
|
||||
**When to use:**
|
||||
|
||||
- Modifying specific fields while preserving others
|
||||
- Working with path-based NACM permissions
|
||||
- Incremental configuration changes
|
||||
- Safer alternative to PUT for most use cases
|
||||
|
||||
**Characteristics:**
|
||||
|
||||
- Merges changes with existing configuration
|
||||
- Only specified fields are modified
|
||||
- Unspecified fields remain unchanged
|
||||
- Works with partial data structures
|
||||
- NACM-friendly (respects path-based permissions)
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
~$ ./curl.sh -h example.local PATCH /ietf-interfaces:interfaces \
|
||||
-d '{"ietf-interfaces:interfaces":{"interface":[{"name":"e0","description":"WAN"}]}}'
|
||||
```
|
||||
|
||||
> [!TIP] Best practice
|
||||
> Use PATCH instead of PUT for most configuration updates.
|
||||
|
||||
### POST - Create New Resource
|
||||
|
||||
Create a new resource within a collection or invoke an RPC.
|
||||
|
||||
**When to use:**
|
||||
|
||||
- Adding new list entries (interfaces, users, routes, etc.)
|
||||
- Creating resources at specific paths
|
||||
- Invoking RPC operations (reboot, factory-reset, etc.)
|
||||
|
||||
**Characteristics:**
|
||||
|
||||
- Creates new resources
|
||||
- For lists: adds a new element
|
||||
- For RPCs: executes the operation
|
||||
- Returns error if resource already exists (for configuration)
|
||||
|
||||
**Example - Add IP address:**
|
||||
```bash
|
||||
~$ ./curl.sh -h example.local POST \
|
||||
/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \
|
||||
-d '{"prefix-length": 32}'
|
||||
```
|
||||
|
||||
**Example - Invoke RPC:**
|
||||
```bash
|
||||
~$ curl -kX POST -u admin:admin \
|
||||
-H "Content-Type: application/yang-data+json" \
|
||||
https://example.local/restconf/operations/ietf-system:system-restart
|
||||
```
|
||||
|
||||
### DELETE - Remove Resource
|
||||
|
||||
Delete a resource or configuration element.
|
||||
|
||||
**When to use:**
|
||||
|
||||
- Removing interfaces, routes, users, etc.
|
||||
- Deleting specific configuration items
|
||||
- Cleaning up unwanted configuration
|
||||
|
||||
**Characteristics:**
|
||||
|
||||
- Removes the resource completely
|
||||
- Cannot be undone (except by reconfiguration)
|
||||
- Returns error if resource doesn't exist
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
~$ ./curl.sh -h example.local DELETE \
|
||||
/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254
|
||||
```
|
||||
|
||||
### Quick Reference
|
||||
|
||||
| **Method** | **Use Case** | **Safe?** | **Idempotent?** | **NACM Impact** |
|
||||
|------------|-------------------------|-----------|-----------------|--------------------------|
|
||||
| GET | Read data | ✓ | ✓ | Read permissions |
|
||||
| PUT | Replace entire resource | ✗ | ✓ | Full write access needed |
|
||||
| PATCH | Merge/update fields | ✓ | ✓ | Path-specific write |
|
||||
| POST | Create new/invoke RPC | ✗ | ✗ | Create/exec permissions |
|
||||
| DELETE | Remove resource | ✗ | ✓ | Delete permissions |
|
||||
|
||||
**Key takeaways:**
|
||||
|
||||
- **Use PATCH for updates** - Safer than PUT, works with NACM
|
||||
- **Use PUT sparingly** - Only when you need complete replacement
|
||||
- **GET is always safe** - Read as much as you need
|
||||
- **POST for creation/RPCs** - Creating new items or executing operations
|
||||
- **DELETE with care** - Cannot be undone
|
||||
|
||||
## Discovery & Common Patterns
|
||||
|
||||
Before working with specific configuration items, you often need to discover
|
||||
@@ -436,68 +245,6 @@ Example of updating configuration with inline JSON data:
|
||||
-d '{"ietf-system:system":{"hostname":"bar"}}'
|
||||
```
|
||||
|
||||
### Update Interface Description
|
||||
|
||||
PATCH allows you to modify specific parts of the configuration without
|
||||
replacing the entire container. This is particularly useful when working
|
||||
with NACM (Network Access Control Model) permissions that grant access to
|
||||
specific paths.
|
||||
|
||||
**Why use PATCH instead of PUT:**
|
||||
|
||||
- **Partial updates**: Only changes specified fields, preserves others
|
||||
- **NACM-friendly**: Works with path-based access control rules
|
||||
- **Safer**: Reduces risk of accidentally removing unrelated configuration
|
||||
|
||||
**Example - Modify an interface description:**
|
||||
|
||||
```bash
|
||||
~$ curl -kX PATCH -u admin:admin \
|
||||
-H 'Content-Type: application/yang-data+json' \
|
||||
-d '{"ietf-interfaces:interfaces":{"interface":[{"name":"e0","description":"WAN Port"}]}}' \
|
||||
https://example.local/restconf/data/ietf-interfaces:interfaces
|
||||
```
|
||||
|
||||
**Using curl.sh:**
|
||||
|
||||
```bash
|
||||
~$ ./curl.sh -h example.local PATCH /ietf-interfaces:interfaces \
|
||||
-d '{"ietf-interfaces:interfaces":{"interface":[{"name":"e0","description":"WAN Port"}]}}'
|
||||
```
|
||||
|
||||
**Formatted for readability:**
|
||||
|
||||
```bash
|
||||
~$ curl -kX PATCH -u admin:admin \
|
||||
-H 'Content-Type: application/yang-data+json' \
|
||||
-d '{
|
||||
"ietf-interfaces:interfaces": {
|
||||
"interface": [
|
||||
{
|
||||
"name": "e0",
|
||||
"description": "WAN Port"
|
||||
}
|
||||
]
|
||||
}
|
||||
}' \
|
||||
https://example.local/restconf/data/ietf-interfaces:interfaces
|
||||
```
|
||||
|
||||
**Key points:**
|
||||
|
||||
- PATCH URL targets the **container** (`/interfaces`), not a specific interface
|
||||
- JSON body includes the full structure with the interface array
|
||||
- Only specified fields are modified; other interface settings remain unchanged
|
||||
- The `name` field identifies which interface to update
|
||||
|
||||
**Verify the change:**
|
||||
|
||||
```bash
|
||||
~$ ./curl.sh -h example.local GET /ietf-interfaces:interfaces/interface=e0 2>/dev/null \
|
||||
| jq '.["ietf-interfaces:interface"][0].description'
|
||||
"WAN Port"
|
||||
```
|
||||
|
||||
### Add IP Address to Interface
|
||||
|
||||
Add an IP address to the loopback interface:
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
> [!WARNING] Deprecated - Use RESTCONF Instead
|
||||
>
|
||||
> This legacy interface requires elevated privileges (`sudo sysrepocfg`) even
|
||||
> for admin users and is no longer intended for production use. All scripting
|
||||
> should use [RESTCONF][1] as the standard management interface. There is
|
||||
> however an NACM compliant replacement `copy` that can be used without sudo.
|
||||
> [!NOTE]
|
||||
> This method is a legacy "simple and human-friendly" way to manage the
|
||||
> system. These days we strongly recommend using [RESTCONF][1] instead.
|
||||
|
||||
# Legacy Scripting
|
||||
|
||||
|
||||
+6
-13
@@ -5,20 +5,14 @@ provides a convenient way to collect comprehensive system diagnostics.
|
||||
This command gathers configuration files, logs, network state, and other
|
||||
system information into a single compressed archive.
|
||||
|
||||
> [!NOTE]
|
||||
> The `support collect` command should be run with `sudo` to collect
|
||||
> complete system information (kernel logs, hardware details, etc.).
|
||||
> Use the `--unprivileged` option to run as a regular user in degraded
|
||||
> data collection mode.
|
||||
|
||||
## Collecting Support Data
|
||||
|
||||
To collect support data and save it to a file:
|
||||
|
||||
```bash
|
||||
admin@host:~$ sudo support collect > support-data.tar.gz
|
||||
admin@host:~$ support collect > support-data.tar.gz
|
||||
(admin@host) Password: ***********
|
||||
Starting support data collection from host...
|
||||
Collecting to: /var/lib/support
|
||||
This may take up to a minute. Please wait...
|
||||
Tailing /var/log/messages for 30 seconds (please wait)...
|
||||
Log tail complete.
|
||||
@@ -30,7 +24,7 @@ admin@host:~$ ls -l support-data.tar.gz
|
||||
The command can also be run remotely via SSH from your workstation:
|
||||
|
||||
```bash
|
||||
$ ssh admin@host 'sudo support collect' > support-data.tar.gz
|
||||
$ ssh admin@host support collect > support-data.tar.gz
|
||||
...
|
||||
```
|
||||
|
||||
@@ -44,9 +38,8 @@ For secure transmission of support data, the archive can be encrypted
|
||||
with GPG using a password:
|
||||
|
||||
```bash
|
||||
admin@host:~$ sudo support collect -p mypassword > support-data.tar.gz.gpg
|
||||
admin@host:~$ support collect -p mypassword > support-data.tar.gz.gpg
|
||||
Starting support data collection from host...
|
||||
Collecting to: /var/lib/support
|
||||
This may take up to a minute. Please wait...
|
||||
...
|
||||
Collection complete. Creating archive...
|
||||
@@ -59,8 +52,8 @@ but the local ssh client may then echo the password.
|
||||
|
||||
> [!TIP]
|
||||
> To hide the encryption password for an SSH session, the script supports
|
||||
> reading from stdin:
|
||||
> `echo "$MYSECRET" | ssh user@device 'sudo support collect -p' >
|
||||
> reading from stdin:
|
||||
> `echo "$MYSECRET" | ssh user@device support collect -p >
|
||||
> file.tar.gz.gpg`
|
||||
|
||||
After transferring the resulting file to your workstation, decrypt it
|
||||
|
||||
+93
-78
@@ -21,19 +21,20 @@ an example.
|
||||
|
||||
For a list of available log facilities, see the table in a later section.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit syslog actions log-file file:/media/log/mylog</b>
|
||||
admin@example:/config/syslog/…/file:/media/log/mylog/> <b>set facility-list</b>
|
||||
```
|
||||
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/> <b>set facility-list all severity</b>
|
||||
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/> <b>set facility-list all severity critical</b>
|
||||
admin@example:/config/syslog/…/file:/media/log/mylog/> <b>set facility-list mail severity warning</b>
|
||||
admin@example:/config/syslog/…/file:/media/log/mylog/> <b>leave</b>
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The `log-file` syntax requires the leading prefix `file:`. If the
|
||||
@@ -49,10 +50,11 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/syslog/> <b>do show log</b>
|
||||
```
|
||||
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/> <b>do show log log.1.gz</b>
|
||||
</code></pre>
|
||||
admin@example:/config/syslog/> do show log log.1.gz
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Use the Tab key on your keyboard list available log files. The `do`
|
||||
@@ -66,48 +68,51 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit syslog file-rotation</b>
|
||||
admin@example:/config/syslog/file-rotation/> <b>show</b>
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit syslog file-rotation
|
||||
admin@example:/config/syslog/file-rotation/> show
|
||||
admin@example:/config/syslog/file-rotation/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
The defaults are not shown. We can inspect them by asking the YANG
|
||||
model for the help texts:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/syslog/file-rotation/> <b>help</b>
|
||||
```
|
||||
admin@example:/config/syslog/file-rotation/> help
|
||||
max-file-size number-of-files
|
||||
admin@example:/config/syslog/file-rotation/> <b>help max-file-size</b>
|
||||
<b>NAME</b>
|
||||
admin@example:/config/syslog/file-rotation/> help max-file-size
|
||||
NAME
|
||||
max-file-size kilobytes
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
DESCRIPTION
|
||||
Maximum log file size (kiB), before rotation.
|
||||
|
||||
<b>DEFAULT</b>
|
||||
DEFAULT
|
||||
1024
|
||||
admin@example:/config/syslog/file-rotation/> <b>help number-of-files</b>
|
||||
<b>NAME</b>
|
||||
admin@example:/config/syslog/file-rotation/> help number-of-files
|
||||
NAME
|
||||
number-of-files [0..4294967295]
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
DESCRIPTION
|
||||
Maximum number of log files retained.
|
||||
|
||||
<b>DEFAULT</b>
|
||||
DEFAULT
|
||||
10
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
To change the defaults to something smaller, 512 kiB and 20 (remember
|
||||
everything after .0 is compressed, and text compresses well):
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/syslog/file-rotation/> <b>set max-file-size 512</b>
|
||||
admin@example:/config/syslog/file-rotation/> <b>set number-of-files 20</b>
|
||||
admin@example:/config/syslog/file-rotation/> <b>show</b>
|
||||
```
|
||||
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/> <b>leave</b>
|
||||
admin@example:/config/syslog/file-rotation/> leave
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
## Log Format
|
||||
|
||||
@@ -130,13 +135,14 @@ perform time stamping at the time of arrival.
|
||||
|
||||
Configuring the log format is the same for log files and remotes:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit syslog actions log-file file:foobar</b>
|
||||
admin@example:/config/syslog/…/file:foobar/> <b>set log-format</b>
|
||||
```
|
||||
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/> <b>set log-format rfc5424</b>
|
||||
admin@example:/config/syslog/…/file:foobar/> <b>leave</b>
|
||||
admin@example:/config/syslog/…/file:foobar/> set log-format rfc5424
|
||||
admin@example:/config/syslog/…/file:foobar/> leave
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
## Log to Remote Server
|
||||
|
||||
@@ -152,18 +158,19 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit syslog</b>
|
||||
```
|
||||
admin@example:/config/> edit syslog
|
||||
actions file-rotation server
|
||||
admin@example:/config/> <b>edit syslog actions destination moon</b>
|
||||
admin@example:/config/syslog/…/moon/> <b>set</b>
|
||||
admin@example:/config/> edit syslog actions destination moon
|
||||
admin@example:/config/syslog/…/moon/> set
|
||||
facility-list log-format udp
|
||||
admin@example:/config/syslog/…/moon/> <b>set udp</b>
|
||||
admin@example:/config/syslog/…/moon/> set udp
|
||||
address port
|
||||
admin@example:/config/syslog/…/moon/> <b>set udp address 192.168.0.12</b>
|
||||
admin@example:/config/syslog/…/moon/> <b>set facility-list container severity all</b>
|
||||
admin@example:/config/syslog/…/moon/> <b>leave</b>
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> The alternatives shown below each prompt in the example above can be
|
||||
@@ -174,13 +181,14 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit syslog server</b>
|
||||
admin@example:/config/syslog/server/> <b>set enabled true</b>
|
||||
admin@example:/config/syslog/server/> <b>set listen udp 514 address 10.0.0.1</b>
|
||||
admin@example:/config/syslog/server/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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
|
||||
@@ -200,12 +208,13 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit syslog actions log-file file:errors</b>
|
||||
admin@example:/config/syslog/…/file:errors/> <b>set pattern-match "ERROR|CRITICAL|FATAL"</b>
|
||||
admin@example:/config/syslog/…/file:errors/> <b>set facility-list all severity info</b>
|
||||
admin@example:/config/syslog/…/file:errors/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
This will log all messages containing ERROR, CRITICAL, or FATAL.
|
||||
|
||||
@@ -215,20 +224,22 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit syslog actions log-file file:daemon-errors</b>
|
||||
admin@example:/config/syslog/…/file:daemon-errors/> <b>set facility-list daemon</b>
|
||||
admin@example:/config/syslog/…/daemon/> <b>set severity error</b>
|
||||
admin@example:/config/syslog/…/daemon/> <b>set advanced-compare compare equals</b>
|
||||
admin@example:/config/syslog/…/daemon/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
This will log only `error` severity messages, not higher severities.
|
||||
|
||||
You can also block specific severities:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/syslog/…/daemon/> <b>set advanced-compare action block</b>
|
||||
</code></pre>
|
||||
```
|
||||
admin@example:/config/syslog/…/daemon/> set advanced-compare action block
|
||||
```
|
||||
|
||||
This will exclude `error` messages from the log.
|
||||
|
||||
@@ -237,12 +248,13 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit syslog actions log-file file:router1</b>
|
||||
admin@example:/config/syslog/…/file:router1/> <b>set hostname-filter router1</b>
|
||||
admin@example:/config/syslog/…/file:router1/> <b>set facility-list all severity info</b>
|
||||
admin@example:/config/syslog/…/file:router1/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
Multiple hostnames can be added to the filter list.
|
||||
|
||||
@@ -251,14 +263,15 @@ Multiple hostnames can be added to the filter list.
|
||||
For more advanced filtering, you can match on specific message properties
|
||||
using various comparison operators:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit syslog actions log-file file:myapp</b>
|
||||
admin@example:/config/syslog/…/file:myapp/> <b>edit property-filter</b>
|
||||
admin@example:/config/syslog/…/property-filter/> <b>set property programname</b>
|
||||
admin@example:/config/syslog/…/property-filter/> <b>set operator isequal</b>
|
||||
admin@example:/config/syslog/…/property-filter/> <b>set value myapp</b>
|
||||
admin@example:/config/syslog/…/property-filter/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
Available properties:
|
||||
- `msg`: Message body
|
||||
@@ -277,13 +290,15 @@ Available operators:
|
||||
|
||||
The comparison can be made case-insensitive:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/syslog/…/property-filter/> <b>set case-insensitive true</b>
|
||||
</code></pre>
|
||||
```
|
||||
admin@example:/config/syslog/…/property-filter/> set case-insensitive true
|
||||
```
|
||||
|
||||
Or negated to exclude matching messages:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/syslog/…/property-filter/> <b>set negate true</b>
|
||||
</code></pre>
|
||||
```
|
||||
admin@example:/config/syslog/…/property-filter/> set negate true
|
||||
```
|
||||
|
||||
### Facilities
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# System Tuning Guide
|
||||
|
||||
## Memory
|
||||
|
||||
Default memory tuning is defined in `/etc/sysctl.d/vm.conf`, optimized for embedded network devices with 512MB-4GB RAM.
|
||||
|
||||
### For Systems with 4GB+ Memory
|
||||
|
||||
Systems with more memory can afford to be less aggressive with cache reclaim.
|
||||
|
||||
```conf
|
||||
# Allow more dirty pages before writeback
|
||||
vm.dirty_ratio=15
|
||||
vm.dirty_background_ratio=10
|
||||
|
||||
# Less aggressive watermark (memory pressure less critical)
|
||||
vm.watermark_scale_factor=100
|
||||
```
|
||||
|
||||
### For Systems with Heavy Filesystem Activity
|
||||
|
||||
Unusual for network equipment, but may occur on systems with extensive logging or storage features.
|
||||
|
||||
```conf
|
||||
# Allow more dirty pages for better write batching
|
||||
vm.dirty_ratio=20
|
||||
vm.dirty_background_ratio=10
|
||||
|
||||
# Longer dirty page expiration for write coalescing
|
||||
vm.dirty_expire_centisecs=3000
|
||||
```
|
||||
|
||||
+124
-337
@@ -6,7 +6,7 @@ like Message of the Day (login message) and user login shell. More
|
||||
on this later on in this document.
|
||||
|
||||
For the sake of brevity, the hostname in the following examples has been
|
||||
shortened to `example`. The default hostname is composed from a product
|
||||
shortened to `host`. The default hostname is composed from a product
|
||||
specific string followed by the last three octets of the system base MAC
|
||||
address, e.g., `switch-12-34-56`. An example of how to change the
|
||||
hostname is included below.
|
||||
@@ -22,12 +22,13 @@ hostname is included below.
|
||||
User management, including passwords, SSH keys, remote authentication is
|
||||
available in the system authentication configuration context.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit system authentication user admin</b>
|
||||
admin@example:/config/system/…/user/admin/> <b>change password</b>
|
||||
```
|
||||
admin@host:/config/> edit system authentication user admin
|
||||
admin@host:/config/system/authentication/user/admin/> change password
|
||||
New password:
|
||||
Retype password:
|
||||
admin@example:/config/system/…/user/admin/> <b>leave</b>
|
||||
</code></pre>
|
||||
admin@host:/config/system/authentication/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
|
||||
@@ -55,331 +56,116 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit system authentication user admin</b>
|
||||
admin@example:/config/system/…/user/admin/> <b>edit authorized-key admin@example</b>
|
||||
admin@example:/config/system/…/example@host/> <b>set algorithm ssh-rsa</b>
|
||||
admin@example:/config/system/…/example@host/> <b>set key-data AAAAB3NzaC1yc2EAAAADAQABAAABgQC8iBL42yeMBioFay7lty1C4ZDTHcHyo739gc91rTTH8SKvAE4g8Rr97KOz/8PFtOObBrE9G21K7d6UBuPqmd0RUF2CkXXN/eN2PBSHJ50YprRFt/z/304bsBYkDdflKlPDjuSmZ/+OMp4pTsq0R0eNFlX9wcwxEzooIb7VPEdvWE7AYoBRUdf41u3KBHuvjGd1M6QYJtbFLQMMTiVe5IUfyVSZ1RCxEyAB9fR9CBhtVheTVsY3iG0fZc9eCEo89ErDgtGUTJK4Hxt5yCNwI88YaVmkE85cNtw8YwubWQL3/tGZHfbbQ0fynfB4kWNloyRHFr7E1kDxuX5+pbv26EqRdcOVGucNn7hnGU6C1+ejLWdBD7vgsoilFrEaBWF41elJEPKDzpszEijQ9gTrrWeYOQ+x++lvmOdssDu4KvGmj2K/MQTL2jJYrMJ7GDzsUu3XikChRL7zNfS2jYYQLzovboUCgqfPUsVba9hqeX3U67GsJo+hy5MG9RSry4+ucHs=</b>
|
||||
admin@example:/config/system/…/example@host/> <b>show</b>
|
||||
```
|
||||
admin@host:/config/> edit system authentication user admin
|
||||
admin@host:/config/system/authentication/user/admin/> edit authorized-key example@host
|
||||
admin@host:/config/system/authentication/user/admin/authorized-key/example@host/> set algorithm ssh-rsa
|
||||
admin@host:/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@host:/config/system/authentication/user/admin/authorized-key/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/…/example@host/> <b>leave</b>
|
||||
</code></pre>
|
||||
admin@host:/config/system/authentication/user/admin/authorized-key/example@host/> leave
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> The `ssh-keygen` program already base64 encodes the public key data,
|
||||
> so there is no need to use the `text-editor` command, `set` does the
|
||||
> job.
|
||||
|
||||
|
||||
## Multiple Users
|
||||
|
||||
The factory configuration provides three hierarchical user group levels by
|
||||
default: **guest ⊂ operator ⊂ admin**. These levels work out-of-the-box
|
||||
with sensible permissions - operators can configure the system immediately,
|
||||
while sensitive items (passwords, cryptographic keys) remain protected.
|
||||
The system supports multiple users and multiple user levels, or groups,
|
||||
that a user can be a member of. Access control is entirely handled by
|
||||
the NETCONF ["NACM"][3] YANG model, which provides granular access to
|
||||
configuration, data, and RPC commands over NETCONF.
|
||||
|
||||
The default levels provide different access to system resources and
|
||||
configuration:
|
||||
|
||||
- **Admin**: Full system access - can manage users, upgrade software,
|
||||
restart the system, and modify all configuration including network
|
||||
settings, routing, and firewall rules.
|
||||
|
||||
- **Operator**: Configuration access - can modify most system settings
|
||||
including network interfaces, routing, firewall, hostname, and more.
|
||||
*Cannot access* password hashes, cryptographic keys, or perform
|
||||
sensitive operations (factory reset, software upgrade).
|
||||
|
||||
- **Guest**: Read-only access - can view operational state and
|
||||
configuration but cannot modify anything or execute operations.
|
||||
|
||||
System access control is handled by the [ietf-netconf-acm][3] YANG model,
|
||||
usually referred to as [NACM](nacm.md), which provides granular access to
|
||||
configuration, data, and RPC commands. The hierarchical levels in the system
|
||||
are determined by:
|
||||
|
||||
1. **NACM permissions** - what the user can access
|
||||
2. **Shell setting** - which command-line interface the user can use
|
||||
|
||||
By default the system ships with a single user, `admin`, in the `admin`
|
||||
group. There are no restrictions on the number of users with admin
|
||||
privileges, nor is the `admin` user reserved or protected -- it can be
|
||||
removed from the configuration. However, it is strongly recommended to
|
||||
keep at least one user with administrator privileges, otherwise the only
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show nacm</b>
|
||||
enabled : yes
|
||||
default read access : permit
|
||||
default write access : permit
|
||||
default exec access : permit
|
||||
denied operations : 0
|
||||
denied data writes : 0
|
||||
denied notifications : 0
|
||||
|
||||
┌──────────┬─────────┬─────────┬─────────┐
|
||||
│ GROUP │ READ │ WRITE │ EXEC │
|
||||
├──────────┼─────────┼─────────┼─────────┤
|
||||
│ admin │ ✓ │ ✓ │ ✓ │
|
||||
│ operator │ ⚠ │ ⚠ │ ⚠ │
|
||||
│ guest │ ⚠ │ ✗ │ ✗ │
|
||||
└──────────┴─────────┴─────────┴─────────┘
|
||||
✓ Full ⚠ Restricted ✗ Denied
|
||||
|
||||
<span class="header">USER SHELL LOGIN </span>
|
||||
admin bash password+key
|
||||
jacky clish password
|
||||
monitor false key
|
||||
|
||||
<span class="header">GROUP USERS </span>
|
||||
admin admin
|
||||
operator jacky
|
||||
guest monitor
|
||||
</code></pre>
|
||||
|
||||
The permissions matrix shows effective access for each NACM group:
|
||||
|
||||
- **✓ Full** (green) - unrestricted access
|
||||
- **⚠ Restricted** (yellow) - access with exceptions, use `show nacm group`
|
||||
for details
|
||||
- **✗ Denied** (red) - no access
|
||||
|
||||
For detailed information about a specific group's rules:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show nacm group operator</b>
|
||||
members : jacky
|
||||
read permission : restricted
|
||||
write permission : restricted
|
||||
exec permission : restricted
|
||||
applicable rules : 4
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">permit-system-rpcs</span>
|
||||
action : permit
|
||||
operations : exec
|
||||
target : ietf-system (rpc: *)
|
||||
comment : Operators can reboot, shutdown, and set system time.
|
||||
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">deny-password-access (via '*')</span>
|
||||
action : deny
|
||||
operations : *
|
||||
target : /ietf-system:system/authentication/user/password
|
||||
comment : No user except admins can access password hashes.
|
||||
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">deny-keystore-access (via '*')</span>
|
||||
action : deny
|
||||
operations : *
|
||||
target : ietf-keystore
|
||||
comment : No user except admins can access cryptographic keys.
|
||||
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">deny-truststore-access (via '*')</span>
|
||||
action : deny
|
||||
operations : *
|
||||
target : ietf-truststore
|
||||
comment : No user except admins can access trust store.
|
||||
</code></pre>
|
||||
|
||||
For user details:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show nacm user jacky</b>
|
||||
shell : clish
|
||||
login : password
|
||||
nacm group : operator
|
||||
read permission : restricted
|
||||
write permission : restricted
|
||||
exec permission : restricted
|
||||
|
||||
For detailed rules, use: show nacm group <name>
|
||||
</code></pre>
|
||||
By default the system ships with a single group, `admin`, which the
|
||||
default user `admin` is a member of. The broad permissions granted by
|
||||
the `admin` group is what gives its users full system administrator
|
||||
privileges. There are no restrictions on the number of users with
|
||||
administrator privileges, nor is the `admin` user reserved or protected
|
||||
in any way -- it is completely possible to remove the default `admin`
|
||||
user from the configuration. However, it is recommended to keep at
|
||||
least one user with administrator privileges in the system, otherwise
|
||||
the only way to regain full access is to perform a *factory reset*.
|
||||
|
||||
### Adding a User
|
||||
|
||||
Creating a new user starts with defining the user account in the system:
|
||||
Similar to how to change password, adding a new user is done using the
|
||||
same set of commands:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit system authentication user jacky</b>
|
||||
admin@example:/config/system/…/user/jacky/> <b>change password</b>
|
||||
```
|
||||
admin@host:/config/> edit system authentication user jacky
|
||||
admin@host:/config/system/authentication/user/jacky/> change password
|
||||
New password:
|
||||
Retype password:
|
||||
admin@example:/config/system/…/user/jacky/> <b>leave</b>
|
||||
</code></pre>
|
||||
admin@host:/config/system/authentication/user/jacky/> leave
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> It is also possible to use <kbd>set password ...</kbd> 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 <kbd>do
|
||||
> password encrypt [OPTS]</kbd>. The `do` prefix is handy for reaching
|
||||
> all top-level commands when in configure context.
|
||||
An authorized SSH key is added the same way as presented previously.
|
||||
|
||||
An authorized SSH key can be added the same way as described in the
|
||||
previous sections.
|
||||
### Adding a User to the Admin Group
|
||||
|
||||
By default, shell access is disabled (`shell false`). To allow CLI/SSH
|
||||
access, set the shell:
|
||||
The following commands add user `jacky` to the `admin` group.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit system authentication user jacky</b>
|
||||
admin@example:/config/system/…/user/jacky/> <b>set shell clish</b>
|
||||
admin@example:/config/system/…/user/jacky/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
Available shells:
|
||||
|
||||
- `bash` - Full Bourne-again shell (recommended for admins only)
|
||||
- `sh` - POSIX shell (recommended for admins only)
|
||||
- `clish` - Limited CLI-only shell (recommended for operators and guests)
|
||||
- `false` - No shell access (default)
|
||||
|
||||
> [!WARNING] Security Notice
|
||||
> For security reasons, it is strongly recommended to limit non-admin users
|
||||
> to the `clish` shell, which provides CLI access without exposing the
|
||||
> underlying UNIX system. Reserve `bash` and `sh` for administrators who
|
||||
> need full system access for debugging and maintenance.
|
||||
>
|
||||
> Note that shell and CLI access is not always necessary - the system
|
||||
> supports NETCONF and RESTCONF for remote management and automation.
|
||||
> Setting `shell false` for users who only need programmatic access
|
||||
> minimizes the attack surface and improves overall system security.
|
||||
|
||||
### Adding a User to a Group
|
||||
|
||||
To assign a user to a specific privilege level, add them to the
|
||||
corresponding NACM group:
|
||||
|
||||
**Operator user:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit nacm group operator</b>
|
||||
admin@example:/config/nacm/group/operator/> <b>set user-name jacky</b>
|
||||
admin@example:/config/nacm/group/operator/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
**Adding another admin:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit nacm group admin</b>
|
||||
admin@example:/config/nacm/group/admin/> <b>set user-name alice</b>
|
||||
admin@example:/config/nacm/group/admin/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
**Guest user:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit nacm group guest</b>
|
||||
admin@example:/config/nacm/group/guest/> <b>set user-name monitor</b>
|
||||
admin@example:/config/nacm/group/guest/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
> [!TIP]
|
||||
> For technical details about NACM rule evaluation, module-name vs path
|
||||
> matching, and creating custom access control policies, see the
|
||||
> [NACM Technical Guide](nacm.md).
|
||||
|
||||
### Access Control Matrix
|
||||
|
||||
The following table shows what each user level can do based on the NACM rules
|
||||
and shell access configured for each user:
|
||||
|
||||
- **Admin**: `bash` — full system access
|
||||
- **Operator**: `clish` — CLI-only access without UNIX system exposure
|
||||
- **Guest**: `false` — no shell access
|
||||
|
||||
| Feature | Admin | Operator | Guest |
|
||||
|------------------------|-------|----------|-----------|
|
||||
| Network interfaces | ✓ | ✓ | Read only |
|
||||
| Routing (FRR) | ✓ | ✓ | Read only |
|
||||
| Firewall rules | ✓ | ✓ | Read only |
|
||||
| VLANs/bridges | ✓ | ✓ | Read only |
|
||||
| Containers | ✓ | ✓ | Read only |
|
||||
| Hostname/system config | ✓ | ✓ | Read only |
|
||||
| CLI/SSH access | ✓ | ✓ | ✗ |
|
||||
| System restart | ✓ | ✓ | ✗ |
|
||||
| Set date/time | ✓ | ✓ | ✗ |
|
||||
| System reboot | ✓ | ✓ | ✗ |
|
||||
| System shutdown | ✓ | ✓ | ✗ |
|
||||
| User management | ✓ | ✗ | Read only |
|
||||
| Keystore (certs/keys) | ✓ | ✗ | ✗ |
|
||||
| Truststore | ✓ | ✗ | ✗ |
|
||||
| Read passwords/secrets | ✓ | ✗ | ✗ |
|
||||
| NACM rules | ✓ | ✗ | ✗ |
|
||||
| Factory reset | ✓ | ✗ | ✗ |
|
||||
| Software upgrade | ✓ | ✗ | ✗ |
|
||||
```
|
||||
admin@host:/config/> edit nacm group admin
|
||||
admin@host:/config/nacm/group/admin/> set user-name jacky
|
||||
admin@host:/config/nacm/group/admin/> leave
|
||||
```
|
||||
|
||||
### Security Aspects
|
||||
|
||||
The three default user levels are implemented through a combination of NACM
|
||||
rules and UNIX group membership. Access control is permission-based, not
|
||||
name-based - the system detects user levels by examining their NACM
|
||||
permissions and shell settings.
|
||||
|
||||
**Admin users** have unrestricted NACM access with the following rule:
|
||||
The NACM user levels apply primarily to NETCONF, with exception of the
|
||||
`admin` group which is granted full system administrator privileges to
|
||||
the underlying UNIX system with the following ACL rules:
|
||||
|
||||
```json
|
||||
...
|
||||
"module-name": "*",
|
||||
"access-operations": "*",
|
||||
"action": "permit"
|
||||
"action": "permit",
|
||||
...
|
||||
```
|
||||
|
||||
Admin users are automatically added to the UNIX `wheel` and `frrvty`
|
||||
groups, granting them `sudo` privileges and access to FRR routing
|
||||
protocols. This makes it possible to use all the underlying UNIX
|
||||
tooling, which can be very useful for debugging, but please use with
|
||||
care -- the system is designed to be managed through the CLI and
|
||||
NETCONF, not directly via shell commands.
|
||||
A user in the `admin` group is allowed to also use a POSIX login shell
|
||||
and use the `sudo` command to perform system administrative commands.
|
||||
This makes it possible to use all the underlying UNIX tooling, which
|
||||
to many can be very useful, in particular when debugging a system, but
|
||||
please remember to use with care -- the system is not built to require
|
||||
managing from the shell. The tools available in the CLI and automated
|
||||
services, started from the system's configuration, are the recommended
|
||||
way of using the system, in addition to NETCONF tooling.
|
||||
|
||||
**Operator users** use the permit-by-default NACM model (`write-default:
|
||||
"permit"`), which means they can configure most system settings without
|
||||
explicit permit rules. This design is "future proof" - when new features
|
||||
are added, operators can immediately use them.
|
||||
|
||||
The following are explicitly denied to operators through global NACM rules:
|
||||
|
||||
- Password hashes (`/ietf-system:system/authentication/user/password`)
|
||||
- Cryptographic keys (`ietf-keystore` module)
|
||||
- Trust store certificates (`ietf-truststore` module)
|
||||
|
||||
Additionally, sensitive operations like factory reset, software upgrades,
|
||||
and system shutdown are protected by YANG-level `nacm:default-deny-all`
|
||||
annotations and remain restricted to administrators.
|
||||
|
||||
Operators are automatically added to the UNIX `operator` and `frrvty`
|
||||
groups, granting them `sudo` privileges for network operations and FRR
|
||||
access.
|
||||
|
||||
**Guest users** have read-only NACM access through an explicit deny rule
|
||||
that blocks all write and exec operations (`create update delete exec`),
|
||||
while `read-default: "permit"` allows viewing configuration and state.
|
||||
Guests receive no special UNIX group memberships. The shell setting
|
||||
determines whether guests can access the CLI (`clish`) or are restricted
|
||||
from shell access entirely (`false`).
|
||||
|
||||
All users, regardless of level, are denied access to password hashes and
|
||||
cryptographic key material through global NACM rules.
|
||||
|
||||
## Changing Hostname
|
||||
|
||||
Notice how the hostname in the prompt does not change until the change
|
||||
is committed by issuing the `leave` command.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit system</b>
|
||||
admin@example:/config/system/> <b>set hostname myrouter</b>
|
||||
admin@example:/config/system/> <b>leave</b>
|
||||
admin@myrouter:/>
|
||||
</code></pre>
|
||||
```
|
||||
admin@host:/config/> edit system
|
||||
admin@host:/config/system/> set hostname example
|
||||
admin@host:/config/system/> leave
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
The hostname is advertised over mDNS-SD in the `.local` domain. If
|
||||
another device already has claimed the `myrouter.local` CNAME, in our
|
||||
another device already has claimed the `example.local` CNAME, in our
|
||||
case, mDNS will advertise a "uniqified" variant, usually suffixing with
|
||||
an index, e.g., `myrouter-1.local`. Use an mDNS browser to scan for
|
||||
an index, e.g., `example-1.local`. Use an mDNS browser to scan for
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit system</b>
|
||||
admin@example:/config/system/> <b>set hostname foo.example.com</b>
|
||||
admin@example:/config/system/> <b>leave</b>
|
||||
```
|
||||
admin@host:/config/> edit system
|
||||
admin@host:/config/system/> set hostname foo.example.com
|
||||
admin@host:/config/system/> leave
|
||||
admin@foo:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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
|
||||
@@ -401,11 +187,12 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit system</b>
|
||||
admin@example:/config/system/> <b>text-editor motd-banner</b>
|
||||
admin@example:/config/system/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
admin@host:/config/> edit system
|
||||
admin@host:/config/system/> text-editor motd-banner
|
||||
admin@host:/config/system/> leave
|
||||
admin@host:/>
|
||||
```
|
||||
|
||||
Log out and log back in again to inspect the changes.
|
||||
|
||||
@@ -421,12 +208,13 @@ as the `text-editor` command:
|
||||
|
||||
To change the editor to GNU Nano:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit system</b>
|
||||
admin@example:/config/system/> <b>set text-editor nano</b>
|
||||
admin@example:/config/system/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
admin@host:/> configure
|
||||
admin@host:/config/> edit system
|
||||
admin@host:/config/system/> set text-editor nano
|
||||
admin@host:/config/system/> leave
|
||||
admin@host:/>
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Configuration changes only take effect after issuing the `leave`
|
||||
@@ -440,17 +228,18 @@ The system supports both static and dynamic (DHCP) DNS setup. The
|
||||
locally configured (static) server is preferred over any acquired
|
||||
from a DHCP client.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit system dns-resolver</b>
|
||||
admin@example:/config/system/dns-resolver/> <b>set server google udp-and-tcp address 8.8.8.8</b>
|
||||
admin@example:/config/system/dns-resolver/> <b>show</b>
|
||||
```
|
||||
admin@host:/> configure
|
||||
admin@host:/config/> edit system dns-resolver
|
||||
admin@host:/config/system/dns-resolver/> set server google udp-and-tcp address 8.8.8.8
|
||||
admin@host:/config/system/dns-resolver/> show
|
||||
server google {
|
||||
udp-and-tcp {
|
||||
address 8.8.8.8;
|
||||
}
|
||||
}
|
||||
admin@example:/config/system/dns-resolver/> <b>leave</b>
|
||||
</code></pre>
|
||||
admin@host:/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
|
||||
@@ -467,15 +256,16 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit system ntp</b>
|
||||
admin@example:/config/system/ntp/> <b>set enabled</b>
|
||||
admin@example:/config/system/ntp/> <b>set server ntp-pool</b>
|
||||
admin@example:/config/system/ntp/> <b>set server ntp-pool udp address pool.ntp.org</b>
|
||||
admin@example:/config/system/ntp/> <b>set server ntp-pool iburst</b>
|
||||
admin@example:/config/system/ntp/> <b>set server ntp-pool prefer</b>
|
||||
admin@example:/config/system/ntp/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
admin@host:/> configure
|
||||
admin@host:/config/> edit system ntp
|
||||
admin@host:/config/system/ntp/> set enabled
|
||||
admin@host:/config/system/ntp/> set server ntp-pool
|
||||
admin@host:/config/system/ntp/> set server ntp-pool udp address pool.ntp.org
|
||||
admin@host:/config/system/ntp/> set server ntp-pool iburst
|
||||
admin@host:/config/system/ntp/> set server ntp-pool prefer
|
||||
admin@host:/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`
|
||||
@@ -495,38 +285,36 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ntp</b>
|
||||
Mode : Client
|
||||
Stratum : 3
|
||||
Ref time (UTC) : Sat Jan 24 23:41:42 2026
|
||||
|
||||
<span class="header">ADDRESS MODE STATE STRATUM POLL</span>
|
||||
147.78.228.41 server outlier 2 64s
|
||||
192.168.0.1 server unusable 0 128s
|
||||
176.126.86.247 server selected 2 64s
|
||||
</code></pre>
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
### Show NTP Status
|
||||
|
||||
To check the status of NTP synchronization (only availble in CLI), use
|
||||
the following command:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show ntp tracking</b>
|
||||
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
|
||||
</code></pre>
|
||||
```
|
||||
admin@host:/> 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@host:/>
|
||||
```
|
||||
|
||||
This output provides detailed information about the NTP status, including
|
||||
reference ID, stratum, time offsets, frequency, and root delay.
|
||||
@@ -539,4 +327,3 @@ 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
|
||||
|
||||
+70
-61
@@ -28,13 +28,14 @@ IPv6 tunnels in two modes:
|
||||
|
||||
A basic GRE tunnel for routing between two sites:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface gre0</b>
|
||||
admin@example:/config/interface/gre0/> <b>set gre local 192.168.3.1 remote 192.168.3.2</b>
|
||||
admin@example:/config/interface/gre0/> <b>set ipv4 address 10.255.0.1 prefix-length 30</b>
|
||||
admin@example:/config/interface/gre0/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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
|
||||
@@ -44,16 +45,17 @@ the inner IP addressing.
|
||||
|
||||
GRETAP tunnels operate at Layer 2, allowing bridging across the tunnel:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface gretap0</b>
|
||||
admin@example:/config/interface/gretap0/> <b>set type gretap</b>
|
||||
admin@example:/config/interface/gretap0/> <b>set gre local 192.168.3.1 remote 192.168.3.2</b>
|
||||
admin@example:/config/interface/gretap0/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
GRETAP interfaces can be added to a bridge, bridging local and remote Ethernet
|
||||
segments. See the [Bridge Configuration](bridging.md)
|
||||
segments. See the [Bridge Configuration](networking.md#bridging)
|
||||
for more on bridges.
|
||||
|
||||
### OSPF over GRE
|
||||
@@ -67,35 +69,37 @@ exchange routes.
|
||||
|
||||
**Site A configuration:**
|
||||
|
||||
<pre class="cli"><code>admin@siteA:/> <b>configure</b>
|
||||
admin@siteA:/config/> <b>edit interface gre0</b>
|
||||
admin@siteA:/config/interface/gre0/> <b>set gre local 203.0.113.1 remote 203.0.113.2</b>
|
||||
admin@siteA:/config/interface/gre0/> <b>set ipv4 address 10.255.0.1 prefix-length 30</b>
|
||||
admin@siteA:/config/interface/gre0/> <b>set ipv4 forwarding</b>
|
||||
admin@siteA:/config/interface/gre0/> <b>end</b>
|
||||
admin@siteA:/config/> <b>edit routing control-plane-protocol ospfv2 name default ospf</b>
|
||||
admin@siteA:/config/routing/…/ospf/> <b>set area 0.0.0.0 interface gre0</b>
|
||||
admin@siteA:/config/routing/…/ospf/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
**Site B configuration:**
|
||||
|
||||
<pre class="cli"><code>admin@siteB:/> <b>configure</b>
|
||||
admin@siteB:/config/> <b>edit interface gre0</b>
|
||||
admin@siteB:/config/interface/gre0/> <b>set gre local 203.0.113.2 remote 203.0.113.1</b>
|
||||
admin@siteB:/config/interface/gre0/> <b>set ipv4 address 10.255.0.2 prefix-length 30</b>
|
||||
admin@siteB:/config/interface/gre0/> <b>set ipv4 forwarding</b>
|
||||
admin@siteB:/config/interface/gre0/> <b>end</b>
|
||||
admin@siteB:/config/> <b>edit routing control-plane-protocol ospfv2 name default ospf</b>
|
||||
admin@siteB:/config/routing/…/ospf/> <b>set area 0.0.0.0 interface gre0</b>
|
||||
admin@siteB:/config/routing/…/ospf/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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](routing.md#ospfv2-routing).
|
||||
configuration, see [OSPFv2 Routing](networking.md#ospfv2-routing).
|
||||
|
||||
> [!NOTE]
|
||||
> Consider adjusting MTU on the tunnel interface to account for GRE
|
||||
@@ -114,10 +118,11 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface gre0</b>
|
||||
admin@example:/config/interface/gre0/> <b>set gre ttl 255</b>
|
||||
admin@example:/config/interface/gre0/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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.
|
||||
@@ -131,10 +136,11 @@ from the encapsulated packet.
|
||||
|
||||
The ToS setting controls QoS marking for tunnel traffic:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface gre0</b>
|
||||
admin@example:/config/interface/gre0/> <b>set gre tos 0x10</b>
|
||||
admin@example:/config/interface/gre0/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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.
|
||||
@@ -145,10 +151,11 @@ 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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface gre0</b>
|
||||
admin@example:/config/interface/gre0/> <b>set gre pmtudisc false</b>
|
||||
admin@example:/config/interface/gre0/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
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.
|
||||
@@ -168,14 +175,15 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface vxlan100</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>set vxlan local 192.168.3.1</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>set vxlan remote 192.168.3.2</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>set vxlan vni 100</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
The VNI uniquely identifies the VXLAN segment and must match on both
|
||||
tunnel endpoints.
|
||||
@@ -185,15 +193,16 @@ tunnel endpoints.
|
||||
The default VXLAN UDP destination port is 4789 (IANA assigned). In some
|
||||
cases you may need to use a different port:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface vxlan100</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>set vxlan local 192.168.3.1</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>set vxlan remote 192.168.3.2</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>set vxlan vni 100</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>set vxlan remote-port 8472</b>
|
||||
admin@example:/config/interface/vxlan100/> <b>leave</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
The remote-port setting allows interoperability with systems using
|
||||
non-standard VXLAN ports.
|
||||
|
||||
+102
-80
@@ -8,14 +8,16 @@ 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`).
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show software</b>
|
||||
Boot order : primary secondary net
|
||||
```
|
||||
admin@example:/> show software
|
||||
BOOT ORDER
|
||||
primary secondary net
|
||||
|
||||
<span class="header">NAME STATE VERSION DATE </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
YANG support for upgrading Infix, inspecting and _modifying_ the
|
||||
boot-order, is defined in [infix-system-software][2].
|
||||
@@ -39,47 +41,52 @@ valid values.
|
||||
|
||||
Example: View current boot order and change it:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show boot-order</b>
|
||||
```
|
||||
admin@example:/> show boot-order
|
||||
primary secondary net
|
||||
admin@example:/> <b>set boot-order secondary primary net</b>
|
||||
admin@example:/> <b>show boot-order</b>
|
||||
admin@example:/> set boot-order secondary primary net
|
||||
admin@example:/> show boot-order
|
||||
secondary primary net
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
Example: Set boot order to only try primary partition:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show boot-order</b>
|
||||
```
|
||||
admin@example:/> show boot-order
|
||||
secondary primary net
|
||||
admin@example:/> <b>set boot-order primary</b>
|
||||
admin@example:/> <b>show boot-order</b>
|
||||
admin@example:/> set boot-order primary
|
||||
admin@example:/> show boot-order
|
||||
primary
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
Example: Using tab-completion (press TAB to see available options):
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>set boot-order </b><kbd>TAB</kbd>
|
||||
```
|
||||
admin@example:/> set boot-order <TAB>
|
||||
net primary secondary
|
||||
admin@example:/> <b>set boot-order secondary </b><kbd>TAB</kbd>
|
||||
admin@example:/> set boot-order secondary <TAB>
|
||||
net primary secondary
|
||||
admin@example:/> <b>set boot-order secondary primary</b>
|
||||
admin@example:/> <b>show boot-order</b>
|
||||
admin@example:/> set boot-order secondary primary
|
||||
admin@example:/> show boot-order
|
||||
secondary primary
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
The new boot order takes effect on the next reboot and can be verified
|
||||
with `show boot-order` or `show software`:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show software</b>
|
||||
Boot order : secondary primary
|
||||
```
|
||||
admin@example:/> show software
|
||||
BOOT ORDER
|
||||
secondary primary
|
||||
|
||||
<span class="header">NAME STATE VERSION DATE </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> The boot order is automatically updated when performing an upgrade.
|
||||
@@ -120,28 +127,27 @@ configuration before performing an upgrade. The backup is useful if the
|
||||
upgrade fails, and makes a later [downgrade](#downgrading) a smoother
|
||||
process.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>dir /cfg</b>
|
||||
```
|
||||
admin@example:/> dir /cfg
|
||||
/cfg directory
|
||||
backup/ ssl/ startup-config.cfg
|
||||
|
||||
admin@example:/> <b>copy /cfg/startup-config.cfg /cfg/v25.01.0-startup-config.cfg</b>
|
||||
admin@example:/> <b>dir /cfg</b>
|
||||
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:/>
|
||||
</code></pre>
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
*Upgrade:* Here the image *pkg bundle* was made available via TFTP.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>upgrade tftp://198.18.117.1/infix-aarch64-25.03.1.pkg</b>
|
||||
```
|
||||
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
|
||||
@@ -150,13 +156,14 @@ installing
|
||||
100% Installing done.
|
||||
Installing `tftp://198.18.117.1/infix-aarch64-25.03.1.pkg` succeeded
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
*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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>reboot</b>
|
||||
```
|
||||
admin@example:/> reboot
|
||||
[ OK ] Stopping Static routing daemon
|
||||
[ OK ] Stopping Zebra routing daemon
|
||||
...
|
||||
@@ -166,7 +173,7 @@ of startup configuration if applicable.
|
||||
[ OK ] Starting Status daemon
|
||||
|
||||
Infix OS — Immutable.Friendly.Secure v25.03.1 (ttyS0)
|
||||
example login: <b>admin</b>
|
||||
example login: admin
|
||||
Password:
|
||||
.-------.
|
||||
| . . | Infix OS — Immutable.Friendly.Secure
|
||||
@@ -175,18 +182,19 @@ Password:
|
||||
|
||||
Run the command 'cli' for interactive OAM
|
||||
|
||||
admin@example:~$ <b>cli</b>
|
||||
admin@example:~$ cli
|
||||
|
||||
See the 'help' command for an introduction to the system
|
||||
|
||||
admin@example:/> <b>show software</b>
|
||||
Boot order : secondary primary net
|
||||
admin@example:/> show software
|
||||
BOOT ORDER
|
||||
secondary primary net
|
||||
|
||||
<span class="header">NAME STATE VERSION DATE </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
As shown, the *boot order* has been updated, so that *secondary* is
|
||||
now the preferred boot source.
|
||||
@@ -209,18 +217,20 @@ numbering). The startup configuration is migrated to `1.5`
|
||||
definitions and stored, while a backup previous startup configuration
|
||||
is stored in directory `/cfg/backup/`.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>dir /cfg/backup/</b>
|
||||
```
|
||||
admin@example:/> dir /cfg/backup/
|
||||
/cfg/backup/ directory
|
||||
startup-config-1.4.cfg
|
||||
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
The modifications made to the startup configuration can be viewed by
|
||||
comparing the files from the *shell*. An example is shown below.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>exit</b>
|
||||
admin@example:~$ <b>diff /cfg/backup/startup-config-1.4.cfg /cfg/startup-config.cfg</b>
|
||||
```
|
||||
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
|
||||
...
|
||||
@@ -234,7 +244,7 @@ admin@example:~$ <b>diff /cfg/backup/startup-config-1.4.cfg /cfg/startup-config.
|
||||
+ "version": "1.5"
|
||||
...
|
||||
admin@example:~$
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
## Downgrading
|
||||
|
||||
@@ -249,14 +259,16 @@ 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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show software</b>
|
||||
Boot order : primary secondary net
|
||||
```
|
||||
admin@example:/> show software
|
||||
BOOT ORDER
|
||||
primary secondary net
|
||||
|
||||
<span class="header">NAME STATE VERSION DATE </span>
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
### With Backup `startup-config`
|
||||
|
||||
@@ -280,22 +292,24 @@ 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`:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>dir /cfg</b>
|
||||
```
|
||||
admin@example:/> dir /cfg
|
||||
/cfg directory
|
||||
backup/ ssl/ startup-config.cfg v25.01.0-startup-config.cfg
|
||||
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
The alternative is to use a startup config implicitly backed up by the
|
||||
system as part of [Configuration Migration](#configuration-migration).
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>dir /cfg/backup/</b>
|
||||
```
|
||||
admin@example:/> dir /cfg/backup/
|
||||
/cfg/backup/ directory
|
||||
startup-config-1.4.cfg
|
||||
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
> [!CAUTION]
|
||||
> Using a backup configuration file stored when the unit was running the
|
||||
@@ -316,7 +330,8 @@ config*.
|
||||
|
||||
*Use `upgrade` command to downgrade:*
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>upgrade tftp://198.18.117.1/infix-aarch64-25.01.0.pkg</b>
|
||||
```
|
||||
admin@example:/> upgrade tftp://198.18.117.1/infix-aarch64-25.01.0.pkg
|
||||
installing
|
||||
0% Installing
|
||||
0% Determining slot states
|
||||
@@ -327,32 +342,35 @@ installing
|
||||
100% Installing done.
|
||||
Installing `tftp://198.18.117.1/infix-aarch64-25.01.0.pkg` succeeded
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
*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.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>copy /cfg/v25.01.0-startup-config.cfg /cfg/startup-config.cfg</b>
|
||||
Overwrite existing file /cfg/startup-config.cfg (y/N)? <b>y</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
An alternative is to use a backup file stored when the system
|
||||
conducted a [configuration migration](#configuration-migration). See
|
||||
the *caution* note above.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>copy /cfg/backup/startup-config-1.4.cfg /cfg/startup-config.cfg</b>
|
||||
Overwrite existing file /cfg/startup-config.cfg (y/N)? <b>y</b>
|
||||
```
|
||||
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:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
*Reboot:*
|
||||
|
||||
The unit will come up with the applied backup configuration.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>reboot</b>
|
||||
```
|
||||
admin@example:/> reboot
|
||||
[ OK ] Saving system clock to file
|
||||
[ OK ] Stopping Software update service
|
||||
[ OK ] Stopping Status daemon
|
||||
@@ -366,7 +384,7 @@ The unit will come up with the applied backup configuration.
|
||||
|
||||
Infix OS — Immutable.Friendly.Secure v25.01.0 (ttyS0)
|
||||
example login:
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If the unit despite these measures ends up in *failure config*, see
|
||||
@@ -385,7 +403,8 @@ its default login credentials[^1].
|
||||
|
||||
*Use `upgrade` command to downgrade:*
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>upgrade tftp://198.18.117.1/infix-aarch64-25.01.0.pkg</b>
|
||||
```
|
||||
admin@example:/> upgrade tftp://198.18.117.1/infix-aarch64-25.01.0.pkg
|
||||
installing
|
||||
0% Installing
|
||||
0% Determining slot states
|
||||
@@ -396,7 +415,7 @@ installing
|
||||
100% Installing done.
|
||||
Installing `tftp://198.18.117.1/infix-aarch64-25.01.0.pkg` succeeded
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
*Reboot:*
|
||||
|
||||
@@ -407,7 +426,8 @@ 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*.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>reboot</b>
|
||||
```
|
||||
admin@example:/> reboot
|
||||
[ OK ] Saving system clock to file
|
||||
[ OK ] Stopping Software update service
|
||||
[ OK ] Stopping Status daemon
|
||||
@@ -424,30 +444,32 @@ 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:
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>failed-00-00-00 login: <b>admin</b>
|
||||
```
|
||||
failed-00-00-00 login: admin
|
||||
Password:
|
||||
|
||||
Run the command 'cli' for interactive OAM
|
||||
|
||||
admin@failed-00-00-00:~$
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
<pre class="cli"><code>admin@failed-00-00-00:~$ <b>factory</b>
|
||||
Factory reset device (y/N)? <b>y</b>
|
||||
```
|
||||
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)? <b>y</b>
|
||||
Reboot now to perform reset, (y/N)? y
|
||||
[ OK ] Saving system time (UTC) to RTC
|
||||
[ OK ] Stopping mDNS alias advertiser
|
||||
...
|
||||
@@ -463,7 +485,7 @@ Please press Enter to activate this console.
|
||||
|
||||
Infix OS — Immutable.Friendly.Secure v25.01.0 (ttyS0)
|
||||
example login:
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
Continued configuration is done as with any unit after factory reset.
|
||||
|
||||
|
||||
+4
-4
@@ -18,11 +18,11 @@ QEMU
|
||||
> relevant Qemu packages are pulled in as well. This trick, installing
|
||||
> [virt-manager][virt], helps set up Qemu networking on your system.
|
||||
|
||||
A virtualized Infix x86_64 instance can be launched from a Linux system,
|
||||
with [Qemu][] installed, by issuing:
|
||||
A virtualized Infix x86_64 instance can easily be launched from a Linux
|
||||
system, with [Qemu][] installed, by issuing:
|
||||
|
||||
```
|
||||
$ ./qemu/run.sh
|
||||
$ ./qemu.sh
|
||||
...
|
||||
```
|
||||
|
||||
@@ -35,7 +35,7 @@ $ make run
|
||||
```
|
||||
|
||||
To change settings, e.g. networking, <kbd>make run-menuconfig</kbd>, or
|
||||
from a pre-built Infix release tarball, using <kbd>./qemu/run.sh -c</kbd>
|
||||
from a pre-built Infix release tarball, using <kbd>./qemu.sh -c</kbd>
|
||||
|
||||
The Infix test suite is built around Qemu and [Qeneth][qeth], see:
|
||||
|
||||
|
||||
@@ -1,424 +0,0 @@
|
||||
# WireGuard VPN
|
||||
|
||||
> [!NOTE]
|
||||
> For a general introduction to VPN concepts and deployment models, see
|
||||
> [VPN Configuration](vpn.md).
|
||||
|
||||
WireGuard is a modern, high-performance VPN protocol that uses state-of-the-art
|
||||
cryptography. It is significantly simpler and faster than traditional VPN
|
||||
solutions like IPsec or OpenVPN, while maintaining strong security guarantees.
|
||||
|
||||
Key features of WireGuard:
|
||||
|
||||
- **Simple Configuration:** Minimal settings required compared to IPsec
|
||||
- **High Performance:** Runs in kernel space with efficient cryptography
|
||||
- **Strong Cryptography:** Uses Curve25519, ChaCha20, Poly1305, and BLAKE2
|
||||
- **Roaming Support:** Seamlessly handles endpoint IP address changes
|
||||
- **Dual-Stack:** Supports IPv4 and IPv6 for both tunnel endpoints and traffic
|
||||
|
||||
> [!IMPORTANT]
|
||||
> When issuing `leave` to activate your changes, remember to also save
|
||||
> your settings, `copy running-config startup-config`. See the [CLI
|
||||
> Introduction](cli/introduction.md) for a background.
|
||||
|
||||
## Key Management
|
||||
|
||||
WireGuard uses public-key cryptography similar to SSH. Each WireGuard interface
|
||||
requires a private key, and each peer is identified by its public key.
|
||||
|
||||
**Generate a WireGuard key pair using the `wg` command:**
|
||||
|
||||
```bash
|
||||
admin@example:~$ wg genkey | tee privatekey | wg pubkey > publickey
|
||||
admin@example:~$ cat privatekey
|
||||
aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=
|
||||
admin@example:~$ cat publickey
|
||||
bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=
|
||||
```
|
||||
|
||||
This generates a private key, saves it to `privatekey`, derives the public key,
|
||||
and saves it to `publickey`.
|
||||
|
||||
**Import the private key into the keystore:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit keystore asymmetric-key wg-site-a</b>
|
||||
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set public-key-format x25519-public-key-format</b>
|
||||
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set private-key-format x25519-private-key-format</b>
|
||||
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set public-key bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=</b>
|
||||
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>set private-key aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=</b>
|
||||
admin@example:/config/keystore/asymmetric-key/wg-site-a/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
**Import peer public keys into the truststore:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit truststore public-key-bag wg-peers public-key peer-b</b>
|
||||
admin@example:/config/truststore/…/peer-b/> <b>set public-key-format x25519-public-key-format</b>
|
||||
admin@example:/config/truststore/…/peer-b/> <b>set public-key PEER_PUBLIC_KEY_HERE</b>
|
||||
admin@example:/config/truststore/…/peer-b/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Keep private keys secure! Never share your private key. Only exchange
|
||||
> public keys with peers. Delete the `privatekey` file after importing it
|
||||
> into the keystore.
|
||||
|
||||
## Point-to-Point Configuration
|
||||
|
||||
> [!TIP]
|
||||
> If you name your WireGuard interface `wgN`, where `N` is a number, the
|
||||
> CLI infers the interface type automatically.
|
||||
|
||||
A basic WireGuard tunnel between two sites:
|
||||
|
||||
**Site A configuration:**
|
||||
|
||||
<pre class="cli"><code>admin@siteA:/> <b>configure</b>
|
||||
admin@siteA:/config/> <b>edit interface wg0</b>
|
||||
admin@siteA:/config/interface/wg0/> <b>set wireguard listen-port 51820</b>
|
||||
admin@siteA:/config/interface/wg0/> <b>set wireguard private-key wg-site-a</b>
|
||||
admin@siteA:/config/interface/wg0/> <b>set ipv4 address 10.0.0.1 prefix-length 24</b>
|
||||
admin@siteA:/config/interface/wg0/> <b>edit wireguard peer wg-peers peer-b</b>
|
||||
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> <b>set endpoint 203.0.113.2</b>
|
||||
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> <b>set endpoint-port 51820</b>
|
||||
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> <b>set allowed-ips 10.0.0.2/32</b>
|
||||
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> <b>set persistent-keepalive 25</b>
|
||||
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/> <b>leave</b>
|
||||
admin@siteA:/>
|
||||
</code></pre>
|
||||
|
||||
**Site B configuration:**
|
||||
|
||||
<pre class="cli"><code>admin@siteB:/> <b>configure</b>
|
||||
admin@siteB:/config/> <b>edit interface wg0</b>
|
||||
admin@siteB:/config/interface/wg0/> <b>set wireguard listen-port 51820</b>
|
||||
admin@siteB:/config/interface/wg0/> <b>set wireguard private-key wg-site-b</b>
|
||||
admin@siteB:/config/interface/wg0/> <b>set ipv4 address 10.0.0.2 prefix-length 24</b>
|
||||
admin@siteB:/config/interface/wg0/> <b>edit wireguard peer wg-peers peer-a</b>
|
||||
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> <b>set endpoint 203.0.113.1</b>
|
||||
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> <b>set endpoint-port 51820</b>
|
||||
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> <b>set allowed-ips 10.0.0.1/32</b>
|
||||
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> <b>set persistent-keepalive 25</b>
|
||||
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/> <b>leave</b>
|
||||
admin@siteB:/>
|
||||
</code></pre>
|
||||
|
||||
This creates an encrypted tunnel with Site A at 10.0.0.1 and Site B at 10.0.0.2.
|
||||
|
||||
## Understanding Allowed IPs
|
||||
|
||||
The `allowed-ips` setting in WireGuard serves two critical purposes:
|
||||
|
||||
1. **Ingress Filtering:** Only packets with source IPs in the allowed list
|
||||
are accepted from the peer
|
||||
2. **Cryptokey Routing:** Determines which peer receives outbound packets
|
||||
for a given destination
|
||||
|
||||
Think of `allowed-ips` as a combination of firewall rules and routing table.
|
||||
|
||||

|
||||
*Figure: WireGuard key exchange and allowed-ips configuration between two peers*
|
||||
|
||||
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:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/…/wg-peers/peer/peer-a/> <b>set allowed-ips 10.0.0.2/32</b>
|
||||
admin@example:/config/interface/…/wg-peers/peer/peer-a/> <b>set allowed-ips 192.168.2.0/24</b>
|
||||
</code></pre>
|
||||
|
||||
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.
|
||||
|
||||
> [!NOTE]
|
||||
> When routing traffic to networks behind WireGuard peers, you also need
|
||||
> to configure static routes pointing to the WireGuard interface. See
|
||||
> [Static Routes](routing.md) for more information.
|
||||
|
||||
## Peer Configuration and Key Bags
|
||||
|
||||
WireGuard peer configuration supports a two-level hierarchy that allows
|
||||
efficient management of multiple peers with shared settings.
|
||||
|
||||
**Public Key Bags** group related peers together (e.g., all mobile clients,
|
||||
all branch offices) and allow you to configure default settings that apply
|
||||
to all peers in the bag. Individual peers can then override these defaults
|
||||
when needed.
|
||||
|
||||
Settings that support bag-level defaults and per-peer overrides:
|
||||
|
||||
- `endpoint` - Remote peer's IP address
|
||||
- `endpoint-port` - Remote peer's UDP port (defaults to 51820 at bag level)
|
||||
- `persistent-keepalive` - Keepalive interval in seconds
|
||||
- `preshared-key` - Optional pre-shared key for additional quantum resistance
|
||||
- `allowed-ips` - IP addresses allowed to/from this peer
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Key Bag Configuration Rules:**
|
||||
> - **Single key in bag:** You can use bag-level settings (endpoint, allowed-ips, etc.)
|
||||
> without specifying individual peer configurations. All settings apply to that one peer.
|
||||
> - **Multiple keys in bag:** You MUST provide individual `peer` configuration for
|
||||
> each key in the bag. Settings like `endpoint` and `allowed-ips` must be unique
|
||||
> per peer and cannot be shared at the bag level when multiple peers exist.
|
||||
>
|
||||
> This prevents configuration errors where multiple peers would incorrectly share
|
||||
> the same endpoint address or allowed-ips ranges.
|
||||
|
||||
**Example with bag-level defaults:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface wg0</b>
|
||||
admin@example:/config/interface/wg0/> <b>set wireguard listen-port 51820</b>
|
||||
admin@example:/config/interface/wg0/> <b>set wireguard private-key wg-key</b>
|
||||
admin@example:/config/interface/wg0/> <b>set ipv4 address 10.0.0.1 prefix-length 24</b>
|
||||
|
||||
# Configure defaults for all peers in the 'branch-offices' bag
|
||||
admin@example:/config/interface/wg0/> <b>edit wireguard peers branch-offices</b>
|
||||
admin@example:/config/interface/…/wireguard/peers/branch-offices/> <b>set endpoint-port 51820</b>
|
||||
admin@example:/config/interface/…/wireguard/peers/branch-offices/> <b>set persistent-keepalive 25</b>
|
||||
admin@example:/config/interface/…/wireguard/peers/branch-offices/> <b>end</b>
|
||||
|
||||
# Configure peer-specific settings (inherits endpoint-port and keepalive from bag)
|
||||
admin@example:/config/interface/…/wireguard/peers/branch-offices/> <b>edit peer office-east</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-east/> <b>set endpoint 203.0.113.10</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-east/> <b>set allowed-ips 10.0.0.10/32</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-east/> <b>set allowed-ips 192.168.10.0/24</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-east/> <b>end</b>
|
||||
|
||||
# Another peer with an override for persistent-keepalive
|
||||
admin@example:/config/interface/…/wireguard/peers/branch-offices/> <b>edit peer office-west</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-west/> <b>set endpoint 203.0.113.20</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-west/> <b>set allowed-ips 10.0.0.20/32</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-west/> <b>set allowed-ips 192.168.20.0/24</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-west/> <b>set persistent-keepalive 10</b>
|
||||
admin@example:/config/interface/…/branch-offices/peer/office-west/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
In this example:
|
||||
- Both peers inherit `endpoint-port 51820` and `persistent-keepalive 25` from the bag
|
||||
- `office-west` overrides the keepalive to 10 seconds while `office-east` uses the default 25
|
||||
- Each peer has its own `endpoint` and `allowed-ips` configuration
|
||||
|
||||
This approach simplifies management when you have many peers with similar
|
||||
configurations - set the common defaults once at the bag level, then only
|
||||
specify per-peer differences.
|
||||
|
||||
## Site-to-Site VPN
|
||||
|
||||

|
||||
*Figure: Site-to-Site VPN connecting two office networks*
|
||||
|
||||
A site-to-site VPN connects entire networks across locations, creating a unified
|
||||
private network over the internet. This allows devices in one location to
|
||||
seamlessly access resources in another as if they were on the same local network.
|
||||
|
||||
This is the point-to-point configuration shown earlier, extended with routing
|
||||
to allow access to networks behind each peer. Configure the WireGuard tunnel
|
||||
as shown in [Point-to-Point Configuration](#point-to-point-configuration),
|
||||
then add the remote network to `allowed-ips` and configure static routes.
|
||||
|
||||
## Road Warrior VPN
|
||||
|
||||

|
||||
*Figure: Mobile clients connecting to corporate network*
|
||||
|
||||
For mobile clients or peers without fixed IPs, omit the `endpoint` setting.
|
||||
WireGuard learns the peer's endpoint from authenticated incoming packets:
|
||||
|
||||
<pre class="cli"><code>admin@hub:/> <b>configure</b>
|
||||
admin@hub:/config/> <b>edit interface wg0 wireguard peers wg-peers peer mobile-client</b>
|
||||
admin@hub:/config/interface/…/wg-peers/peer/mobile-client/> <b>set allowed-ips 10.0.0.10/32</b>
|
||||
admin@hub:/config/interface/…/wg-peers/peer/mobile-client/> <b>leave</b>
|
||||
admin@hub:/>
|
||||
</code></pre>
|
||||
|
||||
The mobile client configures the hub's endpoint normally. The hub learns
|
||||
and tracks the mobile client's changing IP address automatically.
|
||||
|
||||
## Hub-and-Spoke Topology
|
||||
|
||||

|
||||
*Figure: Hub-and-Spoke topology with central hub routing traffic between spokes*
|
||||
|
||||
WireGuard excels at hub-and-spoke (star) topologies where multiple remote
|
||||
sites connect to a central hub.
|
||||
|
||||
**Hub configuration:**
|
||||
|
||||
<pre class="cli"><code>admin@hub:/> <b>configure</b>
|
||||
admin@hub:/config/> <b>edit interface wg0</b>
|
||||
admin@hub:/config/interface/wg0/> <b>set ipv4 address 10.0.0.1 prefix-length 24</b>
|
||||
admin@hub:/config/interface/wg0/> <b>set wireguard listen-port 51820</b>
|
||||
admin@hub:/config/interface/wg0/> <b>set wireguard private-key wg-hub</b>
|
||||
admin@hub:/config/interface/wg0/> <b>edit wireguard peers wg-peers</b>
|
||||
|
||||
# Spoke 1
|
||||
admin@hub:/config/interface/…/wireguard/peers/wg-peers/> <b>edit peer spoke1</b>
|
||||
admin@hub:/config/interface/…/wg-peers/peer/spoke1/> <b>set allowed-ips 10.0.0.2/32</b>
|
||||
admin@hub:/config/interface/…/wg-peers/peer/spoke1/> <b>set allowed-ips 192.168.1.0/24</b>
|
||||
admin@hub:/config/interface/…/wg-peers/peer/spoke1/> <b>end</b>
|
||||
|
||||
# Spoke 2
|
||||
admin@hub:/config/interface/…/wireguard/peers/wg-peers/> <b>edit peer spoke2</b>
|
||||
admin@hub:/config/interface/…/wg-peers/peer/spoke2/> <b>set allowed-ips 10.0.0.3/32</b>
|
||||
admin@hub:/config/interface/…/wg-peers/peer/spoke2/> <b>set allowed-ips 192.168.2.0/24</b>
|
||||
admin@hub:/config/interface/…/wg-peers/peer/spoke2/> <b>leave</b>
|
||||
|
||||
# Add routes for spoke networks
|
||||
admin@hub:/> <b>configure</b>
|
||||
admin@hub:/config/> <b>edit routing control-plane-protocol static name default</b>
|
||||
admin@hub:/config/routing/…/static/name/default/> <b>set ipv4 route 192.168.1.0/24 wg0</b>
|
||||
admin@hub:/config/routing/…/static/name/default/> <b>set ipv4 route 192.168.2.0/24 wg0</b>
|
||||
admin@hub:/config/routing/…/static/name/default/> <b>leave</b>
|
||||
admin@hub:/>
|
||||
</code></pre>
|
||||
|
||||
**Spoke 1 configuration:**
|
||||
|
||||
<pre class="cli"><code>admin@spoke1:/> <b>configure</b>
|
||||
admin@spoke1:/config/> <b>edit interface wg0</b>
|
||||
admin@spoke1:/config/interface/wg0/> <b>set wireguard listen-port 51820</b>
|
||||
admin@spoke1:/config/interface/wg0/> <b>set wireguard private-key wg-spoke1</b>
|
||||
admin@spoke1:/config/interface/wg0/> <b>set ipv4 address 10.0.0.2 prefix-length 24</b>
|
||||
admin@spoke1:/config/interface/wg0/> <b>edit wireguard peers wg-peers peer hub</b>
|
||||
admin@spoke1:/config/interface/…/wg-peers/peer/hub/> <b>set endpoint 203.0.113.1</b>
|
||||
admin@spoke1:/config/interface/…/wg-peers/peer/hub/> <b>set endpoint-port 51820</b>
|
||||
admin@spoke1:/config/interface/…/wg-peers/peer/hub/> <b>set allowed-ips 10.0.0.1/32</b>
|
||||
admin@spoke1:/config/interface/…/wg-peers/peer/hub/> <b>set allowed-ips 10.0.0.3/32</b>
|
||||
admin@spoke1:/config/interface/…/wg-peers/peer/hub/> <b>set allowed-ips 192.168.0.0/24</b>
|
||||
admin@spoke1:/config/interface/…/wg-peers/peer/hub/> <b>set allowed-ips 192.168.2.0/24</b>
|
||||
admin@spoke1:/config/interface/…/wg-peers/peer/hub/> <b>set persistent-keepalive 25</b>
|
||||
admin@spoke1:/config/interface/…/wg-peers/peer/hub/> <b>leave</b>
|
||||
admin@spoke1:/> <b>configure</b>
|
||||
admin@spoke1:/config/> <b>edit routing control-plane-protocol static name default</b>
|
||||
admin@spoke1:/config/routing/…/static/name/default/> <b>set ipv4 route 192.168.0.0/24 wg0</b>
|
||||
admin@spoke1:/config/routing/…/static/name/default/> <b>set ipv4 route 192.168.2.0/24 wg0</b>
|
||||
admin@spoke1:/config/routing/…/static/name/default/> <b>leave</b>
|
||||
admin@spoke1:/>
|
||||
</code></pre>
|
||||
|
||||
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
|
||||
communication through the central hub.
|
||||
|
||||
## Persistent Keepalive
|
||||
|
||||
The `persistent-keepalive` setting sends periodic packets to keep the tunnel
|
||||
active through NAT devices and firewalls:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/…/wg-peers/peer/hub/> <b>set persistent-keepalive 25</b>
|
||||
</code></pre>
|
||||
|
||||
This is particularly important when:
|
||||
|
||||
- The peer is behind NAT
|
||||
- Intermediate firewalls have connection timeouts
|
||||
- You need the tunnel to remain ready for bidirectional traffic
|
||||
|
||||
A value of 25 seconds is recommended for most scenarios. Omit this setting
|
||||
for peers with public static IPs that initiate connections.
|
||||
|
||||
> [!NOTE]
|
||||
> Only the peer behind NAT needs `persistent-keepalive` configured. The
|
||||
> peer with a public IP learns the NAT endpoint from incoming packets.
|
||||
|
||||
## IPv6 Endpoints
|
||||
|
||||
WireGuard fully supports IPv6 for tunnel endpoints:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface wg0</b>
|
||||
admin@example:/config/interface/wg0/> <b>set wireguard listen-port 51820</b>
|
||||
admin@example:/config/interface/wg0/> <b>set wireguard private-key wg-key</b>
|
||||
admin@example:/config/interface/wg0/> <b>set ipv4 address 10.0.0.1 prefix-length 24</b>
|
||||
admin@example:/config/interface/wg0/> <b>set ipv6 address fd00::1 prefix-length 64</b>
|
||||
admin@example:/config/interface/wg0/> <b>edit wireguard peers wg-peers peer remote</b>
|
||||
admin@example:/config/interface/…/wg-peers/peer/remote/> <b>set endpoint 2001:db8::2</b>
|
||||
admin@example:/config/interface/…/wg-peers/peer/remote/> <b>set endpoint-port 51820</b>
|
||||
admin@example:/config/interface/…/wg-peers/peer/remote/> <b>set allowed-ips 10.0.0.2/32</b>
|
||||
admin@example:/config/interface/…/wg-peers/peer/remote/> <b>set allowed-ips fd00::2/128</b>
|
||||
admin@example:/config/interface/…/wg-peers/peer/remote/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
WireGuard can carry both IPv4 and IPv6 traffic regardless of whether the
|
||||
tunnel endpoints use IPv4 or IPv6.
|
||||
|
||||
## Monitoring WireGuard Status
|
||||
|
||||
Check WireGuard interface status and peer connections:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interfaces</b>
|
||||
wg0 wireguard UP 2 peers (1 up)
|
||||
ipv4 10.0.0.1/24 (static)
|
||||
ipv6 fd00::1/64 (static)
|
||||
|
||||
admin@example:/> <b>show interfaces wg0</b>
|
||||
name : wg0
|
||||
type : wireguard
|
||||
index : 12
|
||||
operational status : up
|
||||
peers : 2
|
||||
|
||||
Peer 1:
|
||||
status : UP
|
||||
endpoint : 203.0.113.2:51820
|
||||
latest handshake : 2025-12-09T10:23:45+0000
|
||||
transfer tx : 125648 bytes
|
||||
transfer rx : 98432 bytes
|
||||
|
||||
Peer 2:
|
||||
status : DOWN
|
||||
endpoint : 203.0.113.3:51820
|
||||
latest handshake : 2025-12-09T09:15:22+0000
|
||||
transfer tx : 45120 bytes
|
||||
transfer rx : 32768 bytes
|
||||
</code></pre>
|
||||
|
||||
The connection status shows `UP` if a handshake occurred within the last 3
|
||||
minutes, indicating an active tunnel. The `latest handshake` timestamp shows
|
||||
when the peers last successfully authenticated and exchanged keys.
|
||||
|
||||
## Post-Quantum Security (Preshared Keys)
|
||||
|
||||
WireGuard supports optional preshared keys (PSK) that add an extra layer of
|
||||
symmetric encryption alongside Curve25519. This provides defense-in-depth
|
||||
against future quantum computers that might break elliptic curve cryptography.
|
||||
|
||||
PSKs protect your data from "harvest now, decrypt later" attacks - adversaries
|
||||
recording traffic today would still need the PSK even if they break Curve25519
|
||||
later. However, peer authentication still relies on Curve25519, so PSKs don't
|
||||
provide complete post-quantum security.
|
||||
|
||||
**Generate a preshared key using `wg genpsk`:**
|
||||
|
||||
```bash
|
||||
admin@example:~$ wg genpsk > preshared.key
|
||||
admin@example:~$ cat preshared.key
|
||||
cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=
|
||||
```
|
||||
|
||||
**Import the preshared key into the keystore:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit keystore symmetric-key wg-psk</b>
|
||||
admin@example:/config/keystore/symmetric-key/wg-psk/> <b>set key-format wireguard-symmetric-key-format</b>
|
||||
admin@example:/config/keystore/symmetric-key/wg-psk/> <b>set key cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=</b>
|
||||
admin@example:/config/keystore/symmetric-key/wg-psk/> <b>end</b>
|
||||
admin@example:/config/interface/wg0/> <b>edit wireguard peers wg-peers peer remote</b>
|
||||
admin@example:/config/interface/…/wg-peers/peer/remote/> <b>set preshared-key wg-psk</b>
|
||||
admin@example:/config/interface/…/wg-peers/peer/remote/> <b>leave</b>
|
||||
admin@example:/>
|
||||
</code></pre>
|
||||
|
||||
The preshared key must be securely shared between both peers and configured
|
||||
on both sides.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Preshared keys must be kept secret and exchanged through a secure channel,
|
||||
> just like passwords. Delete the `preshared.key` file after importing it
|
||||
> into both peer keystores.
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
# VPN Configuration
|
||||
|
||||
A Virtual Private Network (VPN) creates encrypted tunnels over public networks,
|
||||
enabling secure communication between remote locations or users. Unlike plain
|
||||
tunnels (GRE, VXLAN) that only provide encapsulation, VPNs add authentication
|
||||
and encryption to protect data confidentiality and integrity.
|
||||
|
||||
|
||||
## Configuring VPN
|
||||
|
||||
For detailed configuration instructions and examples, see:
|
||||
|
||||
- **[WireGuard VPN](vpn-wireguard.md)** - Complete guide to configuring
|
||||
WireGuard tunnels, including site-to-site, road warrior, and hub-and-spoke
|
||||
topologies.
|
||||
|
||||
## Understanding VPN Tunnels
|
||||
|
||||
VPN tunnels establish secure connections across untrusted networks by:
|
||||
|
||||
- **Authentication:** Verifying the identity of tunnel endpoints using
|
||||
cryptographic keys or certificates
|
||||
- **Encryption:** Protecting data confidentiality with strong ciphers
|
||||
- **Integrity:** Detecting tampering through message authentication codes
|
||||
|
||||
This makes VPNs essential for connecting sites over the internet, enabling
|
||||
remote access for mobile users, and securing traffic in untrusted environments.
|
||||
|
||||
### VPN Deployment Models
|
||||
|
||||
VPNs are typically deployed in one of several models:
|
||||
|
||||
**Site-to-Site VPN**
|
||||
|
||||

|
||||
*Figure: Site-to-Site VPN connecting two office networks*
|
||||
|
||||
Connects entire networks across locations, creating a unified private network
|
||||
over the internet. Routers or firewalls at each site maintain persistent
|
||||
tunnels, allowing seamless access between locations.
|
||||
|
||||
- Use case: Connecting branch offices to headquarters
|
||||
- Characteristics: Always-on, connects networks not individual devices
|
||||
- Example: Main office (192.168.1.0/24) ↔ Branch office (192.168.2.0/24)
|
||||
|
||||
**Remote Access VPN (Road Warrior)**
|
||||
|
||||

|
||||
*Figure: Mobile clients connecting to corporate network*
|
||||
|
||||
Enables individual users to securely access a private network from remote
|
||||
locations. Clients initiate connections as needed from dynamic IP addresses.
|
||||
|
||||
- Use case: Remote employees accessing corporate resources
|
||||
- Characteristics: On-demand, handles dynamic endpoints and roaming
|
||||
- Example: Mobile laptop ↔ Corporate network
|
||||
|
||||
**Hub-and-Spoke VPN**
|
||||
|
||||

|
||||
*Figure: Hub-and-Spoke topology with central hub routing traffic between spokes*
|
||||
|
||||
A central hub connects to multiple remote sites (spokes), routing traffic
|
||||
between them. Spokes don't connect directly to each other but communicate
|
||||
through the hub.
|
||||
|
||||
- Use case: Central office connecting multiple remote locations
|
||||
- Characteristics: Centralized control, simplified management
|
||||
- Example: HQ ↔ (Branch A, Branch B, Branch C)
|
||||
|
||||
### VPN Protocol Comparison
|
||||
|
||||
Different VPN protocols offer varying trade-offs between security, performance,
|
||||
and complexity:
|
||||
|
||||
| Protocol | Complexity | Performance | Use Case |
|
||||
|------------|------------|-------------|---------------------------------|
|
||||
| WireGuard | Simple | Very High | Modern deployments, all models |
|
||||
| IPsec | Complex | High | Legacy systems, compliance reqs |
|
||||
| OpenVPN | Moderate | Moderate | Maximum compatibility |
|
||||
|
||||
Infix supports WireGuard as its primary VPN solution, offering the best
|
||||
balance of simplicity, security, and performance for modern networks.
|
||||
+107
-436
@@ -1,50 +1,14 @@
|
||||
# Wi-Fi (Wireless LAN)
|
||||
|
||||
Infix includes comprehensive Wi-Fi support for both client (Station) and
|
||||
Access Point modes. When a compatible Wi-Fi adapter is detected, the system
|
||||
automatically creates a WiFi radio (PHY) in factory-config, that can
|
||||
host virtual interfaces.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
## 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.
|
||||
Infix includes built-in Wi-Fi client support for connecting to
|
||||
wireless networks. When a compatible Wi-Fi adapter is detected, the
|
||||
system automatically begins scanning for available networks.
|
||||
|
||||
## Current Limitations
|
||||
|
||||
- Only client mode is supported (no access point functionality)
|
||||
- USB hotplug is not supported - adapters must be present at boot
|
||||
- Interface naming may be inconsistent with multiple USB Wi-Fi adapters
|
||||
- AP and Station modes cannot be mixed on the same radio
|
||||
|
||||
## Supported Wi-Fi Adapters
|
||||
|
||||
@@ -52,430 +16,137 @@ Wi-Fi support is primarily tested with Realtek chipset-based adapters.
|
||||
|
||||
### Known Working Chipsets
|
||||
|
||||
- Built-in Wi-Fi on Banana Pi BPi-R3
|
||||
- Built-in Wi-Fi on Raspberry Pi 4/CM4
|
||||
- Realtek:
|
||||
- RTL8188CU
|
||||
- RTL8188FU
|
||||
- RTL8821CU
|
||||
- RTL8821CU
|
||||
- Other Realtek chipsets may work but are not guaranteed
|
||||
|
||||
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
|
||||
## Configuration
|
||||
|
||||
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:
|
||||
Add a supported Wi-Fi network device. To verify that it has been
|
||||
detected, look for `wifi0` in `show interface`
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit hardware component radio0 wifi-radio</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set probe-timeout 30</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>leave</b>
|
||||
</code></pre>
|
||||
```
|
||||
admin@example:/> show interface
|
||||
INTERFACE PROTOCOL STATE DATA
|
||||
lo loopback UP
|
||||
ipv4 127.0.0.1/8 (static)
|
||||
ipv6 ::1/128 (static)
|
||||
e1 ethernet UP 02:00:00:00:00:01
|
||||
ipv6 fe80::ff:fe00:1/64 (link-layer)
|
||||
ipv6 fec0::ff:fe00:1/64 (link-layer)
|
||||
wifi0 ethernet DOWN f0:09:0d:36:5f:86
|
||||
wifi ssid: ------, signal: ------
|
||||
|
||||
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.
|
||||
```
|
||||
Add the new Wi-Fi interface to the configuration to start scanning.
|
||||
```
|
||||
admin@example:/config/> set interface wifi0
|
||||
admin@example:/config/> leave
|
||||
```
|
||||
Now the system will now start scanning in the background. To
|
||||
see the result read the operational datastore for interface `wifi0` or
|
||||
use the CLI
|
||||
|
||||
## Radio Configuration
|
||||
|
||||
Before configuring WiFi interfaces, you must first configure the WiFi radio.
|
||||
Radios are automatically discovered and named `radio0`, `radio1`, etc.
|
||||
|
||||
### 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).
|
||||
|
||||
> [!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:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit hardware component radio0 wifi-radio</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set country-code DE</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
**For Access Point mode:**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit hardware component radio0 wifi-radio</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set country-code DE</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set band 5GHz</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set channel 36</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
**Key radio parameters:**
|
||||
|
||||
- `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.
|
||||
|
||||
### 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.
|
||||
|
||||
**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
|
||||
|
||||
Before connecting to a WiFi network, you need to discover which networks
|
||||
are available. Infix automatically scans for networks when a WiFi interface
|
||||
is created with a radio reference.
|
||||
|
||||
### Enable Background Scanning
|
||||
|
||||
To enable scanning without connecting, configure the radio and create a WiFi
|
||||
interface referencing it:
|
||||
|
||||
**Step 1: Configure the radio**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit hardware component radio0 wifi-radio</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set country-code DE</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
**Step 2: Create WiFi interface with radio reference only**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface wifi0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi radio radio0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
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
|
||||
access-point).
|
||||
|
||||
### View Available Networks
|
||||
|
||||
Use `show interface` to see discovered networks and their signal strength:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interface wifi0</b>
|
||||
```
|
||||
admin@infix-00-00-00:/> show interface wifi0
|
||||
name : wifi0
|
||||
type : wifi
|
||||
index : 3
|
||||
mtu : 1500
|
||||
operational status : up
|
||||
ip forwarding : enabled
|
||||
operational status : down
|
||||
physical address : f0:09:0d:36:5f:86
|
||||
ipv4 addresses : 192.168.1.100/24 (dhcp)
|
||||
ipv4 addresses :
|
||||
ipv6 addresses :
|
||||
in-octets : 148388
|
||||
out-octets : 24555
|
||||
mode : station
|
||||
ssid : MyNetwork
|
||||
signal : -45 dBm (good)
|
||||
rx bitrate : 72.2 Mbps
|
||||
tx bitrate : 86.6 Mbps
|
||||
──────────────────────────────────────────────────────────────────────
|
||||
<span class="title">Available Networks</span>
|
||||
<span class="header">SSID BSSID SECURITY SIGNAL CHANNEL</span>
|
||||
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
|
||||
</code></pre>
|
||||
SSID : ----
|
||||
Signal : ----
|
||||
|
||||
In the CLI, signal strength is reported as: excellent, good, fair or bad.
|
||||
For precise signal strength values in dBm, use NETCONF or RESTCONF to access
|
||||
the `signal-strength` leaf in the operational datastore.
|
||||
SSID ENCRYPTION SIGNAL
|
||||
ssid1 WPA2-Personal excellent
|
||||
ssid2 WPA2-Personal excellent
|
||||
ssid3 WPA2-Personal excellent
|
||||
ssid4 WPA2-Personal good
|
||||
ssid5 WPA2-Personal good
|
||||
ssid6 WPA2-Personal good
|
||||
```
|
||||
|
||||
## Station Mode (Client)
|
||||
In the CLI, signal strength is reported as: excellent, good, poor or
|
||||
bad. For precise values, use NETCONF or RESTCONF, where the RSSI (in
|
||||
dBm) is available in the operational datastore.
|
||||
|
||||
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.
|
||||
Configure your Wi-Fi secret in the keystore, it should be between 8
|
||||
and 63 characters
|
||||
|
||||
### Step 1: Configure Password
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit keystore symmetric-key example
|
||||
admin@example:/config/keystore/…/example/> set key-format wifi-preshared-key-format
|
||||
admin@example:/config/keystore/…/example/> set cleartext-key mysecret
|
||||
admin@example:/config/keystore/…/example/> leave
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
Create a keystore entry for your WiFi password (8-63 characters):
|
||||
Configure the Wi-Fi settings, set secret to the name selected above
|
||||
for the symmetric key, in this case `example`.
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit keystore symmetric-key my-wifi-key</b>
|
||||
admin@example:/config/keystore/…/my-wifi-key/> <b>set key-format wifi-preshared-key-format</b>
|
||||
admin@example:/config/keystore/…/my-wifi-key/> <b>set symmetric-key MyPassword123</b>
|
||||
admin@example:/config/keystore/…/my-wifi-key/> <b>leave</b>
|
||||
</code></pre>
|
||||
WPA2 or WPA3 encryption will be automatically selected based on what
|
||||
the access point supports. No manual selection is required unless
|
||||
connecting to an open network. No support for certificate based
|
||||
authentication yet.
|
||||
|
||||
### Step 2: Connect to Network
|
||||
Unencrypted network is also supported, to connect to an unencrypted
|
||||
network (generally not recommended):
|
||||
```
|
||||
admin@example:/config/interface/wifi0/> set wifi encryption disabled
|
||||
```
|
||||
|
||||
Configure station mode with the SSID and password to connect:
|
||||
A valid `country-code` is also required for regulatory compliance, the
|
||||
valid codes are documented in the YANG model `infix-wifi-country-codes`
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface wifi0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi station ssid MyHomeNetwork</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi station security secret my-wifi-key</b>
|
||||
admin@example:/config/interface/wifi0/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
The connection attempt will start immediately. You can verify the connection status:
|
||||
```
|
||||
admin@example:/> configure
|
||||
admin@example:/config/> edit interface wifi0
|
||||
admin@example:/config/interface/wifi0/>
|
||||
admin@example:/config/interface/wifi0/> set wifi ssid ssid1
|
||||
admin@example:/config/interface/wifi0/> set wifi secret example
|
||||
admin@example:/config/interface/wifi0/> set wifi country-code SE
|
||||
admin@example:/config/interface/wifi0/> leave
|
||||
```
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>show interface wifi0</b>
|
||||
name : wifi0
|
||||
type : wifi
|
||||
operational status : up
|
||||
physical address : f0:09:0d:36:5f:86
|
||||
SSID : MyHomeNetwork
|
||||
Signal : excellent
|
||||
</code></pre>
|
||||
The Wi-Fi negotiation should now start immediately, provided that the
|
||||
SSID and pre-shared key are correct. You can verify the connection by
|
||||
running `show interface` again.
|
||||
|
||||
**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
|
||||
- `disabled`: open network
|
||||
- `station security secret`: Reference to keystore entry, required unless mode
|
||||
is `disabled`
|
||||
```
|
||||
admin@example:/> show interface
|
||||
INTERFACE PROTOCOL STATE DATA
|
||||
lo loopback UP
|
||||
ipv4 127.0.0.1/8 (static)
|
||||
ipv6 ::1/128 (static)
|
||||
e1 ethernet UP 02:00:00:00:00:01
|
||||
ipv6 fe80::ff:fe00:1/64 (link-layer)
|
||||
ipv6 fec0::ff:fe00:1/64 (link-layer)
|
||||
wifi0 ethernet UP f0:09:0d:36:5f:86
|
||||
wifi ssid: ssid1, signal: excellent
|
||||
|
||||
> [!NOTE]
|
||||
> The `auto` security mode automatically selects WPA3-SAE or WPA2-PSK based on
|
||||
> what the access point supports, prioritizing WPA3 for better security.
|
||||
> Certificate-based authentication (802.1X/EAP) is not yet supported.
|
||||
admin@example:/>
|
||||
```
|
||||
|
||||
## Access Point Mode
|
||||
## Troubleshooting Connection Issues
|
||||
|
||||
Access Point (AP) mode allows your device to create a WiFi network that
|
||||
other devices can connect to. APs are configured as virtual interfaces on
|
||||
a WiFi radio.
|
||||
Use `show wifi scan wifi0` and `show interface` to verify signal strength
|
||||
and connection status. If issues arise, try the following
|
||||
troubleshooting steps:
|
||||
|
||||
### Basic AP Configuration
|
||||
1. **Verify signal strength**: Check that the target network shows "good" or "excellent" signal
|
||||
2. **Check credentials**: Verify the preshared key in `ietf-keystore`
|
||||
3. **Review logs**: Check system logs with `show log` for Wi-Fi related errors
|
||||
4. **Regulatory compliance**: Ensure the country-code matches your location
|
||||
5. **Hardware detection**: Confirm the adapter appears in `show interface`
|
||||
|
||||
First, ensure the radio is configured (see Radio Configuration above). Then
|
||||
create a keystore entry for your WiFi password and configure the AP interface:
|
||||
|
||||
**Step 1: Create keystore entry for the WiFi password**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit keystore symmetric-key my-wifi-secret</b>
|
||||
admin@example:/config/keystore/…/my-wifi-secret/> <b>set key-format wifi-preshared-key-format</b>
|
||||
admin@example:/config/keystore/…/my-wifi-secret/> <b>set symmetric-key MySecurePassword123</b>
|
||||
admin@example:/config/keystore/…/my-wifi-secret/> <b>end</b>
|
||||
</code></pre>
|
||||
|
||||
**Step 2: Create the AP interface**
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/> <b>edit interface wifi0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi radio radio0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi access-point ssid MyNetwork</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi access-point security mode wpa2-personal</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi access-point security secret my-wifi-secret</b>
|
||||
admin@example:/config/interface/wifi0/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
> [!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)
|
||||
- `access-point security mode`: Security mode (see below)
|
||||
- `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)
|
||||
- `wpa2-wpa3-personal`: Mixed mode (maximum compatibility)
|
||||
|
||||
### SSID Hiding
|
||||
|
||||
To create a hidden network that doesn't broadcast its SSID:
|
||||
|
||||
<pre class="cli"><code>admin@example:/config/interface/wifi0/> <b>set wifi access-point hidden true</b>
|
||||
</code></pre>
|
||||
|
||||
### Multi-SSID Configuration
|
||||
|
||||
Multiple AP interfaces on the same radio allow broadcasting multiple SSIDs,
|
||||
each with independent security settings. This is useful for guest networks,
|
||||
IoT devices, or segregating traffic into different VLANs.
|
||||
|
||||
**Step 1: Configure the radio** (shared by all APs)
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit hardware component radio0 wifi-radio</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set country-code DE</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set band 5GHz</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>set channel 36</b>
|
||||
admin@example:/config/hardware/component/radio0/wifi-radio/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
**Step 2: Configure keystore secrets**
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit keystore symmetric-key main-secret</b>
|
||||
admin@example:/config/keystore/…/main-secret/> <b>set key-format wifi-preshared-key-format</b>
|
||||
admin@example:/config/keystore/…/main-secret/> <b>set symmetric-key MyMainPassword</b>
|
||||
admin@example:/config/> <b>edit keystore symmetric-key guest-secret</b>
|
||||
admin@example:/config/keystore/…/guest-secret/> <b>set key-format wifi-preshared-key-format</b>
|
||||
admin@example:/config/keystore/…/guest-secret/> <b>set symmetric-key GuestPassword123</b>
|
||||
admin@example:/config/> <b>edit keystore symmetric-key iot-secret</b>
|
||||
admin@example:/config/keystore/…/iot-secret/> <b>set key-format wifi-preshared-key-format</b>
|
||||
admin@example:/config/keystore/…/iot-secret/> <b>set symmetric-key IoTDevices2025</b>
|
||||
admin@example:/config/keystore/…/iot-secret/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
**Step 3: Create multiple AP interfaces** (all on radio0)
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
# Primary AP - Main network (WPA3 for maximum security)
|
||||
admin@example:/config/> <b>edit interface wifi0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi radio radio0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi access-point ssid MainNetwork</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi access-point security mode wpa3-personal</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set wifi access-point security secret main-secret</b>
|
||||
|
||||
# Guest AP - Guest network (WPA2/WPA3 mixed for compatibility)
|
||||
admin@example:/config/> <b>edit interface wifi1</b>
|
||||
admin@example:/config/interface/wifi1/> <b>set wifi radio radio0</b>
|
||||
admin@example:/config/interface/wifi1/> <b>set wifi access-point ssid GuestNetwork</b>
|
||||
admin@example:/config/interface/wifi1/> <b>set wifi access-point security mode wpa2-wpa3-personal</b>
|
||||
admin@example:/config/interface/wifi1/> <b>set wifi access-point security secret guest-secret</b>
|
||||
admin@example:/config/interface/wifi1/> <b>set custom-phys-address static 00:0c:43:26:60:01</b>
|
||||
|
||||
# IoT AP - IoT devices (WPA2 for older device compatibility)
|
||||
admin@example:/config/> <b>edit interface wifi2</b>
|
||||
admin@example:/config/interface/wifi2/> <b>set wifi radio radio0</b>
|
||||
admin@example:/config/interface/wifi2/> <b>set wifi access-point ssid IoT-Devices</b>
|
||||
admin@example:/config/interface/wifi2/> <b>set wifi access-point security mode wpa2-personal</b>
|
||||
admin@example:/config/interface/wifi2/> <b>set wifi access-point security secret iot-secret</b>
|
||||
admin@example:/config/interface/wifi2/> <b>set custom-phys-address static 00:0c:43:26:60:02</b>
|
||||
admin@example:/config/interface/wifi2/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **MAC Address Requirement for Multi-SSID:**
|
||||
> When creating multiple AP interfaces on the same radio, you **must** configure
|
||||
> a unique MAC address for each secondary interface (wifi1, wifi2, etc.) using
|
||||
> `set custom-phys-address static <MAC>`. All interfaces on the same radio inherit
|
||||
> the radio's hardware MAC address by default, which causes network conflicts. Only
|
||||
> the primary interface (alphabetically first, e.g., wifi0) should use the default
|
||||
> hardware MAC address.
|
||||
>
|
||||
> Choose MAC addresses from the same locally-administered range:
|
||||
> - Primary (wifi0): Uses hardware MAC (e.g., `00:0c:43:26:60:00`)
|
||||
> - Secondary (wifi1): `00:0c:43:26:60:01` (increment last octet)
|
||||
> - 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
|
||||
- Bridge membership
|
||||
|
||||
You can verify the configuration with `show hardware component radio0` to see
|
||||
radio settings, and `show interface` to see all active AP interfaces.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> AP and Station modes cannot be mixed on the same radio. All virtual interfaces
|
||||
> on a radio must be the same mode (all APs or all Stations).
|
||||
|
||||
### AP as Bridge Port
|
||||
|
||||
WiFi AP interfaces can be added to bridges to integrate wireless devices
|
||||
into your LAN:
|
||||
|
||||
<pre class="cli"><code>admin@example:/> <b>configure</b>
|
||||
admin@example:/config/> <b>edit interface br0</b>
|
||||
admin@example:/config/interface/br0/> <b>set type bridge</b>
|
||||
|
||||
admin@example:/config/> <b>edit interface wifi0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>set bridge-port bridge br0</b>
|
||||
admin@example:/config/interface/wifi0/> <b>leave</b>
|
||||
</code></pre>
|
||||
|
||||
## 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]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
|
||||
If issues persist, check the system log for specific error messages that can help identify the root cause.
|
||||
|
||||
+4
-14
@@ -28,29 +28,18 @@ nav:
|
||||
- Upgrading: cli/upgrade.md
|
||||
- Docker Containers: container.md
|
||||
- Networking:
|
||||
- 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
|
||||
- Network Configuration: networking.md
|
||||
- Firewall Configuration: firewall.md
|
||||
- Quality of Service: qos.md
|
||||
- RMON Counters: eth-counters.md
|
||||
- Tunneling (L2/L3): tunnels.md
|
||||
- VPN Tunnels:
|
||||
- Overview: vpn.md
|
||||
- WireGuard: vpn-wireguard.md
|
||||
- Wireless LAN (WiFi): wifi.md
|
||||
- Services:
|
||||
- Device Discovery: discovery.md
|
||||
- DHCP Server: dhcp.md
|
||||
- NTP Server: ntp.md
|
||||
- System:
|
||||
- Boot Procedure: boot.md
|
||||
- Configuration: system.md
|
||||
- Access Control (NACM): nacm.md
|
||||
- Hardware Info & Status: hardware.md
|
||||
- Management: management.md
|
||||
- Syslog Support: syslog.md
|
||||
@@ -59,15 +48,16 @@ nav:
|
||||
- Scripting:
|
||||
- Introduction: scripting.md
|
||||
- Legacy Scripting: scripting-sysrepocfg.md
|
||||
- NETCONF Scripting: scripting-netconf.md
|
||||
- RESTCONF Scripting: scripting-restconf.md
|
||||
- Production Testing: scripting-prod.md
|
||||
- With NETCONF: scripting-netconf.md
|
||||
- With RESTCONF: scripting-restconf.md
|
||||
- Developer's Corner:
|
||||
- Branding & Releases: branding.md
|
||||
- Developer's Guide: developers-guide.md
|
||||
- Developing with Buildroot: override-package.md
|
||||
- Netboot HowTo: netboot.md
|
||||
- Regression Testing: testing.md
|
||||
- System Tuning Guide: system-tuning.md
|
||||
- Test System Architecture: test-arch.md
|
||||
- Virtual Environments: virtual.md
|
||||
- Vital Product Data (VPD): vpd.md
|
||||
|
||||
@@ -34,6 +34,7 @@ source "$BR2_EXTERNAL_INFIX_PATH/package/podman/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/python-libyang/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/python-yangdoc/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/skeleton-init-finit/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/show/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/tetris/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/libyang-cpp/Config.in"
|
||||
source "$BR2_EXTERNAL_INFIX_PATH/package/sysrepo-cpp/Config.in"
|
||||
|
||||
@@ -5,8 +5,4 @@ config BR2_PACKAGE_BIN
|
||||
help
|
||||
Misc. tools for CLI and shell users.
|
||||
|
||||
Includes show (show.py) copy (NACM-aware datastore operations),
|
||||
rpc (YANG RPC execution with NACM enforcement), erase, and files
|
||||
commands.
|
||||
|
||||
https://github.com/kernelkit/infix
|
||||
|
||||
+1
-30
@@ -10,9 +10,7 @@ BIN_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/bin
|
||||
BIN_LICENSE = BSD-3-Clause
|
||||
BIN_LICENSE_FILES = LICENSE
|
||||
BIN_REDISTRIBUTE = NO
|
||||
BIN_DEPENDENCIES = sysrepo libite \
|
||||
host-python3 python3 host-python-pypa-build host-python-installer \
|
||||
host-python-poetry-core
|
||||
BIN_DEPENDENCIES = sysrepo libite
|
||||
BIN_CONF_OPTS = --disable-silent-rules
|
||||
BIN_AUTORECONF = YES
|
||||
|
||||
@@ -20,31 +18,4 @@ define BIN_CONF_ENV
|
||||
CFLAGS="$(INFIX_CFLAGS)"
|
||||
endef
|
||||
|
||||
define BIN_PERMISSIONS
|
||||
/usr/bin/copy d 04750 root klish - - - - -
|
||||
endef
|
||||
|
||||
define BIN_BUILD_PYTHON
|
||||
cd $(BIN_SITE) && \
|
||||
$(PKG_PYTHON_PEP517_ENV) $(HOST_DIR)/bin/python3 $(PKG_PYTHON_PEP517_BUILD_CMD) -o $(@D)/dist
|
||||
mkdir -p $(TARGET_DIR)/usr/bin
|
||||
rm -f $(TARGET_DIR)/usr/bin/show
|
||||
cd $(@D) && \
|
||||
$(HOST_DIR)/bin/python3 $(TOPDIR)/support/scripts/pyinstaller.py \
|
||||
dist/*.whl \
|
||||
--interpreter=/usr/bin/python3 \
|
||||
--script-kind=posix \
|
||||
--purelib=$(TARGET_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \
|
||||
--headers=$(TARGET_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \
|
||||
--scripts=$(TARGET_DIR)/usr/bin \
|
||||
--data=$(TARGET_DIR)
|
||||
endef
|
||||
BIN_POST_INSTALL_TARGET_HOOKS += BIN_BUILD_PYTHON
|
||||
|
||||
define BIN_INSTALL_BASH_COMPLETION
|
||||
install -D $(@D)/bash_completion.d/show \
|
||||
$(TARGET_DIR)/etc/bash_completion.d/show
|
||||
endef
|
||||
BIN_POST_INSTALL_TARGET_HOOKS += BIN_INSTALL_BASH_COMPLETION
|
||||
|
||||
$(eval $(autotools-package))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user