diff --git a/.github/workflows/add-issue-to-project.yml b/.github/workflows/add-issue-to-project.yml new file mode 100644 index 00000000..9b303d6e --- /dev/null +++ b/.github/workflows/add-issue-to-project.yml @@ -0,0 +1,16 @@ +name: Adds all issues to project Infix & C:o + +on: + issues: + types: + - opened + +jobs: + add-to-project: + name: Add issue to project Infix&co + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@v1.0.2 + with: + project-url: https://github.com/orgs/kernelkit/projects/3 + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index 997e919c..8da14ba6 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -3,6 +3,16 @@ Change Log All notable changes to the project are documented in this file. +[v24.10.0][] - UNRELEASED +------------------------- +### Changes +- OSPF: Add limitation to only allow one interface per area. + +### Fixes +- Fix #499 by adding a NACM rule to factory config, which by default + deny everyone to read the user password hash. +- Fix BFD in OSPF, previously you could not enable BFD on a single + interface without it was enabled on all interfaces. [v24.09.0][] - 2024-09-30 ------------------------- diff --git a/src/confd/share/factory.d/10-nacm.json b/src/confd/share/factory.d/10-nacm.json index 39748814..49583a20 100644 --- a/src/confd/share/factory.d/10-nacm.json +++ b/src/confd/share/factory.d/10-nacm.json @@ -1,5 +1,6 @@ { "ietf-netconf-acm:nacm": { + "enable-nacm": true, "groups": { "group": [ { @@ -25,6 +26,19 @@ "comment": "Allow 'admin' group complete access to all operations and data." } ] + }, + { + "name": "default-deny-all", + "group": ["*"], + "rule": [ + { + "name": "deny-password-read", + "module-name": "ietf-system", + "path": "/ietf-system:system/authentication/user/password", + "access-operations": "*", + "action": "deny" + } + ] } ] } diff --git a/src/confd/src/ietf-routing.c b/src/confd/src/ietf-routing.c index 46e0cc2b..9e0a6ae9 100644 --- a/src/confd/src/ietf-routing.c +++ b/src/confd/src/ietf-routing.c @@ -29,7 +29,7 @@ log facility local2\n" int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FILE *fp) { struct lyd_node *interface, *interfaces, *area; - int bfd_enabled = 0; + int num_bfd_enabled = 0; LY_LIST_FOR(lyd_child(areas), area) { const char *area_id; @@ -41,11 +41,13 @@ int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FIL const char *hello, *dead, *retransmit, *transmit, *interface_type, *cost; if (lydx_get_bool(interface, "enabled")) { + int passive = 0, bfd_enabled = 0; struct lyd_node *bfd; - int passive = 0; bfd = lydx_get_child(interface, "bfd"); - bfd_enabled += lydx_get_bool(bfd, "enabled"); + bfd_enabled = lydx_get_bool(bfd, "enabled"); + num_bfd_enabled += bfd_enabled; + passive = lydx_get_bool(interface, "passive"); fprintf(fp, "interface %s\n", lydx_get_cattr(interface, "name")); @@ -77,7 +79,7 @@ int parse_ospf_interfaces(sr_session_ctx_t *session, struct lyd_node *areas, FIL } } - return bfd_enabled; + return num_bfd_enabled; } int parse_ospf_redistribute(sr_session_ctx_t *session, struct lyd_node *redistributes, FILE *fp) diff --git a/src/confd/yang/Makefile.am b/src/confd/yang/Makefile.am index 3e287aca..0fd59504 100644 --- a/src/confd/yang/Makefile.am +++ b/src/confd/yang/Makefile.am @@ -1,2 +1,2 @@ yangdir = $(YANGDIR) -yang_DATA = $(wildcard *.yang) +yang_DATA = $(wildcard *@*.yang) ieee802-types.yang ieee802-dot1ab-types.yang diff --git a/src/confd/yang/confd.inc b/src/confd/yang/confd.inc index d2091178..40ef9a2a 100644 --- a/src/confd/yang/confd.inc +++ b/src/confd/yang/confd.inc @@ -27,7 +27,7 @@ MODULES=( "ieee802-dot1q-types@2022-10-29.yang" "infix-ip@2024-09-16.yang" "infix-if-type@2024-01-29.yang" - "infix-routing@2024-09-23.yang" + "infix-routing@2024-10-01.yang" "ieee802-dot1ab-lldp@2022-03-15.yang" "infix-lldp@2023-08-23.yang" "infix-dhcp-client@2024-09-20.yang" diff --git a/src/confd/yang/infix-containers.yang b/src/confd/yang/infix-containers.yang new file mode 100644 index 00000000..c9dfc9d6 --- /dev/null +++ b/src/confd/yang/infix-containers.yang @@ -0,0 +1,413 @@ +/* + * Infix Containers YANG module + */ +module infix-containers { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:infix-containers"; + prefix infix-cont; + + import ietf-yang-types { + prefix yang; + } + + import ietf-interfaces { + prefix if; + } + + import ietf-inet-types { + prefix inet; + } + + import infix-interfaces { + prefix infix-if; + } + + revision 2024-03-27 { + description "Add support for capabilities."; + reference "internal"; + } + + revision 2024-02-01 { + description "Initial revision"; + reference "internal"; + } + + /* + * Typedefs + */ + + typedef mount-type { + type enumeration { + enum bind { + description "Regular bind mount of host path to container."; + value 1; + } + enum glob { + description "Glob match and bind mount matching host paths to container."; + value 2; + } + } + } + + typedef restart-policy { + type enumeration { + enum never { + description "Do not restart containers that exit/crash."; + value 1; + } + enum retry { + description "Restart containers up to 10 times before giving up."; + value 2; + } + enum always { + description "Always restart containers when they exit."; + value 3; + } + } + } + + typedef capabilities { + type enumeration { + enum dac_override; + enum fsetid; + enum net_admin; + enum net_bind_service; + enum net_raw; + enum setgid; + enum setuid; + enum setpcap; + enum syslog; + enum sys_admin; + enum sys_chroot; + enum sys_module; + enum sys_ptrace; + enum sys_rawio; + enum sys_time; + } + } + + /* + * Data Nodes + */ + + container containers { + list container { + key "name"; + + leaf enabled { + description "Enable or disable a container configuration."; + type boolean; + default true; + } + + leaf name { + description "Name of the container"; + type string; + } + + leaf id { + description "Container ID, unique hash."; + config false; + type string; + } + + leaf image { + description "Docker image for the container: [transport]name[:tag|@digest] + + quay.io/username/myimage -- Pull myimage:latest + docker://busybox -- Pull busybox:latest from Docker Hub + docker://ghcr.io/usr/img -- Pull img:latest from GitHub packages + dir:/media/usb/myimage:1.1 -- Use myimage v1.1 from USB media + docker-archive:/tmp/archive -- Use archive:latest from tarball + oci-archive:/lib/oci/archive -- Use archive:latest from OCI archive + May be in .tar or .tar.gz format + + Note: if a remote repository cannot be reached, the creation of the + container will be put on a queue that retries pull every time + there is a route change in the host's system."; + mandatory true; + type string; + } + + leaf image-id { + description "Docker image ID, exact hash used."; + config false; + type string; + } + + list env { + description "Set environment variables, key=\"value\" pairs."; + key key; + + leaf key { + description "Single word."; + type string { + pattern '[a-zA-Z_][a-zA-Z0-9_]*'; + length "1..253"; + } + } + + leaf value { + description "Argument to key can be a single word or quoted multiple words."; + mandatory true; + type string; + } + } + + leaf command { + description "Override ENTRYPOINT from image and run command + args."; + type string; + } + + leaf hostname { + description "Sets the container host name that is available inside the container."; + type inet:domain-name; + } + + leaf privileged { + description "Give container extended privileges, e.g., access to devices."; + type boolean; + } + + leaf restart-policy { + description "Restart policy to when containers exit/crash."; + type restart-policy; + default always; + } + + leaf manual { + description "Auto-start or manual start after creation/reboot."; + type boolean; + } + + container network { + description "Select network mode: none, host, or container network interfaces."; + + leaf host { + description "Run in same network namespace as host, share DNS and publish all ports."; + type boolean; + } + + list interface { + description "Container network interface(s) to connect to the container."; + key name; + + leaf name { + description "Container network (interface name) to connect to the container."; + type if:interface-ref; + must "/if:interfaces/if:interface[if:name = current()]/infix-if:container-network" { + error-message "Container networks must be interfaces classified as container-network."; + } + } + + leaf-list option { + when "deref(../name)/../infix-if:container-network/infix-if:type = 'infix-if:bridge'"; + description "Options for masquerading container bridges. + + Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6) + mac=00:01:02:c0:ff:ee -- set fixed MAC address in container + interface_name=foo0 -- set interface name inside container"; + type string; + } + } + + leaf-list publish { + description "Publish container port, or a range of ports, to the host. + + Syntax: [[ip:][hostPort]:]containerPort[/protocol] + + Sample: 8080:80 -- forward tcp port 8080 to container port 80 + 69:69/udp -- forward udp port 69 to container port 69 + 127.0.0.1:8080:80 -- forward only from loopback interface"; + type string; + } + + leaf-list dns { + description "Set custom DNS servers, or 'none' to use /etc/resolv.conf in image."; + type inet:ip-address; + } + + leaf-list search { + description "Set custom DNS search domains, or '.' to not set search domain."; + type inet:domain-name; + } + + must "(host and not(interface)) or (not(host) and interface) or (not(host) and not(interface))" { + error-message "Host and interfaces are mutually exclusive"; + } + } + + leaf read-only { + description "Create a read-only container. Use volumes for writable directories."; + type boolean; + } + + container capabilities { + description "Capabilities to add for unprivileged and drop for privileged containers."; + + leaf-list add { + type capabilities; + description "List of capabilities to add to (an unprivileged) container."; + } + + leaf-list drop { + type capabilities; + description "List of capabilities to drop from (a privileged) container."; + } + } + + list mount { + description "Files, content, and directories to mount inside container."; + key name; + + leaf name { + description "Unique name to identify mount, e.g., 'ntpd.conf' or 'leds'. + + Set the source path or *content* to mount in the container, + the latter means the file contents are stored in the host's + startup-config, base64 encoded. + + Example source paths: + 1. /etc/ntpd.conf File name to bind mount to 'path' + 2. /sys/class/leds/ Control LEDs from a container + 3. /dev/sda* Share all matching files (type glob!) + + For persistent writable directories, *volumes* may be a + better fit for your container and easier to set up."; + type string; + } + + leaf type { + description "Mount type, strict bind mount or glob match."; + type mount-type; + default bind; + } + + choice data { + case source { + leaf source { + description "Host path to mount in container, may be a glob. + + When mounting files, directories (and globs) from the host, + the source must be an absolute path."; + type string { + pattern '/.*'; + } + } + } + case content { + leaf content { + description "File contents, in base64 native format (XML/JSON). + + With this setting the source path is not used, instead + a temporary read-only file is created on the host with + this content and bind-mounted into the container at the + target destination path. + + In the CLI, use 'set content' without and argument to + open an editor for easy copy-paste. On exit from the + editor the contents are base64 encoded automatically."; + type binary; + } + } + } + + leaf target { + description "Absolute path to target destination inside container. + + For example, to mount file on /etc/ntpd.conf set this path and + then use either the 'source' path to a file on the host system, + or import the text file using the 'content' node."; + mandatory true; + type string { + pattern '/.*'; + } + } + + leaf read-only { + description "All mounts are read-only by default. + Use this option to allow containers to write to files + and directories on the host system. + + NOTE: 'content' files can also be set read-write, but + no changes are saved back to hosts's datastore."; + type boolean; + default true; + } + } + + list volume { + description "Create a writable volume that survive container upgrades."; + key name; + + leaf name { + description "Single word to identify this (named) volume. + + Volumes are retained over the lifetime of a container and + survive both upgrading the image and configuration changes, + which otherwise wipe the default writable layer a container + is given. + + Volumes combine well with 'read-only' containers, when you + know which files/directories you want to persist. + + Compared to a bind mount, a volume is automatically 'synced' + with the contents of the container's file system on first + use. Hence, upgrading the container image will not update + the volume if the image has new/removed files at 'path'."; + type string { + pattern '[a-zA-Z_][a-zA-Z0-9_]*'; + length "1..64"; + } + } + + leaf target { + description "Absolute path to target destination directory inside the container."; + mandatory true; + type string { + pattern '/.*'; + } + } + } + + leaf running { + description "Status of container, running or not."; + config false; + type boolean; + } + + leaf status { + description "Status of container, human friendly."; + config false; + type string; + } + + action start { + description "Start a stopped container."; + } + + action stop { + description "Stop a running container."; + } + + action restart { + description "Restart a running, or start, a stopped container."; + } + } + } + + rpc oci-load { + description "Load an OCI archive from file or URL to an image."; + input { + leaf uri { + description "The URL or local file path, e.g., /lib/oci/archive.tar.gz"; + type string; + mandatory true; + } + leaf name { + description "Image name[:tag], default: basename of archive dir + :latest"; + type string; + } + } + } +} diff --git a/src/confd/yang/infix-containers@2024-03-27.yang b/src/confd/yang/infix-containers@2024-03-27.yang deleted file mode 100644 index c9dfc9d6..00000000 --- a/src/confd/yang/infix-containers@2024-03-27.yang +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Infix Containers YANG module - */ -module infix-containers { - yang-version 1.1; - namespace "urn:ietf:params:xml:ns:yang:infix-containers"; - prefix infix-cont; - - import ietf-yang-types { - prefix yang; - } - - import ietf-interfaces { - prefix if; - } - - import ietf-inet-types { - prefix inet; - } - - import infix-interfaces { - prefix infix-if; - } - - revision 2024-03-27 { - description "Add support for capabilities."; - reference "internal"; - } - - revision 2024-02-01 { - description "Initial revision"; - reference "internal"; - } - - /* - * Typedefs - */ - - typedef mount-type { - type enumeration { - enum bind { - description "Regular bind mount of host path to container."; - value 1; - } - enum glob { - description "Glob match and bind mount matching host paths to container."; - value 2; - } - } - } - - typedef restart-policy { - type enumeration { - enum never { - description "Do not restart containers that exit/crash."; - value 1; - } - enum retry { - description "Restart containers up to 10 times before giving up."; - value 2; - } - enum always { - description "Always restart containers when they exit."; - value 3; - } - } - } - - typedef capabilities { - type enumeration { - enum dac_override; - enum fsetid; - enum net_admin; - enum net_bind_service; - enum net_raw; - enum setgid; - enum setuid; - enum setpcap; - enum syslog; - enum sys_admin; - enum sys_chroot; - enum sys_module; - enum sys_ptrace; - enum sys_rawio; - enum sys_time; - } - } - - /* - * Data Nodes - */ - - container containers { - list container { - key "name"; - - leaf enabled { - description "Enable or disable a container configuration."; - type boolean; - default true; - } - - leaf name { - description "Name of the container"; - type string; - } - - leaf id { - description "Container ID, unique hash."; - config false; - type string; - } - - leaf image { - description "Docker image for the container: [transport]name[:tag|@digest] - - quay.io/username/myimage -- Pull myimage:latest - docker://busybox -- Pull busybox:latest from Docker Hub - docker://ghcr.io/usr/img -- Pull img:latest from GitHub packages - dir:/media/usb/myimage:1.1 -- Use myimage v1.1 from USB media - docker-archive:/tmp/archive -- Use archive:latest from tarball - oci-archive:/lib/oci/archive -- Use archive:latest from OCI archive - May be in .tar or .tar.gz format - - Note: if a remote repository cannot be reached, the creation of the - container will be put on a queue that retries pull every time - there is a route change in the host's system."; - mandatory true; - type string; - } - - leaf image-id { - description "Docker image ID, exact hash used."; - config false; - type string; - } - - list env { - description "Set environment variables, key=\"value\" pairs."; - key key; - - leaf key { - description "Single word."; - type string { - pattern '[a-zA-Z_][a-zA-Z0-9_]*'; - length "1..253"; - } - } - - leaf value { - description "Argument to key can be a single word or quoted multiple words."; - mandatory true; - type string; - } - } - - leaf command { - description "Override ENTRYPOINT from image and run command + args."; - type string; - } - - leaf hostname { - description "Sets the container host name that is available inside the container."; - type inet:domain-name; - } - - leaf privileged { - description "Give container extended privileges, e.g., access to devices."; - type boolean; - } - - leaf restart-policy { - description "Restart policy to when containers exit/crash."; - type restart-policy; - default always; - } - - leaf manual { - description "Auto-start or manual start after creation/reboot."; - type boolean; - } - - container network { - description "Select network mode: none, host, or container network interfaces."; - - leaf host { - description "Run in same network namespace as host, share DNS and publish all ports."; - type boolean; - } - - list interface { - description "Container network interface(s) to connect to the container."; - key name; - - leaf name { - description "Container network (interface name) to connect to the container."; - type if:interface-ref; - must "/if:interfaces/if:interface[if:name = current()]/infix-if:container-network" { - error-message "Container networks must be interfaces classified as container-network."; - } - } - - leaf-list option { - when "deref(../name)/../infix-if:container-network/infix-if:type = 'infix-if:bridge'"; - description "Options for masquerading container bridges. - - Example: ip=1.2.3.4 -- request a specific IP (IPv4 or IPv6) - mac=00:01:02:c0:ff:ee -- set fixed MAC address in container - interface_name=foo0 -- set interface name inside container"; - type string; - } - } - - leaf-list publish { - description "Publish container port, or a range of ports, to the host. - - Syntax: [[ip:][hostPort]:]containerPort[/protocol] - - Sample: 8080:80 -- forward tcp port 8080 to container port 80 - 69:69/udp -- forward udp port 69 to container port 69 - 127.0.0.1:8080:80 -- forward only from loopback interface"; - type string; - } - - leaf-list dns { - description "Set custom DNS servers, or 'none' to use /etc/resolv.conf in image."; - type inet:ip-address; - } - - leaf-list search { - description "Set custom DNS search domains, or '.' to not set search domain."; - type inet:domain-name; - } - - must "(host and not(interface)) or (not(host) and interface) or (not(host) and not(interface))" { - error-message "Host and interfaces are mutually exclusive"; - } - } - - leaf read-only { - description "Create a read-only container. Use volumes for writable directories."; - type boolean; - } - - container capabilities { - description "Capabilities to add for unprivileged and drop for privileged containers."; - - leaf-list add { - type capabilities; - description "List of capabilities to add to (an unprivileged) container."; - } - - leaf-list drop { - type capabilities; - description "List of capabilities to drop from (a privileged) container."; - } - } - - list mount { - description "Files, content, and directories to mount inside container."; - key name; - - leaf name { - description "Unique name to identify mount, e.g., 'ntpd.conf' or 'leds'. - - Set the source path or *content* to mount in the container, - the latter means the file contents are stored in the host's - startup-config, base64 encoded. - - Example source paths: - 1. /etc/ntpd.conf File name to bind mount to 'path' - 2. /sys/class/leds/ Control LEDs from a container - 3. /dev/sda* Share all matching files (type glob!) - - For persistent writable directories, *volumes* may be a - better fit for your container and easier to set up."; - type string; - } - - leaf type { - description "Mount type, strict bind mount or glob match."; - type mount-type; - default bind; - } - - choice data { - case source { - leaf source { - description "Host path to mount in container, may be a glob. - - When mounting files, directories (and globs) from the host, - the source must be an absolute path."; - type string { - pattern '/.*'; - } - } - } - case content { - leaf content { - description "File contents, in base64 native format (XML/JSON). - - With this setting the source path is not used, instead - a temporary read-only file is created on the host with - this content and bind-mounted into the container at the - target destination path. - - In the CLI, use 'set content' without and argument to - open an editor for easy copy-paste. On exit from the - editor the contents are base64 encoded automatically."; - type binary; - } - } - } - - leaf target { - description "Absolute path to target destination inside container. - - For example, to mount file on /etc/ntpd.conf set this path and - then use either the 'source' path to a file on the host system, - or import the text file using the 'content' node."; - mandatory true; - type string { - pattern '/.*'; - } - } - - leaf read-only { - description "All mounts are read-only by default. - Use this option to allow containers to write to files - and directories on the host system. - - NOTE: 'content' files can also be set read-write, but - no changes are saved back to hosts's datastore."; - type boolean; - default true; - } - } - - list volume { - description "Create a writable volume that survive container upgrades."; - key name; - - leaf name { - description "Single word to identify this (named) volume. - - Volumes are retained over the lifetime of a container and - survive both upgrading the image and configuration changes, - which otherwise wipe the default writable layer a container - is given. - - Volumes combine well with 'read-only' containers, when you - know which files/directories you want to persist. - - Compared to a bind mount, a volume is automatically 'synced' - with the contents of the container's file system on first - use. Hence, upgrading the container image will not update - the volume if the image has new/removed files at 'path'."; - type string { - pattern '[a-zA-Z_][a-zA-Z0-9_]*'; - length "1..64"; - } - } - - leaf target { - description "Absolute path to target destination directory inside the container."; - mandatory true; - type string { - pattern '/.*'; - } - } - } - - leaf running { - description "Status of container, running or not."; - config false; - type boolean; - } - - leaf status { - description "Status of container, human friendly."; - config false; - type string; - } - - action start { - description "Start a stopped container."; - } - - action stop { - description "Stop a running container."; - } - - action restart { - description "Restart a running, or start, a stopped container."; - } - } - } - - rpc oci-load { - description "Load an OCI archive from file or URL to an image."; - input { - leaf uri { - description "The URL or local file path, e.g., /lib/oci/archive.tar.gz"; - type string; - mandatory true; - } - leaf name { - description "Image name[:tag], default: basename of archive dir + :latest"; - type string; - } - } - } -} diff --git a/src/confd/yang/infix-containers@2024-03-27.yang b/src/confd/yang/infix-containers@2024-03-27.yang new file mode 120000 index 00000000..bd4684b1 --- /dev/null +++ b/src/confd/yang/infix-containers@2024-03-27.yang @@ -0,0 +1 @@ +infix-containers.yang \ No newline at end of file diff --git a/src/confd/yang/infix-dhcp-client.yang b/src/confd/yang/infix-dhcp-client.yang new file mode 100644 index 00000000..9d59be45 --- /dev/null +++ b/src/confd/yang/infix-dhcp-client.yang @@ -0,0 +1,166 @@ +module infix-dhcp-client { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:infix-dhcp-client"; + prefix dhc4-clnt; + + import ietf-interfaces { + prefix "if"; + } + + contact "kernelkit@googlegroups.com"; + description "This module implements an IPv4 DHCP client"; + + revision 2024-09-20 { + description "Routes are installed in Frr (staticd), clarify preference + vs metric and adjust default preference 100 -> 5."; + reference "internal"; + } + revision 2024-04-12 { + description "Adjust DHCP client hostname option, max 64 charachters."; + reference "internal"; + } + revision 2024-01-30 { + description "Add DHCP client options, arping, and route preference."; + reference "internal"; + } + revision 2023-05-22 { + description "Initial revision."; + reference "rfc2131 rfc7950"; + } + + /* + * Typedefs + */ + + typedef route-preference { + type uint32; + description "This type is used for selecting route preference (distance)."; + } + + typedef dhcp-options { + type union { + type string; + type enumeration { + enum subnet { + value 1; + description "Subnet (IP address and netmask)"; + } + enum router { + value 3; + description "Default route(s)"; + } + enum dns { + value 6; + description "DNS server"; + } + enum hostname { + value 12; + description "Hostname"; + } + enum domain { + value 15; + description "Domain name"; + } + enum broadcast { + value 28; + description "Broadcast address"; + } + enum ntpsrv { + value 42; + description "NTP server"; + } + enum address { + value 50; + description "Requested (previously cached) address"; + } + enum clientid { + value 61; + description "Client ID (default MAC, and option 12)"; + } + enum fqdn { + value 81; + description "Request DNS update of client FQDN argument"; + } + enum search { + value 119; + description "Domain search list"; + } + enum staticroutes { + value 121; + description "Classless static routes"; + } + enum msstaticroutes { + value 249; + description "Microsoft classless static routes"; + } + } + } + description "Supported DHCP client request options"; + } + + /* + * Data Nodes + */ + + container dhcp-client { + description + "DHCPv4 client configuration"; + leaf enabled { + type boolean; + default "true"; + description "Globally enables the DHCP client function."; + } + list client-if { + key "if-name"; + description "List of interfaces requesting DHCPv4 configuration."; + leaf if-name { + type if:interface-ref; + mandatory true; + description "Name of the interface."; + } + leaf enabled { + type boolean; + default "true"; + description "Enable DHCP client for this interface."; + } + leaf client-id { + type string; + description "Optional Client ID, option 61, default: MAC address."; + } + leaf arping { + type boolean; + default "true"; + description "ARP for lease to check for IP address collisions (slow)."; + } + list option { + key "name"; + description + "List of DHCP options to request (and accept). The default is an + empty list, meaning all supported options. To restrict the + client to only get IP address and default route, set this to: + 'subnet router'"; + leaf name { + type dhcp-options; + description "DHCP option to request from, or inform server of."; + } + leaf value { + type string; + description "Optional value, only used for non-flag request options. + Example: option:hostname, value:xyzzy + option:clientid, value:01:02:03:04:05:06:07:08:09:0a + option:0x51, value:xyzzy.example.com"; + must "../name != 'hostname' or re-match(., '[a-zA-Z0-9\\-_]{1,64}')"; + } + } + leaf route-preference { + type route-preference; + default 5; + description + "The preference (administrative distance) that all DHCP routes are + installed with, option 3, 33 and 121. The default preferfence (5) + is higher (less worth) than static routes, but lower than those + learned via dynamic routing protocols, like OSPF."; + } + } + } +} diff --git a/src/confd/yang/infix-dhcp-client@2024-09-20.yang b/src/confd/yang/infix-dhcp-client@2024-09-20.yang deleted file mode 100644 index 9d59be45..00000000 --- a/src/confd/yang/infix-dhcp-client@2024-09-20.yang +++ /dev/null @@ -1,166 +0,0 @@ -module infix-dhcp-client { - yang-version 1.1; - namespace "urn:ietf:params:xml:ns:yang:infix-dhcp-client"; - prefix dhc4-clnt; - - import ietf-interfaces { - prefix "if"; - } - - contact "kernelkit@googlegroups.com"; - description "This module implements an IPv4 DHCP client"; - - revision 2024-09-20 { - description "Routes are installed in Frr (staticd), clarify preference - vs metric and adjust default preference 100 -> 5."; - reference "internal"; - } - revision 2024-04-12 { - description "Adjust DHCP client hostname option, max 64 charachters."; - reference "internal"; - } - revision 2024-01-30 { - description "Add DHCP client options, arping, and route preference."; - reference "internal"; - } - revision 2023-05-22 { - description "Initial revision."; - reference "rfc2131 rfc7950"; - } - - /* - * Typedefs - */ - - typedef route-preference { - type uint32; - description "This type is used for selecting route preference (distance)."; - } - - typedef dhcp-options { - type union { - type string; - type enumeration { - enum subnet { - value 1; - description "Subnet (IP address and netmask)"; - } - enum router { - value 3; - description "Default route(s)"; - } - enum dns { - value 6; - description "DNS server"; - } - enum hostname { - value 12; - description "Hostname"; - } - enum domain { - value 15; - description "Domain name"; - } - enum broadcast { - value 28; - description "Broadcast address"; - } - enum ntpsrv { - value 42; - description "NTP server"; - } - enum address { - value 50; - description "Requested (previously cached) address"; - } - enum clientid { - value 61; - description "Client ID (default MAC, and option 12)"; - } - enum fqdn { - value 81; - description "Request DNS update of client FQDN argument"; - } - enum search { - value 119; - description "Domain search list"; - } - enum staticroutes { - value 121; - description "Classless static routes"; - } - enum msstaticroutes { - value 249; - description "Microsoft classless static routes"; - } - } - } - description "Supported DHCP client request options"; - } - - /* - * Data Nodes - */ - - container dhcp-client { - description - "DHCPv4 client configuration"; - leaf enabled { - type boolean; - default "true"; - description "Globally enables the DHCP client function."; - } - list client-if { - key "if-name"; - description "List of interfaces requesting DHCPv4 configuration."; - leaf if-name { - type if:interface-ref; - mandatory true; - description "Name of the interface."; - } - leaf enabled { - type boolean; - default "true"; - description "Enable DHCP client for this interface."; - } - leaf client-id { - type string; - description "Optional Client ID, option 61, default: MAC address."; - } - leaf arping { - type boolean; - default "true"; - description "ARP for lease to check for IP address collisions (slow)."; - } - list option { - key "name"; - description - "List of DHCP options to request (and accept). The default is an - empty list, meaning all supported options. To restrict the - client to only get IP address and default route, set this to: - 'subnet router'"; - leaf name { - type dhcp-options; - description "DHCP option to request from, or inform server of."; - } - leaf value { - type string; - description "Optional value, only used for non-flag request options. - Example: option:hostname, value:xyzzy - option:clientid, value:01:02:03:04:05:06:07:08:09:0a - option:0x51, value:xyzzy.example.com"; - must "../name != 'hostname' or re-match(., '[a-zA-Z0-9\\-_]{1,64}')"; - } - } - leaf route-preference { - type route-preference; - default 5; - description - "The preference (administrative distance) that all DHCP routes are - installed with, option 3, 33 and 121. The default preferfence (5) - is higher (less worth) than static routes, but lower than those - learned via dynamic routing protocols, like OSPF."; - } - } - } -} diff --git a/src/confd/yang/infix-dhcp-client@2024-09-20.yang b/src/confd/yang/infix-dhcp-client@2024-09-20.yang new file mode 120000 index 00000000..7d67b0ef --- /dev/null +++ b/src/confd/yang/infix-dhcp-client@2024-09-20.yang @@ -0,0 +1 @@ +infix-dhcp-client.yang \ No newline at end of file diff --git a/src/confd/yang/infix-ethernet-interface.yang b/src/confd/yang/infix-ethernet-interface.yang new file mode 100644 index 00000000..ab4f2547 --- /dev/null +++ b/src/confd/yang/infix-ethernet-interface.yang @@ -0,0 +1,86 @@ +module infix-ethernet-interface { + yang-version 1.1; + namespace "urn:infix:ethernet-interface:ns:yang:1.0"; + prefix infix-eth; + + import ieee802-ethernet-interface { + prefix eth; + } + import ietf-interfaces { + prefix if; + } + import ietf-yang-types { + prefix yang; + reference "IETF RFC 6991"; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Extensions and deviations to ieee802-ethernet-interface.yang"; + + revision 2024-02-27 { + description "Add augment for in-good-octets and out-good-octets"; + reference "internal"; + } + + revision 2024-01-22 { + description "Support ethernet but not negotiation-status"; + reference "internal"; + } + + revision 2023-11-22 { + description "Initial revision."; + reference "internal"; + } + + /* + * Data Nodes + */ + augment "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:frame" { + leaf out-good-octets { + type yang:counter64; + units octets; + description "A count of data and padding octets of frames that are successfully transmitted."; + } + leaf in-good-octets { + type yang:counter64; + units octets; + description "A count of data and padding octets in frames that are successfully received."; + } + } + + /* Deviations for config and status */ + + deviation "/if:interfaces/if:interface/eth:ethernet/eth:flow-control" { + deviate not-supported; + } + deviation "/if:interfaces/if:interface/eth:ethernet/eth:max-frame-length" { + deviate not-supported; + } + deviation "/if:interfaces/if:interface/eth:ethernet/eth:mac-control-extension-control" { + deviate not-supported; + } + deviation "/if:interfaces/if:interface/eth:ethernet/eth:frame-limit-slow-protocol" { + deviate not-supported; + } + deviation "/if:interfaces/if:interface/eth:ethernet/eth:capabilities" { + deviate not-supported; + } + deviation "/if:interfaces/if:interface/eth:ethernet/eth:auto-negotiation/eth:negotiation-status" { + deviate not-supported; + } + + /* Deviations for statistics */ + deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:frame/eth:in-total-frames" { + deviate not-supported; + } + deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:frame/eth:out-error-mac-internal-frames" { + deviate not-supported; + } + deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:phy" { + deviate not-supported; + } + deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:mac-control" { + deviate not-supported; + } +} diff --git a/src/confd/yang/infix-ethernet-interface@2024-02-27.yang b/src/confd/yang/infix-ethernet-interface@2024-02-27.yang deleted file mode 100644 index ab4f2547..00000000 --- a/src/confd/yang/infix-ethernet-interface@2024-02-27.yang +++ /dev/null @@ -1,86 +0,0 @@ -module infix-ethernet-interface { - yang-version 1.1; - namespace "urn:infix:ethernet-interface:ns:yang:1.0"; - prefix infix-eth; - - import ieee802-ethernet-interface { - prefix eth; - } - import ietf-interfaces { - prefix if; - } - import ietf-yang-types { - prefix yang; - reference "IETF RFC 6991"; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Extensions and deviations to ieee802-ethernet-interface.yang"; - - revision 2024-02-27 { - description "Add augment for in-good-octets and out-good-octets"; - reference "internal"; - } - - revision 2024-01-22 { - description "Support ethernet but not negotiation-status"; - reference "internal"; - } - - revision 2023-11-22 { - description "Initial revision."; - reference "internal"; - } - - /* - * Data Nodes - */ - augment "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:frame" { - leaf out-good-octets { - type yang:counter64; - units octets; - description "A count of data and padding octets of frames that are successfully transmitted."; - } - leaf in-good-octets { - type yang:counter64; - units octets; - description "A count of data and padding octets in frames that are successfully received."; - } - } - - /* Deviations for config and status */ - - deviation "/if:interfaces/if:interface/eth:ethernet/eth:flow-control" { - deviate not-supported; - } - deviation "/if:interfaces/if:interface/eth:ethernet/eth:max-frame-length" { - deviate not-supported; - } - deviation "/if:interfaces/if:interface/eth:ethernet/eth:mac-control-extension-control" { - deviate not-supported; - } - deviation "/if:interfaces/if:interface/eth:ethernet/eth:frame-limit-slow-protocol" { - deviate not-supported; - } - deviation "/if:interfaces/if:interface/eth:ethernet/eth:capabilities" { - deviate not-supported; - } - deviation "/if:interfaces/if:interface/eth:ethernet/eth:auto-negotiation/eth:negotiation-status" { - deviate not-supported; - } - - /* Deviations for statistics */ - deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:frame/eth:in-total-frames" { - deviate not-supported; - } - deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:frame/eth:out-error-mac-internal-frames" { - deviate not-supported; - } - deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:phy" { - deviate not-supported; - } - deviation "/if:interfaces/if:interface/eth:ethernet/eth:statistics/eth:mac-control" { - deviate not-supported; - } -} diff --git a/src/confd/yang/infix-ethernet-interface@2024-02-27.yang b/src/confd/yang/infix-ethernet-interface@2024-02-27.yang new file mode 120000 index 00000000..25930438 --- /dev/null +++ b/src/confd/yang/infix-ethernet-interface@2024-02-27.yang @@ -0,0 +1 @@ +infix-ethernet-interface.yang \ No newline at end of file diff --git a/src/confd/yang/infix-factory-default.yang b/src/confd/yang/infix-factory-default.yang new file mode 100644 index 00000000..197a38c2 --- /dev/null +++ b/src/confd/yang/infix-factory-default.yang @@ -0,0 +1,23 @@ +module infix-factory-default { + yang-version 1.1; + namespace "urn:infix:factory-default:ns:yang:1.0"; + prefix infix-fd; + + import ietf-netconf-acm { + prefix nacm; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Infix factory default model."; + + revision 2023-06-28 { + description "Initial revision."; + reference "internal"; + } + + rpc factory-default { + nacm:default-deny-all; + description "Reset the running-config datastore to factory defaults."; + } +} diff --git a/src/confd/yang/infix-factory-default@2023-06-28.yang b/src/confd/yang/infix-factory-default@2023-06-28.yang deleted file mode 100644 index 197a38c2..00000000 --- a/src/confd/yang/infix-factory-default@2023-06-28.yang +++ /dev/null @@ -1,23 +0,0 @@ -module infix-factory-default { - yang-version 1.1; - namespace "urn:infix:factory-default:ns:yang:1.0"; - prefix infix-fd; - - import ietf-netconf-acm { - prefix nacm; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Infix factory default model."; - - revision 2023-06-28 { - description "Initial revision."; - reference "internal"; - } - - rpc factory-default { - nacm:default-deny-all; - description "Reset the running-config datastore to factory defaults."; - } -} diff --git a/src/confd/yang/infix-factory-default@2023-06-28.yang b/src/confd/yang/infix-factory-default@2023-06-28.yang new file mode 120000 index 00000000..ef129934 --- /dev/null +++ b/src/confd/yang/infix-factory-default@2023-06-28.yang @@ -0,0 +1 @@ +infix-factory-default.yang \ No newline at end of file diff --git a/src/confd/yang/infix-hardware.yang b/src/confd/yang/infix-hardware.yang new file mode 100644 index 00000000..71ad21f4 --- /dev/null +++ b/src/confd/yang/infix-hardware.yang @@ -0,0 +1,148 @@ +module infix-hardware { + yang-version 1.1; + namespace "urn:infix:hardware:ns:yang:1.0"; + prefix ih; + import ietf-hardware { + prefix iehw; + } + import iana-hardware { + prefix iahw; + } + + import ietf-yang-types { + prefix yang; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Vital Product Data augmentation of ieee-hardware and deviations."; + + revision 2024-04-25 { + description "Spellcheck leaf: coutry-code -> country-code"; + reference "internal"; + } + revision 2024-01-18 { + description "Initial"; + reference "internal"; + } + + typedef country-code { + type string { + length 2; + pattern "[A-Za-z]+"; + } + description "A two-letter country code."; + } + + identity hardware-class { + description "infix hardware base class"; + } + + identity usb { + base hardware-class; + description "This identity is used to describe a USB port"; + } + identity vpd { + base hardware-class; + description "This identity is used to a VPD memory on the device."; + } + + deviation "/iehw:hardware/iehw:component/iehw:class" { + deviate replace { + type identityref { + base hardware-class; + } + } + } + + deviation "/iehw:hardware/iehw:component/iehw:state/iehw:admin-state" { + deviate add { + must ". = 'locked' or . = 'unlocked'" { + error-message "Only 'locked' and 'unlocked' states are allowed here."; + } + } + } + + deviation "/iehw:hardware/iehw:component/iehw:state/iehw:standby-state" { + deviate not-supported; + } + deviation "/iehw:hardware/iehw:component/iehw:sensor-data" { + deviate not-supported; + } + deviation "/iehw:hardware/iehw:component/iehw:parent" { + deviate not-supported; + } + deviation "/iehw:hardware/iehw:component/iehw:parent-rel-pos" { + deviate not-supported; + } + deviation "/iehw:hardware/iehw:component/iehw:alias" { + deviate not-supported; + } + deviation "/iehw:hardware/iehw:component/iehw:uri" { + deviate not-supported; + } + deviation "/iehw:hardware/iehw:component/iehw:asset-id" { + deviate not-supported; + } + augment "/iehw:hardware/iehw:component" { + container vpd-data { + config false; + leaf product-name { + type string; + } + leaf part-number { + type string; + } + leaf serial-number { + type string; + } + leaf mac-address { + type yang:mac-address; + } + leaf manufacture-date { + type string; + } + leaf device-version { + type uint8; + } + leaf label-revision { + type string; + } + leaf label-version { + type string; + } + leaf platform-name { + type string; + } + leaf onie-version { + type string; + } + leaf num-macs { + type uint16; + } + leaf manufacturer { + type string; + } + leaf country-code { + type country-code; + } + leaf vendor { + type string; + } + leaf diag-version { + type string; + } + leaf service-tag { + type string; + } + list vendor-extension { + leaf iana-enterprise-number { + type uint32; + } + leaf extension-data { + type string; + } + } + } + } +} diff --git a/src/confd/yang/infix-hardware@2024-04-25.yang b/src/confd/yang/infix-hardware@2024-04-25.yang deleted file mode 100644 index 71ad21f4..00000000 --- a/src/confd/yang/infix-hardware@2024-04-25.yang +++ /dev/null @@ -1,148 +0,0 @@ -module infix-hardware { - yang-version 1.1; - namespace "urn:infix:hardware:ns:yang:1.0"; - prefix ih; - import ietf-hardware { - prefix iehw; - } - import iana-hardware { - prefix iahw; - } - - import ietf-yang-types { - prefix yang; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Vital Product Data augmentation of ieee-hardware and deviations."; - - revision 2024-04-25 { - description "Spellcheck leaf: coutry-code -> country-code"; - reference "internal"; - } - revision 2024-01-18 { - description "Initial"; - reference "internal"; - } - - typedef country-code { - type string { - length 2; - pattern "[A-Za-z]+"; - } - description "A two-letter country code."; - } - - identity hardware-class { - description "infix hardware base class"; - } - - identity usb { - base hardware-class; - description "This identity is used to describe a USB port"; - } - identity vpd { - base hardware-class; - description "This identity is used to a VPD memory on the device."; - } - - deviation "/iehw:hardware/iehw:component/iehw:class" { - deviate replace { - type identityref { - base hardware-class; - } - } - } - - deviation "/iehw:hardware/iehw:component/iehw:state/iehw:admin-state" { - deviate add { - must ". = 'locked' or . = 'unlocked'" { - error-message "Only 'locked' and 'unlocked' states are allowed here."; - } - } - } - - deviation "/iehw:hardware/iehw:component/iehw:state/iehw:standby-state" { - deviate not-supported; - } - deviation "/iehw:hardware/iehw:component/iehw:sensor-data" { - deviate not-supported; - } - deviation "/iehw:hardware/iehw:component/iehw:parent" { - deviate not-supported; - } - deviation "/iehw:hardware/iehw:component/iehw:parent-rel-pos" { - deviate not-supported; - } - deviation "/iehw:hardware/iehw:component/iehw:alias" { - deviate not-supported; - } - deviation "/iehw:hardware/iehw:component/iehw:uri" { - deviate not-supported; - } - deviation "/iehw:hardware/iehw:component/iehw:asset-id" { - deviate not-supported; - } - augment "/iehw:hardware/iehw:component" { - container vpd-data { - config false; - leaf product-name { - type string; - } - leaf part-number { - type string; - } - leaf serial-number { - type string; - } - leaf mac-address { - type yang:mac-address; - } - leaf manufacture-date { - type string; - } - leaf device-version { - type uint8; - } - leaf label-revision { - type string; - } - leaf label-version { - type string; - } - leaf platform-name { - type string; - } - leaf onie-version { - type string; - } - leaf num-macs { - type uint16; - } - leaf manufacturer { - type string; - } - leaf country-code { - type country-code; - } - leaf vendor { - type string; - } - leaf diag-version { - type string; - } - leaf service-tag { - type string; - } - list vendor-extension { - leaf iana-enterprise-number { - type uint32; - } - leaf extension-data { - type string; - } - } - } - } -} diff --git a/src/confd/yang/infix-hardware@2024-04-25.yang b/src/confd/yang/infix-hardware@2024-04-25.yang new file mode 120000 index 00000000..154924a0 --- /dev/null +++ b/src/confd/yang/infix-hardware@2024-04-25.yang @@ -0,0 +1 @@ +infix-hardware.yang \ No newline at end of file diff --git a/src/confd/yang/infix-if-base.yang b/src/confd/yang/infix-if-base.yang new file mode 100644 index 00000000..f70e70de --- /dev/null +++ b/src/confd/yang/infix-if-base.yang @@ -0,0 +1,31 @@ +submodule infix-if-base { + yang-version 1.1; + belongs-to infix-interfaces { + prefix infix-if; + } + + import ietf-interfaces { + prefix if; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Linux link aggregates (lag) for ietf-interfaces."; + + revision 2023-08-21 { + description "Initial revision."; + reference "internal"; + } + + /* + * Data Nodes + */ + + augment "/if:interfaces/if:interface" { + description "Augments the interface model with mutually exclusive guards."; + + choice port { + description "An interface can only be member of either a bridge or a link aggregate."; + } + } +} diff --git a/src/confd/yang/infix-if-base@2023-08-21.yang b/src/confd/yang/infix-if-base@2023-08-21.yang deleted file mode 100644 index f70e70de..00000000 --- a/src/confd/yang/infix-if-base@2023-08-21.yang +++ /dev/null @@ -1,31 +0,0 @@ -submodule infix-if-base { - yang-version 1.1; - belongs-to infix-interfaces { - prefix infix-if; - } - - import ietf-interfaces { - prefix if; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Linux link aggregates (lag) for ietf-interfaces."; - - revision 2023-08-21 { - description "Initial revision."; - reference "internal"; - } - - /* - * Data Nodes - */ - - augment "/if:interfaces/if:interface" { - description "Augments the interface model with mutually exclusive guards."; - - choice port { - description "An interface can only be member of either a bridge or a link aggregate."; - } - } -} diff --git a/src/confd/yang/infix-if-base@2023-08-21.yang b/src/confd/yang/infix-if-base@2023-08-21.yang new file mode 120000 index 00000000..11e66635 --- /dev/null +++ b/src/confd/yang/infix-if-base@2023-08-21.yang @@ -0,0 +1 @@ +infix-if-base.yang \ No newline at end of file diff --git a/src/confd/yang/infix-if-bridge.yang b/src/confd/yang/infix-if-bridge.yang new file mode 100644 index 00000000..74806d3f --- /dev/null +++ b/src/confd/yang/infix-if-bridge.yang @@ -0,0 +1,547 @@ +submodule infix-if-bridge { + yang-version 1.1; + belongs-to infix-interfaces { + prefix infix-if; + } + import ietf-yang-types { + prefix yang; + } + import iana-if-type { + prefix ianaift; + } + import ietf-routing-types { + prefix rt-types; + } + import ietf-interfaces { + prefix if; + } + import ietf-inet-types { + prefix inet; + } + import ietf-ip { + prefix ip; + } + import ieee802-dot1q-types { + prefix dot1q-types; + } + import infix-if-type { + prefix infix-ift; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Linux bridge extension for ietf-interfaces."; + + revision 2024-08-26 { + description "Improve must expressions for multicast. + + Add a must expression forcing a port in a dot1q multicast-filter + to also belong to the VLAN. Also add must expression (for both + 8021d and 8021q) to force snooping to be anabled when enable + multicast-filters"; + reference "internal"; + } + revision 2024-03-28 { + description "Rename mdb -> multicast-filters. + + Add support for L2 multicast groups (MAC multicast). They + are currently always in state 'permanent'. + + Change vlan, multicast and mulitcast-filters containers to + presence containers. This means multicast snooping is now + disabled by default when creating a bridge or adding a VLAN. + + Global bridge multicast configuration must now be disabled + when adding VLANs to a bridge. I.e., global multicast is + not inherited to VLANs in any way."; + reference "internal"; + } + revision 2024-03-06 { + description "Drop default value for bridge-port PVID. Should be possible + to drop untagged frames. + + Add must() expression for VLAN memberships. Listed ports must + belong to this bridge and cannot be untagged and tagged at the + same time. + + Also, add must() expression to ensure VLAN filtering bridges + do not have any IP address set since the bridge is always only + a tagged member of VLANs. Use a VLAN interfaces on top of the + bridge for IP addressing."; + reference "internal"; + } + revision 2024-02-19 { + description "Add STP state to bridge port."; + reference "internal"; + } + revision 2023-12-02 { + description "Extend bridge-port must expression to ensure a + bridge cannot be a bridge-port to itself."; + reference "internal"; + } + revision 2023-11-08 { + description "Dropped support for configuring bridge pvid. + Bridge ports need explicit VLAN assignment."; + reference "internal"; + } + revision 2023-08-21 { + description "Minor, lint ordering and add missing description."; + reference "internal"; + } + revision 2023-05-31 { + description "Initial revision."; + reference "internal"; + } + + /* + * Features + */ + + feature vlan-filtering { + description "Indicates if this bridge supports VLAN filtering."; + } + + /* + * Typedefs + */ + + typedef mac-multicast-address { + description "Valid multicast address."; + type string { + pattern "[0-9A-Fa-f][13579BbDdFf](:[0-9A-Fa-f]{2}){5}"; + } + } + + typedef ieee-reserved-groups { + type union { + type uint8 { + range "0..15"; + } + type enumeration { + enum stp { + value 0; + description "Spanning Tree (STP/RSPT/MSTP)."; + } + enum lacp { + value 2; + description "802.3 Slow Protocols, e.g., LACP."; + } + enum dot1x { + value 3; + description "802.1X Port-Based Network Access Control."; + } + enum lldp { + value 14; + description "802.1AB Link Layer Discovery Protocol (LLDP)."; + } + } + } + description + "This is a user-friendly enumeration of the different reserved IEEE + reserved link-local multicast groups, in 01:80:C2:00:00:0X."; + } + + typedef stp-state { + description "User-friendly enumeration of different bridge port operational states."; + type enumeration { + enum disabled { + value 0; + description "Port is in STP DISABLED state"; + } + enum listening { + value 1; + description "Port is in STP LISTENING state"; + } + enum learning { + value 2; + description "Port is in STP LEARNING state"; + } + enum forwarding { + value 3; + description "Port is in STP FORWARDING state. This is the default vlan state."; + } + enum blocking { + value 4; + description "Port is in STP BLOCKING state."; + } + } + } + + typedef querier-mode { + description "Type of IGMP/MLD querier, recommend using 'auto'."; + type enumeration { + enum off { + value 0; + description "Never initiate IGMP/MLD queries."; + } + enum proxy { + value 1; + description "Send proxy queries if no better querier IP exists."; + } + enum auto { + value 2; + description "Participate in querier elections using the interface's address."; + } + } + } + + typedef mrouter-port { + description "Controls forwarding of known multicast on a port, recommend using 'auto'."; + type enumeration { + enum off { + value 0; + description "Very rarely needed, disables auto-detect, never forwards know multicast."; + } + enum auto { + value 1; + description "Auto detects any PIM- or MRDISC-capable multicast routers."; + } + enum permanent { + value 2; + description "Always forward known multicast, regardless of detected multicast routers."; + } + } + } + + typedef mdb-state { + description "Origin of mdb entry for a given port."; + type enumeration { + enum temporary { + value 0; + description "Learned from IGMP/MLD snooping."; + } + enum permanent { + value 1; + description "Static entry, from configuration."; + } + } + } + + /* + * Shared settings + */ + + grouping multicast { + container multicast { + presence multicast; + description "Control multicast filtering and querier options in bridge."; + + leaf snooping { + description "Control multicast snooping in bridge. + + Enabled, IGMP and MLD snooping is used to automatically + handle multicast filtering. By default all multicast is + forwarded, when an IGMP or MLD membership is received + only those groups are filtered. + + Disabled, all multicast is treated as broadcast. Not + even static MDB filters can be used in this mode."; + type boolean; + default true; + } + + leaf querier { + description "IGMP/MLD querier role. Leave default as-is, or read on. + + The querier role is usually the multicast router(s) on the + LAN. In networks without a multicast router a switch can + take on this responsibility. + + For a fully working multicast setup the LAN needs a querier. + If multiple queriers exist, a simple election is made -- the + device with the numerically lowest IP address is the winner, + execpt for source address 0.0.0.0 (IPv4), which is reserved + for 'proxy' queries and must never win an election. Proxy + queries are like a stand-in for the real thing and mostly + work fine in all setups. + + Some embedded and industrial devices do not send multicast + membership reports unless they receive a query, even worse, + some do not understand or misbehave with proxy queriers. + Hence the default 'auto' for this option."; + type querier-mode; + default auto; + } + + leaf query-interval { + description "Query interval when sending multicast queries."; + type uint16 { + range "1..1024"; + } + default 125; + } + } + } + + grouping multicast-filters { + container multicast-filters { + presence multicast; + description "Bridge multicast database."; + + list multicast-filter { + description "Multicast filter entry."; + key "group"; + + leaf group { + description "IP or MAC multicast group address."; + type union { + type rt-types:ip-multicast-group-address; + type mac-multicast-address; + } + } + + list ports { + description "Port members of group."; + must "state = 'permanent'" { + error-message "State must be permanent for static multicast filters"; + } + key "port"; + leaf port { + must "not(deref(.)/../if:type = 'infix-ift:bridge') or re-match(../../group, '[0-9A-Fa-f][13579BbDdFf](:[0-9A-Fa-f]{2}){5}')" { + error-message "Only MAC multicast is possible to add to host."; + } + description "Port with static or dynamic membership of group."; + type if:interface-ref; + } + + leaf state { + description "State of membership, permanent or temporary."; + type mdb-state; + default permanent; + } + } + } + } + } + + /* + * Data Nodes + */ + + augment "/if:interfaces/if:interface" { + when "derived-from-or-self(if:type,'ianaift:bridge')" { + description "Only shown for if:type bridge"; + } + + description "Augment generic interfaces with a basic 802.1Q bridge."; + + container bridge { + description "IEEE 802.1Q style bridge."; + + leaf-list ieee-group-forward { + type ieee-reserved-groups; + description + "List of IEEE link-local protocols to forward, e.g., STP, LLDP"; + } + choice type { + case ieee8021d { + uses multicast; + uses multicast-filters; + } + case ieee8021q { + container vlans { + presence vlans; + if-feature "vlan-filtering"; + description "A VLAN filtering bridge has at least one VLAN."; + + leaf proto { + type dot1q-types:dot1q-tag-type; + default dot1q-types:c-vlan; + description "Standard (1Q/c-vlan) or provider (1ad/s-vlan) bridge."; + } + + list vlan { + key "vid"; + description "List of VLANs associated with the Bridge."; + + leaf vid { + type dot1q-types:vlanid; + description "The VLAN identifier to which this entry applies."; + } + + uses multicast; + uses multicast-filters; + + leaf-list untagged { + type if:interface-ref; + description "The set of ports in the untagged set for VLAN."; + must "current() = ../../../../if:name + or (/if:interfaces/if:interface[if:name = current()]/bridge-port/bridge = ../../../../if:name + and not(../tagged[contains(., current())]))" { + error-message "Port is not a member of this bridge or already set as tagged member in the same VLAN."; + } + } + + leaf-list tagged { + description "The set of ports in the tagged set for VLAN."; + type if:interface-ref; + must "current() = ../../../../if:name + or (/if:interfaces/if:interface[if:name = current()]/bridge-port/bridge = ../../../../if:name + and not(../untagged[contains(., current())]))" { + error-message "Port is not a member of bridge or already untagged in the same VLAN."; + } + } + } + } + } + } + } + } + deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021d/multicast-filters/multicast-filter/ports/port" { + deviate add { + must "current() = ../../../../../if:name + or /if:interfaces/if:interface[if:name = current()]/infix-if:bridge-port/bridge = ../../../../../if:name" { + error-message "Port is not member of bridge"; + } + } + } + deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021d/multicast-filters/multicast-filter" { + deviate add { + must "../../multicast/snooping = 'true'" { + error-message "Multicast snooping is required when configure multicast-filters "; + } + } + } + + deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021q/vlans/vlan/multicast-filters/multicast-filter/ports/port" { + deviate add { + must "current() = ../../../../../../../if:name + or /if:interfaces/if:interface[if:name = current()]/infix-if:bridge-port/bridge = ../../../../../../../if:name" { + error-message "Port is not member of bridge"; + } + } + } + deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021q/vlans/vlan/multicast-filters/multicast-filter/ports/port" { + deviate add { + must "(../../../../untagged[contains(., current())]) or (../../../../tagged[contains(., current())])" { + error-message "Port is not member of of VLAN"; + } + } + } + deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021q/vlans/vlan/multicast-filters/multicast-filter" { + deviate add { + must "../../multicast/snooping = 'true'" { + error-message "Multicast snooping is required when configure multicast-filters "; + } + } + } + + deviation "/if:interfaces/if:interface/ip:ipv4/ip:enabled" { + deviate add { + must "not(.) or count(../../infix-if:bridge/infix-if:vlans/infix-if:vlan) = 0" { + error-message "IPv4 address is not supported on VLAN filtering bridges."; + } + } + } + + deviation "/if:interfaces/if:interface/ip:ipv6/ip:enabled" { + deviate add { + must "not(.) or count(../../infix-if:bridge/infix-if:vlans/infix-if:vlan) = 0" { + error-message "IPv6 address is not supported on VLAN filtering bridges."; + } + } + } + + augment "/if:interfaces/if:interface/infix-if:port" { + when "derived-from-or-self(if:type,'ianaift:bridge') or "+ + "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,'ianaift:ilan')" { + description "Applies when a Bridge interface exists."; + } + + description "Augments the interface model with the Bridge Port"; + + case bridge-port { + description "Extension of the IETF Interfaces model (RFC7223)."; + + container bridge-port { + description "Bridge association and port specific setttngs."; + + leaf bridge { + type if:interface-ref; + must "deref(.)/../bridge and not(. = ../../if:name)" { + error-message "Must refer to a bridge interface (and not itself)."; + } + mandatory true; + description "Bridge interface to which this interface is attached."; + } + + container flood { + description "Control flooding of unknown BUM traffic."; + + leaf broadcast { + description "Flood unknown broadcast traffic on this port."; + type boolean; + default true; + } + + leaf unicast { + description "Flood unknown unicast traffic on this port."; + type boolean; + default true; + } + + leaf multicast { + description "Flood unknown multicast traffic on this port. + + By default this option is enabled to allow MAC multicast + to coexist unregulated with filtering of IP multicast. + + Flooding of IP multicast is done as long as the groups + remain 'unknown', i.e., while there are no MDB entries + set manually or automatically by IGMP/MLD."; + type boolean; + default true; + } + } + + container multicast { + leaf fast-leave { + description "Assume this port is attached to an end-device. + + When enabled the bridge immediately cuts multicast + groups when receiving a membership leave report. + When disabled, group subscriptions linger until the + group specific queries time out."; + type boolean; + } + + leaf router { + description "Forward all known multicast on this port. + + Enable this for ports connected to a multicast router + that is not PIM or multicast router discovery (mrdisc) + capable. + + This setting is also useful for legacy equipment that + does not support IGMP/MLD. However, it is recommended + to instead set up static MDB entries for such ports."; + type mrouter-port; + default auto; + } + } + + leaf stp-state { + type stp-state; + config false; + description "The operation state of the bridge port."; + } + + leaf pvid { + if-feature "vlan-filtering"; + type dot1q-types:vlanid; + description "The primary VID assigned to this bridge port."; + } + + leaf default-priority { + if-feature "vlan-filtering"; + type dot1q-types:priority-type; + default "0"; + description "The default priority assigned to this bridge port."; + } + } + } + } +} diff --git a/src/confd/yang/infix-if-bridge@2024-08-26.yang b/src/confd/yang/infix-if-bridge@2024-08-26.yang deleted file mode 100644 index 74806d3f..00000000 --- a/src/confd/yang/infix-if-bridge@2024-08-26.yang +++ /dev/null @@ -1,547 +0,0 @@ -submodule infix-if-bridge { - yang-version 1.1; - belongs-to infix-interfaces { - prefix infix-if; - } - import ietf-yang-types { - prefix yang; - } - import iana-if-type { - prefix ianaift; - } - import ietf-routing-types { - prefix rt-types; - } - import ietf-interfaces { - prefix if; - } - import ietf-inet-types { - prefix inet; - } - import ietf-ip { - prefix ip; - } - import ieee802-dot1q-types { - prefix dot1q-types; - } - import infix-if-type { - prefix infix-ift; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Linux bridge extension for ietf-interfaces."; - - revision 2024-08-26 { - description "Improve must expressions for multicast. - - Add a must expression forcing a port in a dot1q multicast-filter - to also belong to the VLAN. Also add must expression (for both - 8021d and 8021q) to force snooping to be anabled when enable - multicast-filters"; - reference "internal"; - } - revision 2024-03-28 { - description "Rename mdb -> multicast-filters. - - Add support for L2 multicast groups (MAC multicast). They - are currently always in state 'permanent'. - - Change vlan, multicast and mulitcast-filters containers to - presence containers. This means multicast snooping is now - disabled by default when creating a bridge or adding a VLAN. - - Global bridge multicast configuration must now be disabled - when adding VLANs to a bridge. I.e., global multicast is - not inherited to VLANs in any way."; - reference "internal"; - } - revision 2024-03-06 { - description "Drop default value for bridge-port PVID. Should be possible - to drop untagged frames. - - Add must() expression for VLAN memberships. Listed ports must - belong to this bridge and cannot be untagged and tagged at the - same time. - - Also, add must() expression to ensure VLAN filtering bridges - do not have any IP address set since the bridge is always only - a tagged member of VLANs. Use a VLAN interfaces on top of the - bridge for IP addressing."; - reference "internal"; - } - revision 2024-02-19 { - description "Add STP state to bridge port."; - reference "internal"; - } - revision 2023-12-02 { - description "Extend bridge-port must expression to ensure a - bridge cannot be a bridge-port to itself."; - reference "internal"; - } - revision 2023-11-08 { - description "Dropped support for configuring bridge pvid. - Bridge ports need explicit VLAN assignment."; - reference "internal"; - } - revision 2023-08-21 { - description "Minor, lint ordering and add missing description."; - reference "internal"; - } - revision 2023-05-31 { - description "Initial revision."; - reference "internal"; - } - - /* - * Features - */ - - feature vlan-filtering { - description "Indicates if this bridge supports VLAN filtering."; - } - - /* - * Typedefs - */ - - typedef mac-multicast-address { - description "Valid multicast address."; - type string { - pattern "[0-9A-Fa-f][13579BbDdFf](:[0-9A-Fa-f]{2}){5}"; - } - } - - typedef ieee-reserved-groups { - type union { - type uint8 { - range "0..15"; - } - type enumeration { - enum stp { - value 0; - description "Spanning Tree (STP/RSPT/MSTP)."; - } - enum lacp { - value 2; - description "802.3 Slow Protocols, e.g., LACP."; - } - enum dot1x { - value 3; - description "802.1X Port-Based Network Access Control."; - } - enum lldp { - value 14; - description "802.1AB Link Layer Discovery Protocol (LLDP)."; - } - } - } - description - "This is a user-friendly enumeration of the different reserved IEEE - reserved link-local multicast groups, in 01:80:C2:00:00:0X."; - } - - typedef stp-state { - description "User-friendly enumeration of different bridge port operational states."; - type enumeration { - enum disabled { - value 0; - description "Port is in STP DISABLED state"; - } - enum listening { - value 1; - description "Port is in STP LISTENING state"; - } - enum learning { - value 2; - description "Port is in STP LEARNING state"; - } - enum forwarding { - value 3; - description "Port is in STP FORWARDING state. This is the default vlan state."; - } - enum blocking { - value 4; - description "Port is in STP BLOCKING state."; - } - } - } - - typedef querier-mode { - description "Type of IGMP/MLD querier, recommend using 'auto'."; - type enumeration { - enum off { - value 0; - description "Never initiate IGMP/MLD queries."; - } - enum proxy { - value 1; - description "Send proxy queries if no better querier IP exists."; - } - enum auto { - value 2; - description "Participate in querier elections using the interface's address."; - } - } - } - - typedef mrouter-port { - description "Controls forwarding of known multicast on a port, recommend using 'auto'."; - type enumeration { - enum off { - value 0; - description "Very rarely needed, disables auto-detect, never forwards know multicast."; - } - enum auto { - value 1; - description "Auto detects any PIM- or MRDISC-capable multicast routers."; - } - enum permanent { - value 2; - description "Always forward known multicast, regardless of detected multicast routers."; - } - } - } - - typedef mdb-state { - description "Origin of mdb entry for a given port."; - type enumeration { - enum temporary { - value 0; - description "Learned from IGMP/MLD snooping."; - } - enum permanent { - value 1; - description "Static entry, from configuration."; - } - } - } - - /* - * Shared settings - */ - - grouping multicast { - container multicast { - presence multicast; - description "Control multicast filtering and querier options in bridge."; - - leaf snooping { - description "Control multicast snooping in bridge. - - Enabled, IGMP and MLD snooping is used to automatically - handle multicast filtering. By default all multicast is - forwarded, when an IGMP or MLD membership is received - only those groups are filtered. - - Disabled, all multicast is treated as broadcast. Not - even static MDB filters can be used in this mode."; - type boolean; - default true; - } - - leaf querier { - description "IGMP/MLD querier role. Leave default as-is, or read on. - - The querier role is usually the multicast router(s) on the - LAN. In networks without a multicast router a switch can - take on this responsibility. - - For a fully working multicast setup the LAN needs a querier. - If multiple queriers exist, a simple election is made -- the - device with the numerically lowest IP address is the winner, - execpt for source address 0.0.0.0 (IPv4), which is reserved - for 'proxy' queries and must never win an election. Proxy - queries are like a stand-in for the real thing and mostly - work fine in all setups. - - Some embedded and industrial devices do not send multicast - membership reports unless they receive a query, even worse, - some do not understand or misbehave with proxy queriers. - Hence the default 'auto' for this option."; - type querier-mode; - default auto; - } - - leaf query-interval { - description "Query interval when sending multicast queries."; - type uint16 { - range "1..1024"; - } - default 125; - } - } - } - - grouping multicast-filters { - container multicast-filters { - presence multicast; - description "Bridge multicast database."; - - list multicast-filter { - description "Multicast filter entry."; - key "group"; - - leaf group { - description "IP or MAC multicast group address."; - type union { - type rt-types:ip-multicast-group-address; - type mac-multicast-address; - } - } - - list ports { - description "Port members of group."; - must "state = 'permanent'" { - error-message "State must be permanent for static multicast filters"; - } - key "port"; - leaf port { - must "not(deref(.)/../if:type = 'infix-ift:bridge') or re-match(../../group, '[0-9A-Fa-f][13579BbDdFf](:[0-9A-Fa-f]{2}){5}')" { - error-message "Only MAC multicast is possible to add to host."; - } - description "Port with static or dynamic membership of group."; - type if:interface-ref; - } - - leaf state { - description "State of membership, permanent or temporary."; - type mdb-state; - default permanent; - } - } - } - } - } - - /* - * Data Nodes - */ - - augment "/if:interfaces/if:interface" { - when "derived-from-or-self(if:type,'ianaift:bridge')" { - description "Only shown for if:type bridge"; - } - - description "Augment generic interfaces with a basic 802.1Q bridge."; - - container bridge { - description "IEEE 802.1Q style bridge."; - - leaf-list ieee-group-forward { - type ieee-reserved-groups; - description - "List of IEEE link-local protocols to forward, e.g., STP, LLDP"; - } - choice type { - case ieee8021d { - uses multicast; - uses multicast-filters; - } - case ieee8021q { - container vlans { - presence vlans; - if-feature "vlan-filtering"; - description "A VLAN filtering bridge has at least one VLAN."; - - leaf proto { - type dot1q-types:dot1q-tag-type; - default dot1q-types:c-vlan; - description "Standard (1Q/c-vlan) or provider (1ad/s-vlan) bridge."; - } - - list vlan { - key "vid"; - description "List of VLANs associated with the Bridge."; - - leaf vid { - type dot1q-types:vlanid; - description "The VLAN identifier to which this entry applies."; - } - - uses multicast; - uses multicast-filters; - - leaf-list untagged { - type if:interface-ref; - description "The set of ports in the untagged set for VLAN."; - must "current() = ../../../../if:name - or (/if:interfaces/if:interface[if:name = current()]/bridge-port/bridge = ../../../../if:name - and not(../tagged[contains(., current())]))" { - error-message "Port is not a member of this bridge or already set as tagged member in the same VLAN."; - } - } - - leaf-list tagged { - description "The set of ports in the tagged set for VLAN."; - type if:interface-ref; - must "current() = ../../../../if:name - or (/if:interfaces/if:interface[if:name = current()]/bridge-port/bridge = ../../../../if:name - and not(../untagged[contains(., current())]))" { - error-message "Port is not a member of bridge or already untagged in the same VLAN."; - } - } - } - } - } - } - } - } - deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021d/multicast-filters/multicast-filter/ports/port" { - deviate add { - must "current() = ../../../../../if:name - or /if:interfaces/if:interface[if:name = current()]/infix-if:bridge-port/bridge = ../../../../../if:name" { - error-message "Port is not member of bridge"; - } - } - } - deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021d/multicast-filters/multicast-filter" { - deviate add { - must "../../multicast/snooping = 'true'" { - error-message "Multicast snooping is required when configure multicast-filters "; - } - } - } - - deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021q/vlans/vlan/multicast-filters/multicast-filter/ports/port" { - deviate add { - must "current() = ../../../../../../../if:name - or /if:interfaces/if:interface[if:name = current()]/infix-if:bridge-port/bridge = ../../../../../../../if:name" { - error-message "Port is not member of bridge"; - } - } - } - deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021q/vlans/vlan/multicast-filters/multicast-filter/ports/port" { - deviate add { - must "(../../../../untagged[contains(., current())]) or (../../../../tagged[contains(., current())])" { - error-message "Port is not member of of VLAN"; - } - } - } - deviation "/if:interfaces/if:interface/infix-if:bridge/type/ieee8021q/vlans/vlan/multicast-filters/multicast-filter" { - deviate add { - must "../../multicast/snooping = 'true'" { - error-message "Multicast snooping is required when configure multicast-filters "; - } - } - } - - deviation "/if:interfaces/if:interface/ip:ipv4/ip:enabled" { - deviate add { - must "not(.) or count(../../infix-if:bridge/infix-if:vlans/infix-if:vlan) = 0" { - error-message "IPv4 address is not supported on VLAN filtering bridges."; - } - } - } - - deviation "/if:interfaces/if:interface/ip:ipv6/ip:enabled" { - deviate add { - must "not(.) or count(../../infix-if:bridge/infix-if:vlans/infix-if:vlan) = 0" { - error-message "IPv6 address is not supported on VLAN filtering bridges."; - } - } - } - - augment "/if:interfaces/if:interface/infix-if:port" { - when "derived-from-or-self(if:type,'ianaift:bridge') or "+ - "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,'ianaift:ilan')" { - description "Applies when a Bridge interface exists."; - } - - description "Augments the interface model with the Bridge Port"; - - case bridge-port { - description "Extension of the IETF Interfaces model (RFC7223)."; - - container bridge-port { - description "Bridge association and port specific setttngs."; - - leaf bridge { - type if:interface-ref; - must "deref(.)/../bridge and not(. = ../../if:name)" { - error-message "Must refer to a bridge interface (and not itself)."; - } - mandatory true; - description "Bridge interface to which this interface is attached."; - } - - container flood { - description "Control flooding of unknown BUM traffic."; - - leaf broadcast { - description "Flood unknown broadcast traffic on this port."; - type boolean; - default true; - } - - leaf unicast { - description "Flood unknown unicast traffic on this port."; - type boolean; - default true; - } - - leaf multicast { - description "Flood unknown multicast traffic on this port. - - By default this option is enabled to allow MAC multicast - to coexist unregulated with filtering of IP multicast. - - Flooding of IP multicast is done as long as the groups - remain 'unknown', i.e., while there are no MDB entries - set manually or automatically by IGMP/MLD."; - type boolean; - default true; - } - } - - container multicast { - leaf fast-leave { - description "Assume this port is attached to an end-device. - - When enabled the bridge immediately cuts multicast - groups when receiving a membership leave report. - When disabled, group subscriptions linger until the - group specific queries time out."; - type boolean; - } - - leaf router { - description "Forward all known multicast on this port. - - Enable this for ports connected to a multicast router - that is not PIM or multicast router discovery (mrdisc) - capable. - - This setting is also useful for legacy equipment that - does not support IGMP/MLD. However, it is recommended - to instead set up static MDB entries for such ports."; - type mrouter-port; - default auto; - } - } - - leaf stp-state { - type stp-state; - config false; - description "The operation state of the bridge port."; - } - - leaf pvid { - if-feature "vlan-filtering"; - type dot1q-types:vlanid; - description "The primary VID assigned to this bridge port."; - } - - leaf default-priority { - if-feature "vlan-filtering"; - type dot1q-types:priority-type; - default "0"; - description "The default priority assigned to this bridge port."; - } - } - } - } -} diff --git a/src/confd/yang/infix-if-bridge@2024-08-26.yang b/src/confd/yang/infix-if-bridge@2024-08-26.yang new file mode 120000 index 00000000..d49a6a33 --- /dev/null +++ b/src/confd/yang/infix-if-bridge@2024-08-26.yang @@ -0,0 +1 @@ +infix-if-bridge.yang \ No newline at end of file diff --git a/src/confd/yang/infix-if-container.yang b/src/confd/yang/infix-if-container.yang new file mode 100644 index 00000000..56d52704 --- /dev/null +++ b/src/confd/yang/infix-if-container.yang @@ -0,0 +1,117 @@ +submodule infix-if-container { + yang-version 1.1; + belongs-to infix-interfaces { + prefix infix-if; + } + + import ietf-inet-types { + prefix inet; + } + import ietf-interfaces { + prefix if; + } + import ietf-ip { + prefix ip; + } + import infix-if-type { + prefix infixift; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Container network to interface mapping for ietf-interfaces. + Ensures a container interface can never be a bridge port, or + LAG member, at the same time."; + + revision 2024-01-15 { + description "Initial revision."; + reference "internal"; + } + + /* + * Identities + */ + + identity container-network { + description "Container network type"; + } + + identity bridge { + base container-network; + description "Container bridge with IP masquerading, portmappping, and firewalling."; + } + + identity host { + base container-network; + description "Host device, e.g., one end of a VETH pair or other host interface."; + } + + /* + * Data Nodes + */ + + augment "/if:interfaces/if:interface/infix-if:port" { + description "Augments the interface model with container networks."; + if-feature containers; + + case container-network { + container container-network { + presence "Container network mapping."; + + leaf type { + description "Masquerading container bridge or a host interface"; + type identityref { + base container-network; + } + } + + list subnet { + description "Static IP ranges to hand out addresses to containers from. + + A container bridge forwards DNS, NTP, and SSH by default to + the host interfaces."; + when "../type = 'infix-if:bridge'"; + key subnet; + + leaf subnet { + type inet:ip-prefix; + description "Subnet to assign addresses from, round-robin assignment. + + The default is from a standard Docker setup."; + default "172.17.0.0/16"; + } + + leaf gateway { + type inet:ip-address; + description "Optional gateway address for the subnet, defaults to .1. + + This will be used as the address of the container bridge."; + } + } + + list route { + description "IPv4 or IPv6 routes to be added to container. + + For bridge type interfaces the gateway can be omitted, the + IP address of the container bridge will then be used as the + next-hop address."; + key subnet; + + leaf subnet { + type inet:ip-prefix; + description "Destination (subnet) IP address."; + } + + leaf gateway { + type inet:ip-address; + description "Optional gateway (next-hop) IP address for the route."; + } + } + + must "count(route) = 0 or count(../ip:ipv4/ip:address) or count(../ip:ipv6/ip:address)" { + error-message "Static routes only allowed if a static IP address is set."; + } + } + } + } +} diff --git a/src/confd/yang/infix-if-container@2024-01-15.yang b/src/confd/yang/infix-if-container@2024-01-15.yang deleted file mode 100644 index 56d52704..00000000 --- a/src/confd/yang/infix-if-container@2024-01-15.yang +++ /dev/null @@ -1,117 +0,0 @@ -submodule infix-if-container { - yang-version 1.1; - belongs-to infix-interfaces { - prefix infix-if; - } - - import ietf-inet-types { - prefix inet; - } - import ietf-interfaces { - prefix if; - } - import ietf-ip { - prefix ip; - } - import infix-if-type { - prefix infixift; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Container network to interface mapping for ietf-interfaces. - Ensures a container interface can never be a bridge port, or - LAG member, at the same time."; - - revision 2024-01-15 { - description "Initial revision."; - reference "internal"; - } - - /* - * Identities - */ - - identity container-network { - description "Container network type"; - } - - identity bridge { - base container-network; - description "Container bridge with IP masquerading, portmappping, and firewalling."; - } - - identity host { - base container-network; - description "Host device, e.g., one end of a VETH pair or other host interface."; - } - - /* - * Data Nodes - */ - - augment "/if:interfaces/if:interface/infix-if:port" { - description "Augments the interface model with container networks."; - if-feature containers; - - case container-network { - container container-network { - presence "Container network mapping."; - - leaf type { - description "Masquerading container bridge or a host interface"; - type identityref { - base container-network; - } - } - - list subnet { - description "Static IP ranges to hand out addresses to containers from. - - A container bridge forwards DNS, NTP, and SSH by default to - the host interfaces."; - when "../type = 'infix-if:bridge'"; - key subnet; - - leaf subnet { - type inet:ip-prefix; - description "Subnet to assign addresses from, round-robin assignment. - - The default is from a standard Docker setup."; - default "172.17.0.0/16"; - } - - leaf gateway { - type inet:ip-address; - description "Optional gateway address for the subnet, defaults to .1. - - This will be used as the address of the container bridge."; - } - } - - list route { - description "IPv4 or IPv6 routes to be added to container. - - For bridge type interfaces the gateway can be omitted, the - IP address of the container bridge will then be used as the - next-hop address."; - key subnet; - - leaf subnet { - type inet:ip-prefix; - description "Destination (subnet) IP address."; - } - - leaf gateway { - type inet:ip-address; - description "Optional gateway (next-hop) IP address for the route."; - } - } - - must "count(route) = 0 or count(../ip:ipv4/ip:address) or count(../ip:ipv6/ip:address)" { - error-message "Static routes only allowed if a static IP address is set."; - } - } - } - } -} diff --git a/src/confd/yang/infix-if-container@2024-01-15.yang b/src/confd/yang/infix-if-container@2024-01-15.yang new file mode 120000 index 00000000..c52680d5 --- /dev/null +++ b/src/confd/yang/infix-if-container@2024-01-15.yang @@ -0,0 +1 @@ +infix-if-container.yang \ No newline at end of file diff --git a/src/confd/yang/infix-if-type.yang b/src/confd/yang/infix-if-type.yang new file mode 100644 index 00000000..5a9ed8a8 --- /dev/null +++ b/src/confd/yang/infix-if-type.yang @@ -0,0 +1,82 @@ +module infix-if-type { + yang-version 1.1; + namespace "urn:infix:types:ns:yang:1.0"; + prefix infixift; + + import iana-if-type { + prefix ianaift; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Infix extensions to IANA interfaces types"; + + revision 2023-08-21 { + description "Add infix-inteface-type to reduce number of supported + interfaces. The derived identities are based on both + this new identity and their parent iana-if-type."; + reference "internal"; + } + + revision 2024-01-29 { + description "Add new interface type etherlike"; + reference "internal"; + } + + revision 2023-06-09 { + description "Initial revision."; + reference "internal"; + } + + /* + * Identities + */ + + identity infix-interface-type { + base ianaift:iana-interface-type; + description "Subset of supported iana-if-types."; + } + + identity bridge { + base infix-interface-type; + base ianaift:bridge; + description "IEEE bridge interface."; + } + identity ethernet { + base infix-interface-type; + base ianaift:ethernetCsmacd; + description "Any Ethernet interfaces, regardless of speed, RFC 3635."; + reference "RFC 3635"; + } + identity etherlike { + base infix-interface-type; + base ianaift:ilan; + description "Interface with properties resembling Ethernet"; + reference "RFC 3635"; + } + identity lag { + base infix-interface-type; + base ianaift:ieee8023adLag; + description "IEEE link aggregate interface."; + } + identity loopback { + base infix-interface-type; + base ianaift:softwareLoopback; + description "Linux loopback interface."; + } + identity other { + base infix-interface-type; + base ianaift:other; + description "Other interface, i.e., unknown."; + } + identity veth { + base infix-interface-type; + base ianaift:ilan; + description "Linux virtual Ethernet pair."; + } + identity vlan { + base infix-interface-type; + base ianaift:l2vlan; + description "Layer 2 Virtual LAN using 802.1Q."; + } +} diff --git a/src/confd/yang/infix-if-type@2024-01-29.yang b/src/confd/yang/infix-if-type@2024-01-29.yang deleted file mode 100644 index 5a9ed8a8..00000000 --- a/src/confd/yang/infix-if-type@2024-01-29.yang +++ /dev/null @@ -1,82 +0,0 @@ -module infix-if-type { - yang-version 1.1; - namespace "urn:infix:types:ns:yang:1.0"; - prefix infixift; - - import iana-if-type { - prefix ianaift; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Infix extensions to IANA interfaces types"; - - revision 2023-08-21 { - description "Add infix-inteface-type to reduce number of supported - interfaces. The derived identities are based on both - this new identity and their parent iana-if-type."; - reference "internal"; - } - - revision 2024-01-29 { - description "Add new interface type etherlike"; - reference "internal"; - } - - revision 2023-06-09 { - description "Initial revision."; - reference "internal"; - } - - /* - * Identities - */ - - identity infix-interface-type { - base ianaift:iana-interface-type; - description "Subset of supported iana-if-types."; - } - - identity bridge { - base infix-interface-type; - base ianaift:bridge; - description "IEEE bridge interface."; - } - identity ethernet { - base infix-interface-type; - base ianaift:ethernetCsmacd; - description "Any Ethernet interfaces, regardless of speed, RFC 3635."; - reference "RFC 3635"; - } - identity etherlike { - base infix-interface-type; - base ianaift:ilan; - description "Interface with properties resembling Ethernet"; - reference "RFC 3635"; - } - identity lag { - base infix-interface-type; - base ianaift:ieee8023adLag; - description "IEEE link aggregate interface."; - } - identity loopback { - base infix-interface-type; - base ianaift:softwareLoopback; - description "Linux loopback interface."; - } - identity other { - base infix-interface-type; - base ianaift:other; - description "Other interface, i.e., unknown."; - } - identity veth { - base infix-interface-type; - base ianaift:ilan; - description "Linux virtual Ethernet pair."; - } - identity vlan { - base infix-interface-type; - base ianaift:l2vlan; - description "Layer 2 Virtual LAN using 802.1Q."; - } -} diff --git a/src/confd/yang/infix-if-type@2024-01-29.yang b/src/confd/yang/infix-if-type@2024-01-29.yang new file mode 120000 index 00000000..b0bd9018 --- /dev/null +++ b/src/confd/yang/infix-if-type@2024-01-29.yang @@ -0,0 +1 @@ +infix-if-type.yang \ No newline at end of file diff --git a/src/confd/yang/infix-if-veth.yang b/src/confd/yang/infix-if-veth.yang new file mode 100644 index 00000000..bd29d434 --- /dev/null +++ b/src/confd/yang/infix-if-veth.yang @@ -0,0 +1,48 @@ +submodule infix-if-veth { + yang-version 1.1; + belongs-to infix-interfaces { + prefix infix-if; + } + + import ietf-interfaces { + prefix if; + } + import infix-if-type { + prefix infixift; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Linux virtual Ethernet pair extension for ietf-interfaces."; + + revision 2023-06-05 { + description "Initial revision."; + reference "internal"; + } + + /* + * Data Nodes + */ + + augment "/if:interfaces/if:interface" { + when "derived-from-or-self(if:type, 'infixift:veth')" { + description "Only shown for if:type infixift:veth (ianaift:ilan)"; + } + + description "Augments the interface model with virtual Ethernet pairs."; + + container veth { + description "Virtual Ethernet (veth) pair."; + + leaf peer { + type if:interface-ref; + must '(deref(.)/../if:type = "infixift:veth") and + deref(deref(.)/../veth/peer) = ../../if:name' { + error-message "Must refer to the peer interface (other end of othe pair)."; + } + mandatory true; + description "Peer veth interface to which this interface is connected."; + } + } + } +} diff --git a/src/confd/yang/infix-if-veth@2023-06-05.yang b/src/confd/yang/infix-if-veth@2023-06-05.yang deleted file mode 100644 index bd29d434..00000000 --- a/src/confd/yang/infix-if-veth@2023-06-05.yang +++ /dev/null @@ -1,48 +0,0 @@ -submodule infix-if-veth { - yang-version 1.1; - belongs-to infix-interfaces { - prefix infix-if; - } - - import ietf-interfaces { - prefix if; - } - import infix-if-type { - prefix infixift; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Linux virtual Ethernet pair extension for ietf-interfaces."; - - revision 2023-06-05 { - description "Initial revision."; - reference "internal"; - } - - /* - * Data Nodes - */ - - augment "/if:interfaces/if:interface" { - when "derived-from-or-self(if:type, 'infixift:veth')" { - description "Only shown for if:type infixift:veth (ianaift:ilan)"; - } - - description "Augments the interface model with virtual Ethernet pairs."; - - container veth { - description "Virtual Ethernet (veth) pair."; - - leaf peer { - type if:interface-ref; - must '(deref(.)/../if:type = "infixift:veth") and - deref(deref(.)/../veth/peer) = ../../if:name' { - error-message "Must refer to the peer interface (other end of othe pair)."; - } - mandatory true; - description "Peer veth interface to which this interface is connected."; - } - } - } -} diff --git a/src/confd/yang/infix-if-veth@2023-06-05.yang b/src/confd/yang/infix-if-veth@2023-06-05.yang new file mode 120000 index 00000000..53d1de5f --- /dev/null +++ b/src/confd/yang/infix-if-veth@2023-06-05.yang @@ -0,0 +1 @@ +infix-if-veth.yang \ No newline at end of file diff --git a/src/confd/yang/infix-if-vlan.yang b/src/confd/yang/infix-if-vlan.yang new file mode 100644 index 00000000..c4948f57 --- /dev/null +++ b/src/confd/yang/infix-if-vlan.yang @@ -0,0 +1,101 @@ +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 2024-05-30 { + description "Added basic QoS policy + + Support for mapping the Priority Code Point (PCP) to + internal priority on ingress, and the reverse on + egress."; + } + + 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"; + } + container ingress-qos { + leaf priority { + description "Internal priority assignment + + The policy by which ingressing packets' + internal priority is determined. Supported + modes are to use a fixed value for all packets, + or to derive it from the packet's Priority Code + Point (PCP) field."; + + type union { + type uint8 { + range "0..7"; + } + type enumeration { + enum from-pcp { + description "Map PCP 1:1 to internal priority"; + } + } + } + default 0; + } + } + container egress-qos { + leaf pcp { + description "Priority Code Point (PCP) assignment + + The policy by which egressing packets' PCP + field is determined. Supported modes are to use + a fixed value for all packets, or to derive it + from the packet's internal priority."; + type union { + type uint8 { + range "0..7"; + } + type enumeration { + enum from-priority { + description "Map internal priority 1:1 to PCP"; + } + } + } + default 0; + } + } + } + } +} diff --git a/src/confd/yang/infix-if-vlan@2024-05-30.yang b/src/confd/yang/infix-if-vlan@2024-05-30.yang deleted file mode 100644 index c4948f57..00000000 --- a/src/confd/yang/infix-if-vlan@2024-05-30.yang +++ /dev/null @@ -1,101 +0,0 @@ -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 2024-05-30 { - description "Added basic QoS policy - - Support for mapping the Priority Code Point (PCP) to - internal priority on ingress, and the reverse on - egress."; - } - - 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"; - } - container ingress-qos { - leaf priority { - description "Internal priority assignment - - The policy by which ingressing packets' - internal priority is determined. Supported - modes are to use a fixed value for all packets, - or to derive it from the packet's Priority Code - Point (PCP) field."; - - type union { - type uint8 { - range "0..7"; - } - type enumeration { - enum from-pcp { - description "Map PCP 1:1 to internal priority"; - } - } - } - default 0; - } - } - container egress-qos { - leaf pcp { - description "Priority Code Point (PCP) assignment - - The policy by which egressing packets' PCP - field is determined. Supported modes are to use - a fixed value for all packets, or to derive it - from the packet's internal priority."; - type union { - type uint8 { - range "0..7"; - } - type enumeration { - enum from-priority { - description "Map internal priority 1:1 to PCP"; - } - } - } - default 0; - } - } - } - } -} diff --git a/src/confd/yang/infix-if-vlan@2024-05-30.yang b/src/confd/yang/infix-if-vlan@2024-05-30.yang new file mode 120000 index 00000000..466d340a --- /dev/null +++ b/src/confd/yang/infix-if-vlan@2024-05-30.yang @@ -0,0 +1 @@ +infix-if-vlan.yang \ No newline at end of file diff --git a/src/confd/yang/infix-interfaces.yang b/src/confd/yang/infix-interfaces.yang new file mode 100644 index 00000000..6f807882 --- /dev/null +++ b/src/confd/yang/infix-interfaces.yang @@ -0,0 +1,79 @@ +module infix-interfaces { + yang-version 1.1; + namespace "urn:infix:interfaces:ns:yang:1.0"; + prefix infix-if; + + import infix-if-type { + prefix infixift; + } + import ietf-interfaces { + prefix if; + } + + include infix-if-base; + include infix-if-bridge; + include infix-if-container; + include infix-if-veth; + include infix-if-vlan; + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Linux bridge and lag extensions for ietf-interfaces."; + + revision 2024-09-23 { + description "Drop interfaces-state deviation, already marked deprecated."; + reference "internal"; + } + + revision 2024-01-15 { + description "Add support for container ports (CNI networks)."; + reference "internal"; + } + + revision 2023-09-19 { + description "Add deviation to allow setting phys-address on links."; + reference "internal"; + } + + revision 2023-08-21 { + description "Move port augment to submodule for infix-if-bridge and + infix-if-lag (later) which reference it. + + Add deviation to if:type to limit the iana-if-types to + only those supported, also reduce list for CLI . + + Lint: move include and import to match canonical order."; + reference "internal"; + } + + revision 2023-06-05 { + description "Initial revision."; + reference "internal"; + } + + /* + * Features + */ + + feature containers { + description "Containers is an optional build-time feature in Infix."; + } + + /* + * Data Nodes + */ + + deviation "/if:interfaces/if:interface/if:type" { + deviate replace { + type identityref { + base infixift:infix-interface-type; + } + } + } + + deviation "/if:interfaces/if:interface/if:phys-address" { + deviate replace { + config true; + } + } +} diff --git a/src/confd/yang/infix-interfaces@2024-09-23.yang b/src/confd/yang/infix-interfaces@2024-09-23.yang deleted file mode 100644 index 6f807882..00000000 --- a/src/confd/yang/infix-interfaces@2024-09-23.yang +++ /dev/null @@ -1,79 +0,0 @@ -module infix-interfaces { - yang-version 1.1; - namespace "urn:infix:interfaces:ns:yang:1.0"; - prefix infix-if; - - import infix-if-type { - prefix infixift; - } - import ietf-interfaces { - prefix if; - } - - include infix-if-base; - include infix-if-bridge; - include infix-if-container; - include infix-if-veth; - include infix-if-vlan; - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Linux bridge and lag extensions for ietf-interfaces."; - - revision 2024-09-23 { - description "Drop interfaces-state deviation, already marked deprecated."; - reference "internal"; - } - - revision 2024-01-15 { - description "Add support for container ports (CNI networks)."; - reference "internal"; - } - - revision 2023-09-19 { - description "Add deviation to allow setting phys-address on links."; - reference "internal"; - } - - revision 2023-08-21 { - description "Move port augment to submodule for infix-if-bridge and - infix-if-lag (later) which reference it. - - Add deviation to if:type to limit the iana-if-types to - only those supported, also reduce list for CLI . - - Lint: move include and import to match canonical order."; - reference "internal"; - } - - revision 2023-06-05 { - description "Initial revision."; - reference "internal"; - } - - /* - * Features - */ - - feature containers { - description "Containers is an optional build-time feature in Infix."; - } - - /* - * Data Nodes - */ - - deviation "/if:interfaces/if:interface/if:type" { - deviate replace { - type identityref { - base infixift:infix-interface-type; - } - } - } - - deviation "/if:interfaces/if:interface/if:phys-address" { - deviate replace { - config true; - } - } -} diff --git a/src/confd/yang/infix-interfaces@2024-09-23.yang b/src/confd/yang/infix-interfaces@2024-09-23.yang new file mode 120000 index 00000000..9f14c9e1 --- /dev/null +++ b/src/confd/yang/infix-interfaces@2024-09-23.yang @@ -0,0 +1 @@ +infix-interfaces.yang \ No newline at end of file diff --git a/src/confd/yang/infix-ip.yang b/src/confd/yang/infix-ip.yang new file mode 100644 index 00000000..88a1c93f --- /dev/null +++ b/src/confd/yang/infix-ip.yang @@ -0,0 +1,79 @@ +module infix-ip { + yang-version 1.1; + namespace "urn:infix:params:xml:ns:yang:infix-ip"; + prefix infix-ip; + + import ietf-interfaces { + prefix if; + } + import ietf-ip { + prefix ip; + } + import ietf-inet-types { + prefix inet; + } + import ietf-yang-types { + prefix yang; + } + + description "This module augments ietf-ip with Infix extensions and deviations."; + + revision 2024-09-16 { + description "Add support for IPv4LL request-address."; + reference "Internal."; + } + revision 2023-09-14 { + description "Added deviations for unsupported parts of ietf-ip."; + reference "Internal."; + } + revision 2023-04-24 { + description "Initial revision."; + reference "RFC 7277: A YANG Data Model for IP Management"; + } + + /* + * Data nodes + */ + augment "/if:interfaces/if:interface/ip:ipv4" { + container autoconf { + description "Parameters to control the autoconfiguration of IPv4 address."; + reference "RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses"; + + leaf enabled { + description "Use a ZeroConf/IPv4LL agent to retrieve an 169.254/16 address."; + type boolean; + } + + leaf request-address { + description "Try to acquire the specified IP address, if available. + + With this setting the IPv4LL client will start by + requesting this address. However, if it is not + available it falls back to the default algorithm."; + type inet:ipv4-address; + must "substring(., 1, 7) = '169.254'" { + error-message "Must be from the IPv4LL range 169.254.0.0/16."; + } + must "not(substring(., string-length(.) - 1, 2) = '.0' or substring(., string-length(.) - 3, 4) = '.255')" { + error-message "Addresses ending in .0 or .255 are reserved."; + } + } + } + } + + deviation "/if:interfaces/if:interface/ip:ipv4/ip:address/ip:subnet/ip:netmask" { + deviate not-supported; + } + + deviation "/if:interfaces/if:interface/ip:ipv4/ip:neighbor" { + deviate not-supported; + } + + deviation "/if:interfaces/if:interface/ip:ipv6/ip:address/ip:status" { + deviate not-supported; + } + + deviation "/if:interfaces/if:interface/ip:ipv6/ip:neighbor" { + deviate not-supported; + } +} diff --git a/src/confd/yang/infix-ip@2024-09-16.yang b/src/confd/yang/infix-ip@2024-09-16.yang deleted file mode 100644 index 88a1c93f..00000000 --- a/src/confd/yang/infix-ip@2024-09-16.yang +++ /dev/null @@ -1,79 +0,0 @@ -module infix-ip { - yang-version 1.1; - namespace "urn:infix:params:xml:ns:yang:infix-ip"; - prefix infix-ip; - - import ietf-interfaces { - prefix if; - } - import ietf-ip { - prefix ip; - } - import ietf-inet-types { - prefix inet; - } - import ietf-yang-types { - prefix yang; - } - - description "This module augments ietf-ip with Infix extensions and deviations."; - - revision 2024-09-16 { - description "Add support for IPv4LL request-address."; - reference "Internal."; - } - revision 2023-09-14 { - description "Added deviations for unsupported parts of ietf-ip."; - reference "Internal."; - } - revision 2023-04-24 { - description "Initial revision."; - reference "RFC 7277: A YANG Data Model for IP Management"; - } - - /* - * Data nodes - */ - augment "/if:interfaces/if:interface/ip:ipv4" { - container autoconf { - description "Parameters to control the autoconfiguration of IPv4 address."; - reference "RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses"; - - leaf enabled { - description "Use a ZeroConf/IPv4LL agent to retrieve an 169.254/16 address."; - type boolean; - } - - leaf request-address { - description "Try to acquire the specified IP address, if available. - - With this setting the IPv4LL client will start by - requesting this address. However, if it is not - available it falls back to the default algorithm."; - type inet:ipv4-address; - must "substring(., 1, 7) = '169.254'" { - error-message "Must be from the IPv4LL range 169.254.0.0/16."; - } - must "not(substring(., string-length(.) - 1, 2) = '.0' or substring(., string-length(.) - 3, 4) = '.255')" { - error-message "Addresses ending in .0 or .255 are reserved."; - } - } - } - } - - deviation "/if:interfaces/if:interface/ip:ipv4/ip:address/ip:subnet/ip:netmask" { - deviate not-supported; - } - - deviation "/if:interfaces/if:interface/ip:ipv4/ip:neighbor" { - deviate not-supported; - } - - deviation "/if:interfaces/if:interface/ip:ipv6/ip:address/ip:status" { - deviate not-supported; - } - - deviation "/if:interfaces/if:interface/ip:ipv6/ip:neighbor" { - deviate not-supported; - } -} diff --git a/src/confd/yang/infix-ip@2024-09-16.yang b/src/confd/yang/infix-ip@2024-09-16.yang new file mode 120000 index 00000000..c5481c77 --- /dev/null +++ b/src/confd/yang/infix-ip@2024-09-16.yang @@ -0,0 +1 @@ +infix-ip.yang \ No newline at end of file diff --git a/src/confd/yang/infix-lldp.yang b/src/confd/yang/infix-lldp.yang new file mode 100644 index 00000000..ba560b64 --- /dev/null +++ b/src/confd/yang/infix-lldp.yang @@ -0,0 +1,55 @@ +module infix-lldp { + yang-version 1.1; + namespace "urn:infix:lldp:ns:yang:1.0"; + prefix infix-lldp; + + import ieee802-dot1ab-lldp { + prefix lldp; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Infix augments and deviations to ieee-dot1ab-lldp."; + + revision 2023-08-23 { + description "Initial revision."; + reference "internal"; + } + + /* + * Data nodes + */ + + augment "/lldp:lldp" { + description "Augment of ieee802-dot1ab-lldp with a global enabled flag."; + leaf enabled { + type boolean; + description "Globally enable or disable IEEE 802.1ab LLDP agent."; + } + } + + deviation "/lldp:lldp/lldp:message-fast-tx" { + deviate not-supported; + } + deviation "/lldp:lldp/lldp:message-tx-hold-multiplier" { + deviate not-supported; + } + deviation "/lldp:lldp/lldp:message-tx-interval" { + deviate not-supported; + } + deviation "/lldp:lldp/lldp:notification-interval" { + deviate not-supported; + } + deviation "/lldp:lldp/lldp:port" { + deviate not-supported; + } + deviation "/lldp:lldp/lldp:reinit-delay" { + deviate not-supported; + } + deviation "/lldp:lldp/lldp:tx-credit-max" { + deviate not-supported; + } + deviation "/lldp:lldp/lldp:tx-fast-init" { + deviate not-supported; + } +} diff --git a/src/confd/yang/infix-lldp@2023-08-23.yang b/src/confd/yang/infix-lldp@2023-08-23.yang deleted file mode 100644 index ba560b64..00000000 --- a/src/confd/yang/infix-lldp@2023-08-23.yang +++ /dev/null @@ -1,55 +0,0 @@ -module infix-lldp { - yang-version 1.1; - namespace "urn:infix:lldp:ns:yang:1.0"; - prefix infix-lldp; - - import ieee802-dot1ab-lldp { - prefix lldp; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Infix augments and deviations to ieee-dot1ab-lldp."; - - revision 2023-08-23 { - description "Initial revision."; - reference "internal"; - } - - /* - * Data nodes - */ - - augment "/lldp:lldp" { - description "Augment of ieee802-dot1ab-lldp with a global enabled flag."; - leaf enabled { - type boolean; - description "Globally enable or disable IEEE 802.1ab LLDP agent."; - } - } - - deviation "/lldp:lldp/lldp:message-fast-tx" { - deviate not-supported; - } - deviation "/lldp:lldp/lldp:message-tx-hold-multiplier" { - deviate not-supported; - } - deviation "/lldp:lldp/lldp:message-tx-interval" { - deviate not-supported; - } - deviation "/lldp:lldp/lldp:notification-interval" { - deviate not-supported; - } - deviation "/lldp:lldp/lldp:port" { - deviate not-supported; - } - deviation "/lldp:lldp/lldp:reinit-delay" { - deviate not-supported; - } - deviation "/lldp:lldp/lldp:tx-credit-max" { - deviate not-supported; - } - deviation "/lldp:lldp/lldp:tx-fast-init" { - deviate not-supported; - } -} diff --git a/src/confd/yang/infix-lldp@2023-08-23.yang b/src/confd/yang/infix-lldp@2023-08-23.yang new file mode 120000 index 00000000..077ef1b3 --- /dev/null +++ b/src/confd/yang/infix-lldp@2023-08-23.yang @@ -0,0 +1 @@ +infix-lldp.yang \ No newline at end of file diff --git a/src/confd/yang/infix-meta.yang b/src/confd/yang/infix-meta.yang new file mode 100644 index 00000000..e7c2fc12 --- /dev/null +++ b/src/confd/yang/infix-meta.yang @@ -0,0 +1,22 @@ +module infix-meta { + yang-version 1.1; + namespace "urn:infix:meta:ns:yang:1.0"; + prefix infix-meta; + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Infix metadata."; + + revision 2024-06-19 { + description "Initial revision."; + reference "internal"; + } + + container meta { + leaf version { + status obsolete; // Ensure frontends don't show this, used for migration. + description "Configuration file format version, automatically generated."; + type string; + } + } +} diff --git a/src/confd/yang/infix-meta@2024-06-19.yang b/src/confd/yang/infix-meta@2024-06-19.yang deleted file mode 100644 index e7c2fc12..00000000 --- a/src/confd/yang/infix-meta@2024-06-19.yang +++ /dev/null @@ -1,22 +0,0 @@ -module infix-meta { - yang-version 1.1; - namespace "urn:infix:meta:ns:yang:1.0"; - prefix infix-meta; - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Infix metadata."; - - revision 2024-06-19 { - description "Initial revision."; - reference "internal"; - } - - container meta { - leaf version { - status obsolete; // Ensure frontends don't show this, used for migration. - description "Configuration file format version, automatically generated."; - type string; - } - } -} diff --git a/src/confd/yang/infix-meta@2024-06-19.yang b/src/confd/yang/infix-meta@2024-06-19.yang new file mode 120000 index 00000000..317e4234 --- /dev/null +++ b/src/confd/yang/infix-meta@2024-06-19.yang @@ -0,0 +1 @@ +infix-meta.yang \ No newline at end of file diff --git a/src/confd/yang/infix-routing@2024-09-23.yang b/src/confd/yang/infix-routing.yang similarity index 98% rename from src/confd/yang/infix-routing@2024-09-23.yang rename to src/confd/yang/infix-routing.yang index 1f1f633b..59d7bcb6 100644 --- a/src/confd/yang/infix-routing@2024-09-23.yang +++ b/src/confd/yang/infix-routing.yang @@ -26,6 +26,10 @@ module infix-routing { contact "kernelkit@googlegroups.com"; description "Deviations and augments for ietf-routing and ietf-ospf."; + revision 2024-10-01 { + description "Remove possibility to have loopack in multiple areas."; + reference "internal"; + } revision 2024-09-23 { description "Augment static routes with optional route-preference (distance)."; reference "internal"; @@ -272,7 +276,7 @@ module infix-routing { } deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/ospf:ospf/ospf:areas/ospf:area/ospf:interfaces/ospf:interface" { deviate add { - must "current()/name = 'lo' or count(../../../../ospf:areas/ospf:area/ospf:interfaces/ospf:interface[ospf:name=current()/name]) <= 1" { + must "count(../../../../ospf:areas/ospf:area/ospf:interfaces/ospf:interface[ospf:name=current()/name]) <= 1" { error-message "Only one area per interface is allowed."; } } diff --git a/src/confd/yang/infix-routing@2024-10-01.yang b/src/confd/yang/infix-routing@2024-10-01.yang new file mode 120000 index 00000000..d06fa2eb --- /dev/null +++ b/src/confd/yang/infix-routing@2024-10-01.yang @@ -0,0 +1 @@ +infix-routing.yang \ No newline at end of file diff --git a/src/confd/yang/infix-services.yang b/src/confd/yang/infix-services.yang new file mode 100644 index 00000000..92dfbf77 --- /dev/null +++ b/src/confd/yang/infix-services.yang @@ -0,0 +1,82 @@ +module infix-services { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:infix-services"; + prefix infix-svc; + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Infix services, generic."; + + revision 2024-05-30 { + description "Add support for RESTCONF enable/disable as a web service."; + reference "internal"; + } + revision 2024-04-08 { + description "Initial support for web services."; + reference "internal"; + } + revision 2023-10-16 { + description "Drop SSDP support, mDNS-SD is now available in Windows 10."; + reference "internal"; + } + revision 2023-08-22 { + description "Initial revision, add SSDP and mDNS-SD enable/disable only."; + reference "internal"; + } + + /* + * Data nodes + */ + + container mdns { + description "Advertise system and services over mDNS-SD, IPv4 and IPv6."; + + leaf enabled { + description "Globally enable or disable mDNS/SD on all interfaces."; + type boolean; + } + } + + container web { + description "Web services"; + + leaf enabled { + description "Enable or disable on all web services. + + Enabling this setting activates a web proxy server reponsible + for routing requests to other web applications, as well as it + redirecting all insecure HTTP requests to HTTPS. + + Disabling this setting disables the web proxy server and all + other services/applications that run behind it."; + type boolean; + } + + container console { + description "Web console interface."; + + leaf enabled { + description "Enable or disable web console interface on port 7681."; + type boolean; + } + } + + container netbrowse { + description "mDNS Network Browser."; + + leaf enabled { + description "Enable or disable mDNS Network Browser at https://network.local."; + type boolean; + } + } + + container restconf { + description "IETF RESTCONF Server."; + + leaf enabled { + description "Enable or disable https://device.local/resconf API endpoint."; + type boolean; + } + } + } +} diff --git a/src/confd/yang/infix-services@2024-05-30.yang b/src/confd/yang/infix-services@2024-05-30.yang deleted file mode 100644 index 92dfbf77..00000000 --- a/src/confd/yang/infix-services@2024-05-30.yang +++ /dev/null @@ -1,82 +0,0 @@ -module infix-services { - yang-version 1.1; - namespace "urn:ietf:params:xml:ns:yang:infix-services"; - prefix infix-svc; - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Infix services, generic."; - - revision 2024-05-30 { - description "Add support for RESTCONF enable/disable as a web service."; - reference "internal"; - } - revision 2024-04-08 { - description "Initial support for web services."; - reference "internal"; - } - revision 2023-10-16 { - description "Drop SSDP support, mDNS-SD is now available in Windows 10."; - reference "internal"; - } - revision 2023-08-22 { - description "Initial revision, add SSDP and mDNS-SD enable/disable only."; - reference "internal"; - } - - /* - * Data nodes - */ - - container mdns { - description "Advertise system and services over mDNS-SD, IPv4 and IPv6."; - - leaf enabled { - description "Globally enable or disable mDNS/SD on all interfaces."; - type boolean; - } - } - - container web { - description "Web services"; - - leaf enabled { - description "Enable or disable on all web services. - - Enabling this setting activates a web proxy server reponsible - for routing requests to other web applications, as well as it - redirecting all insecure HTTP requests to HTTPS. - - Disabling this setting disables the web proxy server and all - other services/applications that run behind it."; - type boolean; - } - - container console { - description "Web console interface."; - - leaf enabled { - description "Enable or disable web console interface on port 7681."; - type boolean; - } - } - - container netbrowse { - description "mDNS Network Browser."; - - leaf enabled { - description "Enable or disable mDNS Network Browser at https://network.local."; - type boolean; - } - } - - container restconf { - description "IETF RESTCONF Server."; - - leaf enabled { - description "Enable or disable https://device.local/resconf API endpoint."; - type boolean; - } - } - } -} diff --git a/src/confd/yang/infix-services@2024-05-30.yang b/src/confd/yang/infix-services@2024-05-30.yang new file mode 120000 index 00000000..d57781e5 --- /dev/null +++ b/src/confd/yang/infix-services@2024-05-30.yang @@ -0,0 +1 @@ +infix-services.yang \ No newline at end of file diff --git a/src/confd/yang/infix-syslog.yang b/src/confd/yang/infix-syslog.yang new file mode 100644 index 00000000..1d895d03 --- /dev/null +++ b/src/confd/yang/infix-syslog.yang @@ -0,0 +1,200 @@ +module infix-syslog { + yang-version 1.1; + namespace "urn:infix:syslog:ns:yang:1.0"; + prefix infix-syslog; + + + import ietf-inet-types { + prefix inet; + reference "RFC 6991: Common YANG Data Types"; + } + import ietf-syslog { + prefix syslog; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Infix augments and deviations to ietf-syslog, draft 32."; + + revision 2024-07-19 { + description "Initial revision, based on IETF syslog YANG draft 32. + The following changes have been made in this model: + + - Add support for global file rotation settings + - Add support for acting as a remote server + - Add support for local facility names + - Add support for log format selection per action + - Disable TLS transport, not yet supported + - Disable facility override, not yet supported + - Removed 1 log file default + - Replaced default 'megabytes' unit with 'kilobytes'"; + reference "internal"; + } + + /* + * Identities + */ + + identity rauc { + base syslog:syslog-facility; + description "Local facility for the RAUC firmware update subsystem, local0."; + } + + identity container { + base syslog:syslog-facility; + description "Local facility reserved for Docker containers, local1."; + } + + identity web { + base syslog:syslog-facility; + description "Local facility reserved for web server, local7."; + } + + // Log format + + identity format-type { + description "This identity is used as a base for all log formats."; + reference "RFC 5424: The Syslog Protocol"; + } + + identity bsd { + base format-type; + description "Original BSD UNIX log format, default when sending remote."; + } + + identity rfc3164 { + base format-type; + description "Default log format, except when sending remote."; + } + + identity rfc5424 { + base format-type; + description "Latest format, better time granularity, structured data, etc."; + } + + /* + * Shared settings + */ + + grouping log-format { + leaf log-format { + description "Log format, one of: BSD*, RFC3164, or RFC5424. + + BSD : myproc[8710]: Kilroy was here. + RFC3164 : Aug 24 05:14:15 192.0.2.1 myproc[8710]: Kilroy was here. + RFC5424 : 2003-08-24T05:14:15.000003-07:00 192.0.2.1 myproc 8710 - - Kilroy was here. + + Please note, BSD format is only applicable to remote logging."; + type identityref { + base format-type; + } + } + } + + /* + * Data Nodes + */ + + augment "/syslog:syslog" { + container file-rotation { + description "Global configuration parameters for log file rotation. + + By default the last 10 rotated files are kept. From + the second rotation the files are gzipped. + + Example: syslog -> syslog.0 -> syslog.1.gz ..."; + + leaf number-of-files { + type uint32; + default 10; + description "Maximum number of log files retained."; + } + + leaf max-file-size { + type uint32; + default 1024; + units "kilobytes"; + description "Maximum log file size (kiB), before rotation."; + } + } + + container server { + description "Syslog server settings, acting as a remote server (sink)"; + + leaf enabled { + description "Control listen to incoming syslog messages, default: off. + + When enabled, the server listen on port 514 on all interfaces. + Use the listen directive to limit this to one or more on any + given port, if needed."; + type boolean; + default false; + } + + container listen { + description "Limit listen to the given interfaces[:port]."; + choice listen { + case udp { + list udp { + key "port"; + leaf address { + description "Interface to listen on, default: any."; + type inet:ip-address; + } + + leaf port { + description "The Internet port to listen on, default: 514."; + type inet:port-number; + default 514; + } + } + } + } + } + } + } + + augment "/syslog:syslog/syslog:actions/syslog:file/syslog:log-file" { + description "Configurable log format for file logging."; + uses log-format { + refine log-format { + default rfc3164; + must "not(../log-format = 'infix-syslog:bsd')" { + error-message "BSD log format is not applicable to file logging, only remote."; + } + } + } + } + + augment "/syslog:syslog/syslog:actions/syslog:remote/syslog:destination" { + description "Configurable log format for remote logging."; + uses log-format { + refine log-format { + default bsd; + } + } + } + + deviation "/syslog:syslog/syslog:actions/syslog:file/syslog:log-file/syslog:file-rotation/syslog:number-of-files" { + description "Drop default 1 log file, defaults are handled by global file-rotation settings."; + deviate delete { + default 1; + } + } + deviation "/syslog:syslog/syslog:actions/syslog:file/syslog:log-file/syslog:file-rotation/syslog:max-file-size" { + description "Replace default 'megabytes' unit with 'kilobytes' to allow for better control."; + deviate replace { + type uint32; + units "kilobytes"; + } + } + + deviation "/syslog:syslog/syslog:actions/syslog:remote/syslog:destination/syslog:transport/syslog:tls" { + description "Not yet supported by underlying daemon."; + deviate not-supported; + } + deviation "/syslog:syslog/syslog:actions/syslog:remote/syslog:destination/syslog:facility-override" { + description "Not yet supported by underlying daemon."; + deviate not-supported; + } +} diff --git a/src/confd/yang/infix-syslog@2024-07-19.yang b/src/confd/yang/infix-syslog@2024-07-19.yang deleted file mode 100644 index 1d895d03..00000000 --- a/src/confd/yang/infix-syslog@2024-07-19.yang +++ /dev/null @@ -1,200 +0,0 @@ -module infix-syslog { - yang-version 1.1; - namespace "urn:infix:syslog:ns:yang:1.0"; - prefix infix-syslog; - - - import ietf-inet-types { - prefix inet; - reference "RFC 6991: Common YANG Data Types"; - } - import ietf-syslog { - prefix syslog; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Infix augments and deviations to ietf-syslog, draft 32."; - - revision 2024-07-19 { - description "Initial revision, based on IETF syslog YANG draft 32. - The following changes have been made in this model: - - - Add support for global file rotation settings - - Add support for acting as a remote server - - Add support for local facility names - - Add support for log format selection per action - - Disable TLS transport, not yet supported - - Disable facility override, not yet supported - - Removed 1 log file default - - Replaced default 'megabytes' unit with 'kilobytes'"; - reference "internal"; - } - - /* - * Identities - */ - - identity rauc { - base syslog:syslog-facility; - description "Local facility for the RAUC firmware update subsystem, local0."; - } - - identity container { - base syslog:syslog-facility; - description "Local facility reserved for Docker containers, local1."; - } - - identity web { - base syslog:syslog-facility; - description "Local facility reserved for web server, local7."; - } - - // Log format - - identity format-type { - description "This identity is used as a base for all log formats."; - reference "RFC 5424: The Syslog Protocol"; - } - - identity bsd { - base format-type; - description "Original BSD UNIX log format, default when sending remote."; - } - - identity rfc3164 { - base format-type; - description "Default log format, except when sending remote."; - } - - identity rfc5424 { - base format-type; - description "Latest format, better time granularity, structured data, etc."; - } - - /* - * Shared settings - */ - - grouping log-format { - leaf log-format { - description "Log format, one of: BSD*, RFC3164, or RFC5424. - - BSD : myproc[8710]: Kilroy was here. - RFC3164 : Aug 24 05:14:15 192.0.2.1 myproc[8710]: Kilroy was here. - RFC5424 : 2003-08-24T05:14:15.000003-07:00 192.0.2.1 myproc 8710 - - Kilroy was here. - - Please note, BSD format is only applicable to remote logging."; - type identityref { - base format-type; - } - } - } - - /* - * Data Nodes - */ - - augment "/syslog:syslog" { - container file-rotation { - description "Global configuration parameters for log file rotation. - - By default the last 10 rotated files are kept. From - the second rotation the files are gzipped. - - Example: syslog -> syslog.0 -> syslog.1.gz ..."; - - leaf number-of-files { - type uint32; - default 10; - description "Maximum number of log files retained."; - } - - leaf max-file-size { - type uint32; - default 1024; - units "kilobytes"; - description "Maximum log file size (kiB), before rotation."; - } - } - - container server { - description "Syslog server settings, acting as a remote server (sink)"; - - leaf enabled { - description "Control listen to incoming syslog messages, default: off. - - When enabled, the server listen on port 514 on all interfaces. - Use the listen directive to limit this to one or more on any - given port, if needed."; - type boolean; - default false; - } - - container listen { - description "Limit listen to the given interfaces[:port]."; - choice listen { - case udp { - list udp { - key "port"; - leaf address { - description "Interface to listen on, default: any."; - type inet:ip-address; - } - - leaf port { - description "The Internet port to listen on, default: 514."; - type inet:port-number; - default 514; - } - } - } - } - } - } - } - - augment "/syslog:syslog/syslog:actions/syslog:file/syslog:log-file" { - description "Configurable log format for file logging."; - uses log-format { - refine log-format { - default rfc3164; - must "not(../log-format = 'infix-syslog:bsd')" { - error-message "BSD log format is not applicable to file logging, only remote."; - } - } - } - } - - augment "/syslog:syslog/syslog:actions/syslog:remote/syslog:destination" { - description "Configurable log format for remote logging."; - uses log-format { - refine log-format { - default bsd; - } - } - } - - deviation "/syslog:syslog/syslog:actions/syslog:file/syslog:log-file/syslog:file-rotation/syslog:number-of-files" { - description "Drop default 1 log file, defaults are handled by global file-rotation settings."; - deviate delete { - default 1; - } - } - deviation "/syslog:syslog/syslog:actions/syslog:file/syslog:log-file/syslog:file-rotation/syslog:max-file-size" { - description "Replace default 'megabytes' unit with 'kilobytes' to allow for better control."; - deviate replace { - type uint32; - units "kilobytes"; - } - } - - deviation "/syslog:syslog/syslog:actions/syslog:remote/syslog:destination/syslog:transport/syslog:tls" { - description "Not yet supported by underlying daemon."; - deviate not-supported; - } - deviation "/syslog:syslog/syslog:actions/syslog:remote/syslog:destination/syslog:facility-override" { - description "Not yet supported by underlying daemon."; - deviate not-supported; - } -} diff --git a/src/confd/yang/infix-syslog@2024-07-19.yang b/src/confd/yang/infix-syslog@2024-07-19.yang new file mode 120000 index 00000000..3d72dd3f --- /dev/null +++ b/src/confd/yang/infix-syslog@2024-07-19.yang @@ -0,0 +1 @@ +infix-syslog.yang \ No newline at end of file diff --git a/src/confd/yang/infix-system-software.yang b/src/confd/yang/infix-system-software.yang new file mode 100644 index 00000000..2cc449ab --- /dev/null +++ b/src/confd/yang/infix-system-software.yang @@ -0,0 +1,201 @@ +submodule infix-system-software { + yang-version 1.1; + belongs-to infix-system { + prefix ixsys; + } + + import ietf-yang-types { + prefix yang; + } + + import ietf-netconf-acm { + prefix nacm; + } + + import ietf-system { + prefix sys; + } + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Software status and upgrade."; + + revision 2023-06-27 { + description "Initial revision."; + reference "internal"; + } + + grouping rauc-stage-log { + leaf datetime { + type yang:date-and-time; + description + "The time of the event."; + } + + leaf count { + type uint32; + description + "The total number of occurrences of the event."; + } + } + + grouping installer-state { + leaf operation { + type string; + description + "The current operation of the installer service."; + } + + container progress { + leaf percentage { + type uint8 { + range "0 .. 100"; + } + } + + leaf message { + type string; + } + } + + leaf last-error { + type string; + description + "The last error encountered by the installer service."; + } + } + + augment "/sys:system-state" { + container software { + description + "Installed software information + + Determined by RAUC, which manages all software upgrades."; + reference "https://rauc.io/"; + + leaf compatible { + type string; + description + "Platform identifier + + Software bundles' compatible attributes are matched against this + one, to determine if they are compatible with one another."; + } + + leaf variant { + type string; + description + "Hardware variant + + Identifies the exact system type."; + } + + leaf booted { + type string; + description + "Slot from which the system was booted."; + } + + container installer { + description + "The current state of the software installer service."; + + uses installer-state; + + // TODO: Support sending notifications during bundle installation + // notification state-changed { + // uses installer-state; + // } + } + + list slot { + key "name"; + description + "Details the installed software and current state of a particular + storage slot (partition)."; + + leaf name { + type string; + description + "RAUC's internal name for the slot, in . notation."; + } + + leaf bootname { + type string; + description + "Short name of the slot."; + } + + leaf class { + type string; + description + "Class of software compatible with the slot."; + } + + leaf state { + type string; + description + "The slot's state."; + } + + container bundle { + leaf compatible { + type string; + description + "Platform identifier of the installed software image."; + } + + leaf version { + type string; + description + "Version of the installed software image."; + } + } + + leaf size { + type uint64; + description + "Size, in bytes, of the installed software image."; + } + + leaf sha256 { + type string { + pattern '[a-fA-F0-9]{64}'; + } + description + "Checksum of the installed software image."; + } + container installed { + description + "Logs the time of the last installation and the total number of + updates to this slot."; + + uses rauc-stage-log; + } + + container activated { + description + "Logs the first time the current slot was activated and the total + number of activations."; + uses rauc-stage-log; + } + } + } + } + + rpc install-bundle { +nacm:default-deny-all; + description + "Upgrade the system's software by installing the specified bundle."; + input { + leaf url { + type string; + mandatory true; + description + "The location of the software bundle, specified as a Uniform + Resource Locator (URL). Currently supported protocols include + FTP, HTTP(S) and SCP."; + } + } + } +} diff --git a/src/confd/yang/infix-system-software@2023-06-27.yang b/src/confd/yang/infix-system-software@2023-06-27.yang deleted file mode 100644 index 2cc449ab..00000000 --- a/src/confd/yang/infix-system-software@2023-06-27.yang +++ /dev/null @@ -1,201 +0,0 @@ -submodule infix-system-software { - yang-version 1.1; - belongs-to infix-system { - prefix ixsys; - } - - import ietf-yang-types { - prefix yang; - } - - import ietf-netconf-acm { - prefix nacm; - } - - import ietf-system { - prefix sys; - } - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Software status and upgrade."; - - revision 2023-06-27 { - description "Initial revision."; - reference "internal"; - } - - grouping rauc-stage-log { - leaf datetime { - type yang:date-and-time; - description - "The time of the event."; - } - - leaf count { - type uint32; - description - "The total number of occurrences of the event."; - } - } - - grouping installer-state { - leaf operation { - type string; - description - "The current operation of the installer service."; - } - - container progress { - leaf percentage { - type uint8 { - range "0 .. 100"; - } - } - - leaf message { - type string; - } - } - - leaf last-error { - type string; - description - "The last error encountered by the installer service."; - } - } - - augment "/sys:system-state" { - container software { - description - "Installed software information - - Determined by RAUC, which manages all software upgrades."; - reference "https://rauc.io/"; - - leaf compatible { - type string; - description - "Platform identifier - - Software bundles' compatible attributes are matched against this - one, to determine if they are compatible with one another."; - } - - leaf variant { - type string; - description - "Hardware variant - - Identifies the exact system type."; - } - - leaf booted { - type string; - description - "Slot from which the system was booted."; - } - - container installer { - description - "The current state of the software installer service."; - - uses installer-state; - - // TODO: Support sending notifications during bundle installation - // notification state-changed { - // uses installer-state; - // } - } - - list slot { - key "name"; - description - "Details the installed software and current state of a particular - storage slot (partition)."; - - leaf name { - type string; - description - "RAUC's internal name for the slot, in . notation."; - } - - leaf bootname { - type string; - description - "Short name of the slot."; - } - - leaf class { - type string; - description - "Class of software compatible with the slot."; - } - - leaf state { - type string; - description - "The slot's state."; - } - - container bundle { - leaf compatible { - type string; - description - "Platform identifier of the installed software image."; - } - - leaf version { - type string; - description - "Version of the installed software image."; - } - } - - leaf size { - type uint64; - description - "Size, in bytes, of the installed software image."; - } - - leaf sha256 { - type string { - pattern '[a-fA-F0-9]{64}'; - } - description - "Checksum of the installed software image."; - } - container installed { - description - "Logs the time of the last installation and the total number of - updates to this slot."; - - uses rauc-stage-log; - } - - container activated { - description - "Logs the first time the current slot was activated and the total - number of activations."; - uses rauc-stage-log; - } - } - } - } - - rpc install-bundle { -nacm:default-deny-all; - description - "Upgrade the system's software by installing the specified bundle."; - input { - leaf url { - type string; - mandatory true; - description - "The location of the software bundle, specified as a Uniform - Resource Locator (URL). Currently supported protocols include - FTP, HTTP(S) and SCP."; - } - } - } -} diff --git a/src/confd/yang/infix-system-software@2023-06-27.yang b/src/confd/yang/infix-system-software@2023-06-27.yang new file mode 120000 index 00000000..e01b714c --- /dev/null +++ b/src/confd/yang/infix-system-software@2023-06-27.yang @@ -0,0 +1 @@ +infix-system-software.yang \ No newline at end of file diff --git a/src/confd/yang/infix-system.yang b/src/confd/yang/infix-system.yang new file mode 100644 index 00000000..2627ea45 --- /dev/null +++ b/src/confd/yang/infix-system.yang @@ -0,0 +1,302 @@ +module infix-system { + yang-version 1.1; + namespace "urn:infix:system:ns:yang:1.0"; + prefix infix-sys; + + import ietf-system { + prefix sys; + } + import iana-timezones { + prefix iana-tz; + } + + include infix-system-software; + + organization "KernelKit"; + contact "kernelkit@googlegroups.com"; + description "Infix augments and deviations to ietf-system."; + + revision 2024-09-13 { + description "Add some informative help about different shells and security."; + reference "internal"; + } + + revision 2024-06-15 { + description "Merge infix-shell-types.yang to add shell-type identities."; + reference "internal"; + } + + revision 2024-06-14 { + description "Add support for format specifiers in hostname: + - %h default hostname from /etc/os-release + - %i value of ID from /etc/os-release + - %m last three octets of base MAC, e.g., c0-ff-ee + + Add support for yescrypt and $factory$ in password. + The latter is a reserved string which is interpreted + as the device default password from the VPD EEPROM."; + reference "internal"; + } + + revision 2024-04-12 { + description "New type, infix:hostname, for /system/hostname (max 64 chars)."; + reference "internal"; + } + + revision 2024-02-29 { + description "Mark infix-sys:motd as deprecated, to be replaced with type binary."; + reference "internal"; + } + + 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. + + Update/add deviation specifications: + - timezone-name (use tz defs from iana-timezone.yang) + - timezone-utc-offset (updated path for 'not-supported') + - radius ('not-supported') + - dns-resolver port ('not-supported') + - authentication username (limit length and pattern)"; + reference "internal"; + } + + revision 2023-04-11 { + description "Initial revision."; + reference "internal"; + } + + /* + * Identities + */ + + identity editor-type { + description "Base identity from which specific editor types are derived."; + } + + identity emacs { + description "Micro Emacs clone (mg)."; + base editor-type; + } + identity nano { + description "GNU Nano."; + base editor-type; + } + identity vi { + description "The classic UNIX Visual editor."; + base editor-type; + } + + identity shell-type { + description "Base identity from which specific shell types are derived."; + } + + identity bash { + description "Bourne again shell (BASH), standard UNIX shell."; + base shell-type; + } + identity clish { + description "Dedicated switch/router shell, similar to Cisco/JunOS."; + base shell-type; + } + identity sh { + description "POSIX shell, the original plain UNIX shell."; + base shell-type; + } + identity false { + description "Shell login disabled, both console and SSH."; + base shell-type; + } + + /* + * Typedefs + */ + + typedef crypt-hash { + type string { + pattern + '$0$.*' + + '|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}' + + '|$5$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}' + + '|$6$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}' + + '|$y$[a-zA-Z0-9./]+$[a-zA-Z0-9./]{1,86}$[a-zA-Z0-9./]{43}' + + '|$factory$.*'; + } + description + "This type is used to store passwords using a hash function. It + extends the IANA crypt-hash type to support yescrypt as well as + a reserved string '$factory$', used for device-specific factory + default hash. It is up to the underlying system to define this + further, one example is to use Vital Product Data (VPD), e.g., + an onboard EEPROM where a device hash is stored for the initial + 'admin' user. + + A value of this type matches one of the forms: + + $0$ + $$$ + $$$$ + + The '$0$' prefix signals that the value is clear text, and even + though it is supported, it is *not* recommended! When such a + value is received it passes through multiple subsystems before + a hash value is calculated and the string '$$$' or + $$$$ is prepended and the result is stored + in the configuration data store. The hash function used depend + on end system requirements. + + When any other '$$' prefix is received, the system store it + 'as is' in the configuration data store. + + When a server needs to verify a password given by a user, it + finds the stored password hash string for that user, extracts + the salt, and calculates the hash with the salt and given + password as input. If the calculated hash value is the same as + the stored value, the password given by the client is accepted. + + This type defines the following supported hash functions: + + id | hash function | feature + ---+---------------+------------------- + 1 | MD5 | crypt-hash-md5 + 5 | SHA-256 | crypt-hash-sha-256 + 6 | SHA-512 | crypt-hash-sha-512 + y | yescrypt | crypt-hash-yescrypt"; + reference + "IEEE Std 1003.1-2008 - crypt() function + RFC 1321: The MD5 Message-Digest Algorithm + FIPS.180-4.2012: Secure Hash Standard (SHS)"; + } + + typedef username { + type string { + pattern "[_a-zA-Z0-9][-._a-zA-Z0-9]*$?"; + length "1..256"; + } + } + + typedef hostname { + type string { + pattern + '(' + + '(([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?' + + '|%[him]' + + ')' + + '([a-zA-Z0-9\-_\.]|%[him])*'; + length "1..64"; + } + description "Linux have the same restrictions as IETF, only shorter. + Format specifiers are for, default hostname, ID, and the + last three octets in base MAC, e.g., c0-ff-ee"; + } + + /* + * Data nodes + */ + + augment "/sys:system" { + description "Augment of ietf-system for modifying /etc/motd."; + + leaf motd { + description "Legacy MotD (Message of the Day), shown after login. + + Please note, this is obsolete! When set it overrides the + 'motd-banner' setting for backwards compatibility. + + Instead, use 'motd-banner', which takes a base64 encoded + text file as an argument. For CLI users, edit with the + 'text-editor motd-banner' command."; + status obsolete; // Replaced with motd-banner (binary) + type string; + } + + // From openconfig-system, which also has login-banner (TODO) + leaf motd-banner { + description "Message of the Day (MotD), shown after SSH/console login. + + Base64 encoded (binary) file contents for the system file + /etc/motd, displayed after SSH/console login. + + They system may append additional standard information such + as the current system date and time, uptime, last login + timestamp, etc."; + type binary; + } + + leaf text-editor { + description "Text editor to use in CLI for text-editor command."; + type identityref { + base editor-type; + } + default emacs; + } + } + + augment "/sys:system/sys:authentication/sys:user" { + description "Augment of ietf-system to support setting login shell for users."; + leaf shell { + type identityref { + base shell-type; + } + default false; + description "Set UNIX login shell for user. + + For security reasons avoid shells bash and sh for non-admin users. + This since this may open the system for local security issues. + + default: none (security)"; + } + } + + deviation "/sys:system/sys:hostname" { + deviate replace { + type infix-sys:hostname; + } + description "Linux hostname can only be max 64 charachters long."; + } + + deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-name/sys:timezone-name" { + deviate replace { + type iana-tz:iana-timezone; + } + } + + 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" { + deviate not-supported; + } + + deviation "/sys:system/sys:dns-resolver/sys:server/sys:transport/sys:udp-and-tcp/sys:udp-and-tcp/sys:port" { + deviate not-supported; + } + + deviation "/sys:system/sys:authentication/sys:user/sys:name" { + deviate replace { + type infix-sys:username; + } + } + + deviation "/sys:system/sys:authentication/sys:user/sys:password" { + description "Extended password hash, including missing types, and $factory$."; + deviate replace { + type infix-sys:crypt-hash; + } + } +} diff --git a/src/confd/yang/infix-system@2024-09-13.yang b/src/confd/yang/infix-system@2024-09-13.yang deleted file mode 100644 index 2627ea45..00000000 --- a/src/confd/yang/infix-system@2024-09-13.yang +++ /dev/null @@ -1,302 +0,0 @@ -module infix-system { - yang-version 1.1; - namespace "urn:infix:system:ns:yang:1.0"; - prefix infix-sys; - - import ietf-system { - prefix sys; - } - import iana-timezones { - prefix iana-tz; - } - - include infix-system-software; - - organization "KernelKit"; - contact "kernelkit@googlegroups.com"; - description "Infix augments and deviations to ietf-system."; - - revision 2024-09-13 { - description "Add some informative help about different shells and security."; - reference "internal"; - } - - revision 2024-06-15 { - description "Merge infix-shell-types.yang to add shell-type identities."; - reference "internal"; - } - - revision 2024-06-14 { - description "Add support for format specifiers in hostname: - - %h default hostname from /etc/os-release - - %i value of ID from /etc/os-release - - %m last three octets of base MAC, e.g., c0-ff-ee - - Add support for yescrypt and $factory$ in password. - The latter is a reserved string which is interpreted - as the device default password from the VPD EEPROM."; - reference "internal"; - } - - revision 2024-04-12 { - description "New type, infix:hostname, for /system/hostname (max 64 chars)."; - reference "internal"; - } - - revision 2024-02-29 { - description "Mark infix-sys:motd as deprecated, to be replaced with type binary."; - reference "internal"; - } - - 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. - - Update/add deviation specifications: - - timezone-name (use tz defs from iana-timezone.yang) - - timezone-utc-offset (updated path for 'not-supported') - - radius ('not-supported') - - dns-resolver port ('not-supported') - - authentication username (limit length and pattern)"; - reference "internal"; - } - - revision 2023-04-11 { - description "Initial revision."; - reference "internal"; - } - - /* - * Identities - */ - - identity editor-type { - description "Base identity from which specific editor types are derived."; - } - - identity emacs { - description "Micro Emacs clone (mg)."; - base editor-type; - } - identity nano { - description "GNU Nano."; - base editor-type; - } - identity vi { - description "The classic UNIX Visual editor."; - base editor-type; - } - - identity shell-type { - description "Base identity from which specific shell types are derived."; - } - - identity bash { - description "Bourne again shell (BASH), standard UNIX shell."; - base shell-type; - } - identity clish { - description "Dedicated switch/router shell, similar to Cisco/JunOS."; - base shell-type; - } - identity sh { - description "POSIX shell, the original plain UNIX shell."; - base shell-type; - } - identity false { - description "Shell login disabled, both console and SSH."; - base shell-type; - } - - /* - * Typedefs - */ - - typedef crypt-hash { - type string { - pattern - '$0$.*' - + '|$1$[a-zA-Z0-9./]{1,8}$[a-zA-Z0-9./]{22}' - + '|$5$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{43}' - + '|$6$(rounds=\d+$)?[a-zA-Z0-9./]{1,16}$[a-zA-Z0-9./]{86}' - + '|$y$[a-zA-Z0-9./]+$[a-zA-Z0-9./]{1,86}$[a-zA-Z0-9./]{43}' - + '|$factory$.*'; - } - description - "This type is used to store passwords using a hash function. It - extends the IANA crypt-hash type to support yescrypt as well as - a reserved string '$factory$', used for device-specific factory - default hash. It is up to the underlying system to define this - further, one example is to use Vital Product Data (VPD), e.g., - an onboard EEPROM where a device hash is stored for the initial - 'admin' user. - - A value of this type matches one of the forms: - - $0$ - $$$ - $$$$ - - The '$0$' prefix signals that the value is clear text, and even - though it is supported, it is *not* recommended! When such a - value is received it passes through multiple subsystems before - a hash value is calculated and the string '$$$' or - $$$$ is prepended and the result is stored - in the configuration data store. The hash function used depend - on end system requirements. - - When any other '$$' prefix is received, the system store it - 'as is' in the configuration data store. - - When a server needs to verify a password given by a user, it - finds the stored password hash string for that user, extracts - the salt, and calculates the hash with the salt and given - password as input. If the calculated hash value is the same as - the stored value, the password given by the client is accepted. - - This type defines the following supported hash functions: - - id | hash function | feature - ---+---------------+------------------- - 1 | MD5 | crypt-hash-md5 - 5 | SHA-256 | crypt-hash-sha-256 - 6 | SHA-512 | crypt-hash-sha-512 - y | yescrypt | crypt-hash-yescrypt"; - reference - "IEEE Std 1003.1-2008 - crypt() function - RFC 1321: The MD5 Message-Digest Algorithm - FIPS.180-4.2012: Secure Hash Standard (SHS)"; - } - - typedef username { - type string { - pattern "[_a-zA-Z0-9][-._a-zA-Z0-9]*$?"; - length "1..256"; - } - } - - typedef hostname { - type string { - pattern - '(' - + '(([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' - + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?' - + '|%[him]' - + ')' - + '([a-zA-Z0-9\-_\.]|%[him])*'; - length "1..64"; - } - description "Linux have the same restrictions as IETF, only shorter. - Format specifiers are for, default hostname, ID, and the - last three octets in base MAC, e.g., c0-ff-ee"; - } - - /* - * Data nodes - */ - - augment "/sys:system" { - description "Augment of ietf-system for modifying /etc/motd."; - - leaf motd { - description "Legacy MotD (Message of the Day), shown after login. - - Please note, this is obsolete! When set it overrides the - 'motd-banner' setting for backwards compatibility. - - Instead, use 'motd-banner', which takes a base64 encoded - text file as an argument. For CLI users, edit with the - 'text-editor motd-banner' command."; - status obsolete; // Replaced with motd-banner (binary) - type string; - } - - // From openconfig-system, which also has login-banner (TODO) - leaf motd-banner { - description "Message of the Day (MotD), shown after SSH/console login. - - Base64 encoded (binary) file contents for the system file - /etc/motd, displayed after SSH/console login. - - They system may append additional standard information such - as the current system date and time, uptime, last login - timestamp, etc."; - type binary; - } - - leaf text-editor { - description "Text editor to use in CLI for text-editor command."; - type identityref { - base editor-type; - } - default emacs; - } - } - - augment "/sys:system/sys:authentication/sys:user" { - description "Augment of ietf-system to support setting login shell for users."; - leaf shell { - type identityref { - base shell-type; - } - default false; - description "Set UNIX login shell for user. - - For security reasons avoid shells bash and sh for non-admin users. - This since this may open the system for local security issues. - - default: none (security)"; - } - } - - deviation "/sys:system/sys:hostname" { - deviate replace { - type infix-sys:hostname; - } - description "Linux hostname can only be max 64 charachters long."; - } - - deviation "/sys:system/sys:clock/sys:timezone/sys:timezone-name/sys:timezone-name" { - deviate replace { - type iana-tz:iana-timezone; - } - } - - 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" { - deviate not-supported; - } - - deviation "/sys:system/sys:dns-resolver/sys:server/sys:transport/sys:udp-and-tcp/sys:udp-and-tcp/sys:port" { - deviate not-supported; - } - - deviation "/sys:system/sys:authentication/sys:user/sys:name" { - deviate replace { - type infix-sys:username; - } - } - - deviation "/sys:system/sys:authentication/sys:user/sys:password" { - description "Extended password hash, including missing types, and $factory$."; - deviate replace { - type infix-sys:crypt-hash; - } - } -} diff --git a/src/confd/yang/infix-system@2024-09-13.yang b/src/confd/yang/infix-system@2024-09-13.yang new file mode 120000 index 00000000..0be062b6 --- /dev/null +++ b/src/confd/yang/infix-system@2024-09-13.yang @@ -0,0 +1 @@ +infix-system.yang \ No newline at end of file diff --git a/test/case/ietf_hardware/usb/Readme.adoc b/test/case/ietf_hardware/usb/Readme.adoc index b14ebce1..8994018e 100644 --- a/test/case/ietf_hardware/usb/Readme.adoc +++ b/test/case/ietf_hardware/usb/Readme.adoc @@ -31,7 +31,7 @@ endif::topdoc[] . Verify that all USB ports are locked . Unlock USB ports . Verify that all USB ports are unlocked -. Save to startup and reboot +. Save the configuration to startup configuration and reboot . Verify USB port remain unlocked after reboot diff --git a/test/case/ietf_hardware/usb/test.py b/test/case/ietf_hardware/usb/test.py index 4daa9ba7..fa77de80 100755 --- a/test/case/ietf_hardware/usb/test.py +++ b/test/case/ietf_hardware/usb/test.py @@ -101,7 +101,7 @@ with infamy.Test() as test: for port in available: until(lambda: usb.get_usb_state(target, port) == "unlocked") - with test.step("Save to startup and reboot"): + with test.step("Save the configuration to startup configuration and reboot"): target.startup_override() target.copy("running", "startup") target.reboot() diff --git a/test/case/ietf_interfaces/verify_all_interface_types/test.py b/test/case/ietf_interfaces/verify_all_interface_types/test.py index 045b033d..63a4fa34 100755 --- a/test/case/ietf_interfaces/verify_all_interface_types/test.py +++ b/test/case/ietf_interfaces/verify_all_interface_types/test.py @@ -1,24 +1,19 @@ #!/usr/bin/env python3 +# +# lo br-0 br-Q.40 br-D br-X +# | | | | | +# o o eth-Q.10 br-Q veth0a.20 eth-X.30 +# \ / \ | | +# eth-Q veth0b veth0a eth-X +# `---------' + """ -``` - lo br-0 br-Q.40 br-D br-X - | | | | | - o o eth-Q.10 br-Q veth0a.20 eth-X.30 - \ / \ | | - eth-Q veth0b veth0a eth-X - `---------' -``` -Verify that all interface types can be created: -1. Ethernet/Etherlike (ethX) -2. Loopback (lo) -3. Empty bridge (br-0) -4. Ethernet/Etherlike (ethQ) as a bridge port in br-Q -5. VETH pair: veth0a <--> veth0b, veth0b as a bridge port in br-Q -6. VLAN: - 1. ethQ.10 (VLAN 10) on top of an Ethernet/Etherlike interface (ethQ) - 2. br-Q.40 (VLAN 40) on top of a bridge (br-Q) - 3. veth0a.20 (VLAN 20) on top of a VETH interface (veth0a) as a bridge port in br-D - 4. ethX.30 (VLAN 30) as a bridge port in br-X +Verify that all interface types can be created + +This test verify that all interface types can be created +and also, tesing setting the configuration in sequal (this +takes a little longer time than send it once) + """ import infamy @@ -32,9 +27,9 @@ def verify_interface(target, interface, expected_type): actual_type = iface._iface_get_param(target, interface, "type") if expected_type == "infix-if-type:etherlike" and actual_type == "infix-if-type:ethernet": - return # Allow 'etherlike' to match 'ethernet' - - assert actual_type == expected_type, f"Assertion failed! expected tpye: {expected_type}, actual type {actual_type}" + return # Allow 'etherlike' to match 'ethernet' + + assert actual_type == expected_type, f"Assertion failed! expected tpye: {expected_type}, actual type {actual_type}" with infamy.Test() as test: @@ -193,25 +188,28 @@ with infamy.Test() as test: ] } }) - - interfaces_to_verify = { - loopback: "loopback", - eth_X: "etherlike", - eth_Q: "etherlike", - br_0: "bridge", - br_Q: "bridge", - br_X: "bridge", - br_D: "bridge", - veth_b: "veth", - veth_a: "veth", - veth_a_20: "vlan", - eth_Q_10: "vlan", - eth_X_30: "vlan", - br_Q_40: "vlan" - } - for interface, iface_type in interfaces_to_verify.items(): - with test.step(f"Verify {iface_type} interface {interface}"): - verify_interface(target, interface, iface_type) + with test.step("Verify interface 'lo' is of type loopback"): + verify_interface(target, "lo", "loopback") + + with test.step("Verify interfaces 'ethX' and 'ethQ' is of type 'ethernet' (or etherlike if running Qemu)"): + verify_interface(target, eth_X, "etherlike") + verify_interface(target, eth_Q, "etherlike") + + with test.step("Verify interfaces 'br-0', 'br-X', 'br-D' and 'br-Q' is of type 'bridge'"): + verify_interface(target, "br-0", "bridge") + verify_interface(target, "br-X", "bridge") + verify_interface(target, "br-Q", "bridge") + verify_interface(target, "br-D", "bridge") + + with test.step("Verify interfaces 'veth0a' and 'veth0b' is of type 'veth'"): + verify_interface(target, "veth0a", "veth") + verify_interface(target, "veth0b", "veth") + + with test.step("Verify interfaces 'veth0a.20', 'ethQ.10', 'ethX.30', 'ethQ.10' and 'br-Q.40' is of type 'vlan'"): + verify_interface(target, "veth0a.20", "vlan") + verify_interface(target, f"{eth_X}.30", "vlan") + verify_interface(target, f"{eth_Q}.10", "vlan") + verify_interface(target, "br-Q.40", "vlan") test.succeed() diff --git a/test/case/ietf_interfaces/verify_all_interface_types/topology.dot b/test/case/ietf_interfaces/verify_all_interface_types/topology.dot index aba85a8c..c0b81385 100644 --- a/test/case/ietf_interfaces/verify_all_interface_types/topology.dot +++ b/test/case/ietf_interfaces/verify_all_interface_types/topology.dot @@ -7,19 +7,19 @@ graph "1x3" { edge [color="cornflowerblue", penwidth="2"]; host [ - label="host | { tgt | dummy0 | dummy1 }", + label="host | { tgt | dummy0 | dummy1 }", pos="0,12!", kind="controller", ]; target [ - label="{ mgmt | Dport | Qport } | target", + label="{ mgmt | ethX | ethQ } | target", pos="10,12!", kind="infix", ]; host:tgt -- target:mgmt [kind=mgmt] - host:dummy0 -- target:ethQ [color=black] - host:dummy1 -- target:ethX [color=black] + host:dummy0 -- target:ethX [color=black] + host:dummy1 -- target:ethQ [color=black] } diff --git a/test/case/ietf_interfaces/verify_all_interface_types/topology.png b/test/case/ietf_interfaces/verify_all_interface_types/topology.png index 85f31d89..7a819243 100644 Binary files a/test/case/ietf_interfaces/verify_all_interface_types/topology.png and b/test/case/ietf_interfaces/verify_all_interface_types/topology.png differ diff --git a/test/case/ietf_interfaces/veth_delete/Readme.adoc b/test/case/ietf_interfaces/veth_delete/Readme.adoc index 96ce39de..d31a44b7 100644 --- a/test/case/ietf_interfaces/veth_delete/Readme.adoc +++ b/test/case/ietf_interfaces/veth_delete/Readme.adoc @@ -23,7 +23,7 @@ endif::topdoc[] ==== Test sequence . Initialize . Create VETH pair -. Verify VETH pair exists +. Verify interfaces 'veth0a' and 'veth0b' exists . Set IP address on target:eth0 (dummy op) . Set IP address on target:eth1 (dummy op) . Reset configuration diff --git a/test/case/ietf_interfaces/veth_delete/test.py b/test/case/ietf_interfaces/veth_delete/test.py index e4f68ac9..047a83cc 100755 --- a/test/case/ietf_interfaces/veth_delete/test.py +++ b/test/case/ietf_interfaces/veth_delete/test.py @@ -50,7 +50,7 @@ with infamy.Test() as test: } }) - with test.step("Verify VETH pair exists"): + with test.step("Verify interfaces 'veth0a' and 'veth0b' exists"): assert iface.interface_exist(target, veth0a), \ f"Interface <{veth0a}> does not exist." assert iface.interface_exist(target, veth0b), \ diff --git a/test/case/ietf_routing/ospf_multiarea/test.py b/test/case/ietf_routing/ospf_multiarea/test.py index df43da8c..ee846ef0 100755 --- a/test/case/ietf_routing/ospf_multiarea/test.py +++ b/test/case/ietf_routing/ospf_multiarea/test.py @@ -267,9 +267,6 @@ def config_target2(target, ring1, ring2, cross): }, "name": ring1, "hello-interval": 1, - }, { - "name": "lo", - "enabled": True }] } }, { @@ -282,9 +279,6 @@ def config_target2(target, ring1, ring2, cross): "name": cross, "hello-interval": 1, "cost": 2000 - }, { - "name": "lo", - "enabled": True }] } }] diff --git a/test/case/ietf_syslog/basic/Readme.adoc b/test/case/ietf_syslog/basic/Readme.adoc index f77ea932..152a29ed 100644 --- a/test/case/ietf_syslog/basic/Readme.adoc +++ b/test/case/ietf_syslog/basic/Readme.adoc @@ -1,7 +1,6 @@ === Syslog Basic ==== Description -- Add syslog actions to log to local files -- Verify new log files have been created +Add syslog actions to log to local files, then verify new log files have been created. ==== Topology ifdef::topdoc[] @@ -16,9 +15,9 @@ image::topology.png[Syslog Basic topology] endif::testgroup[] endif::topdoc[] ==== Test sequence -. Initializing ... -. Add new syslog file action -. Verify log files have been created ... +. Initializing +. Configure DUT +. Verify log files /var/log/bar.log and /var/log/bar.log have been created <<< diff --git a/test/case/ietf_syslog/basic/test.py b/test/case/ietf_syslog/basic/test.py index 189a22bc..992b6954 100755 --- a/test/case/ietf_syslog/basic/test.py +++ b/test/case/ietf_syslog/basic/test.py @@ -2,22 +2,21 @@ """ Syslog Basic -- Add syslog actions to log to local files -- Verify new log files have been created +Add syslog actions to log to local files, then verify new log files have been created. """ import infamy import infamy.ssh as ssh with infamy.Test() as test: - with test.step("Initializing ..."): + with test.step("Initializing"): env = infamy.Env() target = env.attach("target", "mgmt") tgtssh = env.attach("target", "mgmt", "ssh") factory = env.get_password("target") address = target.get_mgmt_ip() - with test.step("Add new syslog file action"): + with test.step("Configure DUT"): target.put_config_dict("ietf-syslog", { "syslog": { "actions": { @@ -59,7 +58,7 @@ with infamy.Test() as test: } }) - with test.step("Verify log files have been created ..."): + with test.step("Verify log files /var/log/bar.log and /var/log/bar.log have been created"): user = tgtssh.runsh("ls /var/log/{foo,bar.log}").stdout if "/var/log/foo" not in user: test.fail() diff --git a/test/case/ietf_syslog/basic/topology.png b/test/case/ietf_syslog/basic/topology.png index 5c6b4722..21661c18 100644 Binary files a/test/case/ietf_syslog/basic/topology.png and b/test/case/ietf_syslog/basic/topology.png differ diff --git a/test/case/ietf_syslog/remote/Readme.adoc b/test/case/ietf_syslog/remote/Readme.adoc index c25df5ce..e6a4512a 100644 --- a/test/case/ietf_syslog/remote/Readme.adoc +++ b/test/case/ietf_syslog/remote/Readme.adoc @@ -16,9 +16,9 @@ endif::testgroup[] endif::topdoc[] ==== Test sequence . Initialize -. Topology setup -. Syslog setup -. Verify logging from client to server +. Configure DUTs +. Send security:notice log message from client +. Verify reception of client log message, incl. sorting to /log/security on server <<< diff --git a/test/case/ietf_syslog/remote/test.py b/test/case/ietf_syslog/remote/test.py index b85a186f..736374ee 100755 --- a/test/case/ietf_syslog/remote/test.py +++ b/test/case/ietf_syslog/remote/test.py @@ -14,15 +14,15 @@ with infamy.Test() as test: clientssh = env.attach("client", "mgmt", "ssh") serverssh = env.attach("server", "mgmt", "ssh") - with test.step("Topology setup"): - _, client_e1 = env.ltop.xlate("client", "to_server") - _, server_e0 = env.ltop.xlate("server", "to_client") + with test.step("Configure DUTs"): + _, client_link = env.ltop.xlate("client", "link") + _, server_link = env.ltop.xlate("server", "link") client.put_config_dict("ietf-interfaces", { "interfaces": { "interface": [ { - "name": client_e1, + "name": client_link, "enabled": True, "ipv4": { "address": [ @@ -41,7 +41,7 @@ with infamy.Test() as test: "interfaces": { "interface": [ { - "name": server_e0, + "name": server_link, "type": "infix-if-type:bridge", "enabled": True, "ipv4": { @@ -57,7 +57,6 @@ with infamy.Test() as test: } }) - with test.step("Syslog setup"): client.put_config_dict("ietf-syslog", { "syslog": { "actions": { @@ -146,9 +145,11 @@ with infamy.Test() as test: } }) - with test.step("Verify logging from client to server"): - clientssh.runsh("logger -t test -m client -p security.notice Hej") + with test.step("Send security:notice log message from client"): + clientssh.runsh("logger -t test -m client -p security.notice TestMessage") + + with test.step("Verify reception of client log message, incl. sorting to /log/security on server"): infamy.until(lambda: serverssh.runsh( - "grep 'test - client - Hej' /log/security").returncode == 0) + "grep 'test - client - TestMessage' /log/security").returncode == 0) test.succeed() diff --git a/test/case/ietf_syslog/remote/topology.dot b/test/case/ietf_syslog/remote/topology.dot index 698fc0ae..93d55fb0 100644 --- a/test/case/ietf_syslog/remote/topology.dot +++ b/test/case/ietf_syslog/remote/topology.dot @@ -7,24 +7,24 @@ graph "2x2" { edge [color="cornflowerblue", penwidth="2"]; host [ - label="host | { cli_mgmt | ser_mgmt }", + label="host | { client_mgmt | server_mgmt }", pos="0,12!", kind="controller", ]; client [ - label="{ mgmt | to_server} | client", + label="{ mgmt | ĺink} | client", pos="15,18!", kind="infix", ]; server [ - label="{ to_client | mgmt } | server", + label="{ link | mgmt } | server", pos="15,6!", kind="infix", ]; host:cli_mgmt -- client:mgmt [kind=mgmt] host:ser_mgmt -- server:mgmt [kind=mgmt] - client:to_server -- server:to_client [color=black, fontcolor=black, taillabel="10.0.0.2/24", headlabel="10.0.0.1/24"] + client:link -- server:link [color=black, fontcolor=black, taillabel="10.0.0.2/24", headlabel="10.0.0.1/24"] } diff --git a/test/case/ietf_syslog/remote/topology.png b/test/case/ietf_syslog/remote/topology.png index 8cbacfed..91f426c9 100644 Binary files a/test/case/ietf_syslog/remote/topology.png and b/test/case/ietf_syslog/remote/topology.png differ diff --git a/test/spec/generate_spec.py b/test/spec/generate_spec.py index 946d8065..2b0b4d9b 100755 --- a/test/spec/generate_spec.py +++ b/test/spec/generate_spec.py @@ -3,6 +3,8 @@ import os import ast import graphviz import argparse +import io +import sys from pathlib import Path @@ -90,17 +92,17 @@ class TestCase: def parse_directory_tree(directory): directories=[] for dirpath, dirnames, filenames in os.walk(directory): - testscript=False - topology=False + testscript = False + topology = False # Search for directories containing a test.py and a topology # and define the directory as a test directory if filenames: for filename in filenames: if filename == "test.py": - testscript=True + testscript = True if filename == "topology.dot": - topology=True + topology = True if testscript and topology: directories.append(dirpath) return directories @@ -110,7 +112,24 @@ parser.add_argument("-d", "--directory", required=True, help="The directory to p parser.add_argument("-r", "--root-dir", help="Path that all paths should be relative to") args=parser.parse_args() -directories=parse_directory_tree(args.directory) +output_capture = io.StringIO() +sys.stderr = output_capture + +directories = parse_directory_tree(args.directory) +error_string = "" for directory in directories: - test_case=TestCase(directory, args.root_dir) + output_capture.truncate(0) + output_capture.seek(0) + test_case = TestCase(directory, args.root_dir) test_case.generate_specification() + if len(output_capture.getvalue()) > 0: + error_string = output_capture.getvalue() + break + +sys.stdout = sys.__stdout__ + +if len(error_string) > 0: + print(error_string) + exit(1) + +exit(0) diff --git a/test/test.mk b/test/test.mk index 07419f34..9f9b8a40 100644 --- a/test/test.mk +++ b/test/test.mk @@ -36,7 +36,7 @@ test-sh: test-spec: @sed 's/{REPLACE}/$(subst ",,$(INFIX_NAME))/' $(spec-dir)/Readme.adoc.in > $(spec-dir)/Readme.adoc @$(spec-dir)/generate_spec.py -d $(test-dir)/case -r $(BR2_EXTERNAL_INFIX_PATH) - @asciidoctor-pdf --theme $(spec-dir)/theme.yml -a pdf-fontsdir=$(spec-dir)/fonts -o $(test-specification) $(spec-dir)/Readme.adoc + @asciidoctor-pdf --failure-level INFO --theme $(spec-dir)/theme.yml -a pdf-fontsdir=$(spec-dir)/fonts -o $(test-specification) $(spec-dir)/Readme.adoc # Unit tests run with random (-r) hostname and container name to # prevent race conditions when running in CI environments.