mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-23 17:33:01 +02:00
Compare commits
@@ -80,14 +80,20 @@ jobs:
|
||||
name: Upload Latest Build
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: pyTooling/Actions/releaser@main
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: latest
|
||||
rm: false
|
||||
allowUpdates: true
|
||||
omitName: true
|
||||
omitBody: true
|
||||
omitBodyDuringUpdate: true
|
||||
prerelease: true
|
||||
tag: "latest"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: artifact/*
|
||||
artifacts: "artifact/*"
|
||||
- name: Summary
|
||||
run: |
|
||||
cat <<EOF >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Set Build Variables
|
||||
id: vars
|
||||
run: |
|
||||
target=x86_64-minimal
|
||||
target=x86_64
|
||||
echo "dir=infix-$target" >> $GITHUB_OUTPUT
|
||||
echo "tgz=infix-$target.tar.gz" >> $GITHUB_OUTPUT
|
||||
- name: Restore Cache of dl/
|
||||
@@ -52,9 +52,9 @@ jobs:
|
||||
ccache-x86_64-netconf-
|
||||
ccache-x86_64-
|
||||
ccache-
|
||||
- name: Configure Minimal NETCONF
|
||||
- name: Configure NETCONF
|
||||
run: |
|
||||
make x86_64_minimal_defconfig
|
||||
make x86_64_defconfig
|
||||
- name: Build
|
||||
run: |
|
||||
make
|
||||
|
||||
@@ -4,6 +4,11 @@ on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]*.*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -20,7 +25,11 @@ jobs:
|
||||
- name: Set Release Variables
|
||||
id: build
|
||||
run: |
|
||||
ver=${GITHUB_REF#refs/tags/v}
|
||||
if [ -n "${{ inputs.version }}" ]; then
|
||||
ver=${{ inputs.version }}
|
||||
else
|
||||
ver=${GITHUB_REF#refs/tags/v}
|
||||
fi
|
||||
echo "ver=${ver}" >> $GITHUB_OUTPUT
|
||||
if echo $ver | grep -qE '[0-9.]+(-alpha|-beta|-rc)[0-9]*'; then
|
||||
echo "pre=true" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
label Infix (aarch64)
|
||||
kernel /boot/Image
|
||||
fdtdir /boot
|
||||
append ${bootargs_root} ${bootargs_rauc} ${bootargs_log}
|
||||
append ${bootargs_root} ${bootargs_log} -- ${bootargs_user}
|
||||
|
||||
@@ -73,10 +73,6 @@ if [ "$FIT_IMAGE" = "y" ]; then
|
||||
fi
|
||||
|
||||
if [ "$BR2_TARGET_ROOTFS_SQUASHFS" = "y" ]; then
|
||||
if [ -z "${NAME##*minimal*}" ]; then
|
||||
NAME=$(echo "$NAME" | sed 's/-minimal//')
|
||||
fi
|
||||
|
||||
rel=$(ver)
|
||||
ln -sf rootfs.squashfs "$BINARIES_DIR/${NAME}${rel}.img"
|
||||
if [ -n "$rel" ]; then
|
||||
|
||||
@@ -137,6 +137,10 @@ endchoice
|
||||
config QEMU_NET_MODEL
|
||||
string "Interface model"
|
||||
default "virtio-net-pci"
|
||||
help
|
||||
The default, virtio-net-pci, NIC works for most use-cases, but
|
||||
if you want to play with low-level stuff like ethtool, you
|
||||
might want to test the Intel 82545EM driver, e1000.
|
||||
|
||||
config QEMU_NET_BRIDGE_DEV
|
||||
string "Bridge device"
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
Q=$@
|
||||
|
||||
echo "$Q, are you sure? (y/N)"
|
||||
read -n1 yorn
|
||||
|
||||
if [ x$yorn != "xy" ]; then
|
||||
echo "Ok, aborting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -1,141 +0,0 @@
|
||||
_cond()
|
||||
{
|
||||
initctl -pt cond dump | awk '{print $4}' | sed 's/<\(.*\)>/\1/'
|
||||
}
|
||||
|
||||
_ident()
|
||||
{
|
||||
if [ -n "$1" ]; then
|
||||
initctl ident | grep -q $1
|
||||
else
|
||||
initctl ident
|
||||
fi
|
||||
}
|
||||
|
||||
_svc()
|
||||
{
|
||||
initctl ls -pt | grep $1 | sed "s/.*\/\(.*\)/\1/g" | sort -u
|
||||
}
|
||||
|
||||
_enabled()
|
||||
{
|
||||
echo "$(_svc enabled)"
|
||||
}
|
||||
|
||||
_available()
|
||||
{
|
||||
all=$(mktemp)
|
||||
ena=$(mktemp)
|
||||
echo "$(_svc available)" >$all
|
||||
echo "$(_svc enabled)" >$ena
|
||||
grep -v -f $ena $all
|
||||
rm $all $ena
|
||||
}
|
||||
|
||||
# Determine first non-option word. Usually the command
|
||||
_firstword() {
|
||||
local firstword i
|
||||
|
||||
firstword=
|
||||
for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
|
||||
if [[ ${COMP_WORDS[i]} != -* ]]; then
|
||||
firstword=${COMP_WORDS[i]}
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo $firstword
|
||||
}
|
||||
|
||||
# Determine last non-option word. Uusally a sub-command
|
||||
_lastword() {
|
||||
local lastword i
|
||||
|
||||
lastword=
|
||||
for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
|
||||
if [[ ${COMP_WORDS[i]} != -* ]] && [[ -n ${COMP_WORDS[i]} ]] && [[ ${COMP_WORDS[i]} != $cur ]]; then
|
||||
lastword=${COMP_WORDS[i]}
|
||||
fi
|
||||
done
|
||||
|
||||
echo $lastword
|
||||
}
|
||||
|
||||
_initctl()
|
||||
{
|
||||
local cur command
|
||||
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
firstword=$(_firstword)
|
||||
lastword=$(_lastword)
|
||||
|
||||
commands="status cond debug help kill ls log version list enable \
|
||||
disable touch show cat edit create delete reload start \
|
||||
stop restart signal cgroup ps top plugins runlevel reboot \
|
||||
halt poweroff suspend utmp"
|
||||
cond_cmds="set get clear status dump"
|
||||
cond_types="hook net pid service task usr"
|
||||
signals="int term hup stop tstp cont usr1 usr2 pwr"
|
||||
options="-b --batch \
|
||||
-c --create \
|
||||
-d --debug \
|
||||
-f --force \
|
||||
-h --help \
|
||||
-j --json \
|
||||
-n --noerr \
|
||||
-1 --once \
|
||||
-p --plain \
|
||||
-q --quiet \
|
||||
-t --no-heading \
|
||||
-v --verbose \
|
||||
-V --version"
|
||||
|
||||
case "${firstword}" in
|
||||
enable)
|
||||
COMPREPLY=($(compgen -W "$(_available)" -- $cur))
|
||||
;;
|
||||
disable|touch)
|
||||
COMPREPLY=($(compgen -W "$(_enabled)" -- $cur))
|
||||
;;
|
||||
show|cat|edit|delete)
|
||||
COMPREPLY=($(compgen -W "$(_svc .)" -- $cur))
|
||||
;;
|
||||
start|stop|restart|log|status)
|
||||
COMPREPLY=($(compgen -W "$(_ident)" -- $cur))
|
||||
;;
|
||||
signal|kill)
|
||||
if $(_ident "${prev}"); then
|
||||
COMPREPLY=($(compgen -W "$signals" -- $cur))
|
||||
else
|
||||
COMPREPLY=($(compgen -W "$(_ident)" -- $cur))
|
||||
fi
|
||||
;;
|
||||
cond)
|
||||
case "${lastword}" in
|
||||
set|clear)
|
||||
compopt -o nospace
|
||||
COMPREPLY=($(compgen -W "usr/" -- $cur))
|
||||
;;
|
||||
get)
|
||||
COMPREPLY=($(compgen -W "$(_cond)" -- $cur))
|
||||
;;
|
||||
dump)
|
||||
COMPREPLY=($(compgen -W "$cond_types" -- $cur))
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=($(compgen -W "$cond_cmds" -- $cur))
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=($(compgen -W "$commands" -- $cur))
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=($(compgen -W "$options" -- $cur))
|
||||
fi
|
||||
}
|
||||
|
||||
complete -F _initctl initctl
|
||||
@@ -8,9 +8,13 @@
|
||||
&env {
|
||||
vendor = "infix";
|
||||
bootdelay = "-2";
|
||||
bootcmd = "run ixboot";
|
||||
bootcmd = "run ixbtn";
|
||||
boot_targets = "virtio mmc";
|
||||
|
||||
ixbtn = /incbin/("scripts/ixbtn.sh");
|
||||
ixdevmode = /incbin/("scripts/ixdevmode.sh");
|
||||
ixfactory = /incbin/("scripts/ixfactory.sh");
|
||||
ixbtn = /incbin/("scripts/ixbtn.sh");
|
||||
ixboot = /incbin/("scripts/ixboot.sh");
|
||||
ixbootmedia = /incbin/("scripts/ixbootmedia.sh");
|
||||
ixbootslot = /incbin/("scripts/ixbootslot.sh");
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
setenv valid_media no
|
||||
|
||||
for tgt in "${boot_targets}"; do
|
||||
if test "${tgt}" = "mmc0"; then
|
||||
setenv devtype "mmc"
|
||||
@@ -17,7 +19,7 @@ for tgt in "${boot_targets}"; do
|
||||
env import -b ${loadaddr} ${filesize} BOOT_ORDER DEBUG
|
||||
fi
|
||||
|
||||
test -n "${BOOT_ORDER}" || setenv BOOT_ORDER "primary secondary dhcp"
|
||||
test -n "${BOOT_ORDER}" || setenv BOOT_ORDER "primary secondary net"
|
||||
|
||||
if test -n "${DEBUG}"; then
|
||||
setenv bootargs_log "debug"
|
||||
@@ -25,8 +27,16 @@ for tgt in "${boot_targets}"; do
|
||||
setenv bootargs_log "loglevel=4"
|
||||
fi
|
||||
|
||||
setenv valid_media yes
|
||||
run ixbootmedia
|
||||
fi
|
||||
done
|
||||
|
||||
if test "${valid_media}" = "no"; then
|
||||
echo "NO BOOTABLE MEDIA FOUND, falling back to netboot"
|
||||
setenv BOOT_ORDER "net"
|
||||
setenv bootargs_log "debug"
|
||||
run ixbootmedia
|
||||
fi
|
||||
|
||||
reset
|
||||
|
||||
@@ -14,7 +14,13 @@ if test "${prepared}" = "ok"; then
|
||||
if iminfo ${ramdisk_addr_r}; then
|
||||
echo "${slot}: Booting..."
|
||||
|
||||
setenv bootargs_rauc "rauc.slot=${slot}"
|
||||
setenv bootargs_user "rauc.slot=${slot}"
|
||||
if test "${factory_reset}" = "yes"; then
|
||||
setenv bootargs_user "${bootargs_user} finit.cond=factory-reset"
|
||||
fi
|
||||
if test "${dev_mode}" = "yes"; then
|
||||
setenv bootargs_user "${bootargs_user} finit.cond=dev-mode"
|
||||
fi
|
||||
|
||||
blkmap create boot
|
||||
blkmap get boot dev blkmapnum
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
setenv dev_mode no
|
||||
setenv factory_reset no
|
||||
|
||||
echo -n "dev-mode: "
|
||||
run ixdevmode
|
||||
echo -n "factory-reset: "
|
||||
run ixfactory
|
||||
|
||||
if test "${dev_mode}" = "yes"; then
|
||||
sleep 1 && run ixboot
|
||||
else
|
||||
run ixboot
|
||||
fi
|
||||
@@ -0,0 +1,3 @@
|
||||
if button dev-mode; then
|
||||
setenv dev_mode yes
|
||||
fi
|
||||
@@ -0,0 +1,7 @@
|
||||
if button factory-reset; then
|
||||
echo "Keep button pressed for 10 seconds to engage reset"
|
||||
if sleep 10 && button factory-reset; then
|
||||
setenv factory_reset yes
|
||||
echo "FACTORY RESET ENGAGED"
|
||||
fi
|
||||
fi
|
||||
@@ -32,6 +32,16 @@ class Decore():
|
||||
return Decore.decorate("32", txt, "39")
|
||||
|
||||
class Iface:
|
||||
def get_json_data(self, default, *args):
|
||||
data = self.data
|
||||
for arg in args:
|
||||
if data.get(arg):
|
||||
data = data.get(arg)
|
||||
else:
|
||||
return default
|
||||
|
||||
return data
|
||||
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
self.name = data.get('name', '')
|
||||
@@ -46,8 +56,6 @@ class Iface:
|
||||
self.in_octets = ''
|
||||
self.out_octets = ''
|
||||
|
||||
self.parent = data.get('ietf-if-extensions:parent-interface', None)
|
||||
|
||||
if self.data.get('ietf-ip:ipv4'):
|
||||
self.mtu = self.data.get('ietf-ip:ipv4').get('mtu', '')
|
||||
self.ipv4_addr = self.data.get('ietf-ip:ipv4').get('address', '')
|
||||
@@ -65,6 +73,11 @@ class Iface:
|
||||
else:
|
||||
self.bridge = ''
|
||||
|
||||
if self.data.get('infix-interfaces:vlan'):
|
||||
self.lower_if = self.data.get('infix-interfaces:vlan', None).get('lower-layer-if',None)
|
||||
else:
|
||||
self.lower_if = ''
|
||||
|
||||
def is_vlan(self):
|
||||
return self.data['type'] == "infix-if-type:vlan"
|
||||
|
||||
@@ -126,7 +139,7 @@ class Iface:
|
||||
self.pr_name(pipe="")
|
||||
self.pr_proto_eth()
|
||||
|
||||
if self.parent:
|
||||
if self.lower_if:
|
||||
self.pr_proto_ipv4(pipe='│')
|
||||
self.pr_proto_ipv6(pipe='│')
|
||||
else:
|
||||
@@ -134,7 +147,7 @@ class Iface:
|
||||
self.pr_proto_ipv6()
|
||||
return
|
||||
|
||||
parent = find_iface(_ifaces, self.parent)
|
||||
parent = find_iface(_ifaces, self.lower_if)
|
||||
if not parent:
|
||||
print(f"Error, didn't find parent interface for vlan {self.name}")
|
||||
sys.exit(1)
|
||||
@@ -181,6 +194,13 @@ class Iface:
|
||||
print(f"{'in-octets':<{20}}: {self.in_octets}")
|
||||
print(f"{'out-octets':<{20}}: {self.out_octets}")
|
||||
|
||||
frame = self.get_json_data([], 'ieee802-ethernet-interface:ethernet',
|
||||
'statistics', 'frame')
|
||||
if frame:
|
||||
print(f"")
|
||||
for key, val in frame.items():
|
||||
print(f"eth-{key:<{25}}: {val}")
|
||||
|
||||
|
||||
def find_iface(_ifaces, name):
|
||||
for _iface in [Iface(data) for data in _ifaces]:
|
||||
@@ -210,7 +230,7 @@ def pr_interface_list(json):
|
||||
continue
|
||||
|
||||
# These interfaces are printed by there parent, such as bridge
|
||||
if iface.parent:
|
||||
if iface.lower_if:
|
||||
continue
|
||||
if iface.bridge:
|
||||
continue
|
||||
@@ -234,11 +254,21 @@ def ietf_interfaces(json, name):
|
||||
sys.exit(1)
|
||||
return iface.pr_iface()
|
||||
|
||||
def main():
|
||||
try:
|
||||
json_data = json.load(sys.stdin)
|
||||
except json.JSONDecodeError:
|
||||
print("Error, invalid JSON input")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print("Error, unexpected error parsing JSON")
|
||||
sys.exit(1)
|
||||
|
||||
json = json.load(sys.stdin)
|
||||
if args.module == "ietf-interfaces":
|
||||
sys.exit(ietf_interfaces(json_data, args.name))
|
||||
else:
|
||||
print(f"Error, unknown module {args.module}")
|
||||
sys.exit(1)
|
||||
|
||||
if args.module == "ietf-interfaces":
|
||||
sys.exit(ietf_interfaces(json, args.name))
|
||||
else:
|
||||
print(f"Error, unknown module {args.module}")
|
||||
sys.exit(1)
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -81,6 +81,7 @@ BR2_PACKAGE_SOCAT=y
|
||||
BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_TRACEROUTE=y
|
||||
BR2_PACKAGE_ULOGD=y
|
||||
BR2_PACKAGE_BASH=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_IRQBALANCE=y
|
||||
BR2_PACKAGE_KMOD_TOOLS=y
|
||||
|
||||
@@ -77,6 +77,7 @@ BR2_PACKAGE_SOCAT=y
|
||||
BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_TRACEROUTE=y
|
||||
BR2_PACKAGE_ULOGD=y
|
||||
BR2_PACKAGE_BASH=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_IRQBALANCE=y
|
||||
BR2_PACKAGE_KMOD_TOOLS=y
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
BR2_x86_64=y
|
||||
BR2_x86_corei7=y
|
||||
BR2_TOOLCHAIN_EXTERNAL=y
|
||||
BR2_TOOLCHAIN_EXTERNAL_GDB_SERVER_COPY=y
|
||||
BR2_DL_DIR="${BR2_EXTERNAL_INFIX_PATH}/dl"
|
||||
BR2_CCACHE=y
|
||||
BR2_CCACHE_DIR="${BR2_EXTERNAL_INFIX_PATH}/.ccache"
|
||||
BR2_ENABLE_DEBUG=y
|
||||
BR2_GLOBAL_PATCH_DIR="${BR2_EXTERNAL_INFIX_PATH}/patches"
|
||||
BR2_TARGET_GENERIC_HOSTNAME="infix"
|
||||
BR2_TARGET_GENERIC_ISSUE="Minfix by KernelKit"
|
||||
BR2_INIT_FINIT=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/xattrs"
|
||||
BR2_TARGET_GENERIC_GETTY_TERM="xterm"
|
||||
BR2_SYSTEM_DHCP="eth0"
|
||||
BR2_ENABLE_LOCALE_WHITELIST="C en_US en_CA"
|
||||
BR2_GENERATE_LOCALE="en_US en_CA"
|
||||
BR2_TARGET_TZ_INFO=y
|
||||
BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_INFIX_PATH}/board/common/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/x86_64/rootfs ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/rootfs"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/qemu/x86_64/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/common/post-build.sh ${BR2_EXTERNAL_INFIX_PATH}/board/netconf/post-build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_INFIX_PATH}/board/common/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.5.6"
|
||||
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_BUSYBOX_SHOW_OTHERS=y
|
||||
BR2_PACKAGE_JQ=y
|
||||
BR2_PACKAGE_DBUS_CXX=y
|
||||
BR2_PACKAGE_DBUS_GLIB=y
|
||||
BR2_PACKAGE_DBUS_TRIGGERD=y
|
||||
BR2_PACKAGE_EUDEV_RULES_GEN=y
|
||||
# BR2_PACKAGE_EUDEV_ENABLE_HWDB is not set
|
||||
BR2_PACKAGE_RNG_TOOLS=y
|
||||
BR2_PACKAGE_LIBOPENSSL_BIN=y
|
||||
BR2_PACKAGE_NETOPEER2_CLI=y
|
||||
BR2_PACKAGE_NSS_MDNS=y
|
||||
BR2_PACKAGE_ONIGURUMA=y
|
||||
BR2_PACKAGE_AVAHI=y
|
||||
BR2_PACKAGE_AVAHI_DAEMON=y
|
||||
BR2_PACKAGE_AVAHI_DEFAULT_SERVICES=y
|
||||
BR2_PACKAGE_CHRONY=y
|
||||
BR2_PACKAGE_DNSMASQ=y
|
||||
BR2_PACKAGE_ETHTOOL=y
|
||||
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
|
||||
BR2_PACKAGE_LLDPD=y
|
||||
BR2_PACKAGE_OPENRESOLV=y
|
||||
BR2_PACKAGE_OPENSSH=y
|
||||
BR2_PACKAGE_TCPDUMP=y
|
||||
BR2_PACKAGE_KMOD_TOOLS=y
|
||||
BR2_PACKAGE_BASH_COMPLETION=y
|
||||
BR2_PACKAGE_PWGEN=y
|
||||
BR2_PACKAGE_SYSKLOGD=y
|
||||
BR2_PACKAGE_SYSKLOGD_LOGGER=y
|
||||
BR2_PACKAGE_LESS=y
|
||||
BR2_TARGET_ROOTFS_SQUASHFS=y
|
||||
# BR2_TARGET_ROOTFS_TAR is not set
|
||||
BR2_PACKAGE_CONFD=y
|
||||
BR2_PACKAGE_STATD=y
|
||||
BR2_PACKAGE_FACTORY=y
|
||||
BR2_PACKAGE_FINIT_SULOGIN=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOTPLUG=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_HOOK_SCRIPTS=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_MODULES_LOAD=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_RTC=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_TTY=y
|
||||
BR2_PACKAGE_FINIT_PLUGIN_URANDOM=y
|
||||
BR2_PACKAGE_KLISH_PLUGIN_INFIX=y
|
||||
BR2_PACKAGE_NET=y
|
||||
BR2_PACKAGE_PYTHON3=y
|
||||
BR2_PACKAGE_PYTHON3_PYC_ONLY=y
|
||||
# SIGN_ENABLED is not set
|
||||
# GNS3_APPLIANCE is not set
|
||||
+125
-1
@@ -4,6 +4,129 @@ Change Log
|
||||
All notable changes to the project are documented in this file.
|
||||
|
||||
|
||||
[v23.10.0][] - 2023-10-31
|
||||
-------------------------
|
||||
|
||||
> **Note:** upcoming releases will lock the `root` user for system-only
|
||||
> services. Instead an `admin` user will be the only default user with
|
||||
> the CLI as its login shell. This user is already available, so please
|
||||
> consider updating any guidelines or documentation you may have.
|
||||
|
||||
### YANG Status
|
||||
|
||||
- [ietf-system][]:
|
||||
- [infix-system][]: MotD (Message of the Day) augment
|
||||
- [infix-system][]: user login shell augment, default: `/bin/false`
|
||||
- [infix-system-software][]: system-state/software augment for
|
||||
remotely querying firmware version information
|
||||
- [infix-system-software][]: firmware upgrade with `install-bundle` RPC
|
||||
- [infix-system][]: timezone-name deviation, using with IANA timezones,
|
||||
deviation for UTC offset, only support per-hour offsets with [tzdata][].
|
||||
Also, username deviation, clarifying Linux restrictions.
|
||||
- [infix-system][]: deviations for unsupported features, e.g. RADIUS
|
||||
- [ietf-interfaces][]:
|
||||
- [infix-interfaces][]: deviation for `if:phys-address` to allow read-write
|
||||
- [ietf-ip][]: augmented with IPv4LL similar to standardized IPv6LL
|
||||
- [infix-ip][]: deviations (`not-supported`) added for IPv4 and IPv6:
|
||||
- `/if:interfaces/if:interface/ip:ipv4/ip:address/ip:subnet/ip:netmask`
|
||||
- `/if:interfaces/if:interface/ip:ipv6/ip:address/ip:status`
|
||||
- `/if:interfaces/if:interface/ip:ipv4/ip:mtu`
|
||||
- `/if:interfaces/if:interface/ip:ipv6/ip:mtu`
|
||||
- `/if:interfaces/if:interface/ip:ipv4/ip:neighbor`
|
||||
- `/if:interfaces/if:interface/ip:ipv6/ip:neighbor`
|
||||
- ~~[ietf-if-vlan-encapsulation][]:~~ Removed in favor of a native model.
|
||||
- [infix-if-bridge][]: Linux bridge interfaces with native VLAN support
|
||||
- [infix-if-type][]: deviation for interface types, limiting number
|
||||
to supported types only. New identities are derived from default
|
||||
IANA interface types, ensuring compatibility with other standard
|
||||
models, e.g., `ieee802-ethernet-interface.yang`
|
||||
- [infix-if-veth][]: Linux VETH pairs
|
||||
- [infix-if-vlan][]: Linux VLAN interfaces, e.g. `eth0.10` (New model!)
|
||||
- Configurable services:
|
||||
- [ieee802-dot1ab-lldp][]: stripped down to an `enabled` setting
|
||||
- [infix-services][]: support for enabling mDNS service/device discovery
|
||||
|
||||
[tzdata]: https://www.iana.org/time-zones
|
||||
[ieee802-dot1ab-lldp]: https://github.com/kernelkit/infix/tree/50a550b/src/confd/yang/ieee802-dot1ab-lldp%402022-03-15.yang
|
||||
[ietf-system]: https://www.rfc-editor.org/rfc/rfc7317.html
|
||||
[ietf-interfaces]: https://www.rfc-editor.org/rfc/rfc7223.html
|
||||
[ietf-ip]: https://www.rfc-editor.org/rfc/rfc8344.html
|
||||
[ietf-if-vlan-encapsulation]: https://www.ietf.org/id/draft-ietf-netmod-sub-intf-vlan-model-08.html
|
||||
[infix-if-bridge]: https://github.com/kernelkit/infix/blob/fc5310b/src/confd/yang/infix-if-bridge%402023-08-21.yang
|
||||
[infix-if-type]: https://github.com/kernelkit/infix/tree/fc5310b/src/confd/yang/infix-if-type%402023-08-21.yang
|
||||
[infix-if-veth]: https://github.com/kernelkit/infix/tree/fc5310b/src/confd/yang/infix-if-veth%402023-06-05.yang
|
||||
[infix-if-vlan]: https://github.com/kernelkit/infix/blob/fc5310b/src/confd/yang/infix-if-vlan%402023-10-25.yang
|
||||
|
||||
[infix-interfaces]: https://github.com/kernelkit/infix/tree/fc5310b/src/confd/yang/infix-interfaces%402023-09-19.yang
|
||||
[infix-ip]: https://github.com/kernelkit/infix/tree/fc5310b/src/confd/yang/infix-ip%402023-09-14.yang
|
||||
[infix-services]: https://github.com/kernelkit/infix/blob/fc5310b/src/confd/yang/infix-services%402023-10-16.yang
|
||||
[infix-system]: https://github.com/kernelkit/infix/blob/fc5310b/src/confd/yang/infix-system%402023-10-19.yang
|
||||
[infix-system-software]: https://github.com/kernelkit/infix/tree/fc5310b/src/confd/yang/infix-system-software%402023-06-27.yang
|
||||
|
||||
### Changes
|
||||
|
||||
- Add support for setting/querying IPv4/IPv6 MTU, see #152 for details.
|
||||
- Add support for *Fail Secure Mode*: if loading `startup-config` fails,
|
||||
e.g. YANG model validation failure after upgrade, the system now falls back
|
||||
to load `failure-config` instead of just crashing. This config, along with
|
||||
`factory-config`, is generated on every boot to match the active image's
|
||||
YANG models. In case neither config can be loaded, or even bootstrapping
|
||||
YANG models fail, the system will go into an RMA state -- Return to
|
||||
Manufacturer, clearly signaled on the console and, on devices that support
|
||||
it, angry LED signaling. See #154 for more.
|
||||
- Add support for generating GNS3 appliance file for NETCONF Aarch64.
|
||||
- Add support for UTC offset (+/- HH:00) in `ietf-system`, PR #174
|
||||
- Add support for `ietf-factory-default` RPC, PR #175
|
||||
- Add support for performing factory reset (using #175 RPC) from CLI
|
||||
- Replace `ietf-if-vlan-encapsulation` YANG model with the native
|
||||
`infix-if-vlan` model. This fits better with Linux VLAN interfaces and
|
||||
simplifies the syntax greatly. For details, see PR #179
|
||||
|
||||
admin@example:/config/interfaces/interface/eth0.10/> set vlan id 10 lower-layer-if eth0
|
||||
|
||||
- The following new NETCONF interface operational counters have been added:
|
||||
|
||||
| **YANG** | **Linux / Ethtool** |
|
||||
|-----------------------------|-----------------------------------|
|
||||
| `out-frames` | `FramesTransmittedOK` |
|
||||
| `out-multicast-frames` | `MulticastFramesXmittedOK` |
|
||||
| `out-broadcast-frames` | `BroadcastFramesXmittedOK` |
|
||||
| `in-total-frames` | `FramesReceivedOK` |
|
||||
| | + `FrameCheckSequenceErrors` |
|
||||
| | + `FramesLostDueToIntMACRcvError` |
|
||||
| | + `AlignmentErrors` |
|
||||
| | + `etherStatsOversizePkts` |
|
||||
| | + `etherStatsJabbers` |
|
||||
| `in-frames` | `FramesReceivedOK` |
|
||||
| `in-multicast-frames` | `MulticastFramesReceivedOK` |
|
||||
| `in-broadcast-frames` | `BroadcastFramesReceivedOK` |
|
||||
| `in-error-undersize-frames` | `undersize_pkts` |
|
||||
| `in-error-fcs-frames` | `FrameCheckSequenceErrors` |
|
||||
|
||||
- Greatly improved branding support using `make menuconfig`. All the
|
||||
identifying strings, including firmware image, is in `/etc/os-release`, will
|
||||
be used in CLI `show system-information`, the WebUI About dialog, and any
|
||||
prominent areas when booting up (on console), logging in to CLI and WebUI.
|
||||
- IGMP/MLD snooping is now disabled by default on new bridges. Support
|
||||
for multicast filtering bridges expected no later than v24.01.
|
||||
- The SSDP responder, device discovery in Windows, has been removed in favor
|
||||
of Windows 10 (build 1709) native support for mDNS-SD. Details in #166
|
||||
- A GreenPAK programmer has been added, not enabled by default. This is a
|
||||
popular programmable little chip from Renesas. Worth a look!
|
||||
- The `confd` script `gen-interfaces` can now generate bridges and stand-alone
|
||||
interfaces with IPv6 (SLAAC) for `factory-config` et al.
|
||||
- Drop `x86_64_minimal_defconfig`, previously used for regression tests only
|
||||
- Documentation updates of how IPv4/IPv6 addresses are shown in NETCONF
|
||||
operational data, as well as the built-in CLI, see #163 for details.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix #106: confd: drop deviation `ietf-system:timezone-utc-offset`
|
||||
- Fix #151: Operational status broken in v23.09
|
||||
- Fix #159: Hacky generation of `/etc/resolv.conf` at boot
|
||||
- Fix #162: VLAN interface without encapsulation is accepted by YANG model
|
||||
|
||||
|
||||
[v23.09.0][] - 2023-10-02
|
||||
-------------------------
|
||||
|
||||
@@ -216,7 +339,8 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
|
||||
- N/A
|
||||
|
||||
[buildroot]: https://buildroot.org/
|
||||
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v23.08.0...HEAD
|
||||
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v23.10.0...HEAD
|
||||
[v23.10.0]: https://github.com/kernelkit/infix/compare/v23.09.0...v23.10.0
|
||||
[v23.09.0]: https://github.com/kernelkit/infix/compare/v23.08.0...v23.09.0
|
||||
[v23.08.0]: https://github.com/kernelkit/infix/compare/v23.06.0...v23.08.0
|
||||
[v23.06.0]: https://github.com/kernelkit/infix/compare/BASE...v23.06.0
|
||||
|
||||
+26
-1
@@ -103,7 +103,31 @@ Releases
|
||||
--------
|
||||
|
||||
A release build requires the global variable `INFIX_RELEASE` to be set.
|
||||
It can be derived from GIT, if the source tree is kept in GIT VCS.
|
||||
It can be derived from GIT, if the source tree is kept in GIT VCS. First,
|
||||
let us talk about versioning in general.
|
||||
|
||||
### Versioning
|
||||
|
||||
Two popular scheme for versioning a product derived from Infix:
|
||||
|
||||
1. Track Infix major.minor, e.g. *Foobar v23.08.z*, where `z` is
|
||||
your patch level. I.e., Foobar v23.08.0 could be based on Infix
|
||||
v23.08.0, or v23.08.12, it is up to you. Maybe you based it on
|
||||
v23.08.12 and then back ported changes from v23.10.0, but it was
|
||||
the first release you made to your customer(s).
|
||||
2. Start from v1.0.0 and step the major number every time you sync
|
||||
with a new Infix release, or every time Infix bumps to the next
|
||||
Buildroot LTS.
|
||||
|
||||
The important thing is to be consistent, not only for your own sake,
|
||||
but also for your end customers. The *major.minor.patch* style is
|
||||
the most common and often recommended style, which usually maps well
|
||||
to other systems, e.g. PROFINET GSDML files require this (*VX.Y.Z*).
|
||||
But you can of course use only two numbers, *major.minor*, as well.
|
||||
|
||||
> What could be confusing, however, is if you use the name *Infix*
|
||||
> with your own versioning scheme.
|
||||
|
||||
|
||||
### `INFIX_RELEASE`
|
||||
|
||||
@@ -122,3 +146,4 @@ Infix tree and can be changed by setting the menuconfig branding
|
||||
variable `INFIX_OEM_PATH` to that of the br2-external. It is also
|
||||
possible to set the `GIT_VERSION` variable in your `post-build.sh`
|
||||
script to change how the VCS version is extracted.
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# YANG to Ethtool Mapping
|
||||
This column contains the mapping between YANG and Linux / Ethtool counters.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┬──────────────────────────────────┐
|
||||
│ YANG │ Linux / Ethtool │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ out-frames │ FramesTransmittedOK │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ out-multicast-frames │ MulticastFramesXmittedOK │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ out-broadcast-frames │ BroadcastFramesXmittedOK │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ in-total-frames │ FramesReceivedOK, │
|
||||
│ │ FrameCheckSequenceErrors │
|
||||
│ │ FramesLostDueToIntMACRcvError │
|
||||
│ │ AlignmentErrors │
|
||||
│ │ etherStatsOversizePkts │
|
||||
│ │ etherStatsJabbers │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ in-frames │ FramesReceivedOK │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ in-multicast-frames │ MulticastFramesReceivedOK │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ in-broadcast-frames │ BroadcastFramesReceivedOK │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ in-error-undersize-frames │ undersize_pkts │
|
||||
├─────────────────────────────────┼──────────────────────────────────┤
|
||||
│ in-error-fcs-frames │ FrameCheckSequenceErrors │
|
||||
└─────────────────────────────────┴──────────────────────────────────┘
|
||||
```
|
||||
@@ -1,2 +1,3 @@
|
||||
d /run/confd/factory.d - - -
|
||||
d /run/confd/failure.d - - -
|
||||
d /run/resolvconf/interfaces - - -
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# From https://github.com/troglobit/finit/releases/
|
||||
sha256 904af0b0d7b22bcbe7772ea5851a0496445bfb3cff5c9a65935fd74745dcba75 finit-4.5-rc5.tar.gz
|
||||
sha256 ef73d9ba01aefef1a2171483f26339c7aefdf92dd25d7b322f15efa48e78d655 finit-4.5.tar.gz
|
||||
|
||||
# Locally calculated
|
||||
sha256 3a2b964c1772d03ab17b73a389ecce9151e0b190a9247817a2c009b16d356422 LICENSE
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
FINIT_VERSION = 4.5-rc5
|
||||
FINIT_VERSION = 4.5
|
||||
FINIT_SITE = https://github.com/troglobit/finit/releases/download/$(FINIT_VERSION)
|
||||
FINIT_LICENSE = MIT
|
||||
FINIT_LICENSE_FILES = LICENSE
|
||||
@@ -119,6 +119,12 @@ else
|
||||
FINIT_CONF_OPTS += --disable-alsa-utils-plugin
|
||||
endif
|
||||
|
||||
ifeq ($(BR2_PACKAGE_BASH_COMPLETION),y)
|
||||
FINIT_CONF_OPTS += --with-bash-completiond-dir
|
||||
else
|
||||
FINIT_CONF_OPTS += --without-bash-completiond-dir
|
||||
endif
|
||||
|
||||
ifeq ($(BR2_PACKAGE_DBUS),y)
|
||||
FINIT_CONF_OPTS += --enable-dbus-plugin
|
||||
else
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
From 4f0e44e9b494485dc63de3264aa99dad5def5f55 Mon Sep 17 00:00:00 2001
|
||||
From: Henrik Nordstrom <henrik.nordstrom@addiva.se>
|
||||
Date: Wed, 13 Sep 2023 22:45:00 +0200
|
||||
Subject: [PATCH 1/2] cn9130: Default DDR4 4GByte 16-bit/die ECC
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c b/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
|
||||
index 82ce07b09..07753ea97 100644
|
||||
--- a/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
|
||||
+++ b/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c
|
||||
@@ -45,18 +45,18 @@ struct mv_ddr_iface dram_iface_ap0 = {
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0},
|
||||
{0x1, 0x0, 0, 0} },
|
||||
- SPEED_BIN_DDR_2400T, /* speed_bin */
|
||||
- MV_DDR_DEV_WIDTH_8BIT, /* sdram device width */
|
||||
+ SPEED_BIN_DDR_2400R, /* speed_bin */
|
||||
+ MV_DDR_DEV_WIDTH_16BIT, /* sdram device width */
|
||||
MV_DDR_DIE_CAP_8GBIT, /* die capacity */
|
||||
MV_DDR_FREQ_SAR, /* frequency */
|
||||
0, 0, /* cas_l, cas_wl */
|
||||
- MV_DDR_TEMP_LOW} }, /* temperature */
|
||||
+ MV_DDR_TEMP_HIGH} }, /* temperature */
|
||||
#if DDR32
|
||||
MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
|
||||
#else
|
||||
MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
|
||||
#endif
|
||||
- MV_DDR_CFG_SPD, /* ddr configuration data src */
|
||||
+ MV_DDR_CFG_DEFAULT, /* ddr configuration data src */
|
||||
NOT_COMBINED, /* ddr twin-die combined*/
|
||||
{ {0} }, /* raw spd data */
|
||||
{0}, /* timing parameters */
|
||||
--
|
||||
2.34.1
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
From da31240645cdf7ae424727ac330fdb6f6b118691 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Mon, 16 Oct 2023 10:52:19 +0200
|
||||
Subject: [PATCH 2/2] marvell: Allow mv-ddr-marvell to be built from tarball
|
||||
|
||||
Build system relies on the mv-ddr-marvell being a valid GIT working
|
||||
directory, which is not the case when building from a tarball.
|
||||
|
||||
Therefore, reduce this requirement from a hard error to a warning.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
plat/marvell/armada/a8k/common/ble/ble.mk | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/plat/marvell/armada/a8k/common/ble/ble.mk b/plat/marvell/armada/a8k/common/ble/ble.mk
|
||||
index 752ab419d..db817e996 100644
|
||||
--- a/plat/marvell/armada/a8k/common/ble/ble.mk
|
||||
+++ b/plat/marvell/armada/a8k/common/ble/ble.mk
|
||||
@@ -31,5 +31,5 @@ $(MV_DDR_LIB): FORCE
|
||||
# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
|
||||
$(if $(value MV_DDR_PATH),,$(error "Platform '$(PLAT)' for BLE requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
|
||||
$(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
|
||||
- $(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
|
||||
+ $(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(warning "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
|
||||
@+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(MV_DDR_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
From 4348261902b60f93c217f07069a2b5613a933c17 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 17 Oct 2023 13:15:58 +0200
|
||||
Subject: [PATCH 1/5] net: mv88e6xxx: Add reset-gpios support
|
||||
|
||||
If the switch's RESETn signal is under the CPUs control, release it
|
||||
before starting the probe.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/mv88e6xxx.c | 68 ++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 61 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
|
||||
index 64e860e324..1bf7cfd6a6 100644
|
||||
--- a/drivers/net/mv88e6xxx.c
|
||||
+++ b/drivers/net/mv88e6xxx.c
|
||||
@@ -33,6 +33,8 @@
|
||||
#include <miiphy.h>
|
||||
#include <net/dsa.h>
|
||||
|
||||
+#include <asm-generic/gpio.h>
|
||||
+
|
||||
/* Device addresses */
|
||||
#define DEVADDR_PHY(p) (p)
|
||||
#define DEVADDR_SERDES 0x0F
|
||||
@@ -146,6 +148,8 @@ struct mv88e6xxx_priv {
|
||||
int port_reg_base; /* Base of the switch port registers */
|
||||
u8 global1; /* Offset of Switch Global 1 registers */
|
||||
u8 global2; /* Offset of Switch Global 2 registers */
|
||||
+
|
||||
+ struct gpio_desc reset;
|
||||
};
|
||||
|
||||
/* Wait for the current SMI indirect command to complete */
|
||||
@@ -675,6 +679,37 @@ static int mv88e6xxx_probe_mdio(struct udevice *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int mv88e6xxx_probe_reset(struct udevice *dev)
|
||||
+{
|
||||
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
|
||||
+ int err;
|
||||
+
|
||||
+ if (!CONFIG_IS_ENABLED(DM_GPIO))
|
||||
+ return 0;
|
||||
+
|
||||
+ err = gpio_request_by_name(dev, "reset-gpios", 0,
|
||||
+ &priv->reset, GPIOD_IS_OUT);
|
||||
+ if (err && (err != -ENOENT))
|
||||
+ return err;
|
||||
+
|
||||
+ if (dm_gpio_is_valid(&priv->reset)) {
|
||||
+ dm_gpio_set_value(&priv->reset, 0);
|
||||
+ mdelay(10);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mv88e6xxx_remove_reset(struct udevice *dev)
|
||||
+{
|
||||
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ if (CONFIG_IS_ENABLED(DM_GPIO) && dm_gpio_is_valid(&priv->reset)) {
|
||||
+ dm_gpio_set_value(&priv->reset, 1);
|
||||
+ dm_gpio_free(dev, &priv->reset);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int mv88e6xxx_probe(struct udevice *dev)
|
||||
{
|
||||
struct dsa_pdata *dsa_pdata = dev_get_uclass_plat(dev);
|
||||
@@ -684,17 +719,22 @@ static int mv88e6xxx_probe(struct udevice *dev)
|
||||
if (ofnode_valid(dev_ofnode(dev)) &&
|
||||
!ofnode_is_enabled(dev_ofnode(dev))) {
|
||||
dev_dbg(dev, "switch disabled\n");
|
||||
- return -ENODEV;
|
||||
+ ret = -ENODEV;
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
+ ret = mv88e6xxx_probe_reset(dev);
|
||||
+ if (ret)
|
||||
+ goto err;
|
||||
+
|
||||
/* probe internal mdio bus */
|
||||
ret = mv88e6xxx_probe_mdio(dev);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto err_remove_reset;
|
||||
|
||||
ret = mv88e6xxx_priv_reg_offs_pre_init(dev);
|
||||
if (ret)
|
||||
- return ret;
|
||||
+ goto err_remove_reset;
|
||||
|
||||
dev_dbg(dev, "ID=0x%x PORT_BASE=0x%02x GLOBAL1=0x%02x GLOBAL2=0x%02x\n",
|
||||
priv->id, priv->port_reg_base, priv->global1, priv->global2);
|
||||
@@ -716,28 +756,40 @@ static int mv88e6xxx_probe(struct udevice *dev)
|
||||
priv->port_count = 7;
|
||||
break;
|
||||
default:
|
||||
- return -ENODEV;
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_remove_reset;
|
||||
}
|
||||
|
||||
ret = mv88e6xxx_switch_reset(dev);
|
||||
if (ret < 0)
|
||||
- return ret;
|
||||
+ goto err_remove_reset;
|
||||
|
||||
if (mv88e6xxx_6352_family(dev)) {
|
||||
val = mv88e6xxx_get_cmode(dev, dsa_pdata->cpu_port);
|
||||
if (val < 0)
|
||||
- return val;
|
||||
+ goto err_remove_reset;
|
||||
/* initialize serdes */
|
||||
if (val == PORT_REG_STATUS_CMODE_100BASE_X ||
|
||||
val == PORT_REG_STATUS_CMODE_1000BASE_X ||
|
||||
val == PORT_REG_STATUS_CMODE_SGMII) {
|
||||
ret = mv88e6xxx_serdes_init(dev);
|
||||
if (ret < 0)
|
||||
- return ret;
|
||||
+ goto err_remove_reset;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
+
|
||||
+err_remove_reset:
|
||||
+ mv88e6xxx_remove_reset(dev);
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_remove(struct udevice *dev)
|
||||
+{
|
||||
+ mv88e6xxx_remove_reset(dev);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id mv88e6xxx_ids[] = {
|
||||
@@ -750,6 +802,8 @@ U_BOOT_DRIVER(mv88e6xxx) = {
|
||||
.id = UCLASS_DSA,
|
||||
.of_match = mv88e6xxx_ids,
|
||||
.probe = mv88e6xxx_probe,
|
||||
+ .remove = mv88e6xxx_remove,
|
||||
.ops = &mv88e6xxx_dsa_ops,
|
||||
.priv_auto = sizeof(struct mv88e6xxx_priv),
|
||||
+ .flags = DM_FLAG_OS_PREPARE,
|
||||
};
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
From d87aea2f0d0acfa0d54adb20a980256c0ba95023 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 17 Oct 2023 13:20:19 +0200
|
||||
Subject: [PATCH 2/5] net: mv88e6xxx: Support clause 45 addressing on internal
|
||||
MDIO bus
|
||||
|
||||
This is needed to access SERDES registers on newer chips, like the
|
||||
6393X.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/mv88e6xxx.c | 113 +++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 106 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
|
||||
index 1bf7cfd6a6..eddac332e0 100644
|
||||
--- a/drivers/net/mv88e6xxx.c
|
||||
+++ b/drivers/net/mv88e6xxx.c
|
||||
@@ -114,6 +114,9 @@
|
||||
#define SMI_CMD_CLAUSE_22 BIT(12)
|
||||
#define SMI_CMD_CLAUSE_22_OP_READ (2 << 10)
|
||||
#define SMI_CMD_CLAUSE_22_OP_WRITE (1 << 10)
|
||||
+#define SMI_CMD_CLAUSE_45_OP_WADDR (0 << 10)
|
||||
+#define SMI_CMD_CLAUSE_45_OP_WDATA (1 << 10)
|
||||
+#define SMI_CMD_CLAUSE_45_OP_RDATA (3 << 10)
|
||||
#define SMI_CMD_ADDR_SHIFT 5
|
||||
#define SMI_CMD_ADDR_MASK 0x1f
|
||||
#define SMI_CMD_REG_SHIFT 0
|
||||
@@ -126,6 +129,18 @@
|
||||
(SMI_BUSY | SMI_CMD_CLAUSE_22 | SMI_CMD_CLAUSE_22_OP_WRITE) | \
|
||||
(((addr) & SMI_CMD_ADDR_MASK) << SMI_CMD_ADDR_SHIFT) | \
|
||||
(((reg) & SMI_CMD_REG_MASK) << SMI_CMD_REG_SHIFT)
|
||||
+#define XSMI_CMD_WADDR(port, dev) \
|
||||
+ (SMI_BUSY | SMI_CMD_CLAUSE_45_OP_WADDR) | \
|
||||
+ (((port) & SMI_CMD_ADDR_MASK) << SMI_CMD_ADDR_SHIFT) | \
|
||||
+ (((dev) & SMI_CMD_REG_MASK) << SMI_CMD_REG_SHIFT)
|
||||
+#define XSMI_CMD_WDATA(port, dev) \
|
||||
+ (SMI_BUSY | SMI_CMD_CLAUSE_45_OP_WDATA) | \
|
||||
+ (((port) & SMI_CMD_ADDR_MASK) << SMI_CMD_ADDR_SHIFT) | \
|
||||
+ (((dev) & SMI_CMD_REG_MASK) << SMI_CMD_REG_SHIFT)
|
||||
+#define XSMI_CMD_RDATA(port, dev) \
|
||||
+ (SMI_BUSY | SMI_CMD_CLAUSE_45_OP_RDATA) | \
|
||||
+ (((port) & SMI_CMD_ADDR_MASK) << SMI_CMD_ADDR_SHIFT) | \
|
||||
+ (((dev) & SMI_CMD_REG_MASK) << SMI_CMD_REG_SHIFT)
|
||||
|
||||
/* ID register values for different switch models */
|
||||
#define PORT_SWITCH_ID_6020 0x0200
|
||||
@@ -273,7 +288,41 @@ static int mv88e6xxx_phy_wait(struct udevice *dev)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
-static int mv88e6xxx_phy_read_indirect(struct udevice *dev, int phyad, int devad, int reg)
|
||||
+static int mv88e6xxx_phy_read_indirect_c45(struct udevice *dev, int phyad, int devad, int reg)
|
||||
+{
|
||||
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
|
||||
+ int res;
|
||||
+
|
||||
+ res = mv88e6xxx_reg_write(dev, priv->global2,
|
||||
+ GLOBAL2_REG_PHY_DATA, reg);
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ res = mv88e6xxx_reg_write(dev, priv->global2,
|
||||
+ GLOBAL2_REG_PHY_CMD,
|
||||
+ XSMI_CMD_WADDR(phyad, devad));
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ res = mv88e6xxx_phy_wait(dev);
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ res = mv88e6xxx_reg_write(dev, priv->global2,
|
||||
+ GLOBAL2_REG_PHY_CMD,
|
||||
+ XSMI_CMD_RDATA(phyad, devad));
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ res = mv88e6xxx_phy_wait(dev);
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ return mv88e6xxx_reg_read(dev, priv->global2,
|
||||
+ GLOBAL2_REG_PHY_DATA);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_phy_read_indirect_c22(struct udevice *dev, int phyad, int reg)
|
||||
{
|
||||
struct mv88e6xxx_priv *priv = dev_get_priv(dev);
|
||||
int res;
|
||||
@@ -293,8 +342,16 @@ static int mv88e6xxx_phy_read_indirect(struct udevice *dev, int phyad, int devad
|
||||
GLOBAL2_REG_PHY_DATA);
|
||||
}
|
||||
|
||||
-static int mv88e6xxx_phy_write_indirect(struct udevice *dev, int phyad,
|
||||
- int devad, int reg, u16 data)
|
||||
+static int mv88e6xxx_phy_read_indirect(struct udevice *dev, int phyad, int devad, int reg)
|
||||
+{
|
||||
+ if (devad == MDIO_DEVAD_NONE)
|
||||
+ return mv88e6xxx_phy_read_indirect_c22(dev, phyad, reg);
|
||||
+
|
||||
+ return mv88e6xxx_phy_read_indirect_c45(dev, phyad, devad, reg);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_phy_write_indirect_c22(struct udevice *dev, int phyad,
|
||||
+ int reg, u16 data)
|
||||
{
|
||||
struct mv88e6xxx_priv *priv = dev_get_priv(dev);
|
||||
int res;
|
||||
@@ -315,6 +372,50 @@ static int mv88e6xxx_phy_write_indirect(struct udevice *dev, int phyad,
|
||||
return mv88e6xxx_phy_wait(dev);
|
||||
}
|
||||
|
||||
+static int mv88e6xxx_phy_write_indirect_c45(struct udevice *dev, int phyad,
|
||||
+ int devad, int reg, u16 data)
|
||||
+{
|
||||
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
|
||||
+ int res;
|
||||
+
|
||||
+ res = mv88e6xxx_reg_write(dev, priv->global2,
|
||||
+ GLOBAL2_REG_PHY_DATA, reg);
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ res = mv88e6xxx_reg_write(dev, priv->global2,
|
||||
+ GLOBAL2_REG_PHY_CMD,
|
||||
+ XSMI_CMD_WADDR(phyad, devad));
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ res = mv88e6xxx_phy_wait(dev);
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ res = mv88e6xxx_reg_write(dev, priv->global2,
|
||||
+ GLOBAL2_REG_PHY_DATA, data);
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ res = mv88e6xxx_reg_write(dev, priv->global2,
|
||||
+ GLOBAL2_REG_PHY_CMD,
|
||||
+ XSMI_CMD_WDATA(phyad, devad));
|
||||
+ if (res < 0)
|
||||
+ return res;
|
||||
+
|
||||
+ return mv88e6xxx_phy_wait(dev);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_phy_write_indirect(struct udevice *dev, int phyad,
|
||||
+ int devad, int reg, u16 data)
|
||||
+{
|
||||
+ if (devad == MDIO_DEVAD_NONE)
|
||||
+ return mv88e6xxx_phy_write_indirect_c22(dev, phyad, reg, data);
|
||||
+
|
||||
+ return mv88e6xxx_phy_write_indirect_c45(dev, phyad, devad, reg, data);
|
||||
+}
|
||||
+
|
||||
/* Wrapper function to make calls to phy_read_indirect simpler */
|
||||
static int mv88e6xxx_phy_read(struct udevice *dev, int phy, int reg)
|
||||
{
|
||||
@@ -493,15 +594,13 @@ static int mv88e6xxx_priv_reg_offs_pre_init(struct udevice *dev)
|
||||
|
||||
static int mv88e6xxx_mdio_read(struct udevice *dev, int addr, int devad, int reg)
|
||||
{
|
||||
- return mv88e6xxx_phy_read_indirect(dev->parent, DEVADDR_PHY(addr),
|
||||
- MDIO_DEVAD_NONE, reg);
|
||||
+ return mv88e6xxx_phy_read_indirect(dev->parent, DEVADDR_PHY(addr), devad, reg);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_mdio_write(struct udevice *dev, int addr, int devad,
|
||||
int reg, u16 val)
|
||||
{
|
||||
- return mv88e6xxx_phy_write_indirect(dev->parent, DEVADDR_PHY(addr),
|
||||
- MDIO_DEVAD_NONE, reg, val);
|
||||
+ return mv88e6xxx_phy_write_indirect(dev->parent, DEVADDR_PHY(addr), devad, reg, val);
|
||||
}
|
||||
|
||||
static const struct mdio_ops mv88e6xxx_mdio_ops = {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
From c801299f06f0e5c95bd597fe0ce4ad6c3df9a444 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 17 Oct 2023 13:22:00 +0200
|
||||
Subject: [PATCH 3/5] net: mv88e6xxx: Add support for 6393X
|
||||
|
||||
Only built-in copper PHYs are supported as access ports. Support
|
||||
10GBASE-R SERDES connection to CPU.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/net/mv88e6xxx.c | 134 ++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 130 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/mv88e6xxx.c b/drivers/net/mv88e6xxx.c
|
||||
index eddac332e0..4a4a3ae0b1 100644
|
||||
--- a/drivers/net/mv88e6xxx.c
|
||||
+++ b/drivers/net/mv88e6xxx.c
|
||||
@@ -74,6 +74,7 @@
|
||||
#define PORT_REG_STATUS_SPEED_1000 2
|
||||
|
||||
#define PORT_REG_STATUS_CMODE_MASK 0xF
|
||||
+#define PORT_REG_STATUS_CMODE_10GBASE_R 0xd
|
||||
#define PORT_REG_STATUS_CMODE_SGMII 0xa
|
||||
#define PORT_REG_STATUS_CMODE_1000BASE_X 0x9
|
||||
#define PORT_REG_STATUS_CMODE_100BASE_X 0x8
|
||||
@@ -155,6 +156,7 @@
|
||||
#define PORT_SWITCH_ID_6250 0x2500
|
||||
#define PORT_SWITCH_ID_6320 0x1150
|
||||
#define PORT_SWITCH_ID_6352 0x3520
|
||||
+#define PORT_SWITCH_ID_6393 0x3930
|
||||
|
||||
struct mv88e6xxx_priv {
|
||||
int smi_addr;
|
||||
@@ -475,6 +477,17 @@ static bool mv88e6xxx_6352_family(struct udevice *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
+static bool mv88e6xxx_6393_family(struct udevice *dev)
|
||||
+{
|
||||
+ struct mv88e6xxx_priv *priv = dev_get_priv(dev);
|
||||
+
|
||||
+ switch (priv->id) {
|
||||
+ case PORT_SWITCH_ID_6393:
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static int mv88e6xxx_get_cmode(struct udevice *dev, u8 port)
|
||||
{
|
||||
int res;
|
||||
@@ -529,7 +542,7 @@ static int mv88e6xxx_switch_reset(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int mv88e6xxx_serdes_init(struct udevice *dev)
|
||||
+static int mv88e6352_serdes_init(struct udevice *dev)
|
||||
{
|
||||
int val;
|
||||
|
||||
@@ -549,6 +562,107 @@ static int mv88e6xxx_serdes_init(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mv88e6393_serdes_erratum_4_6(struct udevice *dev, int port)
|
||||
+{
|
||||
+ int val;
|
||||
+
|
||||
+ /* mv88e6393x family errata 4.6:
|
||||
+ * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD
|
||||
+ * mode or P0_mode is configured for [x]MII.
|
||||
+ * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
|
||||
+ *
|
||||
+ * It seems that after this workaround the SERDES is automatically
|
||||
+ * powered up (the bit is cleared), so power it down.
|
||||
+ */
|
||||
+ val = mv88e6xxx_phy_read_indirect(dev, port, MDIO_MMD_PHYXS, 0xf002);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ val &= ~BIT(5);
|
||||
+ val |= MDIO_CTRL1_RESET;
|
||||
+ return mv88e6xxx_phy_write_indirect(dev, port, MDIO_MMD_PHYXS, 0xf002, val);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393_serdes_erratum_5_2(struct udevice *dev, int port, int cmode)
|
||||
+{
|
||||
+ static const struct {
|
||||
+ u16 dev, reg, val, mask;
|
||||
+ } fixes[] = {
|
||||
+ { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff },
|
||||
+ { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff },
|
||||
+ { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff },
|
||||
+ { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f },
|
||||
+ { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 },
|
||||
+ { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff },
|
||||
+ { MDIO_MMD_PHYXS, 0xf002, 0x8000, 0x8000 }
|
||||
+ };
|
||||
+ int val, i;
|
||||
+
|
||||
+ /* mv88e6393x family errata 5.2:
|
||||
+ * For optimal signal integrity the following sequence should be applied
|
||||
+ * to SERDES operating in 10G mode. These registers only apply to 10G
|
||||
+ * operation and have no effect on other speeds.
|
||||
+ */
|
||||
+ if (cmode != PORT_REG_STATUS_CMODE_10GBASE_R)
|
||||
+ return 0;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(fixes); ++i) {
|
||||
+ val = mv88e6xxx_phy_read_indirect(dev, port, fixes[i].dev, fixes[i].reg);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ val &= ~fixes[i].mask;
|
||||
+ val |= fixes[i].val;
|
||||
+
|
||||
+ val = mv88e6xxx_phy_write_indirect(dev, port, fixes[i].dev, fixes[i].reg, val);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mv88e6393_serdes_init(struct udevice *dev, int port, int cmode)
|
||||
+{
|
||||
+ u16 base;
|
||||
+ int val;
|
||||
+
|
||||
+ val = mv88e6393_serdes_erratum_4_6(dev, port);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ val = mv88e6393_serdes_erratum_5_2(dev, port, cmode);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ switch (cmode) {
|
||||
+ case PORT_REG_STATUS_CMODE_10GBASE_R:
|
||||
+ base = 0x1000;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
+ val = mv88e6xxx_phy_read_indirect(dev, port, MDIO_MMD_PHYXS, base);
|
||||
+ if (val < 0)
|
||||
+ return val;
|
||||
+
|
||||
+ val &= ~MDIO_CTRL1_LPOWER;
|
||||
+ val |= MDIO_CTRL1_RESET;
|
||||
+
|
||||
+ return mv88e6xxx_phy_write_indirect(dev, port, MDIO_MMD_PHYXS, base, val);
|
||||
+}
|
||||
+
|
||||
+static int mv88e6xxx_serdes_init(struct udevice *dev, int cpu_port, int cmode)
|
||||
+{
|
||||
+ if (mv88e6xxx_6352_family(dev))
|
||||
+ return mv88e6352_serdes_init(dev);
|
||||
+ else if (mv88e6xxx_6393_family(dev))
|
||||
+ return mv88e6393_serdes_init(dev, cpu_port, cmode);
|
||||
+
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* This function is used to pre-configure the required register
|
||||
* offsets, so that the indirect register access to the PHY registers
|
||||
@@ -569,6 +683,15 @@ static int mv88e6xxx_priv_reg_offs_pre_init(struct udevice *dev)
|
||||
*/
|
||||
priv->port_reg_base = 0x10;
|
||||
priv->id = mv88e6xxx_get_switch_id(dev);
|
||||
+ if (priv->id == 0xfff0) {
|
||||
+ /*
|
||||
+ * Look for a newer device in which ports start at
|
||||
+ * offset 0 (6390/6393 and compatible switches).
|
||||
+ */
|
||||
+ priv->port_reg_base = 0;
|
||||
+ priv->id = mv88e6xxx_get_switch_id(dev);
|
||||
+ }
|
||||
+
|
||||
if (priv->id != 0xfff0) {
|
||||
priv->global1 = 0x1B;
|
||||
priv->global2 = 0x1C;
|
||||
@@ -844,6 +967,7 @@ static int mv88e6xxx_probe(struct udevice *dev)
|
||||
case PORT_SWITCH_ID_6176:
|
||||
case PORT_SWITCH_ID_6240:
|
||||
case PORT_SWITCH_ID_6352:
|
||||
+ case PORT_SWITCH_ID_6393:
|
||||
priv->port_count = 11;
|
||||
break;
|
||||
case PORT_SWITCH_ID_6020:
|
||||
@@ -863,15 +987,17 @@ static int mv88e6xxx_probe(struct udevice *dev)
|
||||
if (ret < 0)
|
||||
goto err_remove_reset;
|
||||
|
||||
- if (mv88e6xxx_6352_family(dev)) {
|
||||
+ if (mv88e6xxx_6352_family(dev) ||
|
||||
+ mv88e6xxx_6393_family(dev)) {
|
||||
val = mv88e6xxx_get_cmode(dev, dsa_pdata->cpu_port);
|
||||
if (val < 0)
|
||||
goto err_remove_reset;
|
||||
/* initialize serdes */
|
||||
if (val == PORT_REG_STATUS_CMODE_100BASE_X ||
|
||||
val == PORT_REG_STATUS_CMODE_1000BASE_X ||
|
||||
- val == PORT_REG_STATUS_CMODE_SGMII) {
|
||||
- ret = mv88e6xxx_serdes_init(dev);
|
||||
+ val == PORT_REG_STATUS_CMODE_SGMII ||
|
||||
+ val == PORT_REG_STATUS_CMODE_10GBASE_R) {
|
||||
+ ret = mv88e6xxx_serdes_init(dev, dsa_pdata->cpu_port, val);
|
||||
if (ret < 0)
|
||||
goto err_remove_reset;
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
From 5013dadfd3ba92eba930f8ea0f88c0f34b8c55a5 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Fri, 20 Oct 2023 13:19:41 +0200
|
||||
Subject: [PATCH 4/5] i2c: pcf8575: Properly address chip
|
||||
|
||||
These devices hold a simple shift register that is accessed without
|
||||
any "register" setup.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
drivers/gpio/pcf8575_gpio.c | 16 ++++++++++++++--
|
||||
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpio/pcf8575_gpio.c b/drivers/gpio/pcf8575_gpio.c
|
||||
index d5930d941f..bc0275b901 100644
|
||||
--- a/drivers/gpio/pcf8575_gpio.c
|
||||
+++ b/drivers/gpio/pcf8575_gpio.c
|
||||
@@ -49,9 +49,15 @@ static int pcf8575_i2c_write(struct udevice *dev, unsigned int word)
|
||||
{
|
||||
struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
|
||||
u8 buf[2] = { word & 0xff, word >> 8, };
|
||||
+ struct i2c_msg wmsg = {
|
||||
+ .addr = chip->chip_addr,
|
||||
+ .flags = 0,
|
||||
+ .buf = buf,
|
||||
+ .len = dev_get_driver_data(dev),
|
||||
+ };
|
||||
int ret;
|
||||
|
||||
- ret = dm_i2c_write(dev, 0, buf, dev_get_driver_data(dev));
|
||||
+ ret = dm_i2c_xfer(dev, &wmsg, 1);
|
||||
if (ret)
|
||||
printf("%s i2c write failed to addr %x\n", __func__,
|
||||
chip->chip_addr);
|
||||
@@ -63,9 +69,15 @@ static int pcf8575_i2c_read(struct udevice *dev)
|
||||
{
|
||||
struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
|
||||
u8 buf[2] = {0x00, 0x00};
|
||||
+ struct i2c_msg rmsg = {
|
||||
+ .addr = chip->chip_addr,
|
||||
+ .flags = I2C_M_RD,
|
||||
+ .buf = buf,
|
||||
+ .len = dev_get_driver_data(dev),
|
||||
+ };
|
||||
int ret;
|
||||
|
||||
- ret = dm_i2c_read(dev, 0, buf, dev_get_driver_data(dev));
|
||||
+ ret = dm_i2c_xfer(dev, &rmsg, 1);
|
||||
if (ret) {
|
||||
printf("%s i2c read failed from addr %x\n", __func__,
|
||||
chip->chip_addr);
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -0,0 +1,576 @@
|
||||
From c0495a607652aef38a4d4480ebdb6dd45e3dd9b9 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
Date: Tue, 24 Oct 2023 22:23:44 +0200
|
||||
Subject: [PATCH 5/5] arm64: mvebu: a8k: Add eFuse support
|
||||
|
||||
Add support for reading and burning LD and HD fuses. Use a specialized
|
||||
commandline implementation over the standard "fuse" command because:
|
||||
|
||||
- We want to reference fuses by the die and module they belong to,
|
||||
rather than a plain integer bank ID.
|
||||
|
||||
- Our lines are wider than 32 bits, meaning that we would have to use
|
||||
similar tactics as arch/arm/mach-mvebu/efuse.c in order to support
|
||||
fuse programming, which is cumbersome.
|
||||
|
||||
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
|
||||
---
|
||||
arch/arm/mach-mvebu/Kconfig | 7 +
|
||||
arch/arm/mach-mvebu/armada8k/Makefile | 2 +
|
||||
arch/arm/mach-mvebu/armada8k/efuse.c | 516 ++++++++++++++++++++++++++
|
||||
3 files changed, 525 insertions(+)
|
||||
create mode 100644 arch/arm/mach-mvebu/armada8k/efuse.c
|
||||
|
||||
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
|
||||
index ac484c73f6..45584b4282 100644
|
||||
--- a/arch/arm/mach-mvebu/Kconfig
|
||||
+++ b/arch/arm/mach-mvebu/Kconfig
|
||||
@@ -421,6 +421,13 @@ config MVEBU_EFUSE_VHV_GPIO_ACTIVE_LOW
|
||||
bool "VHV_Enable GPIO is Active Low"
|
||||
depends on MVEBU_EFUSE_VHV_GPIO != ""
|
||||
|
||||
+config MVEBU_8K_EFUSE
|
||||
+ bool "Enable eFuse support"
|
||||
+ depends on ARMADA_8K
|
||||
+ select HEX_DUMP
|
||||
+ help
|
||||
+ Enable support for reading and writing eFuses on mvebu SoCs.
|
||||
+
|
||||
config SECURED_MODE_IMAGE
|
||||
bool "Build image for trusted boot"
|
||||
default false
|
||||
diff --git a/arch/arm/mach-mvebu/armada8k/Makefile b/arch/arm/mach-mvebu/armada8k/Makefile
|
||||
index 0a4756717a..c1be059b85 100644
|
||||
--- a/arch/arm/mach-mvebu/armada8k/Makefile
|
||||
+++ b/arch/arm/mach-mvebu/armada8k/Makefile
|
||||
@@ -3,3 +3,5 @@
|
||||
# Copyright (C) 2016 Stefan Roese <sr@denx.de>
|
||||
|
||||
obj-y = cpu.o cache_llc.o dram.o
|
||||
+
|
||||
+obj-$(CONFIG_MVEBU_8K_EFUSE) += efuse.o
|
||||
diff --git a/arch/arm/mach-mvebu/armada8k/efuse.c b/arch/arm/mach-mvebu/armada8k/efuse.c
|
||||
new file mode 100644
|
||||
index 0000000000..5438d4466d
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-mvebu/armada8k/efuse.c
|
||||
@@ -0,0 +1,516 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0+
|
||||
+/*
|
||||
+ * Copyright (C) 2015-2016 Reinhard Pfau <reinhard.pfau@gdsys.cc>
|
||||
+ */
|
||||
+
|
||||
+#include <command.h>
|
||||
+#include <common.h>
|
||||
+#include <errno.h>
|
||||
+#include <hexdump.h>
|
||||
+
|
||||
+#include <asm/io.h>
|
||||
+
|
||||
+#include <linux/bitops.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/delay.h>
|
||||
+
|
||||
+enum mvebu_efuse_mod {
|
||||
+ MVEBU_EFUSE_MOD_LD0,
|
||||
+ MVEBU_EFUSE_MOD_LD1,
|
||||
+ MVEBU_EFUSE_MOD_HD,
|
||||
+};
|
||||
+
|
||||
+struct mvebu_efuse_ld {
|
||||
+ u32 array[256 / 32];
|
||||
+#define MVEBU_EFUSE_LD_PARITY_BIT BIT(31)
|
||||
+ u32 burn;
|
||||
+};
|
||||
+
|
||||
+struct mvebu_efuse_hd_line {
|
||||
+ u32 array[2];
|
||||
+#define MVEBU_EFUSE_HD_ECC_MASK 0xfe000000
|
||||
+ u32 lock;
|
||||
+ u32 pad;
|
||||
+};
|
||||
+
|
||||
+struct mvebu_efuse_hd {
|
||||
+#define MVEBU_EFUSE_HD_LINES 64
|
||||
+ struct mvebu_efuse_hd_line line[MVEBU_EFUSE_HD_LINES];
|
||||
+};
|
||||
+
|
||||
+struct mvebu_efuse_die {
|
||||
+ union {
|
||||
+ struct {
|
||||
+ u32 resvd0;
|
||||
+ u32 resvd1;
|
||||
+ u32 ctrl;
|
||||
+ };
|
||||
+
|
||||
+ u8 pad_ctrl[0xf00];
|
||||
+ };
|
||||
+
|
||||
+ union {
|
||||
+ struct mvebu_efuse_ld ld;
|
||||
+ u8 pad_ld[0x100];
|
||||
+ };
|
||||
+
|
||||
+ union {
|
||||
+ struct mvebu_efuse_hd hd;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+static const struct mvebu_efuse_die __iomem *mvebu_efuse_dies[] = {
|
||||
+ (void __iomem *)0xf06f8000,
|
||||
+ (void __iomem *)0xf2400000,
|
||||
+};
|
||||
+
|
||||
+static void mvebu_efuse_program_set(const struct mvebu_efuse_die __iomem *die,
|
||||
+ bool enable)
|
||||
+{
|
||||
+ if (enable)
|
||||
+ setbits_le32(&die->ctrl, BIT(31));
|
||||
+ else
|
||||
+ clrbits_le32(&die->ctrl, BIT(31));
|
||||
+}
|
||||
+
|
||||
+static void mvebu_efuse_secure_set(const struct mvebu_efuse_die __iomem *die,
|
||||
+ bool enable)
|
||||
+{
|
||||
+ if (enable)
|
||||
+ setbits_le32(&die->ctrl, BIT(7));
|
||||
+ else
|
||||
+ clrbits_le32(&die->ctrl, BIT(7));
|
||||
+}
|
||||
+
|
||||
+static void mvebu_efuse_ld_select(const struct mvebu_efuse_die __iomem *die,
|
||||
+ bool ld1)
|
||||
+{
|
||||
+ if (ld1)
|
||||
+ setbits_le32(&die->ctrl, BIT(6));
|
||||
+ else
|
||||
+ clrbits_le32(&die->ctrl, BIT(6));
|
||||
+}
|
||||
+
|
||||
+static void mvebu_efuse_ld_read(const struct mvebu_efuse_die __iomem *die,
|
||||
+ bool ld1, struct mvebu_efuse_ld *ld)
|
||||
+{
|
||||
+ size_t i;
|
||||
+
|
||||
+ mvebu_efuse_ld_select(die, ld1);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(ld->array); i++) {
|
||||
+ ld->array[i] = readl(&die->ld.array[i]);
|
||||
+ if (i & 1)
|
||||
+ ld->array[i] &= ~MVEBU_EFUSE_LD_PARITY_BIT;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int mvebu_efuse_ld_write(const struct mvebu_efuse_die __iomem *die,
|
||||
+ bool ld1, bool secure, const struct mvebu_efuse_ld *ld)
|
||||
+{
|
||||
+ size_t i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(ld->array); i++)
|
||||
+ if ((i & 1) && (ld->array[i] & MVEBU_EFUSE_LD_PARITY_BIT))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mvebu_efuse_ld_select(die, ld1);
|
||||
+ mvebu_efuse_program_set(die, true);
|
||||
+ mvebu_efuse_secure_set(die, secure);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(ld->array); i++)
|
||||
+ writel(ld->array[i], &die->ld.array[i]);
|
||||
+
|
||||
+ writel(0, &die->ld.burn);
|
||||
+ mdelay(1);
|
||||
+
|
||||
+ mvebu_efuse_program_set(die, false);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mvebu_efuse_hd_read_line(const struct mvebu_efuse_die __iomem *die,
|
||||
+ u8 line, struct mvebu_efuse_hd_line *hdl)
|
||||
+{
|
||||
+ if (line >= ARRAY_SIZE(die->hd.line))
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ hdl->array[0] = readl(&die->hd.line[line].array[0]);
|
||||
+ hdl->array[1] = readl(&die->hd.line[line].array[1]);
|
||||
+ hdl->array[1] &= ~MVEBU_EFUSE_HD_ECC_MASK;
|
||||
+ hdl->lock = readl(&die->hd.line[line].lock);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mvebu_efuse_hd_write_line(const struct mvebu_efuse_die __iomem *die,
|
||||
+ u8 line, const struct mvebu_efuse_hd_line *hdl)
|
||||
+{
|
||||
+ if (line >= ARRAY_SIZE(die->hd.line))
|
||||
+ return -ERANGE;
|
||||
+
|
||||
+ if (hdl->array[1] & MVEBU_EFUSE_HD_ECC_MASK)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mvebu_efuse_program_set(die, true);
|
||||
+
|
||||
+ writel(hdl->array[0], &die->hd.line[line].array[0]);
|
||||
+ writel(hdl->array[1], &die->hd.line[line].array[1]);
|
||||
+ writel(0, &die->hd.line[line].lock);
|
||||
+ mdelay(1);
|
||||
+
|
||||
+ mvebu_efuse_program_set(die, false);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Commandline interface
|
||||
+ */
|
||||
+
|
||||
+static int mvefuse_die(const char *diestr,
|
||||
+ const struct mvebu_efuse_die __iomem **diep)
|
||||
+{
|
||||
+ if (!strcmp(diestr, "ap")) {
|
||||
+ *diep = mvebu_efuse_dies[0];
|
||||
+ } else if (!strcmp(diestr, "cp0")) {
|
||||
+ *diep = mvebu_efuse_dies[1];
|
||||
+ } else {
|
||||
+ printf("\"%s\" is not a valid die\n", diestr);
|
||||
+ return CMD_RET_USAGE;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mvefuse_mod(const char *fuse, enum mvebu_efuse_mod *modp)
|
||||
+{
|
||||
+ if (!strcmp(fuse, "ld0")) {
|
||||
+ *modp = MVEBU_EFUSE_MOD_LD0;
|
||||
+ } else if (!strcmp(fuse, "ld1")) {
|
||||
+ *modp = MVEBU_EFUSE_MOD_LD1;
|
||||
+ } else if (!strncmp(fuse, "hd", 2)) {
|
||||
+ *modp = MVEBU_EFUSE_MOD_HD;
|
||||
+ } else {
|
||||
+ printf("\"%s\" is not a valid fuse\n", fuse);
|
||||
+ return CMD_RET_USAGE;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define MVEFUSE_LINE_ALL 0xff
|
||||
+
|
||||
+static int mvefuse_line(const char *fuse, u8 *linep)
|
||||
+{
|
||||
+ unsigned long line;
|
||||
+
|
||||
+ if (!strcmp(fuse, "hd")) {
|
||||
+ *linep = MVEFUSE_LINE_ALL;
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ line = simple_strtoul(&fuse[2], NULL, 0);
|
||||
+ if (line >= MVEBU_EFUSE_HD_LINES) {
|
||||
+ printf("\"%s\" is not valid HD fuse\n", fuse);
|
||||
+ return CMD_RET_USAGE;
|
||||
+ }
|
||||
+
|
||||
+ *linep = line;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mvefuse_parse(char * const *argv,
|
||||
+ const struct mvebu_efuse_die __iomem **diep,
|
||||
+ enum mvebu_efuse_mod *modp,
|
||||
+ u8 *linep)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = mvefuse_die(argv[0], diep);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = mvefuse_mod(argv[1], modp);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (*modp != MVEBU_EFUSE_MOD_HD)
|
||||
+ return 0;
|
||||
+
|
||||
+ return mvefuse_line(argv[1], linep);
|
||||
+}
|
||||
+
|
||||
+static int do_mvefuse_md_ld(const struct mvebu_efuse_die __iomem *die,
|
||||
+ bool ld1)
|
||||
+{
|
||||
+ struct mvebu_efuse_ld ld;
|
||||
+
|
||||
+ mvebu_efuse_ld_read(die, ld1, &ld);
|
||||
+
|
||||
+ print_hex_dump("", DUMP_PREFIX_OFFSET, 16, 4,
|
||||
+ ld.array, sizeof(ld.array), false);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int do_mvefuse_md_hd_line(const struct mvebu_efuse_die __iomem *die,
|
||||
+ u8 line)
|
||||
+{
|
||||
+ struct mvebu_efuse_hd_line hdl;
|
||||
+ int err;
|
||||
+
|
||||
+ err = mvebu_efuse_hd_read_line(die, line, &hdl);
|
||||
+ if (err) {
|
||||
+ printf("Unable to read HD line %u: %d\n", line, err);
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ printf("%08x %08x %s\n", hdl.array[0], hdl.array[1],
|
||||
+ hdl.lock ? "[LOCKED]" : "");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int do_mvefuse_md_hd_all(const struct mvebu_efuse_die __iomem *die)
|
||||
+{
|
||||
+ u8 line;
|
||||
+ int err;
|
||||
+
|
||||
+ for (line = 0; line < MVEBU_EFUSE_HD_LINES; line++) {
|
||||
+ printf("Line %02u: ", line);
|
||||
+ err = do_mvefuse_md_hd_line(die, line);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int do_mvefuse_md(struct cmd_tbl *cmdtp, int flag,
|
||||
+ int argc, char *const *argv)
|
||||
+{
|
||||
+ const struct mvebu_efuse_die __iomem *die;
|
||||
+ enum mvebu_efuse_mod mod;
|
||||
+ u8 line;
|
||||
+ int err;
|
||||
+
|
||||
+ if (argc < 3)
|
||||
+ return CMD_RET_USAGE;
|
||||
+
|
||||
+ err = mvefuse_parse(&argv[1], &die, &mod, &line);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ switch (mod) {
|
||||
+ case MVEBU_EFUSE_MOD_LD0:
|
||||
+ return do_mvefuse_md_ld(die, false);
|
||||
+ case MVEBU_EFUSE_MOD_LD1:
|
||||
+ return do_mvefuse_md_ld(die, true);
|
||||
+ case MVEBU_EFUSE_MOD_HD:
|
||||
+ if (line == MVEFUSE_LINE_ALL)
|
||||
+ return do_mvefuse_md_hd_all(die);
|
||||
+ else
|
||||
+ return do_mvefuse_md_hd_line(die, line);
|
||||
+ }
|
||||
+
|
||||
+ return CMD_RET_FAILURE;
|
||||
+}
|
||||
+
|
||||
+static int do_mvefuse_mw_ld(const struct mvebu_efuse_die __iomem *die,
|
||||
+ bool ld1, int argc, char *const *argv,
|
||||
+ bool interactive)
|
||||
+{
|
||||
+ struct mvebu_efuse_ld ld;
|
||||
+ bool secure = false;
|
||||
+ size_t i;
|
||||
+ int err;
|
||||
+
|
||||
+ mvebu_efuse_ld_read(die, ld1, &ld);
|
||||
+
|
||||
+ switch (argc) {
|
||||
+ case 9:
|
||||
+ if (!strcmp(argv[8], "lock"))
|
||||
+ secure = true;
|
||||
+ else
|
||||
+ return CMD_RET_USAGE;
|
||||
+
|
||||
+ /* fallthrough */
|
||||
+ case 8:
|
||||
+ for (i = 0; i < ARRAY_SIZE(ld.array); i++)
|
||||
+ ld.array[i] |= hextoul(argv[i], NULL);
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ return CMD_RET_USAGE;
|
||||
+ }
|
||||
+
|
||||
+ if (interactive) {
|
||||
+ printf("The following values will be written%s into %s:\n",
|
||||
+ secure ? ", and PERMANENTLY LOCKED," : "",
|
||||
+ ld1 ? "LD1" : "LD0");
|
||||
+
|
||||
+ print_hex_dump("", DUMP_PREFIX_OFFSET, 16, 4,
|
||||
+ ld.array, sizeof(ld.array), false);
|
||||
+
|
||||
+ puts("WARNING: This operation is irreversible\n"
|
||||
+ "Are you sure you want to continue? (y/N)\n");
|
||||
+
|
||||
+ if (!confirm_yesno()) {
|
||||
+ puts("Programming aborted\n");
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ err = mvebu_efuse_ld_write(die, ld1, secure, &ld);
|
||||
+ if (err) {
|
||||
+ printf("Failed to program %s: %d\n", ld1 ? "LD1" : "LD0", err);
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int do_mvefuse_mw_hd_line(const struct mvebu_efuse_die __iomem *die,
|
||||
+ u8 line, int argc, char *const *argv,
|
||||
+ bool interactive)
|
||||
+{
|
||||
+ struct mvebu_efuse_hd_line hdl;
|
||||
+ int err;
|
||||
+
|
||||
+ mvebu_efuse_hd_read_line(die, line, &hdl);
|
||||
+ if (hdl.lock) {
|
||||
+ printf("Unable to program LOCKED line HD%u\n", line);
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ switch (argc) {
|
||||
+ case 3:
|
||||
+ /* In contrast to the LD fuse array, HD fuse lines are
|
||||
+ * always locked when programmed, make sure the user
|
||||
+ * is aware of this by requiring the "lock" keyword to
|
||||
+ * be specified. */
|
||||
+ if (strcmp(argv[2], "lock"))
|
||||
+ return CMD_RET_USAGE;
|
||||
+
|
||||
+ hdl.array[0] |= hextoul(argv[0], NULL);
|
||||
+ hdl.array[1] |= hextoul(argv[1], NULL);
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ return CMD_RET_USAGE;
|
||||
+ }
|
||||
+
|
||||
+ if (interactive) {
|
||||
+ printf("The following values will be PERMANENTLY written into HD%u:\n",
|
||||
+ line);
|
||||
+
|
||||
+ printf("%08x %08x\n", hdl.array[0], hdl.array[1]);
|
||||
+
|
||||
+ puts("WARNING: This operation is irreversible\n"
|
||||
+ "Are you sure you want to continue? (y/N)\n");
|
||||
+
|
||||
+ if (!confirm_yesno()) {
|
||||
+ puts("Programming aborted\n");
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ err = mvebu_efuse_hd_write_line(die, line, &hdl);
|
||||
+ if (err) {
|
||||
+ printf("Failed to program HD%u: %d\n", line, err);
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int do_mvefuse_mw(struct cmd_tbl *cmdtp, int flag,
|
||||
+ int argc, char *const *argv)
|
||||
+{
|
||||
+ const struct mvebu_efuse_die __iomem *die;
|
||||
+ enum mvebu_efuse_mod mod;
|
||||
+ bool interactive = true;
|
||||
+ u8 line;
|
||||
+ int err;
|
||||
+
|
||||
+ /* Pop off "md" */
|
||||
+ argv++, argc--;
|
||||
+
|
||||
+ if (argc && (!strcmp("-y", argv[0]))) {
|
||||
+ interactive = false;
|
||||
+ argv++, argc--;
|
||||
+ }
|
||||
+
|
||||
+ if (argc < 2)
|
||||
+ return CMD_RET_USAGE;
|
||||
+
|
||||
+ err = mvefuse_parse(argv, &die, &mod, &line);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ /* Pop off <die> and <fuse> */
|
||||
+ argv++, argc--;
|
||||
+ argv++, argc--;
|
||||
+
|
||||
+ switch (mod) {
|
||||
+ case MVEBU_EFUSE_MOD_LD0:
|
||||
+ return do_mvefuse_mw_ld(die, false, argc, argv, interactive);
|
||||
+ case MVEBU_EFUSE_MOD_LD1:
|
||||
+ return do_mvefuse_mw_ld(die, true, argc, argv, interactive);
|
||||
+ case MVEBU_EFUSE_MOD_HD:
|
||||
+ if (line == MVEFUSE_LINE_ALL)
|
||||
+ return CMD_RET_USAGE;
|
||||
+ else
|
||||
+ return do_mvefuse_mw_hd_line(die, line, argc, argv, interactive);
|
||||
+ }
|
||||
+
|
||||
+ return CMD_RET_FAILURE;
|
||||
+}
|
||||
+
|
||||
+static int do_mvefuse_unlocked(struct cmd_tbl *cmdtp, int flag,
|
||||
+ int argc, char *const argv[])
|
||||
+{
|
||||
+ const struct mvebu_efuse_die __iomem *die;
|
||||
+ struct mvebu_efuse_hd_line hdl;
|
||||
+ enum mvebu_efuse_mod mod;
|
||||
+ u8 line;
|
||||
+ int err;
|
||||
+
|
||||
+ if (argc != 3)
|
||||
+ return CMD_RET_USAGE;
|
||||
+
|
||||
+ err = mvefuse_parse(&argv[1], &die, &mod, &line);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if (mod != MVEBU_EFUSE_MOD_HD) {
|
||||
+ printf("Only HD fuse lines have individual lock bits\n");
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ if (line == MVEFUSE_LINE_ALL) {
|
||||
+ printf("Only an individual fuse line can be tested\n");
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ err = mvebu_efuse_hd_read_line(die, line, &hdl);
|
||||
+ if (err) {
|
||||
+ printf("Unable to read HD%u: %d\n", line, err);
|
||||
+ return CMD_RET_FAILURE;
|
||||
+ }
|
||||
+
|
||||
+ return !!hdl.lock;
|
||||
+}
|
||||
+
|
||||
+U_BOOT_CMD_WITH_SUBCMDS(
|
||||
+ mvefuse, "Marvell eFuse Access",
|
||||
+ "md <die> <fuse> - Dump the contents of <fuse> from <die>\n"
|
||||
+ "mvefuse mw [-y] <die> <fuse> <words...> [lock] - Program <words..> into\n"
|
||||
+ " <fuse> in <die>, optionally permanently locking it\n"
|
||||
+ "mvefuse unlocked <die> hd<0-63> - Test if an HD fuse line on <die> is \n"
|
||||
+ " unlocked\n"
|
||||
+ "\n"
|
||||
+ "<die>: ap|cp0\n"
|
||||
+ "<fuse>: ld0|ld1|hd<0-63>\n",
|
||||
+
|
||||
+ U_BOOT_SUBCMD_MKENT(md, 3, 1, do_mvefuse_md),
|
||||
+ U_BOOT_SUBCMD_MKENT(mw, 12, 1, do_mvefuse_mw),
|
||||
+ U_BOOT_SUBCMD_MKENT(unlocked, 3, 1, do_mvefuse_unlocked));
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
Index: uboot-2023.07.02/arch/arm/dts/cn9130-crb.dtsi
|
||||
===================================================================
|
||||
--- uboot-2023.07.02.orig/arch/arm/dts/cn9130-crb.dtsi
|
||||
+++ uboot-2023.07.02/arch/arm/dts/cn9130-crb.dtsi
|
||||
@@ -239,7 +239,7 @@
|
||||
|
||||
&cp0_eth0 {
|
||||
status = "okay";
|
||||
- phy-mode = "sfi";
|
||||
+ phy-mode = "10gbase-r";
|
||||
};
|
||||
|
||||
&cp0_eth1 {
|
||||
+14
-5
@@ -1,20 +1,26 @@
|
||||
# Defaults for testing bootstrap script -*-conf-*-
|
||||
#set -x
|
||||
|
||||
TESTING=true
|
||||
|
||||
PATH=.:$PATH
|
||||
INIT_DATA=/etc/sysrepo/factory-default.json
|
||||
SEARCH=/usr/share/yang/modules/confd:/usr/share/yang/modules/libnetconf2:/usr/share/yang/modules/libyang:/usr/share/yang/modules/netopeer2:/usr/share/yang/modules/sysrepo
|
||||
|
||||
CFG_PATH_=/tmp/confd
|
||||
CFG_PATH_=/tmp/confd/cfg
|
||||
RUN_PATH_=/tmp/confd/run
|
||||
|
||||
FACTORY_DEFAULTS_D=../share/factory.d
|
||||
FAILURE_DEFAULTS_D=../share/failure.d
|
||||
|
||||
FACTORY_D=$CFG_PATH_/factory.d
|
||||
FAILURE_D=$CFG_PATH_/failure.d
|
||||
FACTORY_D=$RUN_PATH_/factory.d
|
||||
FAILURE_D=$RUN_PATH_/failure.d
|
||||
|
||||
FACTORY_CFG=$CFG_PATH_/factory-config.cfg
|
||||
FAILURE_CFG=$CFG_PATH_/failure-config.cfg
|
||||
FACTORY_GEN=$RUN_PATH_/factory-config.gen
|
||||
FAILURE_GEN=$RUN_PATH_/failure-config.gen
|
||||
|
||||
FACTORY_CFG=$RUN_PATH_/factory-config.cfg
|
||||
FAILURE_CFG=$RUN_PATH_/failure-config.cfg
|
||||
STARTUP_CFG=$CFG_PATH_/startup-config.cfg
|
||||
|
||||
# Uncomment this line in to create a bridge (br0) with all (classified
|
||||
@@ -26,3 +32,6 @@ STARTUP_CFG=$CFG_PATH_/startup-config.cfg
|
||||
# Default hostname in Fail Secure mode, plus last three octets in the base
|
||||
# MAC address, e.g. "failed-c0-ff-ee".
|
||||
FAIL_HOSTNAME="failed"
|
||||
|
||||
# Only needed for testing
|
||||
mkdir -p "$CFG_PATH_" "$RUN_PATH_" "$FACTORY_D" "$FAILURE_D"
|
||||
|
||||
+44
-46
@@ -1,14 +1,14 @@
|
||||
#!/bin/sh
|
||||
# Bootstrap sysrepo db with all modules required by confd
|
||||
# Bootstrap system factory-config, failure-config and sysrepo db.
|
||||
#
|
||||
# 1. Load all yang models with /cfg/factory-config
|
||||
# 2. [ if /cfg/startup-config is missing :: copy {factory} -> /cfg/startup-config ]
|
||||
# 3. Import /cfg/startup -> {startup} ]
|
||||
# 4. Clear running-config :: import NULL -> {running}
|
||||
# 5. Start sysrepo-plugind
|
||||
# 6. Activate startup-config by :: copy {startup} -> {running}
|
||||
# The system factory-config and failure-config are derived from default
|
||||
# settings snippets, from /usr/share/confd/factory.d, and some generated
|
||||
# snippets, e.g., device unique password, hostname (based on base MAC
|
||||
# address), and number of interfaces.
|
||||
#
|
||||
# It's all really simple ... this script takes care of 1-4
|
||||
# The resulting factory-config is used to create the syrepo db (below)
|
||||
# {factory} datastore. Hence, the factory-config file must match the
|
||||
# the YANG models of the active image.
|
||||
#
|
||||
|
||||
# /etc/confdrc controls the behavior or most of the gen-scripts,
|
||||
@@ -27,17 +27,30 @@ fi
|
||||
# shellcheck disable=SC1090
|
||||
. "$RC"
|
||||
|
||||
FACTORY_GEN="$(dirname "$FACTORY_CFG")/$(basename "$FACTORY_CFG" .cfg).gen"
|
||||
FAILURE_GEN="$(dirname "$FAILURE_CFG")/$(basename "$FAILURE_CFG" .cfg).gen"
|
||||
# shellcheck disable=SC2046,SC2086
|
||||
collate()
|
||||
{
|
||||
gen=$1; shift
|
||||
cfg=$1; shift
|
||||
dir=$*
|
||||
|
||||
# Generate device's factory-config at first boot or on override
|
||||
if [ ! -f "$FACTORY_GEN" ] || [ "$FACTORY_OVERRIDE" = "true" ]; then
|
||||
mkdir -p "$FACTORY_D"
|
||||
rm -f "$gen"
|
||||
jq -s 'reduce .[] as $item ({}; . * $item)' $(find $dir -name '*.json' | sort) >"$gen"
|
||||
chmod 444 "$gen"
|
||||
|
||||
# Save the original templates (from the original image) used to create factory-config
|
||||
for file in $(find "$FACTORY_DEFAULTS_D" -type f); do
|
||||
cp "$file" "$FACTORY_D"
|
||||
done
|
||||
if [ ! -f "$cfg" ]; then
|
||||
cp "$gen" "$cfg"
|
||||
fi
|
||||
}
|
||||
|
||||
# TODO: Look for statically defined factory-config, based on the
|
||||
# system's product ID, or just custom site-specific factory.
|
||||
#
|
||||
# If we haven't found a more specific, better match, settle for
|
||||
# factory-config.gen as the system's factory-config.
|
||||
factory()
|
||||
{
|
||||
gen=$1
|
||||
|
||||
# Create an overlay for /etc/hostname to change the default in an br2-external
|
||||
gen-hostname >"$FACTORY_D/20-hostname.json"
|
||||
@@ -52,26 +65,17 @@ if [ ! -f "$FACTORY_GEN" ] || [ "$FACTORY_OVERRIDE" = "true" ]; then
|
||||
|
||||
rm -f "$FACTORY_GEN"
|
||||
# shellcheck disable=SC2046
|
||||
jq -s 'reduce .[] as $item ({}; . * $item)' \
|
||||
$(find "$FACTORY_D" -name '*.json' | sort) >"$FACTORY_GEN"
|
||||
jq -s 'reduce .[] as $item ({}; . * $item)' \
|
||||
$(find "$FACTORY_DEFAULTS_D" "$FACTORY_D" -name '*.json' | sort) \
|
||||
>"$FACTORY_GEN"
|
||||
chmod 444 "$FACTORY_GEN"
|
||||
|
||||
# TODO: Look for statically defined factory-config, based on the
|
||||
# system's product ID, or just custom site-specific factory.
|
||||
collate "$FACTORY_GEN" "$FACTORY_CFG" "$FACTORY_DEFAULTS_D" "$FACTORY_D"
|
||||
}
|
||||
|
||||
# If we haven't found a more specific, better match, settle for
|
||||
# factory-config.gen as the system's factory-config.
|
||||
[ -h "$FACTORY_CFG" ] || ln -sf "$(basename "$FACTORY_GEN")" "$FACTORY_CFG"
|
||||
fi
|
||||
|
||||
# Generate device's failure-config at first boot
|
||||
if [ ! -f "$FAILURE_GEN" ] || [ "$FAILURE_OVERRIDE" = "true" ]; then
|
||||
mkdir -p "$FAILURE_D"
|
||||
|
||||
# Save the original templates (from the original image) used to create failure-config
|
||||
for file in $(find "$FAILURE_DEFAULTS_D" -type f); do
|
||||
cp "$file" "$FAILURE_D"
|
||||
done
|
||||
failure()
|
||||
{
|
||||
gen=$1
|
||||
|
||||
gen-hostname "$FAIL_HOSTNAME" >"$FAILURE_D/20-hostname.json"
|
||||
gen-interfaces >"$FAILURE_D/20-interfaces.json"
|
||||
@@ -81,14 +85,11 @@ if [ ! -f "$FAILURE_GEN" ] || [ "$FAILURE_OVERRIDE" = "true" ]; then
|
||||
# Optional failure/error config to generate (or override) for br2-externals
|
||||
[ -x "$(command -v gen-err-custom)" ] && gen-err-custom >"$FAILURE_D/30-error.json"
|
||||
|
||||
rm -f "$FAILURE_GEN"
|
||||
# shellcheck disable=SC2046
|
||||
jq -s 'reduce .[] as $item ({}; . * $item)' \
|
||||
$(find "$FAILURE_D" -name '*.json' | sort) >"$FAILURE_GEN"
|
||||
chmod 444 "$FAILURE_GEN"
|
||||
collate "$FAILURE_GEN" "$FAILURE_CFG" "$FAILURE_DEFAULTS_D" "$FAILURE_D"
|
||||
}
|
||||
|
||||
[ -h "$FAILURE_CFG" ] || ln -sf "$(basename "$FAILURE_GEN")" "$FAILURE_CFG"
|
||||
fi
|
||||
factory "$FACTORY_GEN"
|
||||
failure "$FAILURE_GEN"
|
||||
|
||||
if [ -n "$TESTING" ]; then
|
||||
echo "Done."
|
||||
@@ -147,11 +148,7 @@ sysrepoctl -s $SEARCH \
|
||||
-i ietf-yang-push@2019-09-09.yang -g wheel -p 0660 \
|
||||
-e on-change \
|
||||
-i iana-if-type@2023-01-26.yang -g wheel -p 0660 \
|
||||
-i ietf-if-extensions@2023-01-26.yang -g wheel -p 0660 \
|
||||
-e sub-interfaces \
|
||||
-i ieee802-dot1q-types@2022-10-29.yang -g wheel -p 0660 \
|
||||
-i ietf-if-vlan-encapsulation@2023-01-26.yang \
|
||||
-g wheel -p 0660 \
|
||||
-i infix-ip@2023-09-14.yang -g wheel -p 0660 \
|
||||
-i infix-if-type@2023-08-21.yang -g wheel -p 0660 \
|
||||
-i infix-interfaces@2023-09-19.yang -g wheel -p 0660 \
|
||||
@@ -160,8 +157,9 @@ sysrepoctl -s $SEARCH \
|
||||
-i infix-lldp@2023-08-23.yang -g wheel -p 0660 \
|
||||
-i infix-dhcp-client@2023-05-22.yang -g wheel -p 0660 \
|
||||
-i infix-shell-type@2023-08-21.yang -g wheel -p 0660 \
|
||||
-i infix-system@2023-08-15.yang -g wheel -p 0660 \
|
||||
-i infix-system@2023-10-19.yang -g wheel -p 0660 \
|
||||
-i infix-services@2023-10-16.yang -g wheel -p 0660 \
|
||||
-i ieee802-ethernet-interface@2019-06-21.yang -g wheel -p 0660 \
|
||||
-I "${INIT_DATA}"
|
||||
rc=$?
|
||||
|
||||
|
||||
@@ -85,13 +85,13 @@ phys_ifaces=$(ip -d -j link show | jq -r '
|
||||
select(.link_type == "ether") |
|
||||
select(.group != "internal") |
|
||||
select(has("parentbus")) |
|
||||
.ifname')
|
||||
.ifname' | sort -V)
|
||||
ports=$(ip -d -j link show group port | jq -r '
|
||||
.[] |
|
||||
select(.link_type == "ether") |
|
||||
select(.group != "internal") |
|
||||
select(has("parentbus")) |
|
||||
.ifname')
|
||||
.ifname' | sort -V)
|
||||
ifaces=""
|
||||
for phy in $phys_ifaces; do
|
||||
found=""
|
||||
|
||||
+12
-6
@@ -15,15 +15,21 @@ if [ "$1" = "-b" ]; then
|
||||
else
|
||||
bootstrap=false
|
||||
fi
|
||||
|
||||
config=$1
|
||||
fn=/cfg/${config}.cfg
|
||||
if [ -f "$config" ]; then
|
||||
fn="$config"
|
||||
else
|
||||
if [ -f "/cfg/${config}.cfg" ]; then
|
||||
fn="/cfg/${config}.cfg"
|
||||
else
|
||||
fn="/run/confd/${config}.cfg"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "$fn" ]; then
|
||||
if [ ! -f "$config" ]; then
|
||||
logger -sik -p user.error "No such file, $fn, aborting!"
|
||||
exit 1
|
||||
fi
|
||||
fn=$config
|
||||
logger -sik -p user.error "No such file, $fn, aborting!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! sysrepocfg -v3 -I"$fn" -f json; then
|
||||
|
||||
+13
-10
@@ -6,15 +6,24 @@ INIT_DATA=/etc/sysrepo/factory-default.json
|
||||
SEARCH=/usr/share/yang/modules/confd:/usr/share/yang/modules/libnetconf2:/usr/share/yang/modules/libyang:/usr/share/yang/modules/netopeer2:/usr/share/yang/modules/sysrepo
|
||||
|
||||
CFG_PATH_=/cfg
|
||||
RUN_PATH_=/run/confd
|
||||
|
||||
# Static defaults, base Infix and any br2-external derivative.
|
||||
FACTORY_DEFAULTS_D=/usr/share/confd/factory.d
|
||||
FAILURE_DEFAULTS_D=/usr/share/confd/failure.d
|
||||
|
||||
FACTORY_D=$CFG_PATH_/factory.d
|
||||
FAILURE_D=$CFG_PATH_/failure.d
|
||||
# Generated config snippets, e.g., hostname, password, and interfaces.
|
||||
FACTORY_D=$RUN_PATH_/factory.d
|
||||
FAILURE_D=$RUN_PATH_/failure.d
|
||||
|
||||
FACTORY_CFG=$CFG_PATH_/factory-config.cfg
|
||||
FAILURE_CFG=$CFG_PATH_/failure-config.cfg
|
||||
# The default config snippets and generated snippets are collated into
|
||||
# RAM-only name-config.gen , which are candidates for name-config.cfg
|
||||
FACTORY_GEN=$RUN_PATH_/factory-config.gen
|
||||
FAILURE_GEN=$RUN_PATH_/failure-config.gen
|
||||
|
||||
# The resulting .cfg files can be peristent (factory-config) or not.
|
||||
FACTORY_CFG=$RUN_PATH_/factory-config.cfg
|
||||
FAILURE_CFG=$RUN_PATH_/failure-config.cfg
|
||||
STARTUP_CFG=$CFG_PATH_/startup-config.cfg
|
||||
|
||||
# Uncomment this line in to create a bridge (br0) with all (classified
|
||||
@@ -26,9 +35,3 @@ STARTUP_CFG=$CFG_PATH_/startup-config.cfg
|
||||
# Default hostname in Fail Secure mode, plus last three octets in the base
|
||||
# MAC address, e.g. "failed-c0-ff-ee".
|
||||
FAIL_HOSTNAME="failed"
|
||||
|
||||
# Uncomment to regenerate factory-config (except hostkeys) on each boot.
|
||||
#FACTORY_OVERRIDE=true
|
||||
|
||||
# Uncomment to regenerate failure-config (except hostkeys) on each boot.
|
||||
#FAILURE_OVERRIDE=true
|
||||
|
||||
@@ -28,6 +28,7 @@ confd_plugin_la_SOURCES = \
|
||||
dagger.c dagger.h \
|
||||
ietf-interfaces.c \
|
||||
ietf-system.c \
|
||||
ietf-factory-default.c \
|
||||
infix-dhcp.c \
|
||||
infix-services.c \
|
||||
infix-factory.c \
|
||||
|
||||
@@ -116,6 +116,9 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv)
|
||||
rc = infix_factory_init(&confd);
|
||||
if (rc)
|
||||
goto err;
|
||||
rc = ietf_factory_default_init(&confd);
|
||||
if(rc)
|
||||
goto err;
|
||||
rc = infix_system_sw_init(&confd);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
@@ -132,6 +132,9 @@ int ietf_system_init(struct confd *confd);
|
||||
/* infix-dhcp.c */
|
||||
int infix_dhcp_init(struct confd *confd);
|
||||
|
||||
/* ietf-factory-default */
|
||||
int ietf_factory_default_init(struct confd *confd);
|
||||
|
||||
/* infix-factory.c */
|
||||
int infix_factory_init(struct confd *confd);
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
|
||||
#include "core.h"
|
||||
|
||||
static int factory_reset(sr_session_ctx_t *session, uint32_t sub_id, const char *xpath,
|
||||
const sr_val_t *input, const size_t input_cnt, sr_event_t event,
|
||||
unsigned request_id, sr_val_t **output, size_t *output_cnt, void *priv)
|
||||
{
|
||||
DEBUG("%s", xpath);
|
||||
return systemf("factory -y");
|
||||
}
|
||||
|
||||
int ietf_factory_default_init(struct confd *confd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
REGISTER_RPC(confd->session, "/ietf-factory-default:factory-reset", factory_reset, NULL, &confd->fsub);
|
||||
return SR_ERR_OK;
|
||||
fail:
|
||||
ERROR("failed: %s", sr_strerror(rc));
|
||||
return rc;
|
||||
}
|
||||
@@ -168,43 +168,37 @@ static int ifchange_cand_infer_vlan(sr_session_ctx_t *session, const char *path)
|
||||
goto out_free_ifname;
|
||||
|
||||
err = srx_nitems(session, &cnt,
|
||||
"%s/ietf-if-extensions:parent-interface", xpath);
|
||||
"%s/infix-if-vlan:vlan"
|
||||
"/lower-layer-if", xpath);
|
||||
if (!err && !cnt) {
|
||||
inferred.data.string_val = ifname;
|
||||
err = srx_set_item(session, &inferred, 0,
|
||||
"%s/ietf-if-extensions:parent-interface", xpath);
|
||||
"%s/infix-if-vlan:vlan"
|
||||
"/lower-layer-if", xpath);
|
||||
if (err)
|
||||
goto out_free_ifname;
|
||||
}
|
||||
|
||||
err = srx_nitems(session, &cnt,
|
||||
"%s"
|
||||
"/ietf-if-extensions:encapsulation"
|
||||
"/ietf-if-vlan-encapsulation:dot1q-vlan"
|
||||
"/outer-tag/tag-type", xpath);
|
||||
"%s/infix-if-vlan:vlan"
|
||||
"/tag-type", xpath);
|
||||
if (!err && !cnt) {
|
||||
inferred.data.string_val = "ieee802-dot1q-types:c-vlan";
|
||||
err = srx_set_item(session, &inferred, 0,
|
||||
"%s"
|
||||
"/ietf-if-extensions:encapsulation"
|
||||
"/ietf-if-vlan-encapsulation:dot1q-vlan"
|
||||
"/outer-tag/tag-type", xpath);
|
||||
"%s/infix-if-vlan:vlan"
|
||||
"/tag-type", xpath);
|
||||
if (err)
|
||||
goto out_free_ifname;
|
||||
}
|
||||
|
||||
err = srx_nitems(session, &cnt,
|
||||
"%s"
|
||||
"/ietf-if-extensions:encapsulation"
|
||||
"/ietf-if-vlan-encapsulation:dot1q-vlan"
|
||||
"/outer-tag/vlan-id", xpath);
|
||||
"%s/infix-if-vlan:vlan"
|
||||
"/id", xpath);
|
||||
if (!err && !cnt) {
|
||||
inferred.data.string_val = vidstr;
|
||||
err = srx_set_item(session, &inferred, 0,
|
||||
"%s"
|
||||
"/ietf-if-extensions:encapsulation"
|
||||
"/ietf-if-vlan-encapsulation:dot1q-vlan"
|
||||
"/outer-tag/vlan-id", xpath);
|
||||
"%s/infix-if-vlan:vlan"
|
||||
"/id", xpath);
|
||||
if (err)
|
||||
goto out_free_ifname;
|
||||
}
|
||||
@@ -891,38 +885,36 @@ static int netdag_gen_veth(struct dagger *net, struct lyd_node *dif,
|
||||
static int netdag_gen_vlan(struct dagger *net, struct lyd_node *dif,
|
||||
struct lyd_node *cif, FILE *ip)
|
||||
{
|
||||
const char *parent = lydx_get_cattr(cif, "parent-interface");
|
||||
const char *ifname = lydx_get_cattr(cif, "name");
|
||||
struct lydx_diff typed, vidd;
|
||||
struct lyd_node *otag;
|
||||
struct lyd_node *vlan;
|
||||
const char *lower_if;
|
||||
const char *proto;
|
||||
int err;
|
||||
|
||||
DEBUG("ifname %s parent %s", ifname, parent);
|
||||
|
||||
err = dagger_add_dep(net, ifname, parent);
|
||||
if (err)
|
||||
return ERR_IFACE(cif, err, "Unable to add dep \"%s\"", parent);
|
||||
|
||||
otag = lydx_get_descendant(lyd_child(dif ? : cif),
|
||||
"encapsulation",
|
||||
"dot1q-vlan",
|
||||
"outer-tag",
|
||||
NULL);
|
||||
if (!otag) {
|
||||
vlan = lydx_get_descendant(lyd_child(dif ? : cif), "vlan", NULL);
|
||||
if (!vlan) {
|
||||
/*
|
||||
* Note: this is only an error if outer-tag is missing
|
||||
* Note: this is only an error if vlan subcontext is missing
|
||||
* from cif, otherwise it just means the interface had a
|
||||
* a change that was not related to the VLAN config.
|
||||
*/
|
||||
if (!dif)
|
||||
ERROR("%s: missing mandatory outer-tag", ifname);
|
||||
ERROR("%s: missing mandatory vlan", ifname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lower_if = lydx_get_cattr(vlan, "lower-layer-if");
|
||||
DEBUG("ifname %s lower if %s\n", ifname, lower_if);
|
||||
|
||||
fprintf(ip, "link add dev %s down link %s type vlan", ifname, parent);
|
||||
err = dagger_add_dep(net, ifname, lower_if);
|
||||
if (err)
|
||||
return ERR_IFACE(cif, err, "Unable to add dep \"%s\"", lower_if);
|
||||
|
||||
if (lydx_get_diff(lydx_get_child(otag, "tag-type"), &typed)) {
|
||||
|
||||
fprintf(ip, "link add dev %s down link %s type vlan", ifname, lower_if);
|
||||
|
||||
if (lydx_get_diff(lydx_get_child(vlan, "tag-type"), &typed)) {
|
||||
proto = bridge_tagtype2str(typed.new);
|
||||
if (!proto)
|
||||
return ERR_IFACE(cif, -ENOSYS, "Unsupported tag type \"%s\"", typed.new);
|
||||
@@ -930,7 +922,7 @@ static int netdag_gen_vlan(struct dagger *net, struct lyd_node *dif,
|
||||
fprintf(ip, " proto %s", proto);
|
||||
}
|
||||
|
||||
if (lydx_get_diff(lydx_get_child(otag, "vlan-id"), &vidd))
|
||||
if (lydx_get_diff(lydx_get_child(vlan, "id"), &vidd))
|
||||
fprintf(ip, " id %s", vidd.new);
|
||||
|
||||
fputc('\n', ip);
|
||||
@@ -996,24 +988,15 @@ static bool netdag_must_del(struct lyd_node *dif, struct lyd_node *cif)
|
||||
{
|
||||
const char *iftype = lydx_get_cattr(cif, "type");
|
||||
|
||||
if (!strcmp(iftype, "infix-if-type:bridge")) {
|
||||
if (is_phys_addr_deleted(dif))
|
||||
return true;
|
||||
} else if (!strcmp(iftype, "infix-if-type:vlan")) {
|
||||
if (strcmp(iftype, "infix-if-type:ethernet")) {
|
||||
if (is_phys_addr_deleted(dif))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lydx_get_cattr(dif, "parent-interface") ||
|
||||
lydx_get_descendant(lyd_child(dif),
|
||||
"encapsulation",
|
||||
"dot1q-vlan",
|
||||
"outer-tag",
|
||||
NULL))
|
||||
if (!strcmp(iftype, "infix-if-type:vlan")) {
|
||||
if (lydx_get_descendant(lyd_child(dif), "vlan", NULL))
|
||||
return true;
|
||||
} else if (!strcmp(iftype, "infix-if-type:veth")) {
|
||||
if (is_phys_addr_deleted(dif))
|
||||
return true;
|
||||
|
||||
if (lydx_get_descendant(lyd_child(dif), "peer", NULL))
|
||||
return true;
|
||||
/*
|
||||
|
||||
@@ -96,6 +96,7 @@ static char *fmtime(time_t t, char *buf, size_t len)
|
||||
struct tm tm;
|
||||
size_t i, n;
|
||||
|
||||
tzset();
|
||||
localtime_r(&t, &tm);
|
||||
n = strftime(buf, len, isofmt, &tm);
|
||||
i = n - 5;
|
||||
@@ -300,6 +301,8 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char *
|
||||
const char *xpath, sr_event_t event, unsigned request_id, void *priv)
|
||||
{
|
||||
char *timezone;
|
||||
char *tz_utc_offset;
|
||||
char tz_name[14];
|
||||
|
||||
switch (event) {
|
||||
case SR_EV_ENABLED: /* first time, on register. */
|
||||
@@ -328,13 +331,20 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char *
|
||||
|
||||
default:
|
||||
return SR_ERR_OK;
|
||||
|
||||
}
|
||||
tz_utc_offset = srx_get_str(session, XPATH_BASE_"/clock/timezone-utc-offset");
|
||||
timezone = srx_get_str(session, XPATH_BASE_"/clock/timezone-name");
|
||||
if (!timezone && !tz_utc_offset) {
|
||||
snprintf(tz_name,sizeof(tz_name),"Etc/UTC");
|
||||
timezone = tz_name;
|
||||
}
|
||||
|
||||
/* XXX: add support also for /ietf-system:system/clock/timezone-utc-offset (deviation) */
|
||||
timezone = srx_get_str(session, XPATH_BASE_"/clock/timezone-name");
|
||||
if (!timezone) {
|
||||
ERROR("Failed reading timezone-name");
|
||||
return SR_ERR_VALIDATION_FAILED;
|
||||
if (tz_utc_offset) {
|
||||
int8_t offset = atol(tz_utc_offset);
|
||||
/* When using Etc/GMT offsets, the +/- is inverted in tzdata. */
|
||||
snprintf(tz_name,sizeof(tz_name), "Etc/GMT%s%.2d", offset>-1?"":"+", -offset);
|
||||
timezone = tz_name;
|
||||
}
|
||||
|
||||
remove("/etc/localtime+");
|
||||
|
||||
@@ -0,0 +1,928 @@
|
||||
module ieee802-ethernet-interface {
|
||||
yang-version 1.1;
|
||||
|
||||
namespace
|
||||
"urn:ieee:std:802.3:yang:ieee802-ethernet-interface";
|
||||
|
||||
prefix ieee802-eth-if;
|
||||
|
||||
import ietf-yang-types {
|
||||
prefix yang;
|
||||
reference "IETF RFC 6991";
|
||||
}
|
||||
|
||||
import ietf-interfaces {
|
||||
prefix if;
|
||||
reference "IETF RFC 8343";
|
||||
}
|
||||
|
||||
import iana-if-type {
|
||||
prefix ianaift;
|
||||
reference "http://www.iana.org/assignments/yang-parameters/
|
||||
iana-if-type@2018-07-03.yang";
|
||||
}
|
||||
|
||||
organization
|
||||
"IEEE Std 802.3 Ethernet Working Group
|
||||
Web URL: http://www.ieee802.org/3/";
|
||||
|
||||
contact
|
||||
"Web URL: http://www.ieee802.org/3/";
|
||||
|
||||
description
|
||||
"This module contains YANG definitions for configuring IEEE Std
|
||||
802.3 Ethernet Interfaces.
|
||||
In this YANG module, 'Ethernet interface' can be interpreted
|
||||
as referring to 'IEEE Std 802.3 compliant Ethernet
|
||||
interfaces'.";
|
||||
|
||||
revision 2019-06-21{
|
||||
description "Initial revision.";
|
||||
reference "IEEE Std 802.3-2018, unless dated explicitly";
|
||||
}
|
||||
|
||||
typedef eth-if-speed-type {
|
||||
type decimal64 {
|
||||
fraction-digits 3;
|
||||
}
|
||||
units "Gb/s";
|
||||
description
|
||||
"Used to represent the configured, negotiated, or actual speed
|
||||
of an Ethernet interface in Gigabits per second (Gb/s),
|
||||
accurate to 3 decimal places (i.e., accurate to 1 Mb/s).";
|
||||
}
|
||||
|
||||
typedef duplex-type {
|
||||
type enumeration {
|
||||
enum full {
|
||||
description
|
||||
"Full duplex.";
|
||||
}
|
||||
enum half {
|
||||
description
|
||||
"Half duplex.";
|
||||
}
|
||||
enum unknown {
|
||||
description
|
||||
"Link is currently disconnected or initializing.";
|
||||
}
|
||||
}
|
||||
default full;
|
||||
description
|
||||
"Used to represent the configured, negotiated, or actual
|
||||
duplex mode of an Ethernet interface.";
|
||||
reference "IEEE Std 802.3, 30.3.1.1.32, aDuplexStatus";
|
||||
}
|
||||
|
||||
typedef pause-fc-direction-type {
|
||||
type enumeration {
|
||||
enum "disabled" {
|
||||
description
|
||||
"Flow-control disabled in both ingress and egress
|
||||
directions, i.e., PAUSE frames are not transmitted and
|
||||
PAUSE frames received in the ingress direction are
|
||||
discarded without processing.";
|
||||
}
|
||||
enum "ingress-only" {
|
||||
description
|
||||
"PAUSE frame based flow control is enabled in the ingress
|
||||
direction only, i.e., PAUSE frames may be transmitted to
|
||||
reduce the ingress traffic flow, but PAUSE frames received
|
||||
in the ingress direction are discarded without reducing
|
||||
the egress traffic rate.";
|
||||
}
|
||||
enum "egress-only" {
|
||||
description
|
||||
"PAUSE frame based flow control is enabled in the egress
|
||||
direction only, i.e., PAUSE frames are not transmitted,
|
||||
but PAUSE frames received in the ingress direction are
|
||||
processed to reduce the egress traffic rate.";
|
||||
}
|
||||
enum "bi-directional" {
|
||||
description
|
||||
"PAUSE frame based flow control is enabled in both ingress
|
||||
and egress directions, i.e., PAUSE frames may be
|
||||
transmitted to reduce the ingress traffic flow, and
|
||||
PAUSE frames received on ingress are processed to reduce
|
||||
the egress traffic rate.";
|
||||
}
|
||||
enum "undefined" {
|
||||
description
|
||||
"Link is currently disconnected or initializing.";
|
||||
}
|
||||
}
|
||||
description
|
||||
"Used to represent the configured, negotiated, or actual
|
||||
PAUSE frame-based flow control setting.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3.1, dot3PauseAdminMode and dot3PauseOperMode";
|
||||
}
|
||||
|
||||
feature ethernet-pfc {
|
||||
description
|
||||
"This device supports Ethernet priority flow-control.";
|
||||
}
|
||||
|
||||
feature ethernet-pause {
|
||||
description
|
||||
"This device supports Ethernet PAUSE.";
|
||||
}
|
||||
|
||||
augment "/if:interfaces/if:interface" {
|
||||
when "derived-from-or-self(if:type, 'ianaift:ethernetCsmacd')" {
|
||||
description
|
||||
"Applies to all P2P Ethernet interfaces.";
|
||||
}
|
||||
description
|
||||
"Augment interface model with Ethernet interface
|
||||
specific configuration nodes.";
|
||||
|
||||
container ethernet {
|
||||
description
|
||||
"Contains all Ethernet interface related configuration.";
|
||||
|
||||
container auto-negotiation {
|
||||
presence
|
||||
"The presence of this container indicates that
|
||||
auto-negotiation is supported on this Ethernet
|
||||
interface.";
|
||||
description
|
||||
"Contains auto-negotiation transmission parameters
|
||||
|
||||
This container contains a data node that allows the
|
||||
advertised duplex value in the negotiation to be
|
||||
restricted.
|
||||
|
||||
If not specified then the default behavior for the duplex
|
||||
data node is to negotiate all available values for the
|
||||
particular type of Ethernet PHY associated with the
|
||||
interface.
|
||||
|
||||
If auto-negotiation is enabled, and PAUSE frame based flow
|
||||
control has not been explicitly configured, then the
|
||||
default PAUSE frame based flow control capabilities that
|
||||
are negotiated allow for bi-directional or egress-only
|
||||
PAUSE frame based flow control.
|
||||
|
||||
If auto-negotiation is enabled, and PAUSE frame based flow
|
||||
control has been explicitly configured, then the
|
||||
configuration settings restrict the values that may be
|
||||
negotiated. However, it should be noted that the protocol
|
||||
does not allow only egress PAUSE frame based flow control
|
||||
to be negotiated without also allowing bi-directional
|
||||
PAUSE frame based flow control.";
|
||||
reference
|
||||
"IEEE Std 802.3, Clause 28 and Annexes 28A-D";
|
||||
|
||||
leaf enable {
|
||||
type boolean;
|
||||
default true;
|
||||
|
||||
description
|
||||
"Controls whether auto-negotiation is enabled or
|
||||
disabled.
|
||||
For interface types that support auto-negotiation then
|
||||
it defaults to being enabled.
|
||||
|
||||
For interface types that do not support auto-negotiation,
|
||||
the related configuration data is ignored.";
|
||||
}
|
||||
leaf negotiation-status {
|
||||
when "../enable = 'true'";
|
||||
type enumeration {
|
||||
enum in-progress {
|
||||
description
|
||||
"The auto-negotiation protocol is running and
|
||||
negotiation is currently in-progress.";
|
||||
}
|
||||
enum complete {
|
||||
description
|
||||
"The auto-negotiation protocol has completed
|
||||
successfully.";
|
||||
}
|
||||
enum failed {
|
||||
description
|
||||
"The auto-negotiation protocol has failed.";
|
||||
}
|
||||
enum unknown {
|
||||
description
|
||||
"The auto-negotiation status is not currently known,
|
||||
this could be because it is still negotiating or the
|
||||
protocol cannot run (e.g., if no medium is present).";
|
||||
}
|
||||
enum no-negotiation {
|
||||
description
|
||||
"No auto-negotiation is executed.
|
||||
The auto-negotation function is either not supported
|
||||
on this interface or has not been enabled.";
|
||||
}
|
||||
}
|
||||
config false;
|
||||
description
|
||||
"The status of the auto-negotiation protocol.";
|
||||
reference
|
||||
"IEEE 802.3, 30.6.1.1.4, aAutoNegAutoConfig";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
leaf duplex {
|
||||
type duplex-type;
|
||||
description
|
||||
"Operational duplex mode of the Ethernet interface.";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.32 aDuplexStatus";
|
||||
}
|
||||
|
||||
leaf speed {
|
||||
type eth-if-speed-type;
|
||||
units "Gb/s";
|
||||
description
|
||||
"Operational speed (data rate) of the Ethernet interface.
|
||||
The default value is implementation-dependent.";
|
||||
}
|
||||
|
||||
container flow-control {
|
||||
description
|
||||
"Holds the different types of Ethernet PAUSE frame based
|
||||
flow control that can be enabled.";
|
||||
container pause {
|
||||
if-feature "ethernet-pause";
|
||||
description
|
||||
"IEEE Std 802.3 PAUSE frame based PAUSE frame based flow
|
||||
control.";
|
||||
reference
|
||||
"IEEE Std 802.3, Annex 31B";
|
||||
leaf direction {
|
||||
type pause-fc-direction-type;
|
||||
description
|
||||
"Indicates which direction PAUSE frame based flow
|
||||
control is enabled in, or whether it is disabled.
|
||||
The default flow-control settings are vendor specific.
|
||||
If auto-negotiation is enabled, then PAUSE based
|
||||
flow-control is negotiated by default.
|
||||
The default value is implementation-dependent.";
|
||||
}
|
||||
|
||||
container statistics {
|
||||
config false;
|
||||
description
|
||||
"Contains the number of PAUSE frames received or
|
||||
transmitted.";
|
||||
leaf in-frames-pause {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of PAUSE MAC Control frames transmitted on
|
||||
this Ethernet interface.
|
||||
|
||||
Discontinuities in the values of counters in
|
||||
this container can occur at re-initialization of the
|
||||
management system, and at other times as indicated
|
||||
by the value of the 'discontinuity-time' leaf
|
||||
defined in the ietf-interfaces YANG module
|
||||
(IETF RFC 8343).";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.4.3 aPAUSEMACCtrlFramesReceived";
|
||||
}
|
||||
leaf out-frames-pause {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of PAUSE MAC Control frames transmitted on
|
||||
this Ethernet interface.
|
||||
|
||||
Discontinuities in the values of counters in
|
||||
this container can occur at re-initialization of the
|
||||
management system, and at other times as indicated
|
||||
by the value of the 'discontinuity-time' leaf
|
||||
defined in the ietf-interfaces YANG module
|
||||
(IETF RFC 8343).";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.4.2
|
||||
aPAUSEMACCtrlFramesTransmitted";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
container pfc {
|
||||
if-feature "ethernet-pfc";
|
||||
description
|
||||
"IEEE Std 802.3 Priority-based flow control.";
|
||||
reference
|
||||
"IEEE Std 802.3, Annex 31D";
|
||||
|
||||
leaf enable {
|
||||
type boolean;
|
||||
|
||||
description
|
||||
"True indicates that IEEE Std 802.3 priority-based
|
||||
flow control is enabled, false indicates that
|
||||
IEEE Std 802.3 priority-based flow control is disabled.
|
||||
For interfaces that have auto-negotiation,
|
||||
the priority-based flow control is enabled by default.";
|
||||
}
|
||||
|
||||
container statistics {
|
||||
config false;
|
||||
description
|
||||
"This container collects all statistics for
|
||||
Ethernet interfaces.";
|
||||
|
||||
leaf in-frames-pfc {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of PFC MAC Control frames received on this
|
||||
Ethernet interface.
|
||||
|
||||
Discontinuities in the values of counters in
|
||||
this container can occur at re-initialization of the
|
||||
management system, and at other times as indicated
|
||||
by the value of the 'discontinuity-time' leaf
|
||||
defined in the ietf-interfaces YANG module
|
||||
(IETF RFC 8343).";
|
||||
reference
|
||||
"IEEE Std 802.3.1, dot3HCInPFCFrames";
|
||||
}
|
||||
|
||||
leaf out-frames-pfc {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of PFC MAC Control frames transmitted on
|
||||
this interface.
|
||||
|
||||
Discontinuities in the values of counters in
|
||||
this container can occur at re-initialization of the
|
||||
management system, and at other times as indicated
|
||||
by the value of the 'discontinuity-time' leaf
|
||||
defined in the ietf-interfaces YANG module
|
||||
(IETF RFC 8343).";
|
||||
reference
|
||||
"IEEE Std 802.3.1, dot3HCInPFCFrames";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
leaf force-flow-control {
|
||||
type boolean;
|
||||
default false;
|
||||
description
|
||||
"Explicitly forces the local PAUSE frame based flow control
|
||||
settings regardless of what has been negotiated.
|
||||
|
||||
Since the auto-negotiation of flow-control settings
|
||||
does not allow all sane combinations to be negotiated
|
||||
(e.g., consider a device that is only capable of sending
|
||||
PAUSE frames connected to a peer device that is only
|
||||
capable of receiving and acting on PAUSE frames) and
|
||||
failing to agree on the flow-control settings does not
|
||||
cause the auto-negotiation to fail completely, then it is
|
||||
sometimes useful to be able to explicitly enable
|
||||
particular PAUSE frame based flow control settings on
|
||||
the local device regardless of what is being advertised
|
||||
or negotiated.";
|
||||
reference
|
||||
"IEEE Std 802.3, Table 28B-3";
|
||||
}
|
||||
}
|
||||
|
||||
leaf max-frame-length {
|
||||
type uint16;
|
||||
units octets;
|
||||
config false;
|
||||
description
|
||||
"This indicates the MAC frame length (including FCS bytes)
|
||||
at which frames are dropped for being too long.";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.37 aMaxFrameLength";
|
||||
}
|
||||
|
||||
leaf mac-control-extension-control {
|
||||
type boolean;
|
||||
config false;
|
||||
description
|
||||
"A value that identifies the current EXTENSION MAC Control
|
||||
function, as specified in IEEE Std 802.3, Annex 31C.";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.8.3 aEXTENSIONMACCtrlStatus
|
||||
IEEE Std 802.3.1, dot3ExtensionMacCtrlStatus ";
|
||||
}
|
||||
|
||||
leaf frame-limit-slow-protocol {
|
||||
type uint64;
|
||||
units f/s;
|
||||
default 10;
|
||||
config false;
|
||||
description
|
||||
"The maximum number of Slow Protocol frames of a given
|
||||
subtype that can be transmitted in a one second interval.
|
||||
The default value is 10.";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.38 aSlowProtocolFrameLimit";
|
||||
}
|
||||
|
||||
container capabilities {
|
||||
config false;
|
||||
description
|
||||
"Container all Ethernet interface specific capabilities.";
|
||||
|
||||
leaf auto-negotiation {
|
||||
type boolean;
|
||||
description
|
||||
"Indicates whether auto-negotiation may be configured on
|
||||
this interface.";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
container statistics {
|
||||
config false;
|
||||
description
|
||||
"Contains statistics specific to Ethernet interfaces.
|
||||
|
||||
Discontinuities in the values of counters in the
|
||||
container can occur at re-initialization of the management
|
||||
system, and at other times as indicated by the value of
|
||||
the 'discontinuity-time' leaf defined in the
|
||||
ietf-interfaces YANG module (IETF RFC 8343).";
|
||||
|
||||
container frame {
|
||||
description
|
||||
"Contains frame statistics specific to Ethernet
|
||||
interfaces.
|
||||
|
||||
All octet frame lengths include the 4 byte FCS.
|
||||
|
||||
Error counters are only reported once ... The count
|
||||
represented by an instance of this object is incremented
|
||||
when the frameCheckError status is returned by the MAC
|
||||
service to the LLC (or other MAC user). Received frames
|
||||
for which multiple error conditions pertain are,
|
||||
according to the conventions of IEEE Std 802.3 Layer
|
||||
Management, counted exclusively according to the error
|
||||
status presented to the LLC.
|
||||
|
||||
A frame that is counted by an instance of this object is
|
||||
also counted by the corresponding instance of 'in-errors'
|
||||
leaf defined in the ietf-interfaces YANG module
|
||||
(IETF RFC 8343).
|
||||
|
||||
Discontinuities in the values of counters in the
|
||||
container can occur at re-initialization of the
|
||||
management system, and at other times as indicated by
|
||||
the value of the 'discontinuity-time' leaf defined in
|
||||
the ietf-interfaces YANG module (IETF RFC 8343).";
|
||||
|
||||
leaf in-total-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"The total number of frames (including bad frames)
|
||||
received on the Ethernet interface.
|
||||
|
||||
This counter is calculated by summing the following
|
||||
IEEE Std 802.3, Clause 30 counters:
|
||||
aFramesReceivedOK +
|
||||
aFrameCheckSequenceErrors +
|
||||
aAlignmentErrors +
|
||||
aFrameTooLongErrors +
|
||||
aFramesLostDueToIntMACRcvError
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, Clause 30 counters, as specified
|
||||
in the description above.";
|
||||
}
|
||||
|
||||
leaf in-total-octets {
|
||||
type yang:counter64;
|
||||
units octets;
|
||||
description
|
||||
"The total number of octets of data (including those in
|
||||
bad frames) received on the Ethernet interface.
|
||||
|
||||
Includes the 4-octet FCS.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IETF RFC 2819, etherStatsOctets";
|
||||
}
|
||||
|
||||
leaf in-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of frames (including unicast, multicast and
|
||||
broadcast) that have been successfully received on the
|
||||
Ethernet interface.
|
||||
|
||||
This count does not include frames received with
|
||||
frame-too-long, FCS, length or alignment errors, or
|
||||
frames lost due to internal MAC sublayer error.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.5 aFramesReceivedOK";
|
||||
}
|
||||
|
||||
leaf in-multicast-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of multicast frames that have been
|
||||
successfully received on the Ethernet interface.
|
||||
|
||||
This counter represents a subset of the frames counted
|
||||
by in-frames.
|
||||
|
||||
This count does not include frames received with
|
||||
frame-too-long, FCS, length or alignment errors, or
|
||||
frames lost due to internal MAC sublayer error.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.21 aMulticastFramesReceivedOK";
|
||||
}
|
||||
|
||||
leaf in-broadcast-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of broadcast frames that have been
|
||||
successfully received on the Ethernet interface.
|
||||
|
||||
This counter represents a subset of the frames counted
|
||||
by in-frames.
|
||||
|
||||
This count does not include frames received with
|
||||
frame-too-long, FCS, length or alignment errors, or
|
||||
frames lost due to internal MAC sublayer error.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.22 aBroadcastFramesReceivedOK";
|
||||
}
|
||||
|
||||
leaf in-error-fcs-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of receive frames that are of valid length,
|
||||
but do not pass the FCS check, regardless of whether
|
||||
or not the frames are an integral number of octets in
|
||||
length.
|
||||
|
||||
This count effectively comprises
|
||||
aFrameCheckSequenceErrors and aAlignmentErrors added
|
||||
together.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.6 aFrameCheckSequenceErrors;
|
||||
IEEE Std 802.3, 30.3.1.1.7 aAlignmentErrors";
|
||||
}
|
||||
|
||||
leaf in-error-undersize-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of frames received on a particular Ethernet
|
||||
interface that are less than 64 bytes in length, and
|
||||
are discarded.
|
||||
|
||||
This counter is incremented regardless of whether the
|
||||
frame passes the FCS check.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IETF RFC 2819, etherStatsUndersizePkts and
|
||||
etherStatsFragments";
|
||||
}
|
||||
|
||||
leaf in-error-oversize-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of frames received on a particular Ethernet
|
||||
interface that exceed the maximum permitted frame
|
||||
size, that is specified in max-frame-length, and are
|
||||
discarded.
|
||||
|
||||
This counter is incremented regardless of whether the
|
||||
frame passes the FCS check.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference "IEEE Std 802.3, 30.3.1.1.25 aFrameTooLongErrors";
|
||||
}
|
||||
|
||||
leaf in-error-mac-internal-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of frames for which reception on a particular
|
||||
Ethernet interface fails due to an internal MAC
|
||||
sublayer receive error.
|
||||
|
||||
A frame is only counted by an instance of this object
|
||||
if it is not counted by the corresponding instance of
|
||||
either the in-error-fcs-frames, in-error-undersize-frames,
|
||||
or in-error-oversize-frames. The precise meaning of the
|
||||
count represented by an instance of this object is
|
||||
implementation-specific.
|
||||
|
||||
In particular, an instance of this object may
|
||||
represent a count of receive errors on a particular
|
||||
Ethernet interface that are not otherwise counted.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.15
|
||||
aFramesLostDueToIntMACRcvError";
|
||||
}
|
||||
|
||||
leaf out-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of frames (including unicast, multicast and
|
||||
broadcast) that have been successfully transmitted on
|
||||
the Ethernet interface.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.2 aFramesTransmittedOK";
|
||||
}
|
||||
|
||||
leaf out-multicast-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of multicast frames that have been
|
||||
successfully transmitted on the Ethernet interface.
|
||||
|
||||
This counter represents a subset of the frames counted
|
||||
by out-frames.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.18 aMulticastFramesXmittedOK";
|
||||
}
|
||||
|
||||
leaf out-broadcast-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of broadcast frames that have been
|
||||
successfully transmitted on the Ethernet interface.
|
||||
|
||||
This counter represents a subset of the frames counted
|
||||
by out-frames.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.19 aBroadcastFramesXmittedOK";
|
||||
}
|
||||
|
||||
leaf out-error-mac-internal-frames {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of frames for which transmission on a
|
||||
particular Ethernet interface fails due to an internal
|
||||
MAC sublayer transmit error.
|
||||
|
||||
The precise meaning of the count represented by an
|
||||
instance of this object is implementation-specific. In
|
||||
particular, an instance of this object may represent a
|
||||
count of transmission errors on a particular Ethernet
|
||||
interface that are not otherwise counted.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.1.1.12
|
||||
aFramesLostDueToIntMACXmitError";
|
||||
}
|
||||
}
|
||||
|
||||
container phy {
|
||||
description
|
||||
"Ethernet statistics related to the PHY layer.
|
||||
|
||||
Discontinuities in the values of counters in the
|
||||
container can occur at re-initialization of the
|
||||
management system, and at other times as indicated by
|
||||
the value of the 'discontinuity-time' leaf defined in
|
||||
the ietf-interfaces YANG module (IETF RFC 8343).";
|
||||
|
||||
leaf in-error-symbol {
|
||||
type yang:counter64;
|
||||
units errors;
|
||||
description
|
||||
"A count of the number of symbol errors that have
|
||||
occurred.
|
||||
|
||||
For the precise definition of when the symbol error
|
||||
counter is incremented, please see the 'description'
|
||||
text associated with aSymbolErrorDuringCarrier,
|
||||
specified in IEEE Std 802.3, 30.3.2.1.5.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'phy-statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.2.1.5 aSymbolErrorDuringCarrier";
|
||||
}
|
||||
|
||||
container lpi {
|
||||
description
|
||||
"Physical Ethernet statistics for the energy efficiency
|
||||
related low power idle indications.";
|
||||
|
||||
leaf in-lpi-transitions {
|
||||
type yang:counter64;
|
||||
units transitions;
|
||||
description
|
||||
"A count of occurrences of the transition from
|
||||
DEASSERT to ASSERT of the LPI_INDICATE
|
||||
parameter. The indication reflects the state of the
|
||||
PHY according to the requirements of the RS (see
|
||||
IEEE Std 802.3, 22.7, 35.4, and 46.4).
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'phy-statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.2.1.11 aReceiveLPITransitions";
|
||||
}
|
||||
|
||||
leaf in-lpi-time {
|
||||
type decimal64 {
|
||||
fraction-digits 6;
|
||||
}
|
||||
units seconds;
|
||||
description
|
||||
"A count reflecting the total amount of time (in
|
||||
seconds) that the LPI_REQUEST parameter has the
|
||||
value ASSERT. The request is indicated to the PHY
|
||||
according to the requirements of the RS (see IEEE Std
|
||||
802.3, 22.7, 35.4, and 46.4).
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'phy-statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.2.1.9 aReceiveLPIMicroseconds";
|
||||
}
|
||||
|
||||
leaf out-lpi-transitions {
|
||||
type yang:counter64;
|
||||
units transitions;
|
||||
description
|
||||
"A count of occurrences of the transition from state
|
||||
LPI_DEASSERTED to state LPI_ASSERTED in the LPI
|
||||
transmit state diagram of the RS. The state
|
||||
transition corresponds to the assertion of the
|
||||
LPI_REQUEST parameter. The request is indicated to
|
||||
the PHY according to the requirements of the RS (see
|
||||
IEEE Std 802.3, 22.7, 35.4, 46.4.)
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'phy-statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.2.1.10 aTransmitLPITransitions";
|
||||
}
|
||||
|
||||
leaf out-lpi-time {
|
||||
type decimal64 {
|
||||
fraction-digits 6;
|
||||
}
|
||||
units seconds;
|
||||
description
|
||||
"A count reflecting the total amount of time (in
|
||||
seconds) that the LPI_INDICATION parameter has the
|
||||
value ASSERT. The request is indicated to the PHY
|
||||
according to the requirements of the RS (see IEEE
|
||||
802.3, 22.7, 35.4, and 46.4).
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'phy-statistics' container for additional
|
||||
common semantics related to this counter.";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.2.1.8 aTransmitLPIMicroseconds";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
container mac-control {
|
||||
description
|
||||
"A group of statistics specific to MAC Control operation
|
||||
of selected Ethernet interfaces.
|
||||
|
||||
Discontinuities in the values of counters in the
|
||||
container can occur at re-initialization of the
|
||||
management system, and at other times as indicated by
|
||||
the value of the 'discontinuity-time' leaf defined in
|
||||
the ietf-interfaces YANG module (IETF RFC 8343).";
|
||||
|
||||
reference
|
||||
"IEEE Std 802.3.1, dot3ExtensionTable";
|
||||
|
||||
leaf in-frames-mac-control-unknown {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of MAC Control frames with an unsupported
|
||||
opcode received on this Ethernet interface.
|
||||
|
||||
Frames counted against this counter are also counted
|
||||
against in-discards defined in the ietf-interfaces
|
||||
YANG module (IETF RFC 8343).
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'mac-control-statistics' container for
|
||||
additional semantics.";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.3.5 aUnsupportedOpcodesReceived";
|
||||
}
|
||||
|
||||
leaf in-frames-mac-control-extension {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"The count of Extension MAC Control frames received on
|
||||
this Ethernet interface.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'mac-control-statistics' container for
|
||||
additional semantics.";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.8.2
|
||||
aEXTENSIONMACCtrlFramesReceived";
|
||||
}
|
||||
|
||||
leaf out-frames-mac-control-extension {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"The count of Extension MAC Control frames transmitted
|
||||
on this Ethernet interface.
|
||||
|
||||
Also see the 'description' statement associated with
|
||||
the parent 'mac-control-statistics' container for
|
||||
additional semantics.";
|
||||
reference
|
||||
"IEEE Std 802.3, 30.3.8.1
|
||||
aEXTENSIONMACCtrlFramesTransmitted";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,535 +0,0 @@
|
||||
module ietf-if-extensions {
|
||||
yang-version 1.1;
|
||||
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-if-extensions";
|
||||
|
||||
prefix if-ext;
|
||||
|
||||
import ietf-yang-types {
|
||||
prefix yang;
|
||||
reference "RFC 6991: Common YANG Data Types";
|
||||
}
|
||||
|
||||
import ietf-interfaces {
|
||||
prefix if;
|
||||
reference
|
||||
"RFC 8343: A YANG Data Model For Interface Management";
|
||||
}
|
||||
|
||||
import iana-if-type {
|
||||
prefix ianaift;
|
||||
reference "RFC 7224: IANA Interface Type YANG Module";
|
||||
}
|
||||
|
||||
organization
|
||||
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <http://tools.ietf.org/wg/netmod/>
|
||||
WG List: <mailto:netmod@ietf.org>
|
||||
|
||||
Editor: Robert Wilton
|
||||
<mailto:rwilton@cisco.com>";
|
||||
|
||||
description
|
||||
"This module contains common definitions for extending the IETF
|
||||
interface YANG model (RFC 8343) with common configurable layer 2
|
||||
properties.
|
||||
|
||||
Copyright (c) 2023 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject to
|
||||
the license terms contained in, the Revised BSD License set
|
||||
forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(https://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC XXXX
|
||||
(https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself
|
||||
for full legal notices.
|
||||
|
||||
The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
|
||||
NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
|
||||
'MAY', and 'OPTIONAL' in this document are to be interpreted as
|
||||
described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
|
||||
they appear in all capitals, as shown here.";
|
||||
|
||||
revision 2023-01-26 {
|
||||
description
|
||||
"Initial revision.";
|
||||
|
||||
reference
|
||||
"RFC XXXX, Common Interface Extension YANG Data Models";
|
||||
}
|
||||
|
||||
feature link-flap-suppression {
|
||||
description
|
||||
"This feature indicates that configurable interface link
|
||||
delay is supported, which is a feature is used to limit the
|
||||
propagation of very short interface link state flaps.";
|
||||
reference "RFC XXXX, Section 2.1 Link Flap Suppression";
|
||||
}
|
||||
|
||||
feature dampening {
|
||||
description
|
||||
"This feature indicates that the device supports interface
|
||||
dampening, which is a feature that is used to limit the
|
||||
propagation of interface link state flaps over longer
|
||||
periods.";
|
||||
reference "RFC XXXX, Section 2.2 Dampening";
|
||||
}
|
||||
|
||||
feature loopback {
|
||||
description
|
||||
"This feature indicates that configurable interface loopback is
|
||||
supported.";
|
||||
reference "RFC XXXX, Section 2.4 Loopback";
|
||||
}
|
||||
|
||||
feature max-frame-size {
|
||||
description
|
||||
"This feature indicates that the device supports configuring or
|
||||
reporting the maximum frame size on interfaces.";
|
||||
reference "RFC XXXX, Section 2.5 Maximum Frame Size";
|
||||
}
|
||||
|
||||
feature sub-interfaces {
|
||||
description
|
||||
"This feature indicates that the device supports the
|
||||
instantiation of sub-interfaces. Sub-interfaces are defined
|
||||
as logical child interfaces that allow features and forwarding
|
||||
decisions to be applied to a subset of the traffic processed
|
||||
on the specified parent interface.";
|
||||
reference "RFC XXXX, Section 2.6 Sub-interface";
|
||||
}
|
||||
|
||||
/*
|
||||
* Define common identities to help allow interface types to be
|
||||
* assigned properties.
|
||||
*/
|
||||
identity sub-interface {
|
||||
description
|
||||
"Base type for generic sub-interfaces.
|
||||
|
||||
New or custom interface types can derive from this type to
|
||||
inherit generic sub-interface configuration.";
|
||||
reference "RFC XXXX, Section 2.6 Sub-interface";
|
||||
}
|
||||
|
||||
identity ethSubInterface{
|
||||
base ianaift:l2vlan;
|
||||
base sub-interface;
|
||||
|
||||
description
|
||||
"This identity represents the child sub-interface of any
|
||||
interface types that uses Ethernet framing (with or without
|
||||
802.1Q tagging).";
|
||||
}
|
||||
|
||||
identity loopback {
|
||||
description "Base identity for interface loopback options";
|
||||
reference "RFC XXXX, Section 2.4";
|
||||
}
|
||||
identity internal {
|
||||
base loopback;
|
||||
description
|
||||
"All egress traffic on the interface is internally looped back
|
||||
within the interface to be received on the ingress path.";
|
||||
reference "RFC XXXX, Section 2.4";
|
||||
}
|
||||
identity line {
|
||||
base loopback;
|
||||
description
|
||||
"All ingress traffic received on the interface is internally
|
||||
looped back within the interface to the egress path.";
|
||||
reference "RFC XXXX, Section 2.4";
|
||||
}
|
||||
identity connector {
|
||||
base loopback;
|
||||
description
|
||||
"The interface has a physical loopback connector attached that
|
||||
loops all egress traffic back into the interface's ingress
|
||||
path, with equivalent semantics to loopback internal.";
|
||||
reference "RFC XXXX, Section 2.4";
|
||||
}
|
||||
|
||||
identity forwarding-mode {
|
||||
description "Base identity for forwarding-mode options.";
|
||||
reference "RFC XXXX, Section 2.7";
|
||||
}
|
||||
identity physical {
|
||||
base forwarding-mode;
|
||||
description
|
||||
"Physical layer forwarding. This includes DWDM or OTN based
|
||||
optical switching.";
|
||||
reference "RFC XXXX, Section 2.7";
|
||||
}
|
||||
identity data-link {
|
||||
base forwarding-mode;
|
||||
description
|
||||
"Layer 2 based forwarding, such as Ethernet/VLAN based
|
||||
switching, or L2VPN services.";
|
||||
reference "RFC XXXX, Section 2.7";
|
||||
}
|
||||
identity network {
|
||||
base forwarding-mode;
|
||||
description
|
||||
"Network layer based forwarding, such as IP, MPLS, or L3VPNs.";
|
||||
reference "RFC XXXX, Section 2.7";
|
||||
}
|
||||
|
||||
/*
|
||||
* Augments the IETF interfaces model with leaves to configure
|
||||
* and monitor link-flap-suppression on an interface.
|
||||
*/
|
||||
augment "/if:interfaces/if:interface" {
|
||||
description
|
||||
"Augments the IETF interface model with optional common
|
||||
interface level commands that are not formally covered by any
|
||||
specific standard.";
|
||||
|
||||
/*
|
||||
* Defines standard YANG for the Link Flap Suppression feature.
|
||||
*/
|
||||
container link-flap-suppression {
|
||||
if-feature "link-flap-suppression";
|
||||
description
|
||||
"Holds link flap related feature configuration.";
|
||||
leaf down {
|
||||
type uint32;
|
||||
units milliseconds;
|
||||
description
|
||||
"Delays the propagation of a 'loss of carrier signal' event
|
||||
that would cause the interface state to go down, i.e. the
|
||||
command allows short link flaps to be suppressed. The
|
||||
configured value indicates the minimum time interval (in
|
||||
milliseconds) that the link signal must be continuously
|
||||
down before the interface state is brought down. If not
|
||||
configured, the behavior on loss of link signal is
|
||||
vendor/interface specific, but with the general
|
||||
expectation that there should be little or no delay.";
|
||||
}
|
||||
leaf up {
|
||||
type uint32;
|
||||
units milliseconds;
|
||||
description
|
||||
"Defines the minimum time interval (in milliseconds) that
|
||||
the link signal must be continuously present and error
|
||||
free before the interface state is allowed to transition
|
||||
from down to up. If not configured, the behavior is
|
||||
vendor/interface specific, but with the general
|
||||
expectation that sufficient default delay should be used
|
||||
to ensure that the interface is stable when enabled before
|
||||
being reported as being up. Configured values that are
|
||||
too low for the hardware capabilties may be rejected.";
|
||||
}
|
||||
leaf carrier-transitions {
|
||||
type yang:counter64;
|
||||
units transitions;
|
||||
config false;
|
||||
description
|
||||
"Defines the number of times the underlying link state
|
||||
has changed to, or from, state up. This counter should be
|
||||
incremented even if the high layer interface state changes
|
||||
are being suppressed by a running link flap suppression
|
||||
timer.";
|
||||
}
|
||||
leaf timer-running {
|
||||
type enumeration {
|
||||
enum none {
|
||||
description
|
||||
"No link flap suppression timer is running.";
|
||||
}
|
||||
enum up {
|
||||
description
|
||||
"link-flap-suppression up timer is running. The
|
||||
underlying link state is up, but interface state is
|
||||
not reported as up.";
|
||||
}
|
||||
enum down {
|
||||
description
|
||||
"link-flap-suppression down timer is running.
|
||||
Interface state is reported as up, but the underlying
|
||||
link state is actually down.";
|
||||
}
|
||||
}
|
||||
config false;
|
||||
description
|
||||
"Reports whether a link flap suppression timer is actively
|
||||
running, in which case the interface state does not match
|
||||
the underlying link state.";
|
||||
}
|
||||
|
||||
reference "RFC XXXX, Section 2.1 Link Flap Suppression";
|
||||
}
|
||||
|
||||
/*
|
||||
* Augments the IETF interfaces model with a container to hold
|
||||
* generic interface dampening
|
||||
*/
|
||||
container dampening {
|
||||
if-feature "dampening";
|
||||
presence
|
||||
"Enable interface link flap dampening with default settings
|
||||
(that are vendor/device specific).";
|
||||
description
|
||||
"Interface dampening limits the propagation of interface link
|
||||
state flaps over longer periods.";
|
||||
reference "RFC XXXX, Section 2.2 Dampening";
|
||||
|
||||
leaf half-life {
|
||||
type uint32;
|
||||
units seconds;
|
||||
description
|
||||
"The time (in seconds) after which a penalty would be half
|
||||
its original value. Once the interface has been assigned
|
||||
a penalty, the penalty is decreased at a decay rate
|
||||
equivalent to the half-life. For some devices, the
|
||||
allowed values may be restricted to particular multiples
|
||||
of seconds. The default value is vendor/device
|
||||
specific.";
|
||||
reference "RFC XXXX, Section 2.3.2 Half-Life Period";
|
||||
}
|
||||
|
||||
leaf reuse {
|
||||
type uint32;
|
||||
description
|
||||
"Penalty value below which a stable interface is
|
||||
unsuppressed (i.e. brought up) (no units). The default
|
||||
value is vendor/device specific. The penalty value for a
|
||||
link up->down state change is 1000 units.";
|
||||
reference "RFC XXXX, Section 2.2.3 Reuse Threshold";
|
||||
}
|
||||
|
||||
leaf suppress {
|
||||
type uint32;
|
||||
description
|
||||
"Limit at which an interface is suppressed (i.e. held down)
|
||||
when its penalty exceeds that limit (no units). The value
|
||||
must be greater than the reuse threshold. The default
|
||||
value is vendor/device specific. The penalty value for a
|
||||
link up->down state change is 1000 units.";
|
||||
reference "RFC XXXX, Section 2.2.1 Suppress Threshold";
|
||||
}
|
||||
|
||||
leaf max-suppress-time {
|
||||
type uint32;
|
||||
units seconds;
|
||||
description
|
||||
"Maximum time (in seconds) that an interface can be
|
||||
suppressed before being unsuppressed if no further link
|
||||
up->down state change penalties have been applied. This
|
||||
value effectively acts as a ceiling that the penalty value
|
||||
cannot exceed. The default value is vendor/device
|
||||
specific.";
|
||||
reference "RFC XXXX, Section 2.2.4 Maximum Suppress Time";
|
||||
}
|
||||
|
||||
leaf penalty {
|
||||
type uint32;
|
||||
config false;
|
||||
description
|
||||
"The current penalty value for this interface. When the
|
||||
penalty value exceeds the 'suppress' leaf then the
|
||||
interface is suppressed (i.e. held down).";
|
||||
reference "RFC XXXX, Section 2.2 Dampening";
|
||||
}
|
||||
|
||||
leaf suppressed {
|
||||
type boolean;
|
||||
config false;
|
||||
description
|
||||
"Represents whether the interface is suppressed (i.e. held
|
||||
down) because the 'penalty' leaf value exceeds the
|
||||
'suppress' leaf.";
|
||||
reference "RFC XXXX, Section 2.2 Dampening";
|
||||
}
|
||||
|
||||
leaf time-remaining {
|
||||
when '../suppressed = "true"' {
|
||||
description
|
||||
"Only suppressed interfaces have a time remaining.";
|
||||
}
|
||||
type uint32;
|
||||
units seconds;
|
||||
config false;
|
||||
description
|
||||
"For a suppressed interface, this leaf represents how long
|
||||
(in seconds) that the interface will remain suppressed
|
||||
before it is allowed to go back up again.";
|
||||
reference "RFC XXXX, Section 2.2 Dampening";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Various types of interfaces support a configurable layer 2
|
||||
* encapsulation, any that are supported by YANG should be
|
||||
* listed here.
|
||||
*
|
||||
* Different encapsulations can hook into the common encaps-type
|
||||
* choice statement.
|
||||
*/
|
||||
container encapsulation {
|
||||
when
|
||||
"derived-from-or-self(../if:type,
|
||||
'ianaift:ethernetCsmacd') or
|
||||
derived-from-or-self(../if:type,
|
||||
'ianaift:ieee8023adLag') or
|
||||
derived-from-or-self(../if:type, 'ianaift:pos') or
|
||||
derived-from-or-self(../if:type,
|
||||
'ianaift:atmSubInterface') or
|
||||
derived-from-or-self(../if:type, 'ianaift:l2vlan') or
|
||||
derived-from-or-self(../if:type, 'ethSubInterface')" {
|
||||
|
||||
description
|
||||
"All interface types that can have a configurable L2
|
||||
encapsulation.";
|
||||
}
|
||||
|
||||
description
|
||||
"Holds the OSI layer 2 encapsulation associated with an
|
||||
interface.";
|
||||
choice encaps-type {
|
||||
description
|
||||
"Extensible choice of layer 2 encapsulations";
|
||||
reference "RFC XXXX, Section 2.3 Encapsulation";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Various types of interfaces support loopback configuration,
|
||||
* any that are supported by YANG should be listed here.
|
||||
*/
|
||||
leaf loopback {
|
||||
when "derived-from-or-self(../if:type,
|
||||
'ianaift:ethernetCsmacd') or
|
||||
derived-from-or-self(../if:type, 'ianaift:sonet') or
|
||||
derived-from-or-self(../if:type, 'ianaift:atm') or
|
||||
derived-from-or-self(../if:type, 'ianaift:otnOtu')" {
|
||||
description
|
||||
"All interface types that support loopback configuration.";
|
||||
}
|
||||
if-feature "loopback";
|
||||
type identityref {
|
||||
base loopback;
|
||||
}
|
||||
description "Enables traffic loopback.";
|
||||
reference "RFC XXXX, Section 2.4 Loopback";
|
||||
}
|
||||
|
||||
/*
|
||||
* Allows the maximum frame size to be configured or reported.
|
||||
*/
|
||||
leaf max-frame-size {
|
||||
if-feature "max-frame-size";
|
||||
type uint32 {
|
||||
range "64 .. max";
|
||||
}
|
||||
description
|
||||
"The maximum size of layer 2 frames that may be transmitted
|
||||
or received on the interface (including any frame header,
|
||||
maximum frame payload size, and frame checksum sequence).
|
||||
|
||||
If configured, the max-frame-size also limits the maximum
|
||||
frame size of any child sub-interfaces. The MTU available
|
||||
to higher layer protocols is restricted to the maximum frame
|
||||
payload size, and MAY be further restricted by explicit
|
||||
layer 3 or protocol specific MTU configuration.";
|
||||
|
||||
reference "RFC XXXX, Section 2.5 Maximum Frame Size";
|
||||
}
|
||||
|
||||
/*
|
||||
* Augments the IETF interfaces model with a leaf that indicates
|
||||
* which mode, or layer, is being used to forward the traffic.
|
||||
*/
|
||||
leaf forwarding-mode {
|
||||
type identityref {
|
||||
base forwarding-mode;
|
||||
}
|
||||
config false;
|
||||
|
||||
description
|
||||
"The forwarding mode that the interface is operating in.";
|
||||
reference "RFC XXXX, Section 2.7 Forwarding Mode";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add generic support for sub-interfaces.
|
||||
*
|
||||
* This should be extended to cover all interface types that are
|
||||
* child interfaces of other interfaces.
|
||||
*/
|
||||
augment "/if:interfaces/if:interface" {
|
||||
when "derived-from(if:type, 'sub-interface') or
|
||||
derived-from-or-self(if:type, 'ianaift:l2vlan') or
|
||||
derived-from-or-self(if:type, 'ianaift:atmSubInterface') or
|
||||
derived-from-or-self(if:type, 'ianaift:frameRelay')" {
|
||||
description
|
||||
"Any ianaift:types that explicitly represent sub-interfaces
|
||||
or any types that derive from the sub-interface identity.";
|
||||
}
|
||||
if-feature "sub-interfaces";
|
||||
|
||||
description
|
||||
"Adds a parent interface field to interfaces that model
|
||||
sub-interfaces.";
|
||||
leaf parent-interface {
|
||||
|
||||
type if:interface-ref;
|
||||
|
||||
mandatory true;
|
||||
description
|
||||
"This is the reference to the parent interface of this
|
||||
sub-interface.";
|
||||
reference "RFC XXXX, Section 2.6 Sub-interface";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add discard counter for unknown sub-interface encapsulation
|
||||
*/
|
||||
augment "/if:interfaces/if:interface/if:statistics" {
|
||||
when "derived-from-or-self(../if:type,
|
||||
'ianaift:ethernetCsmacd') or
|
||||
derived-from-or-self(../if:type,
|
||||
'ianaift:ieee8023adLag') or
|
||||
derived-from-or-self(../if:type, 'ianaift:ifPwType')" {
|
||||
description
|
||||
"Applies to interfaces that can demultiplex ingress frames to
|
||||
sub-interfaces.";
|
||||
}
|
||||
if-feature "sub-interfaces";
|
||||
|
||||
description
|
||||
"Augment the interface model statistics with a sub-interface
|
||||
demux discard counter.";
|
||||
leaf in-discard-unknown-encaps {
|
||||
type yang:counter64;
|
||||
units frames;
|
||||
description
|
||||
"A count of the number of frames that were well formed, but
|
||||
otherwise discarded because their encapsulation does not
|
||||
classify the frame to the interface or any child
|
||||
sub-interface. E.g., a frame might be discarded because the
|
||||
it has an unknown VLAN Id, or does not have a VLAN Id when
|
||||
one is expected.
|
||||
|
||||
For consistency, frames counted against this counter are
|
||||
also counted against the IETF interfaces statistics. In
|
||||
particular, they are included in in-octets and in-discards,
|
||||
but are not included in in-unicast-pkts, in-multicast-pkts
|
||||
or in-broadcast-pkts, because they are not delivered to a
|
||||
higher layer.
|
||||
|
||||
Discontinuities in the values of this counter can occur at
|
||||
re-initialization of the management system, and at other
|
||||
times as indicated by the value of the 'discontinuity-time'
|
||||
leaf defined in the ietf-interfaces YANG module
|
||||
(RFC 8343).";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
module ietf-if-vlan-encapsulation {
|
||||
yang-version 1.1;
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-if-vlan-encapsulation";
|
||||
prefix if-vlan;
|
||||
|
||||
import ietf-interfaces {
|
||||
prefix if;
|
||||
reference
|
||||
"RFC 8343: A YANG Data Model For Interface Management";
|
||||
}
|
||||
|
||||
import iana-if-type {
|
||||
prefix ianaift;
|
||||
reference
|
||||
"RFC 7224: IANA Interface Type YANG Module";
|
||||
}
|
||||
|
||||
import ieee802-dot1q-types {
|
||||
prefix dot1q-types;
|
||||
revision-date 2022-10-29;
|
||||
reference
|
||||
"IEEE Std 802.1Q-2022: IEEE Standard for Local and
|
||||
metropolitan area networks -- Bridges and Bridged Networks";
|
||||
}
|
||||
|
||||
import ietf-if-extensions {
|
||||
prefix if-ext;
|
||||
reference
|
||||
"RFC XXXX: Common Interface Extension YANG Data Models";
|
||||
}
|
||||
|
||||
organization
|
||||
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <http://tools.ietf.org/wg/netmod/>
|
||||
WG List: <mailto:netmod@ietf.org>
|
||||
|
||||
Editor: Robert Wilton
|
||||
<mailto:rwilton@cisco.com>";
|
||||
|
||||
description
|
||||
"This YANG module models configuration to classify IEEE 802.1Q
|
||||
VLAN tagged Ethernet traffic by exactly matching the tag type
|
||||
and VLAN identifier of one or two 802.1Q VLAN tags in the frame.
|
||||
|
||||
Copyright (c) 2023 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject to
|
||||
the license terms contained in, the Revised BSD License set
|
||||
forth in Section 4.c of the IETF Trust's Legal Provisions
|
||||
Relating to IETF Documents
|
||||
(https://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC XXXX
|
||||
(https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself
|
||||
for full legal notices.
|
||||
|
||||
The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
|
||||
NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
|
||||
'MAY', and 'OPTIONAL' in this document are to be interpreted as
|
||||
described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
|
||||
they appear in all capitals, as shown here.";
|
||||
|
||||
revision 2023-01-26 {
|
||||
description
|
||||
"Latest draft revision";
|
||||
reference
|
||||
"RFC XXXX: Sub-interface VLAN YANG Data Models";
|
||||
}
|
||||
|
||||
augment "/if:interfaces/if:interface/if-ext:encapsulation/"
|
||||
+ "if-ext:encaps-type" {
|
||||
when "derived-from-or-self(../if:type,
|
||||
'ianaift:ethernetCsmacd') or
|
||||
derived-from-or-self(../if:type,
|
||||
'ianaift:ieee8023adLag') or
|
||||
derived-from-or-self(../if:type, 'ianaift:l2vlan') or
|
||||
derived-from-or-self(../if:type,
|
||||
'if-ext:ethSubInterface')" {
|
||||
description
|
||||
"Applies only to Ethernet-like interfaces and
|
||||
sub-interfaces.";
|
||||
}
|
||||
|
||||
description
|
||||
"Augment the generic interface encapsulation with basic 802.1Q
|
||||
VLAN tag classifications";
|
||||
|
||||
case dot1q-vlan {
|
||||
container dot1q-vlan {
|
||||
|
||||
description
|
||||
"Classifies 802.1Q VLAN tagged Ethernet frames to a
|
||||
sub-interface (or interface) by exactly matching the
|
||||
number of tags, tag type(s) and VLAN identifier(s).
|
||||
|
||||
Only frames matching the classification configured on a
|
||||
sub-interface/interface are processed on that
|
||||
sub-interface/interface.
|
||||
|
||||
Frames that do not match any sub-interface are processed
|
||||
directly on the parent interface, if it is associated with
|
||||
a forwarding instance, otherwise they are dropped.";
|
||||
|
||||
container outer-tag {
|
||||
must 'tag-type = "dot1q-types:s-vlan" or '
|
||||
+ 'tag-type = "dot1q-types:c-vlan"' {
|
||||
|
||||
error-message
|
||||
"Only C-VLAN and S-VLAN tags can be matched.";
|
||||
|
||||
description
|
||||
"For IEEE 802.1Q interoperability, only C-VLAN and
|
||||
S-VLAN tags are matched.";
|
||||
}
|
||||
|
||||
description
|
||||
"Specifies the VLAN tag values to match against the
|
||||
outermost (first) 802.1Q VLAN tag in the frame.";
|
||||
|
||||
uses dot1q-types:dot1q-tag-classifier-grouping;
|
||||
}
|
||||
|
||||
container second-tag {
|
||||
must '../outer-tag/tag-type = "dot1q-types:s-vlan" and '
|
||||
+ 'tag-type = "dot1q-types:c-vlan"' {
|
||||
|
||||
error-message
|
||||
"When matching two 802.1Q VLAN tags, the outermost
|
||||
(first) tag in the frame MUST be specified and be of
|
||||
S-VLAN type and the second tag in the frame must be of
|
||||
C-VLAN tag type.";
|
||||
|
||||
description
|
||||
"For IEEE 802.1Q interoperability, when matching two
|
||||
802.1Q VLAN tags, it is REQUIRED that the outermost
|
||||
tag exists and is an S-VLAN, and the second tag is a
|
||||
C-VLAN.";
|
||||
}
|
||||
|
||||
presence "Classify frames that have two 802.1Q VLAN tags.";
|
||||
|
||||
description
|
||||
"Specifies the VLAN tag values to match against the
|
||||
second outermost 802.1Q VLAN tag in the frame.";
|
||||
|
||||
uses dot1q-types:dot1q-tag-classifier-grouping;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
submodule infix-if-vlan {
|
||||
yang-version 1.1;
|
||||
belongs-to infix-interfaces {
|
||||
prefix infix-if;
|
||||
}
|
||||
|
||||
import ietf-interfaces {
|
||||
prefix if;
|
||||
}
|
||||
|
||||
import infix-if-type {
|
||||
prefix infixift;
|
||||
}
|
||||
import ieee802-dot1q-types {
|
||||
prefix dot1q-types;
|
||||
}
|
||||
contact "kernelkit@googlegroups.com";
|
||||
description
|
||||
"This module implements VLAN (8021q) encapsulation";
|
||||
|
||||
revision 2023-10-25 {
|
||||
description "Initial revision";
|
||||
}
|
||||
|
||||
augment "/if:interfaces/if:interface" {
|
||||
when "derived-from-or-self(if:type, 'infixift:vlan')" {
|
||||
description "Only shown for if:type vlan";
|
||||
}
|
||||
description "Augment to add 802.1Q VLAN tag classifications";
|
||||
container vlan {
|
||||
description "Configure 802.1q/802.1ad VLANs";
|
||||
leaf tag-type {
|
||||
type dot1q-types:dot1q-tag-type;
|
||||
default dot1q-types:c-vlan;
|
||||
description "VLAN type";
|
||||
}
|
||||
leaf id {
|
||||
type dot1q-types:vlanid;
|
||||
mandatory true;
|
||||
description "VLAN Id";
|
||||
}
|
||||
leaf lower-layer-if {
|
||||
type if:interface-ref;
|
||||
mandatory true;
|
||||
description "Base interface for VLAN";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ module infix-interfaces {
|
||||
include infix-if-base;
|
||||
include infix-if-bridge;
|
||||
include infix-if-veth;
|
||||
include infix-if-vlan;
|
||||
|
||||
organization "KernelKit";
|
||||
contact "kernelkit@googlegroups.com";
|
||||
|
||||
+15
-2
@@ -19,6 +19,13 @@ module infix-system {
|
||||
contact "kernelkit@googlegroups.com";
|
||||
description "Infix augments and deviations to ietf-system.";
|
||||
|
||||
revision 2023-10-19 {
|
||||
description "Change deviation for timezone-utc-offset from unsupported to Etc+/-HOUR
|
||||
- Unit is set to hours (tzdata compatibility)
|
||||
- Range is -12 .. 14";
|
||||
|
||||
reference "internal";
|
||||
}
|
||||
revision 2023-08-15 {
|
||||
description "Add support for user login shell.
|
||||
|
||||
@@ -76,8 +83,14 @@ module infix-system {
|
||||
}
|
||||
}
|
||||
|
||||
deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-utc-offset" {
|
||||
deviate not-supported;
|
||||
deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-utc-offset/sys:timezone-utc-offset" {
|
||||
description "Timezone UTC offset should be set in hours, not minutes";
|
||||
deviate replace {
|
||||
type int16 {
|
||||
range "-12 .. 14";
|
||||
}
|
||||
units "hours";
|
||||
}
|
||||
}
|
||||
|
||||
deviation "/sys:system/sys:radius" {
|
||||
@@ -305,6 +305,11 @@
|
||||
<ACTION sym="script">jq -C . /cfg/startup-config.cfg</ACTION>
|
||||
</COMMAND>
|
||||
</COMMAND>
|
||||
<COMMAND name="factory-reset" help="Restore the system to factory state">
|
||||
<ACTION sym="script" interactive="true">/bin/yorn "This will restore the device to factory state"</ACTION>
|
||||
<ACTION sym="rpc@infix">/ietf-factory-default:factory-reset</ACTION>
|
||||
</COMMAND>
|
||||
|
||||
|
||||
<COMMAND name="follow" help="Monitor a log file, use Ctrl-C to abort">
|
||||
<PARAM name="fn" ptype="/LOGFILES" help="Optional log file to monitor, default: syslog"/>
|
||||
|
||||
+2
-1
@@ -4,7 +4,8 @@ LDLIBS += -lsysrepo -lev -lyang -ljansson -lite -lsrx
|
||||
TARGET = statd
|
||||
SRC = statd.c shared.c shared.h \
|
||||
iface-ip-link.c iface-ip-link.h \
|
||||
iface-ip-addr.c iface-ip-addr.h
|
||||
iface-ip-addr.c iface-ip-addr.h \
|
||||
iface-ethtool.c iface-ethtool.h
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <jansson.h>
|
||||
#include <srx/lyx.h>
|
||||
|
||||
#include <srx/common.h>
|
||||
#include <srx/helpers.h>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
static json_t *json_get_ethtool(const char *ifname)
|
||||
{
|
||||
char cmd[512] = {}; /* Size is arbitrary */
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "ethtool --json -S %s --all-groups 2>/dev/null", ifname);
|
||||
|
||||
return json_get_output(cmd);
|
||||
}
|
||||
|
||||
/* We print errors here, but don't return them */
|
||||
static void ly_add_lld(const struct ly_ctx *ctx, struct lyd_node *node, char *xpath,
|
||||
json_t *json, const char *yang, const char *ethtool)
|
||||
{
|
||||
json_t *j_val;
|
||||
int err;
|
||||
|
||||
j_val = json_object_get(json, ethtool);
|
||||
if (!j_val)
|
||||
return;
|
||||
|
||||
if (!json_is_integer(j_val)) {
|
||||
ERROR("Error, expecting integer value for '%s'\n", ethtool);
|
||||
return;
|
||||
}
|
||||
|
||||
err = lydx_new_path(ctx, &node, xpath, (char *)yang, "%lld",
|
||||
json_integer_value(j_val));
|
||||
if (err)
|
||||
ERROR("Error, adding ethtool '%s' to data tree, libyang error %d", yang, err);
|
||||
}
|
||||
|
||||
static uint64_t json_get_lld(json_t *json, int *found, const char *name)
|
||||
{
|
||||
json_t *j_val;
|
||||
|
||||
j_val = json_object_get(json, name);
|
||||
if (!j_val)
|
||||
return 0;
|
||||
|
||||
if (!json_is_integer(j_val)) {
|
||||
ERROR("Error, expecting integer value for '%s'\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*found)++;
|
||||
|
||||
return json_integer_value(j_val);
|
||||
}
|
||||
|
||||
static void ly_add_in_tot_frames(const struct ly_ctx *ctx, struct lyd_node *node,
|
||||
char *xpath, json_t *j_mac, json_t *j_rmon)
|
||||
{
|
||||
char *yang = "in-total-frames";
|
||||
long long int tot = 0;
|
||||
int found = 0;
|
||||
int err;
|
||||
|
||||
tot += json_get_lld(j_mac, &found, "FramesReceivedOK");
|
||||
tot += json_get_lld(j_mac, &found, "FrameCheckSequenceErrors");
|
||||
tot += json_get_lld(j_mac, &found, "FramesLostDueToIntMACRcvError");
|
||||
tot += json_get_lld(j_mac, &found, "AlignmentErrors");
|
||||
tot += json_get_lld(j_rmon, &found, "etherStatsOversizePkts");
|
||||
tot += json_get_lld(j_rmon, &found, "etherStatsJabbers");
|
||||
|
||||
/* Don't add 0 counters for missing data (missing != 0) */
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
err = lydx_new_path(ctx, &node, xpath, yang, "%lld", tot);
|
||||
if (err)
|
||||
ERROR("Error, adding ethtool '%s', libyang error %d", yang, err);
|
||||
}
|
||||
|
||||
static void ly_add_in_err_oz_frames(const struct ly_ctx *ctx, struct lyd_node *node,
|
||||
char *xpath, json_t *j_rmon)
|
||||
{
|
||||
char *yang = "in-error-oversize-frames";
|
||||
long long int tot = 0;
|
||||
int found = 0;
|
||||
int err;
|
||||
|
||||
tot += json_get_lld(j_rmon, &found, "etherStatsOversizePkts");
|
||||
tot += json_get_lld(j_rmon, &found, "etherStatsJabbers");
|
||||
|
||||
/* Don't add 0 counters for missing data (missing != 0) */
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
err = lydx_new_path(ctx, &node, xpath, yang, "%lld", tot);
|
||||
if (err)
|
||||
ERROR("Error, adding ethtool '%s', libyang error %d", yang, err);
|
||||
}
|
||||
|
||||
static int ly_add_eth_stats(const struct ly_ctx *ctx, struct lyd_node **parent,
|
||||
const char *ifname, json_t *j_iface)
|
||||
{
|
||||
char xpath_base[XPATH_BASE_MAX] = {};
|
||||
char xpath[XPATH_MAX] = {};
|
||||
struct lyd_node *frame = NULL;
|
||||
struct lyd_node *stat = NULL;
|
||||
struct lyd_node *eth = NULL;
|
||||
json_t *j_mac;
|
||||
json_t *j_rmon;
|
||||
int err;
|
||||
|
||||
j_mac = json_object_get(j_iface, "eth-mac");
|
||||
if (!j_mac)
|
||||
return SR_ERR_OK;
|
||||
|
||||
j_rmon = json_object_get(j_iface, "rmon");
|
||||
if (!j_rmon)
|
||||
return SR_ERR_OK;
|
||||
|
||||
snprintf(xpath_base, sizeof(xpath_base),
|
||||
"%s/interface[name='%s']/ieee802-ethernet-interface:ethernet",
|
||||
XPATH_IFACE_BASE, ifname);
|
||||
|
||||
err = lyd_new_path(*parent, ctx, xpath_base, NULL, 0, ð);
|
||||
if (err) {
|
||||
ERROR("Failed adding 'eth' node (%s), libyang error %d: %s",
|
||||
xpath_base, err, ly_errmsg(ctx));
|
||||
return SR_ERR_LY;
|
||||
}
|
||||
|
||||
snprintf(xpath, sizeof(xpath), "%s/statistics", xpath_base);
|
||||
err = lyd_new_path(eth, ctx, xpath, NULL, 0, &stat);
|
||||
if (err) {
|
||||
ERROR("Failed adding 'stat' node (%s), libyang error %d: %s",
|
||||
xpath, err, ly_errmsg(ctx));
|
||||
return SR_ERR_LY;
|
||||
}
|
||||
|
||||
snprintf(xpath, sizeof(xpath), "%s/statistics/frame", xpath_base);
|
||||
err = lyd_new_path(stat, ctx, xpath, NULL, 0, &frame);
|
||||
if (err) {
|
||||
ERROR("Failed adding 'frame' node (%s), libyang error %d: %s",
|
||||
xpath, err, ly_errmsg(ctx));
|
||||
return SR_ERR_LY;
|
||||
}
|
||||
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "out-frames", "FramesTransmittedOK");
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "out-multicast-frames", "MulticastFramesXmittedOK");
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "out-broadcast-frames", "BroadcastFramesXmittedOK");
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "in-frames", "FramesReceivedOK");
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "in-multicast-frames", "MulticastFramesReceivedOK");
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "in-broadcast-frames", "BroadcastFramesReceivedOK");
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "in-error-fcs-frames", "FrameCheckSequenceErrors");
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "in-error-undersize-frames", "undersize_pkts");
|
||||
|
||||
ly_add_lld(ctx, frame, xpath, j_mac, "in-error-mac-internal-frames",
|
||||
"FramesLostDueToIntMACRcvError");
|
||||
|
||||
ly_add_in_tot_frames(ctx, frame, xpath, j_mac, j_rmon);
|
||||
ly_add_in_err_oz_frames(ctx, frame, xpath, j_rmon);
|
||||
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
int ly_add_ethtool(const struct ly_ctx *ctx, struct lyd_node **parent, char *ifname)
|
||||
{
|
||||
json_t *j_iface;
|
||||
json_t *j_root;
|
||||
int err;
|
||||
|
||||
j_root = json_get_ethtool(ifname);
|
||||
if (!j_root) {
|
||||
ERROR("Error, parsing ethtool JSON");
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
if (json_array_size(j_root) != 1) {
|
||||
ERROR("Error, expected JSON array of single iface");
|
||||
json_decref(j_root);
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
|
||||
j_iface = json_array_get(j_root, 0);
|
||||
if (!j_iface) {
|
||||
ERROR("Error, getting JSON interface");
|
||||
json_decref(j_root);
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
|
||||
err = ly_add_eth_stats(ctx, parent, ifname, j_iface);
|
||||
if (err) {
|
||||
ERROR("Error, adding ethtool statistics data");
|
||||
json_decref(j_root);
|
||||
return err;
|
||||
}
|
||||
|
||||
json_decref(j_root);
|
||||
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef STATD_IFACE_ETHTOOL_H_
|
||||
#define STATD_IFACE_ETHTOOL_H_
|
||||
|
||||
#include <srx/lyx.h>
|
||||
|
||||
int ly_add_ethtool(const struct ly_ctx *ctx, struct lyd_node **parent, char *ifname);
|
||||
|
||||
#endif
|
||||
+112
-14
@@ -81,6 +81,8 @@ static const char *get_yang_link_type(char *xpath, json_t *iface)
|
||||
return "infix-if-type:vlan";
|
||||
if (strcmp(kind, "bridge") == 0)
|
||||
return "infix-if-type:bridge";
|
||||
if (strcmp(kind, "dsa") == 0)
|
||||
return "infix-if-type:ethernet";
|
||||
|
||||
/**
|
||||
* We could return ethernetCsmacd here, but it might hide some
|
||||
@@ -226,6 +228,77 @@ static int ly_add_ip_link_br(const struct ly_ctx *ctx, struct lyd_node **parent,
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
static int ip_link_kind_is_dsa(json_t *j_iface)
|
||||
{
|
||||
json_t *j_linkinfo;
|
||||
json_t *j_val;
|
||||
|
||||
j_linkinfo = json_object_get(j_iface, "linkinfo");
|
||||
if (!j_linkinfo)
|
||||
return 0;
|
||||
|
||||
j_val = json_object_get(j_linkinfo, "info_kind");
|
||||
if (!j_val)
|
||||
return 0;
|
||||
|
||||
if (!json_is_string(j_val))
|
||||
return 0;
|
||||
|
||||
if (strcmp("dsa", json_string_value(j_val)) != 0)
|
||||
return 0;
|
||||
|
||||
/* This interface has linkinfo -> info_kind = "dsa" */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ly_add_ip_link_parent(const struct ly_ctx *ctx, struct lyd_node **parent,
|
||||
char *xpath, json_t *j_iface)
|
||||
{
|
||||
struct lyd_node *vlan_node;
|
||||
char *vlan_xpath;
|
||||
json_t *j_val;
|
||||
int err;
|
||||
j_val = json_object_get(j_iface, "link");
|
||||
if (!j_val) {
|
||||
/* Interface has no parent */
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
if (ip_link_kind_is_dsa(j_iface)) {
|
||||
/* Skip adding parent interface data for dsa child */
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
if (!json_is_string(j_val)) {
|
||||
ERROR("Expected a JSON string for 'link'");
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
err = asprintf(&vlan_xpath, "%s/infix-interfaces:vlan", xpath);
|
||||
if (err == -1) {
|
||||
ERROR("Error, creating vlan xpath");
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
|
||||
err = lyd_new_path(*parent, ctx, vlan_xpath, NULL, 0, &vlan_node);
|
||||
if (err) {
|
||||
ERROR("Failed adding 'lower-layer-if' node (%s), libyang error %d: %s",
|
||||
vlan_xpath, err, ly_errmsg(ctx));
|
||||
free(vlan_xpath);
|
||||
return SR_ERR_LY;
|
||||
}
|
||||
|
||||
err = lydx_new_path(ctx, &vlan_node, vlan_xpath, "lower-layer-if",
|
||||
"%s", json_string_value(j_val));
|
||||
if (err) {
|
||||
ERROR("Error, adding 'lower-layer-if' to data tree, libyang error %d", err);
|
||||
free(vlan_xpath);
|
||||
return SR_ERR_LY;
|
||||
}
|
||||
|
||||
free(vlan_xpath);
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
static int ly_add_ip_link_data(const struct ly_ctx *ctx, struct lyd_node **parent,
|
||||
char *xpath, json_t *j_iface)
|
||||
{
|
||||
@@ -291,20 +364,10 @@ static int ly_add_ip_link_data(const struct ly_ctx *ctx, struct lyd_node **paren
|
||||
return err;
|
||||
}
|
||||
|
||||
j_val = json_object_get(j_iface, "link");
|
||||
if (j_val) {
|
||||
if (!json_is_string(j_val)) {
|
||||
ERROR("Expected a JSON string for 'link'");
|
||||
return SR_ERR_SYS;
|
||||
}
|
||||
|
||||
err = lydx_new_path(ctx, parent, xpath,
|
||||
"ietf-if-extensions:parent-interface", "%s",
|
||||
json_string_value(j_val));
|
||||
if (err) {
|
||||
ERROR("Error, adding 'link' to data tree, libyang error %d", err);
|
||||
return SR_ERR_LY;
|
||||
}
|
||||
err = ly_add_ip_link_parent(ctx, parent, xpath, j_iface);
|
||||
if (err) {
|
||||
ERROR("Error, adding parent iface to data tree, libyang error %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return SR_ERR_OK;
|
||||
@@ -345,3 +408,38 @@ int ly_add_ip_link(const struct ly_ctx *ctx, struct lyd_node **parent, char *ifn
|
||||
return SR_ERR_OK;
|
||||
}
|
||||
|
||||
/* Returns 1 if the group is "group", 0 if it's not and -1 on error */
|
||||
int ip_link_check_group(char *ifname, const char *group)
|
||||
{
|
||||
json_t *j_iface;
|
||||
json_t *j_root;
|
||||
json_t *j_val;
|
||||
|
||||
j_root = json_get_ip_link(ifname);
|
||||
if (!j_root) {
|
||||
ERROR("Error, parsing ip-link JSON");
|
||||
return -1;
|
||||
}
|
||||
if (json_array_size(j_root) != 1) {
|
||||
ERROR("Error, expected JSON array of single iface");
|
||||
json_decref(j_root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
j_iface = json_array_get(j_root, 0);
|
||||
|
||||
j_val = json_object_get(j_iface, "group");
|
||||
if (!json_is_string(j_val)) {
|
||||
ERROR("Error, expected a JSON string for 'group'");
|
||||
json_decref(j_root);
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(json_string_value(j_val), group) == 0) {
|
||||
json_decref(j_root);
|
||||
return 1;
|
||||
}
|
||||
|
||||
json_decref(j_root);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <srx/lyx.h>
|
||||
|
||||
int ip_link_check_group(char *ifname, const char *group);
|
||||
int ly_add_ip_link(const struct ly_ctx *ctx, struct lyd_node **parent, char *ifname);
|
||||
|
||||
#endif
|
||||
|
||||
+2
-8
@@ -13,20 +13,14 @@ json_t *json_get_output(const char *cmd)
|
||||
|
||||
proc = popenf("re", cmd);
|
||||
if (!proc) {
|
||||
ERROR("Error, running ip link command");
|
||||
ERROR("Error, running command %s", cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
j_root = json_loadf(proc, 0, &j_err);
|
||||
pclose(proc);
|
||||
if (!j_root) {
|
||||
ERROR("Error, parsing ip link JSON");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!json_is_array(j_root)) {
|
||||
ERROR("Expected a JSON array from ip link");
|
||||
json_decref(j_root);
|
||||
ERROR("Error, parsing command JSON (%s)", cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <jansson.h>
|
||||
|
||||
#define XPATH_MAX PATH_MAX
|
||||
#define XPATH_BASE_MAX 2046 /* Size is arbitrary */
|
||||
#define XPATH_IFACE_BASE "/ietf-interfaces:interfaces"
|
||||
|
||||
json_t *json_get_output(const char *cmd);
|
||||
|
||||
+18
-3
@@ -25,6 +25,7 @@
|
||||
#include "shared.h"
|
||||
#include "iface-ip-link.h"
|
||||
#include "iface-ip-addr.h"
|
||||
#include "iface-ethtool.h"
|
||||
|
||||
#define SOCK_RMEM_SIZE 1000000 /* Arbitrary chosen, default = 212992 */
|
||||
#define NL_BUF_SIZE 4096 /* Arbitrary chosen */
|
||||
@@ -139,14 +140,28 @@ static int sr_ifaces_cb(sr_session_ctx_t *session, uint32_t, const char *path,
|
||||
return SR_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
/* Skip internal interfaces (such as dsa0) */
|
||||
if (ip_link_check_group(sub->ifname, "internal") == 1) {
|
||||
err = SR_ERR_OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ly_add_ip_link(ctx, parent, sub->ifname);
|
||||
if (err)
|
||||
if (err) {
|
||||
ERROR("Error, adding ip link info");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ly_add_ip_addr(ctx, parent, sub->ifname);
|
||||
if (err)
|
||||
ERROR("Error, adding ip link info");
|
||||
if (err) {
|
||||
ERROR("Error, adding ip addr info");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ly_add_ethtool(ctx, parent, sub->ifname);
|
||||
if (err)
|
||||
ERROR("Error, adding ethtool info");
|
||||
out:
|
||||
sr_release_context(con);
|
||||
|
||||
return err;
|
||||
|
||||
@@ -189,6 +189,29 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"TEST-DESCR": "Interface ieee802-ethernet-interface stats",
|
||||
"name": "e13",
|
||||
"type": "infix-if-type:ethernet",
|
||||
"oper-status": "up",
|
||||
"if-index": 4,
|
||||
"phys-address": "02:ee:00:00:12:00",
|
||||
"statistics": {
|
||||
"in-octets": "11",
|
||||
"out-octets": "22"
|
||||
},
|
||||
"ieee802-ethernet-interface:ethernet": {
|
||||
"statistics": {
|
||||
"frame": {
|
||||
"in-frames": "1111",
|
||||
"out-frames": "2222"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ietf-ip:ipv4": {
|
||||
"mtu": 1500
|
||||
}
|
||||
},
|
||||
{
|
||||
"TEST-DESCR": "Interface with VLAN on top",
|
||||
"name": "e20",
|
||||
|
||||
@@ -21,14 +21,9 @@ with infamy.Test() as test:
|
||||
{
|
||||
"name": f"{tport}.10",
|
||||
"type": "infix-if-type:vlan",
|
||||
"parent-interface": tport,
|
||||
"encapsulation": {
|
||||
"dot1q-vlan": {
|
||||
"outer-tag": {
|
||||
"tag-type": "ieee802-dot1q-types:c-vlan",
|
||||
"vlan-id": 10,
|
||||
}
|
||||
}
|
||||
"vlan": {
|
||||
"id": 10,
|
||||
"lower-layer-if": tport,
|
||||
},
|
||||
|
||||
"ipv4": {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
---
|
||||
- case: hostname.py
|
||||
- case: add_delete_user.py
|
||||
- case: timezone.py
|
||||
- case: timezone_utc_offset.py
|
||||
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import random, string
|
||||
import time
|
||||
import infamy
|
||||
import lxml
|
||||
with infamy.Test() as test:
|
||||
with test.step("Initialize"):
|
||||
env = infamy.Env(infamy.std_topology("1x1"))
|
||||
target = env.attach("target", "mgmt")
|
||||
|
||||
with test.step("Set timezone"):
|
||||
target.put_config_dict("ietf-system", {
|
||||
"system": {
|
||||
"clock": {
|
||||
"timezone-name": "Australia/Perth" # always +8:00, no DTS
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
with test.step("Verify current time."):
|
||||
root = target.get_dict("/ietf-system:system-state/clock",as_xml=True)
|
||||
current_datetime = root.find('.//{urn:ietf:params:xml:ns:yang:ietf-system}current-datetime').text
|
||||
offset=current_datetime[-6:]
|
||||
|
||||
assert(offset == "+08:00")
|
||||
|
||||
test.succeed()
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import infamy
|
||||
import lxml
|
||||
|
||||
with infamy.Test() as test:
|
||||
with test.step("Initialize"):
|
||||
env = infamy.Env(infamy.std_topology("1x1"))
|
||||
target = env.attach("target", "mgmt")
|
||||
|
||||
with test.step("Set timezone UTC offset"):
|
||||
target.put_config_dict("ietf-system", {
|
||||
"system": {
|
||||
"clock": {
|
||||
"timezone-utc-offset": "12"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
with test.step("Verify current time."):
|
||||
root = target.get_dict("/ietf-system:system-state/clock",as_xml=True)
|
||||
current_datetime = root.find('.//{urn:ietf:params:xml:ns:yang:ietf-system}current-datetime').text
|
||||
offset=current_datetime[-6:]
|
||||
|
||||
assert(offset == "+12:00")
|
||||
|
||||
test.succeed()
|
||||
@@ -41,14 +41,9 @@ with infamy.Test() as test:
|
||||
"name": "vlan10",
|
||||
"type": "infix-if-type:vlan",
|
||||
"enabled": True,
|
||||
"parent-interface": "br0",
|
||||
"encapsulation": {
|
||||
"dot1q-vlan": {
|
||||
"outer-tag": {
|
||||
"tag-type": "ieee802-dot1q-types:c-vlan",
|
||||
"vlan-id": 10,
|
||||
}
|
||||
}
|
||||
"vlan": {
|
||||
"lower-layer-if": "br0",
|
||||
"id": 10,
|
||||
},
|
||||
"ipv4": {
|
||||
"address": [
|
||||
|
||||
+26
-14
@@ -147,7 +147,7 @@ class Device(object):
|
||||
pieces.append("</get-data>")
|
||||
return self._ncc_make_rpc("".join(pieces), msg_id=msg_id)
|
||||
|
||||
def _get(self, xpath, getter):
|
||||
def _get(self, xpath, getter, as_xml=False):
|
||||
# Figure out which modules we are referencing
|
||||
mods = self._modules_in_xpath(xpath)
|
||||
|
||||
@@ -155,30 +155,42 @@ class Device(object):
|
||||
xmlns = " ".join([f"xmlns:{m['name']}=\"{m['namespace']}\"" for m in mods])
|
||||
filt = f"<filter type=\"xpath\" select=\"{xpath}\" {xmlns} />"
|
||||
# pylint: disable=c-extension-no-member
|
||||
cfg = lxml.etree.tostring(getter(filter=filt).data_ele[0])
|
||||
data=getter(filter=filt).data_ele[0]
|
||||
if as_xml:
|
||||
return data
|
||||
else:
|
||||
cfg = lxml.etree.tostring(data)
|
||||
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
|
||||
|
||||
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
|
||||
|
||||
def _get_data(self, xpath):
|
||||
def _get_data(self, xpath,as_xml=False):
|
||||
"""Local member wrapper for netconf-client <get-data> RPC"""
|
||||
# pylint: disable=protected-access
|
||||
(raw, ele) = self.ncc._send_rpc(self._ncc_get_data_rpc(filter=xpath))
|
||||
data = NccGetDataReply(raw, ele)
|
||||
# pylint: disable=c-extension-no-member
|
||||
cfg = lxml.etree.tostring(data.data_ele[0])
|
||||
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
|
||||
if(as_xml):
|
||||
return data
|
||||
else:
|
||||
# pylint: disable=c-extension-no-member
|
||||
cfg = lxml.etree.tostring(data.data_ele[0])
|
||||
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
|
||||
|
||||
def get(self, xpath):
|
||||
def get(self, xpath, as_xml=False):
|
||||
"""RPC <get> (legacy NETCONF) fetches config:false data"""
|
||||
return self._get(xpath, self.ncc.get)
|
||||
return self._get(xpath, self.ncc.get, as_xml)
|
||||
|
||||
def get_dict(self, xpath):
|
||||
def get_dict(self, xpath,as_xml=False):
|
||||
"""Return Python dictionary of <get> RPC data"""
|
||||
return self.get(xpath).print_dict()
|
||||
if(as_xml):
|
||||
return self.get(xpath, as_xml=True)
|
||||
else:
|
||||
return self.get(xpath).print_dict()
|
||||
|
||||
def get_data(self, xpath):
|
||||
def get_data(self, xpath, as_xml=False):
|
||||
"""RPC <get-data> to fetch operational data"""
|
||||
return self._get_data(xpath).print_dict()
|
||||
if(as_xml):
|
||||
return self._get_data(xpath,as_xml)
|
||||
else:
|
||||
return self._get_data(xpath).print_dict()
|
||||
|
||||
def get_config(self, xpath):
|
||||
return self._get(xpath, self.ncc.get_config)
|
||||
|
||||
Reference in New Issue
Block a user