diff --git a/doc/scripting-prod.md b/doc/scripting-prod.md new file mode 100644 index 00000000..4f115b26 --- /dev/null +++ b/doc/scripting-prod.md @@ -0,0 +1,354 @@ +# Scripting for Production Tests + +This document shows how to set up and remotely script devices with a +focus on production testing. + +## VLAN Snake + +As part of production tests, verification of Ethernet ports is usually +expected. A common way for devices with multiple bridged Ethernet ports +is to connect a test PC to two ports and send a *ping* traversing all +ports. This can be achieved by using VLANs, on the switch, as described +in this section. The resulting configuration file can be applied to the +running configuration of the produced unit, e.g, use config file restore +as [described previously][2]. + +In this example we assume a 10 port switch, with ports e1-e10. The +following VLAN configuration and cable connections will be used: + +| VLAN & Ports | Connect | +|:------------------|:----------| +| VLAN 10: e1 & e2 | e2 <=> e3 | +| VLAN 20: e3 & e4 | e4 <=> e5 | +| VLAN 30: e5 & e6 | e6 <=> e7 | +| VLAN 40: e7 & e8 | e8 <=> e9 | +| VLAN 50: e9 & e10 | | + +The test PC is connected to e1 and e10 via different interfaces +(alternatively, two different PCs are used). + +> [!TIP] +> Configuration here is done via console. When configuring remotely +> over SSH, remember to keep one IP address (the one used for the SSH +> connection)! I.e., set a static IP address first, then perform the +> VLAN configuration step. + +## Configuration at Start + +Starting out, we assume a configuration where all ports are network +interfaces (possibly with IPv6 enabled). + +``` +admin@example:/> show interfaces +lo ethernet UP 00:00:00:00:00:00 + ipv4 127.0.0.1/8 (static) + ipv6 ::1/128 (static) +e1 ethernet LOWER-DOWN 00:53:00:06:11:01 +e2 ethernet LOWER-DOWN 00:53:00:06:11:02 +e3 ethernet LOWER-DOWN 00:53:00:06:11:03 +e4 ethernet LOWER-DOWN 00:53:00:06:11:04 +e5 ethernet LOWER-DOWN 00:53:00:06:11:05 +e6 ethernet LOWER-DOWN 00:53:00:06:11:06 +e7 ethernet LOWER-DOWN 00:53:00:06:11:07 +e8 ethernet LOWER-DOWN 00:53:00:06:11:08 +e9 ethernet LOWER-DOWN 00:53:00:06:11:09 +e10 ethernet UP 00:53:00:06:11:0a + ipv6 fe80::0053:00ff:fe06:110a/64 (link-layer) +admin@example:/> +``` + +## Creating Bridge and Adding Ports + +The following example [creates a bridge][8] and adds all Ethernet ports +to it. On a device with layer-2 offloading (switch fabric), this sets +all ports in the same VLAN. The next section sets up VLAN isolation. + +``` +admin@example:/> configure +admin@example:/config/> edit interface br0 +admin@example:/config/interface/br0/> end +admin@example:/config/> set interface e1 bridge-port bridge br0 +admin@example:/config/> set interface e2 bridge-port bridge br0 +admin@example:/config/> set interface e3 bridge-port bridge br0 +admin@example:/config/> set interface e4 bridge-port bridge br0 +admin@example:/config/> set interface e5 bridge-port bridge br0 +admin@example:/config/> set interface e6 bridge-port bridge br0 +admin@example:/config/> set interface e7 bridge-port bridge br0 +admin@example:/config/> set interface e8 bridge-port bridge br0 +admin@example:/config/> set interface e9 bridge-port bridge br0 +admin@example:/config/> set interface e10 bridge-port bridge br0 +admin@example:/config/> +``` + +The interface status can be viewed using `show interfaces` after leaving +configuration context. When configuring via SSH, first assign an IP +address to `br0` *before leaving* configuration context, e.g. + +``` +admin@example:/config/> set interface br0 ipv6 enabled +``` + +This enables IPv6 SLAAC, auto-configured address. Or skip `leave` and +stay in configuration context until you have completed all the device +setup, including [setting IP address](#set-ip-address). + +``` +admin@example:/config/> leave +admin@example:/> +admin@example:/> show interfaces +INTERFACE PROTOCOL STATE DATA +br0 bridge +│ ethernet UP 00:53:00:06:11:01 +├ e1 bridge LOWER-DOWN +├ e2 bridge LOWER-DOWN +├ e3 bridge LOWER-DOWN +├ e4 bridge LOWER-DOWN +├ e5 bridge LOWER-DOWN +├ e6 bridge LOWER-DOWN +├ e7 bridge LOWER-DOWN +├ e8 bridge LOWER-DOWN +├ e9 bridge LOWER-DOWN +└ e10 bridge FORWARDING +lo ethernet UP 00:00:00:00:00:00 + ipv4 127.0.0.1/8 (static) + ipv6 ::1/128 (static) +admin@example:/> +``` + +## Assign VLANs to Ports + +Now, configure VLANs as outlined [previously](#vlan-snake): default VID +for ingress (PVID), which is done per port, and egress mode (untagged), +which is done at the bridge level. See the [VLAN bridges][9] section for +more information. + +``` +admin@example:/> +admin@example:/> configure +admin@example:/config/> set interface e1 bridge-port pvid 10 +admin@example:/config/> set interface e2 bridge-port pvid 10 +admin@example:/config/> set interface e3 bridge-port pvid 20 +admin@example:/config/> set interface e4 bridge-port pvid 20 +admin@example:/config/> set interface e5 bridge-port pvid 30 +admin@example:/config/> set interface e6 bridge-port pvid 30 +admin@example:/config/> set interface e7 bridge-port pvid 40 +admin@example:/config/> set interface e8 bridge-port pvid 40 +admin@example:/config/> set interface e9 bridge-port pvid 50 +admin@example:/config/> set interface e10 bridge-port pvid 50 +admin@example:/config/> edit interface br0 +admin@example:/config/interface/br0/> edit bridge vlans +admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 untagged e1 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 untagged e2 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 20 untagged e3 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 20 untagged e4 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 30 untagged e5 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 30 untagged e6 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 40 untagged e7 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 40 untagged e8 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 50 untagged e9 +admin@example:/config/interface/br0/bridge/vlans/> set vlan 50 untagged e10 +admin@example:/config/interface/br0/bridge/vlans/> leave +admin@example:/> +``` + +Interface status would now should something like the following + +``` +admin@example:/> show interfaces +INTERFACE PROTOCOL STATE DATA +br0 bridge +│ ethernet UP 00:53:00:06:11:01 +├ e1 bridge LOWER-DOWN vlan:10u pvid:10 +├ e2 bridge LOWER-DOWN vlan:10u pvid:10 +├ e3 bridge LOWER-DOWN vlan:20u pvid:20 +├ e4 bridge LOWER-DOWN vlan:20u pvid:20 +├ e5 bridge LOWER-DOWN vlan:30u pvid:30 +├ e6 bridge LOWER-DOWN vlan:30u pvid:30 +├ e7 bridge LOWER-DOWN vlan:40u pvid:40 +├ e8 bridge LOWER-DOWN vlan:40u pvid:40 +├ e9 bridge LOWER-DOWN vlan:50u pvid:50 +└ e10 bridge FORWARDING vlan:50u pvid:50 +lo ethernet UP 00:00:00:00:00:00 + ipv4 127.0.0.1/8 (static) + ipv6 ::1/128 (static) +admin@example:/> +``` + +## Connect Cables and Test + +We can now connect the PC to e1 and e10, while the other ports are +patched according to [above](#vlan-snake). We should see link up and +*FORWARDING* on all ports in the bridge. + +``` +admin@example:/> show interfaces +INTERFACE PROTOCOL STATE DATA +br0 bridge +│ ethernet UP 00:53:00:06:11:01 +├ e1 bridge FORWARDING vlan:10u pvid:10 +├ e2 bridge FORWARDING vlan:10u pvid:10 +├ e3 bridge FORWARDING vlan:20u pvid:20 +├ e4 bridge FORWARDING vlan:20u pvid:20 +├ e5 bridge FORWARDING vlan:30u pvid:30 +├ e6 bridge FORWARDING vlan:30u pvid:30 +├ e7 bridge FORWARDING vlan:40u pvid:40 +├ e8 bridge FORWARDING vlan:40u pvid:40 +├ e9 bridge FORWARDING vlan:50u pvid:50 +└ e10 bridge FORWARDING vlan:50u pvid:50 +lo ethernet UP 00:00:00:00:00:00 + ipv4 127.0.0.1/8 (static) + ipv6 ::1/128 (static) +admin@example:/> +``` + +Here we use IPv6 ping all hosts (ff02::1) on PC interface eth1 to +check reachability to the other interface of the PC. + +> [!TIP] +> We recommend using network namespaces (Linux only) on the PC to ensure +> that traffic is actually sent out to the switch, rather than being +> looped back internally. Alternatively, use two separate PCs. + +``` +~ $ ping -L ff02::1%eth1 +PING ff02::1%eth1(ff02::1%eth1) 56 data bytes +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.496 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.514 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.473 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.736 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=5 ttl=64 time=0.563 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=6 ttl=64 time=0.507 ms +^C +--- ff02::1%eth1 ping statistics --- +6 packets transmitted, 6 received, 0% packet loss, time 5108ms +rtt min/avg/max/mdev = 0.473/0.548/0.736/0.088 ms +~ $ +``` + +We can verify that traffic goes through the switch by disconnecting +one of the patch cables, e.g., between e4 and e5 + +``` +~ $ ping -L ff02::1%eth1 +PING ff02::1%eth1(ff02::1%eth1) 56 data bytes +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.510 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.448 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.583 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.515 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=5 ttl=64 time=0.521 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=6 ttl=64 time=0.495 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=7 ttl=64 time=0.743 ms +... Disconnecting patch cable, thus losing packets +... and reconnecting again. Connectivity resumes. +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=16 ttl=64 time=0.961 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=17 ttl=64 time=0.513 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=18 ttl=64 time=0.794 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=19 ttl=64 time=0.755 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=20 ttl=64 time=0.779 ms +^C +--- ff02::1%eth1 ping statistics --- +20 packets transmitted, 12 received, 40% packet loss, time 19432ms +rtt min/avg/max/mdev = 0.448/0.634/0.961/0.156 ms +~ $ +``` + +## Set IP Address + +The configuration so far does not provide a means to connect to the +switch management via SSH or NETCONF, as the switch has no IP address. +The example below shows how to add the switch to VLAN 10 (as used for +ports e1 and e2) and enables IPv6. + +``` +admin@example:/config/> edit interface vlan10 +admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0 +admin@example:/config/interface/vlan10/> set ipv6 enabled +admin@example:/config/interface/vlan10/> show +type vlan; +ipv6 { + enabled true; +} +vlan { + tag-type c-vlan; + id 10; + lower-layer-if br0; +} +admin@example:/config/interface/vlan10/> +admin@example:/config/interface/vlan10/> end +admin@example:/config/> edit interface br0 bridge vlans +admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 tagged br0 +admin@example:/config/interface/br0/bridge/vlans/> leave +admin@example:/> +``` + +Interface *vlan10* with an auto-configured IPv6 address should appear. + +``` +admin@example:/> show interfaces +INTERFACE PROTOCOL STATE DATA +br0 bridge vlan:10t +│ ethernet UP 00:53:00:06:11:01 +├ e1 bridge FORWARDING vlan:10u pvid:10 +├ e2 bridge FORWARDING vlan:10u pvid:10 +├ e3 bridge FORWARDING vlan:20u pvid:20 +├ e4 bridge FORWARDING vlan:20u pvid:20 +├ e5 bridge FORWARDING vlan:30u pvid:30 +├ e6 bridge FORWARDING vlan:30u pvid:30 +├ e7 bridge FORWARDING vlan:40u pvid:40 +├ e8 bridge FORWARDING vlan:40u pvid:40 +├ e9 bridge FORWARDING vlan:50u pvid:50 +└ e10 bridge FORWARDING vlan:50u pvid:50 +lo ethernet UP 00:00:00:00:00:00 + ipv4 127.0.0.1/8 (static) + ipv6 ::1/128 (static) +vlan10 ethernet UP 00:53:00:06:11:01 +│ ipv6 fe80::0053:00ff:fe06:1101/64 (link-layer) +└ br0 ethernet UP 00:53:00:06:11:01 +admin@example:/> +``` + +When pinging "IPv6 all hosts" from the PC, there should be two +responses for every ping, one from the switch and one from the PC +attached to e10. + +``` +~ $ ping -L ff02::1%eth1 +PING ff02::1%eth1(ff02::1%eth1) 56 data bytes +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.508 ms +64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=1 ttl=64 time=0.968 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.866 ms +64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=2 ttl=64 time=0.867 ms +64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=3 ttl=64 time=0.467 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.469 ms +64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.452 ms +64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=4 ttl=64 time=0.453 ms +^C +--- ff02::1%eth1 ping statistics --- +4 packets transmitted, 4 received, +4 duplicates, 0% packet loss, time 3031ms +rtt min/avg/max/mdev = 0.452/0.631/0.968/0.211 ms +~ $ +``` + +It should now be possible to access the switch from the PC via SSH (or NETCONF). + +``` +~ $ ssh admin@fe80::0053:00ff:fe06:1101%eth1 +admin@fe80::0053:00ff:fe06:1101%eth1's password: +.-------. +| . . | Infix OS — Immutable.Friendly.Secure +|-. v .-| https://kernelkit.org +'-'---'-' + +Run the command 'cli' for interactive OAM + +admin@example:~$ exit +~ $ +``` + +See previous sections on [backup][1] and [restore][2] of +the created configuration. + +[1]: scripting-sysrepocfg.md#backup-configuration +[2]: scripting-sysrepocfg.md#restore-configuration +[8]: networking.md#bridging +[9]: networking.md#vlan-filtering-bridge diff --git a/doc/scripting-restconf.md b/doc/scripting-restconf.md new file mode 100644 index 00000000..3a7c07e2 --- /dev/null +++ b/doc/scripting-restconf.md @@ -0,0 +1,82 @@ +# Examples using RESTCONF + +## Factory Reset + +``` +~$ curl -kX POST -u admin:admin \ + -H "Content-Type: application/yang-data+json" \ + https://example.local/restconf/operations/ietf-factory-default:factory-reset +curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 +``` + +## System Reboot + +``` +~$ curl -kX POST -u admin:admin \ + -H "Content-Type: application/yang-data+json" \ + https://example.local/restconf/operations/ietf-system:system-restart +``` + +## Set Date and Time + +Here's an example of an RPC that takes input/argument: + +``` +~$ curl -kX POST -u admin:admin \ + -H "Content-Type: application/yang-data+json" \ + -d '{"ietf-system:input": {"current-datetime": "2024-04-17T13:48:02-01:00"}}' \ + https://example.local/restconf/operations/ietf-system:set-current-datetime +``` + +You can verify that the changes took by a remote SSH command: + +``` +~$ ssh admin@example.local 'date' +Wed Apr 17 14:48:12 UTC 2024 +~$ +``` + +## Read Hostname + +Example of fetching JSON configuration data to stdout: + +``` +~$ curl -kX GET -u admin:admin \ + -H 'Accept: application/yang-data+json' \ + https://example.local/restconf/data/ietf-system:system/hostname +{ + "ietf-system:system": { + "hostname": "foo" + } +} +``` + +## Set Hostname + +Example of inline JSON data: + +``` +~$ curl -kX PATCH -u admin:admin \ + -H 'Content-Type: application/yang-data+json' \ + -d '{"ietf-system:system":{"hostname":"bar"}}' \ + https://example.local/restconf/data/ietf-system:system +``` + +## Copy Running to Startup + +No copy command available yet to copy between datastores, and the +Rousette back-end also does not support "write-through" to the +startup datastore. + +To save running-config to startup-config, use the following example to +fetch running to a local file and then update startup with it: + +``` +~$ curl -kX GET -u admin:admin -o running-config.json \ + -H 'Accept: application/yang-data+json' \ + https://example.local/restconf/ds/ietf-datastores:running + +~$ curl -kX PUT -u admin:admin -d @running-config.json \ + -H 'Content-Type: application/yang-data+json' \ + https://example.local/restconf/ds/ietf-datastores:startup +``` diff --git a/doc/scripting-sysrepocfg.md b/doc/scripting-sysrepocfg.md new file mode 100644 index 00000000..46e48c85 --- /dev/null +++ b/doc/scripting-sysrepocfg.md @@ -0,0 +1,462 @@ +# Examples using SSH and sysrepocfg + +[sysrepocfg][4] can be used to interact with the YANG models when logged +in to infix. Thus, *set config*, *read config*, *read status* and *RPC* +can be conducted using sysrepocfg for supported YANG models. It is +possible to make configuration changes by operating on the *startup* +database. + +See [sysrepocfg][4] for information. Examples below will utilize + +- `sysrepocfg -I FILE -fjson -d DATABASE` to import/write a JSON + formatted configuration file to the specified database. +- `sysrepocfg -E FILE -fjson -d DATABASE` to edit/merge JSON formatted + configuration in FILE with the specified database. +- `sysrepocfg -R FILE -fjson` to execute remote procedure call (RPC) + defined in FILE (JSON formatted). +- `sysrepocfg -X -fjson -d DATABASE -x xpath` to read configuration or + status from specified database. + +For importing (-I) and editing (-E), `-d running` is typically used in +examples below. Specify `-d startup` to apply changes to startup +configuration. Exporting (-X) could operate on configuration (e.g., +`-d running`) or status (`-d operational`). + +Some commands require a file as input. In the examples below we assume +it has been transferred to the device in advance, e.g. using `scp`: + +``` +~$ cat file.json +{ + "ietf-factory-default:factory-reset": { + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ +``` + +## Factory Reset + +``` +~$ cat file.json +{ + "ietf-factory-default:factory-reset": { + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json' +^C +~$ +``` + +See [Factory Reset](scripting.md#factory-reset) for another (simpler) +alternative. + +If it is only wished to copy factory config to running config the +following RPC is available + +``` +~$ cat file.json +{ + "infix-factory-default:factory-default": { + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json' +^C +~$ +``` + +## System Reboot + +``` +~$ cat /tmp/file.json +{ + "ietf-system:system-restart": { + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json' +~$ +``` + +See [System Reboot](scripting.md#system-reboot) for another (simpler) +alternative. + +## Set Date and Time + +``` +~$ ssh admin@example.local 'date' +Sun Nov 20 10:20:23 UTC 2005 +~$ cat file.json +{ + "ietf-system:set-current-datetime": { + "current-datetime": "2024-04-17T13:48:02-01:00" + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json' +~$ ssh admin@example.local 'date' +Wed Apr 17 14:48:12 UTC 2024 +~$ +``` + +See [Set Date and Time](scripting.md#set-date-and-time) for another +(simpler) alternative. + +## Remote Control of Ethernet Ports + +Reading administrative status of interface *e0* of running configuration. + +``` +~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running -e report-all \ + -x \"/ietf-interfaces:interfaces/interface[name='e0']/enabled\"' +{ + "ietf-interfaces:interfaces": { + "interface": [ + { + "name": "e0", + "enabled": true + } + ] + } +} +~$ +``` + +> [!NOTE] +> Without `-e report-all` argument the line `"enabled: true` would not +> be shown as `true` is default. + +``` +~$ ssh admin@example.local "sysrepocfg -X -fjson -d running \ + -x \"/ietf-interfaces:interfaces/interface[name='e0']/enabled\"" +{ + "ietf-interfaces:interfaces": { + "interface": [ + { + "name": "e0" + } + ] + } +} +~$ +``` + +Setting the administrative status of interface *e0* of running configuration. + +``` +$ cat file.json +{ + "ietf-interfaces:interfaces": { + "interface": [ + { + "name": "e0", + "enabled": false + } + ] + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running' +~$ +``` + +## Enable/Disable DHCPv4 client + +Enabling DHCPv4 client on interface *e0*, with current default options. + +``` +~$ cat /tmp/file.json +{ + "infix-dhcp-client:dhcp-client": { + "enabled": true, + "client-if": [ + { + "if-name": "e0" + } + ] + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running' +~$ +``` + +Disabling DHCPv4 client. + +``` +~$ cat /tmp/file.json +{ + "infix-dhcp-client:dhcp-client": { + "enabled": false + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running' +~$ +``` + +Configuration for client interface *e0* remains, but does not apply as +DHCPv4 is disabled. + +``` +admin@example:~$ sysrepocfg -X -fjson -d running -x "/infix-dhcp-client:dhcp-client" +{ + "infix-dhcp-client:dhcp-client": { + "enabled": false, + "client-if": [ + { + "if-name": "e0" + } + ] + } +} +admin@example:~$ +``` + +To fully remove the DHCPv4 client configuration or a specific +*client-if* with sysrepocfg, one would need to read out the full +configuration, remove relevant parts and read back. + +## Enable/Disable IPv6 + +IPv6 is typically enabled on all interfaces by default. The example +below shows IPv4 and IPv6 addresses assigned on *e0*. + +``` +~$ ssh admin@example.local 'ip addr show dev e0' +2: e0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + link/ether 02:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff + inet 10.0.2.15/24 scope global proto dhcp e0 + valid_lft forever preferred_lft forever + inet6 fec0::ff:fe00:0/64 scope site dynamic mngtmpaddr proto kernel_ra + valid_lft 86380sec preferred_lft 14380sec + inet6 fe80::ff:fe00:0/64 scope link proto kernel_ll + valid_lft forever preferred_lft forever +~$ +``` + +IPv6 is enabled/disabled per interface. The example below disables IPv6 +on interface *e0*. + +``` +~$ cat /tmp/file.json +{ + "ietf-interfaces:interfaces": { + "interface": [ + { + "name": "e0", + "ietf-ip:ipv6": { + "enabled": false + } + } + ] + } +} +~$ scp file.json admin@example.local:/tmp/file.json +~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running' +~$ ssh admin@example.local 'ip addr show dev e0' +2: e0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + link/ether 02:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff + inet 10.0.2.15/24 scope global proto dhcp e0 + valid_lft forever preferred_lft forever +~$ +``` + +## Change a Binary Setting + +A YANG `binary` type setting is Base64 encoded and requires a little bit +more tricks. We take the opportunity to showcase a shell script helper: +`/usr/bin/text-editor`, which works just like the `text-editor` command +in the CLI, but this one takes an XPath argument to the binary leaf to +edit. + +Stripped down, it looks something like this: + +```bash +if tmp=$(sysrepocfg -G "$xpath"); then + file=$(mktemp) + + echo "$tmp" | base64 -d > "$file" + if edit "$file"; then + tmp=$(base64 -w0 < "$file") + sysrepocfg -S "$xpath" -u "$tmp" + fi + + rm -f "$file" +else + echo "Failed to retrieve value for $xpath" + exit 1 +fi +``` + +An example container configuration, with an embedded file that is +mounted to `/var/www/index.html` can look like this: + +```json + "infix-containers:containers": { + "container": [ + { + "name": "web", + "image": "oci-archive:/lib/oci/curios-httpd-latest.tar.gz", + "hostname": "web", + "network": { + "interface": [ + { + "name": "veth-sys0" + } + ] + }, + "mount": [ + { + "name": "index.html", + "content": "PCFET0NUWVBFIGh0bWwjibberish.shortened.down==", + "target": "/var/www/index.html" + } + ] + } + ] + } +``` + +The command to edit this file, and restart the container with the new +contents, look like this: + +``` +admin@infix:~$ cfg edit "/infix-containers:containers/container[name='web']/mount[name='index.html']/content" +``` + +## Backup Configuration + +Displaying running or startup configuration is possible with +`sysrepocfg -X`, as shown below. + +``` +~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running' +{ + "ieee802-dot1ab-lldp:lldp": { + "infix-lldp:enabled": true +... +~$ +``` + +An example for backing up startup configuration from remote PC. + +``` +~$ ssh admin@example.local 'sysrepocfg -X -fjson -d startup > /tmp/backup.json' +~$ scp admin@example.local:/tmp/backup.json . +~$ +``` + +Or possibly skip intermediate storage of file + +``` +~$ ssh admin@example.local 'sysrepocfg -X -fjson -d startup' > backup.json +~$ +``` + +A final example is to only use `scp`. This is simpler, but only works to +backup the startup configuration (not running). + +``` +~$ scp admin@example.local:/cfg/startup-config.cfg backup.json +~$ +``` + +## Restore Configuration + +To restore a backup configuration to startup, the simplest way is to use +`scp` and reboot as shown below + +``` +~$ scp admin@example.local:/cfg/startup-config.cfg backup.json +~$ ssh admin@example.local 'reboot' +Connection to switch.local closed by remote host. +~$ +``` + +An alternative method to restore a backup configuration is to use the +`sysrepocfg -I FILE` (import) command. + +The example below imports the backup configuration to startup, and +reboots the unit. + +``` +~$ scp backup.json admin@example.local:/tmp/ +~$ ssh admin@example.local 'sudo sysrepocfg -I /tmp/backup.json -fjson -d startup' +~$ ssh admin@example.local 'reboot' +Connection to switch.local closed by remote host. +~$ +``` + +> [!NOTE] +> The login credentials (hash) for the `admin` user are stored as part +> of the configuration file. When replacing a switch and applying the +> backed up configuration from the former switch, the password on the +> replacement unit will also change. + +## Copy Running to Startup + +The following command reads out the running config via `sysrepocfg -X` +and writes the result to the startup configuration. + +``` +~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running > /cfg/startup-config.cfg' +~$ +``` + +An alternative is to write it to a temporary file, and use `sysrepocfg +-I` to import it to startup. + +``` +~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running > /tmp/running.json' +~$ ssh admin@example.local 'sysrepocfg -I /tmp/running.json -fjson -d startup' +~$ +``` + +## Read Hardware Information + +The IETF Hardware YANG model has been augmented for ONIE formatted +production data stored in EEPROMs, if available. For details, see the +[VPD documentation][5] and the *ietf-hardware* and *infix-hardware* +YANG models. + +``` +~$ ssh admin@example.local 'sysrepocfg -X -fjson -d operational -x /ietf-hardware:hardware' +{ + "ietf-hardware:hardware": { + "component": [ + { + "name": "product", + "class": "infix-hardware:vpd", + "serial-num": "12345", + "model-name": "Switch2010", + "mfg-date": "2024-01-30T16:42:37+00:00", + "infix-hardware:vpd-data": { + "product-name": "Switch2010", + "part-number": "ABC123-001", + "serial-number": "007", + "mac-address": "00:53:00:01:23:45", + "manufacture-date": "01/30/2024 16:42:37", + "num-macs": 11, + "manufacturer": "ACME Production", + "vendor": "SanFran Networks" + } + }, + { + "name": "USB", + "class": "infix-hardware:usb", + "state": { + "admin-state": "unlocked", + "oper-state": "enabled" + } + } + ] + } +} +~$ +``` + +[4]: https://netopeer.liberouter.org/doc/sysrepo/libyang1/html/sysrepocfg.html +[5]: vpd.md diff --git a/doc/scripting.md b/doc/scripting.md index a491a64f..2c93a053 100644 --- a/doc/scripting.md +++ b/doc/scripting.md @@ -13,17 +13,17 @@ to a remote device over SSH, use Linux/UNIX. With advances lately in both Windows and macOS, many of the user friendly tools previously only available in Linux are now available there too. -- The shell prompt for the PC laptop side: +The shell prompt for the PC laptop side: - ``` - ~$ - ``` +``` +~$ +``` -- The shell prompt when logged in to an Infix device: +The shell prompt when logged in to an Infix device: - ``` - admin@example:~$ - ``` +``` +admin@example:~$ +``` > [!NOTE] > The shell script commands used here are the raw variants which the CLI @@ -76,11 +76,7 @@ case of IPv6: `address%interface`, where interface differs between operating systems. On Linux and macOS the interface name is used, but on Windows the interface index[^1] is used. -[^1]: Press Win-r to bring up the Run dialog, enter `cmd.exe` and press - enter. Then type in `ipconfig /all` to list all interfaces, their - status, as well as interface index. - -**Logging in to a device** +### Logging in to a device ``` ~$ ssh admin@fe80::ff:fe00:0%eth0 @@ -96,9 +92,11 @@ admin@fe80::ff:fe00:0%eth0's password: ***** '-'---'-' Run the command 'cli' for interactive OAM + +admin@infix-c0-ff-ee:/> ``` -**Executing a command on a device** +### Running a remote command ``` ~$ ssh admin@fe80::ff:fe00:0%eth0 echo hej @@ -106,7 +104,7 @@ admin@fe80::ff:fe00:0%eth0's password: ***** hej ``` -**Made Easy** +### Made Easy with mDNS Connecting to networked devices using IP addresses is the way many people are used to. The above example with IPv6 tend to scare off @@ -115,10 +113,13 @@ instead: ``` ~$ ssh admin@infix.local%eth0 -The authenticity of host 'infix.local%eth0 (infix.local%eth0)' can't be established. +The authenticity of host 'infix.local%eth0' can't be established. +Are you sure you want to continue connecting (yes/no/[fingerprint])? yes +... +admin@infix:/> ``` -### Factory Reset +## Factory Reset The command option `-y` disables any "are you sure?" interaction and immediately triggers a factory reset and reboot of the device. It is @@ -129,14 +130,14 @@ when the device boots up it erases all writable storage. admin@infix.local%eth0's password: ***** ``` -### System Reboot +## System Reboot ``` ~$ ssh admin@infix.local%eth0 reboot admin@infix.local%eth0's password: ***** ``` -### Set Date and Time +## Set Date and Time Devices running Infix may have their system time completely off and this can cause problems for upgrading and when accessing the web interface @@ -146,7 +147,8 @@ To set the device's system time, *and* sync that with the RTC: use the PCs current time as argument: ``` -~$ ssh admin@infix.local%eth0 "sudo date -s '2024-03-20 18:14+01:00' && sudo hwclock -w -u" +~$ ssh admin@infix.local%eth0 "sudo date -s '2024-03-20 18:14+01:00' && \ + sudo hwclock -w -u" admin@infix.local%eth0's password: ***** ``` @@ -161,7 +163,7 @@ admin@infix.local%eth0's password: ***** Wed Mar 20 17:14:47 UTC 2024 ``` -### Remote Control of Ethernet Ports +## Remote Control of Ethernet Ports There are two ways to do it: @@ -226,11 +228,13 @@ e9 UP 192.168.2.200/24 fe80::ff:fe00:9/64 br0 UP ``` -### Check Device's Network Connectivity +## Check Network Connectivity -Say you want to perform a [System Upgrade][#system-uprgade] and it just -doesn't work, then you might want to ensure the device actually can -reach the upgrade server. +Say you want to perform a [System Upgrade][#system-upgrade] and it just +does not work, a good place to start troubleshooting is ensuring the +device can actually reach the upgrade server. + +We run the following `ping` command remotely on the device: ``` ~$ ssh admin@infix.local%eth0 ping -c 3 server.local @@ -248,7 +252,7 @@ rtt min/avg/max/mdev = 0.201/0.353/0.432/0.107 ms Here we get a reply, so whatever is the issue with the upgrade was not hiding behind a connectivity issue at least. -### System Upgrade +## System Upgrade The underlying software that handles upgrades is called [RAUC][2]. To trigger an upgrade you (currently) need an FTP/TFTP or HTTP/HTTPS server @@ -296,7 +300,8 @@ the device instead of having to set up an FTP/TFTP or HTTP/HTTPS server. Create an upload directory where `admin` has write permission: ``` -~$ ssh admin@infix.local%eth0 "sudo mkdir /var/tmp/upload; sudo chown admin /var/tmp/upload" +~$ ssh admin@infix.local%eth0 "sudo mkdir /var/tmp/upload; \ + sudo chown admin /var/tmp/upload" admin@infix.local%eth0's password: ``` @@ -331,7 +336,7 @@ admin@infix.local%eth0's password: ***** ~$ ``` -### Controlling LEDs for Production Tests +## Controlling LEDs As part of production testing, LED verification is often expected to be performed. Infix uses standard [Linux support for LED management][6], @@ -366,7 +371,7 @@ When done with LED testing, enable Infix *iitod* daemon again. ~$ ssh admin@example.local 'initctl start iitod' ``` -### Reading Power Feed Status for Production Tests +## Reading Power Feed Status As part of production tests, verification of Power Feed sensors is often expected to be performed. Infix uses standard [Linux support for @@ -382,896 +387,14 @@ two power supplies named *pwr1* and *pwr2*. ~$ ``` -Here, only *pwr1* happened to have power. +Here, only `pwr1` have power. -## Examples using SSH and sysrepocfg - -[sysrepocfg][4] can be used to interact with the YANG models when logged -in to infix. Thus, *set config*, *read config*, *read status* and *RPC* -can be conducted using sysrepocfg for supported YANG models. It is -possible to make configuration changes by operating on the *startup* -database. - -See [sysrepocfg][4] for information. Examples below will utilize - -- `sysrepocfg -I FILE -fjson -d DATABASE` to import/write a JSON - formatted configuration file to the specified database. -- `sysrepocfg -E FILE -fjson -d DATABASE` to edit/merge JSON formatted - configuration in FILE with the specified database. -- `sysrepocfg -R FILE -fjson` to execute remote procedure call (RPC) - defined in FILE (JSON formatted). -- `sysrepocfg -X -fjson -d DATABASE -x xpath` to read configuration or - status from specified database. - -For importing (-I) and editing (-E), `-d running` is typically used in -examples below. Specify `-d startup` to apply changes to startup -configuration. Exporting (-X) could operate on configuration (e.g., -`-d running`) or status (`-d operational`). - -Some commands require a file as input. In examples below we assume -it been transferred to Infix in advance, e.g. using `scp` as shown below. - -``` -~$ cat file.json -{ - "ietf-factory-default:factory-reset": { - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ -``` - -### Factory Reset Using sysrepocfg - -``` -~$ cat file.json -{ - "ietf-factory-default:factory-reset": { - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json' -^C -~$ -``` - -See [Factory Reset](#factory-reset) for another (simpler) alternative. - -If it is only wished to copy factory config to running config the -following RPC is available - -``` -~$ cat file.json -{ - "infix-factory-default:factory-default": { - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json' -^C -~$ -``` - -### System Reboot Using sysrepocfg - -``` -~$ cat /tmp/file.json -{ - "ietf-system:system-restart": { - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json' -~$ -``` - -See [System Reboot](#system-reboot) for another (simpler) alternative. - -### Set Date and Time Using sysrepocfg - -``` -~$ ssh admin@example.local 'date' -Sun Nov 20 10:20:23 UTC 2005 -~$ cat file.json -{ - "ietf-system:set-current-datetime": { - "current-datetime": "2024-04-17T13:48:02-01:00" - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ ssh admin@example.local 'sysrepocfg -fjson -R /tmp/file.json' -~$ ssh admin@example.local 'date' -Wed Apr 17 14:48:12 UTC 2024 -~$ -``` - -See [Set Date and Time](#set-date-and-time) for another (simpler) -alternative. - -### Remote Control of Ethernet Ports Using sysrepocfg - -Reading administrative status of interface *e0* of running configuration. - -``` -~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running -e report-all \ - -x \"/ietf-interfaces:interfaces/interface[name='e0']/enabled\"' -{ - "ietf-interfaces:interfaces": { - "interface": [ - { - "name": "e0", - "enabled": true - } - ] - } -} -~$ -``` - -> [!NOTE] -> Without `-e report-all` argument the line `"enabled: true` would not -> be shown as `true` is default. - -``` -~$ ssh admin@example.local "sysrepocfg -X -fjson -d running \ - -x \"/ietf-interfaces:interfaces/interface[name='e0']/enabled\"" -{ - "ietf-interfaces:interfaces": { - "interface": [ - { - "name": "e0" - } - ] - } -} -~$ -``` - -Setting the administrative status of interface *e0* of running configuration. - -``` -$ cat file.json -{ - "ietf-interfaces:interfaces": { - "interface": [ - { - "name": "e0", - "enabled": false - } - ] - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running' -~$ -``` - -### Enable/Disable DHCPv4 client - -Enabling DHCPv4 client on interface *e0*, with current default options. - -``` -~$ cat /tmp/file.json -{ - "infix-dhcp-client:dhcp-client": { - "enabled": true, - "client-if": [ - { - "if-name": "e0" - } - ] - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running' -~$ -``` - -Disabling DHCPv4 client. - -``` -~$ cat /tmp/file.json -{ - "infix-dhcp-client:dhcp-client": { - "enabled": false - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running' -~$ -``` - -Configuration for client interface *e0* remains, but does not apply as -DHCPv4 is disabled. - -``` -admin@example:~$ sysrepocfg -X -fjson -d running -x "/infix-dhcp-client:dhcp-client" -{ - "infix-dhcp-client:dhcp-client": { - "enabled": false, - "client-if": [ - { - "if-name": "e0" - } - ] - } -} -admin@example:~$ -``` - -To fully remove the DHCPv4 client configuration or a specific -*client-if* with sysrepocfg, one would need to read out the full -configuration, remove relevant parts and read back. - -### Enable/Disable IPv6 - -IPv6 is typically enabled on all interfaces by default. The example -below shows IPv4 and IPv6 addresses assigned on *e0*. - -``` -~$ ssh admin@example.local 'ip addr show dev e0' -2: e0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 - link/ether 02:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff - inet 10.0.2.15/24 scope global proto dhcp e0 - valid_lft forever preferred_lft forever - inet6 fec0::ff:fe00:0/64 scope site dynamic mngtmpaddr proto kernel_ra - valid_lft 86380sec preferred_lft 14380sec - inet6 fe80::ff:fe00:0/64 scope link proto kernel_ll - valid_lft forever preferred_lft forever -~$ -``` - -IPv6 is enabled/disabled per interface. The example below disables IPv6 -on interface *e0*. - -``` -~$ cat /tmp/file.json -{ - "ietf-interfaces:interfaces": { - "interface": [ - { - "name": "e0", - "ietf-ip:ipv6": { - "enabled": false - } - } - ] - } -} -~$ scp file.json admin@example.local:/tmp/file.json -~$ ssh admin@example.local 'sysrepocfg -E /tmp/file.json -fjson -d running' -~$ ssh admin@example.local 'ip addr show dev e0' -2: e0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 - link/ether 02:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff - inet 10.0.2.15/24 scope global proto dhcp e0 - valid_lft forever preferred_lft forever -~$ -``` - -### Change a Binary Setting - -A YANG `binary` type setting is Base64 encoded and requires a little bit -more tricks. We take the opportunity to showcase a shell script helper: -`/usr/bin/text-editor`, which works just like the `text-editor` command -in the CLI, but this one takes an XPath argument to the binary leaf to -edit. - -Stripped down, it looks something like this: - -```bash -if tmp=$(sysrepocfg -G "$xpath"); then - file=$(mktemp) - - echo "$tmp" | base64 -d > "$file" - if edit "$file"; then - tmp=$(base64 -w0 < "$file") - sysrepocfg -S "$xpath" -u "$tmp" - fi - - rm -f "$file" -else - echo "Failed to retrieve value for $xpath" - exit 1 -fi -``` - -An example container configuration, with an embedded file that is -mounted to `/var/www/index.html` can look like this: - -```json - "infix-containers:containers": { - "container": [ - { - "name": "web", - "image": "oci-archive:/lib/oci/curios-httpd-latest.tar.gz", - "hostname": "web", - "network": { - "interface": [ - { - "name": "veth-sys0" - } - ] - }, - "mount": [ - { - "name": "index.html", - "content": "PCFET0NUWVBFIGh0bWwjibberish.shortened.down==", - "target": "/var/www/index.html" - } - ] - } - ] - } -``` - -The command to edit this file, and restart the container with the new -contents, look like this: - -``` -admin@infix:~$ cfg edit "/infix-containers:containers/container[name='web']/mount[name='index.html']/content" -``` - -### Backup Configuration Using sysrepocfg And scp - -Displaying running or startup configuration is possible with -`sysrepocfg -X`, as shown below. - -``` -~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running' -{ - "ieee802-dot1ab-lldp:lldp": { - "infix-lldp:enabled": true -... -~$ -``` - -An example for backing up startup configuration from remote PC. - -``` -~$ ssh admin@example.local 'sysrepocfg -X -fjson -d startup > /tmp/backup.json' -~$ scp admin@example.local:/tmp/backup.json . -~$ -``` - -Or possibly skip intermediate storage of file - -``` -~$ ssh admin@example.local 'sysrepocfg -X -fjson -d startup' > backup.json -~$ -``` - -A final example is to only use `scp`. This is simpler, but only works to -backup the startup configuration (not running). - -``` -~$ scp admin@example.local:/cfg/startup-config.cfg backup.json -~$ -``` - -### Restore Configuration Using sysrepocfg and ssh/scp - -To restore a backup configuration to startup, the simplest way is to use -`scp` and reboot as shown below - -``` -~$ scp admin@example.local:/cfg/startup-config.cfg backup.json -~$ ssh admin@example.local 'reboot' -Connection to switch.local closed by remote host. -~$ -``` - -An alternative method to restore a backup configuration is to use the -`sysrepocfg -I FILE` (import) command. - -The example below imports the backup configuration to startup, and -reboots the unit. - -``` -~$ scp backup.json admin@example.local:/tmp/ -~$ ssh admin@example.local 'sudo sysrepocfg -I /tmp/backup.json -fjson -d startup' -~$ ssh admin@example.local 'reboot' -Connection to switch.local closed by remote host. -~$ -``` - -> [!NOTE] -> The login credentials (hash) for the `admin` user are stored as part -> of the configuration file. When replacing a switch and applying the -> backed up configuration from the former switch, the password on the -> replacement unit will also change. - -### Copy Running to Startup Using sysrepocfg - -The following command reads out the running config via `sysrepocfg -X` -and writes the result to the startup configuration. - -``` -~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running > /cfg/startup-config.cfg' -~$ -``` - -An alternative is to write it to a temporary file, and use `sysrepocfg --I` to import it to startup. - -``` -~$ ssh admin@example.local 'sysrepocfg -X -fjson -d running > /tmp/running.json' -~$ ssh admin@example.local 'sysrepocfg -I /tmp/running.json -fjson -d startup' -~$ -``` - -### Read Out Hardware Information Using sysrepocfg - -Infix supports IETF Hardware YANG with augments for ONIE formatted -production data stored in EEPROMs, if available. See Infix [VPD -documentation][5], as well as *ietf-hardware* and *infix-hardware* YANG -models for details. - -``` -~$ ssh admin@example.local 'sysrepocfg -X -fjson -d operational -x /ietf-hardware:hardware' -{ - "ietf-hardware:hardware": { - "component": [ - { - "name": "product", - "class": "infix-hardware:vpd", - "serial-num": "12345", - "model-name": "Switch2010", - "mfg-date": "2024-01-30T16:42:37+00:00", - "infix-hardware:vpd-data": { - "product-name": "Switch2010", - "part-number": "ABC123-001", - "serial-number": "007", - "mac-address": "00:53:00:01:23:45", - "manufacture-date": "01/30/2024 16:42:37", - "num-macs": 11, - "manufacturer": "ACME Production", - "vendor": "SanFran Networks" - } - }, - { - "name": "USB", - "class": "infix-hardware:usb", - "state": { - "admin-state": "unlocked", - "oper-state": "enabled" - } - } - ] - } -} -~$ -``` - -## Examples using RESTCONF - -### Factory Reset - -``` -~$ curl -kX POST -u admin:admin \ - -H "Content-Type: application/yang-data+json" \ - https://example.local/restconf/operations/ietf-factory-default:factory-reset -curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 -``` - -### System Reboot - -``` -~$ curl -kX POST -u admin:admin \ - -H "Content-Type: application/yang-data+json" \ - https://example.local/restconf/operations/ietf-system:system-restart -``` - -### Set Date and Time - -Here's an example of an RPC that takes input/argument: - -``` -~$ curl -kX POST -u admin:admin \ - -H "Content-Type: application/yang-data+json" \ - -d '{"ietf-system:input": {"current-datetime": "2024-04-17T13:48:02-01:00"}}' \ - https://example.local/restconf/operations/ietf-system:set-current-datetime -``` - -You can verify that the changes took by a remote SSH command: - -``` -~$ ssh admin@example.local 'date' -Wed Apr 17 14:48:12 UTC 2024 -~$ -``` - -### Read Hostname - -Example of fetching JSON configuration data to stdout: - -``` -~$ curl -kX GET -u admin:admin \ - -H 'Accept: application/yang-data+json' \ - https://example.local/restconf/data/ietf-system:system/hostname -{ - "ietf-system:system": { - "hostname": "foo" - } -} -``` - -### Set Hostname - -Example of inline JSON data: - -``` -~$ curl -kX PATCH -u admin:admin \ - -H 'Content-Type: application/yang-data+json' \ - -d '{"ietf-system:system":{"hostname":"bar"}}' \ - https://example.local/restconf/data/ietf-system:system -``` - -### Copy Running to Startup - -No copy command available yet to copy between datastores, and the -Rousette back-end also does not support "write-through" to the -startup datastore. - -To save running-config to startup-config, use the following example to -fetch running to a local file and then update startup with it: - -``` -~$ curl -kX GET -u admin:admin -o running-config.json \ - -H 'Accept: application/yang-data+json' \ - https://example.local/restconf/ds/ietf-datastores:running - -~$ curl -kX PUT -u admin:admin -d @running-config.json \ - -H 'Content-Type: application/yang-data+json' \ - https://example.local/restconf/ds/ietf-datastores:startup -``` - -## Miscellaneous - -### Port Configuration Example for Production Tests - -As part of production tests, verification Ethernet ports are expected to -be performed. A common way is to connect a test PC to two ports and send -a *ping* traversing all ports. This can be achieved by using VLANs on -the switch as described in this section. The resulting configuration -file can be applied to the running configuration of the produced unit, -e.g, use config file restore as described [above](#restore). - -In this example we assume a 10 port switch, with ports e1-e10. - -The following VLAN configuration and cable connections will be used: - -| VLAN & Ports | Connect | -|:------------------|:----------| -| VLAN 10: e1 & e2 | e2 <=> e3 | -| VLAN 20: e3 & e4 | e4 <=> e5 | -| VLAN 30: e5 & e6 | e6 <=> e7 | -| VLAN 40: e7 & e8 | e8 <=> e9 | -| VLAN 50: e9 & e10 | | - -The test PC is connected to e1 and e10 via different interfaces -(alternatively, two different PCs are used). - -> [!TIP] -> Configuration here is done via console. When configuring remotely -> over SSH, remember to keep one IP address (the one used for the SSH -> connection)! I.e., set a static IP address first, then perform the -> VLAN configuration step. - -#### Configuration at Start - -Starting out, we assume a configuration where all ports are network -interfaces (possibly with IPv6 enabled). - -``` -admin@example:/> show interfaces -lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) -e1 ethernet LOWER-DOWN 00:53:00:06:11:01 -e2 ethernet LOWER-DOWN 00:53:00:06:11:02 -e3 ethernet LOWER-DOWN 00:53:00:06:11:03 -e4 ethernet LOWER-DOWN 00:53:00:06:11:04 -e5 ethernet LOWER-DOWN 00:53:00:06:11:05 -e6 ethernet LOWER-DOWN 00:53:00:06:11:06 -e7 ethernet LOWER-DOWN 00:53:00:06:11:07 -e8 ethernet LOWER-DOWN 00:53:00:06:11:08 -e9 ethernet LOWER-DOWN 00:53:00:06:11:09 -e10 ethernet UP 00:53:00:06:11:0a - ipv6 fe80::0053:00ff:fe06:110a/64 (link-layer) -admin@example:/> -``` - -#### Creating Bridge and Adding Ports - -The example below uses Infix documentation on [creating bridges][8]. - -``` -admin@example:/> configure -admin@example:/config/> edit interface br0 -admin@example:/config/interface/br0/> end -admin@example:/config/> set interface e1 bridge-port bridge br0 -admin@example:/config/> set interface e2 bridge-port bridge br0 -admin@example:/config/> set interface e3 bridge-port bridge br0 -admin@example:/config/> set interface e4 bridge-port bridge br0 -admin@example:/config/> set interface e5 bridge-port bridge br0 -admin@example:/config/> set interface e6 bridge-port bridge br0 -admin@example:/config/> set interface e7 bridge-port bridge br0 -admin@example:/config/> set interface e8 bridge-port bridge br0 -admin@example:/config/> set interface e9 bridge-port bridge br0 -admin@example:/config/> set interface e10 bridge-port bridge br0 -admin@example:/config/> -``` - -The interface status can be viewed using "show interface" after -leaving configuration context. If configuration via SSH, first assign -an IP address to br0 before *leaving* configuration context, e.g., -`set interface br0 ipv6 enabled` to get auto-configured IPv6 -address. Or skip 'leave' and stay in configuration context until done -with all sections, including the one on [Add IP on -Switch](#ip-on-switch). - -``` -admin@example:/config/> leave -admin@example:/> -admin@example:/> show interfaces -INTERFACE PROTOCOL STATE DATA -br0 bridge -│ ethernet UP 00:53:00:06:11:01 -├ e1 bridge LOWER-DOWN -├ e2 bridge LOWER-DOWN -├ e3 bridge LOWER-DOWN -├ e4 bridge LOWER-DOWN -├ e5 bridge LOWER-DOWN -├ e6 bridge LOWER-DOWN -├ e7 bridge LOWER-DOWN -├ e8 bridge LOWER-DOWN -├ e9 bridge LOWER-DOWN -└ e10 bridge FORWARDING -lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) -admin@example:/> -``` - -#### Assign VLANs to Ports - -Then configure VLANs as outlined [above](#port-test-intro): default VID -for ingress (PVID), which is done per port, and egress mode (untagged), -which is done at the bridge level. See Infix [documentation for VLAN -bridges][9] for more information. - -``` -admin@example:/> -admin@example:/> configure -admin@example:/config/> set interface e1 bridge-port pvid 10 -admin@example:/config/> set interface e2 bridge-port pvid 10 -admin@example:/config/> set interface e3 bridge-port pvid 20 -admin@example:/config/> set interface e4 bridge-port pvid 20 -admin@example:/config/> set interface e5 bridge-port pvid 30 -admin@example:/config/> set interface e6 bridge-port pvid 30 -admin@example:/config/> set interface e7 bridge-port pvid 40 -admin@example:/config/> set interface e8 bridge-port pvid 40 -admin@example:/config/> set interface e9 bridge-port pvid 50 -admin@example:/config/> set interface e10 bridge-port pvid 50 -admin@example:/config/> edit interface br0 -admin@example:/config/interface/br0/> edit bridge vlans -admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 untagged e1 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 untagged e2 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 20 untagged e3 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 20 untagged e4 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 30 untagged e5 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 30 untagged e6 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 40 untagged e7 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 40 untagged e8 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 50 untagged e9 -admin@example:/config/interface/br0/bridge/vlans/> set vlan 50 untagged e10 -admin@example:/config/interface/br0/bridge/vlans/> leave -admin@example:/> -``` - -Interface status would now should something like the following - -``` -admin@example:/> show interfaces -INTERFACE PROTOCOL STATE DATA -br0 bridge -│ ethernet UP 00:53:00:06:11:01 -├ e1 bridge LOWER-DOWN vlan:10u pvid:10 -├ e2 bridge LOWER-DOWN vlan:10u pvid:10 -├ e3 bridge LOWER-DOWN vlan:20u pvid:20 -├ e4 bridge LOWER-DOWN vlan:20u pvid:20 -├ e5 bridge LOWER-DOWN vlan:30u pvid:30 -├ e6 bridge LOWER-DOWN vlan:30u pvid:30 -├ e7 bridge LOWER-DOWN vlan:40u pvid:40 -├ e8 bridge LOWER-DOWN vlan:40u pvid:40 -├ e9 bridge LOWER-DOWN vlan:50u pvid:50 -└ e10 bridge FORWARDING vlan:50u pvid:50 -lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) -admin@example:/> -``` - -#### Connect Cables and Test - -We can now connect the PC to e1 and e10, and the other ports are -patched according to plan [above](#port-test-intro). We should get -link up on all ports. - -``` -admin@example:/> show interfaces -INTERFACE PROTOCOL STATE DATA -br0 bridge -│ ethernet UP 00:53:00:06:11:01 -├ e1 bridge FORWARDING vlan:10u pvid:10 -├ e2 bridge FORWARDING vlan:10u pvid:10 -├ e3 bridge FORWARDING vlan:20u pvid:20 -├ e4 bridge FORWARDING vlan:20u pvid:20 -├ e5 bridge FORWARDING vlan:30u pvid:30 -├ e6 bridge FORWARDING vlan:30u pvid:30 -├ e7 bridge FORWARDING vlan:40u pvid:40 -├ e8 bridge FORWARDING vlan:40u pvid:40 -├ e9 bridge FORWARDING vlan:50u pvid:50 -└ e10 bridge FORWARDING vlan:50u pvid:50 -lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) -admin@example:/> -``` - -Here we use IPv6 ping all hosts (ff02::1) on PC interface eth1 to -check reachability to the other interface of the PC. - -> [!TIP] -> We recommend using network namespaces (Linux only) on the PC to ensure -> that traffic is actually sent out to the switch, rather than being -> looped back internally. Alternatively, use two separate PCs. - -``` -~ $ ping -L ff02::1%eth1 -PING ff02::1%eth1(ff02::1%eth1) 56 data bytes -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.496 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.514 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.473 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.736 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=5 ttl=64 time=0.563 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=6 ttl=64 time=0.507 ms -^C ---- ff02::1%eth1 ping statistics --- -6 packets transmitted, 6 received, 0% packet loss, time 5108ms -rtt min/avg/max/mdev = 0.473/0.548/0.736/0.088 ms -~ $ -``` - -We can verify that traffic goes through the switch by disconnecting -one of the patch cables, e.g., between e4 and e5 - -``` -~ $ ping -L ff02::1%eth1 -PING ff02::1%eth1(ff02::1%eth1) 56 data bytes -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.510 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.448 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.583 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.515 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=5 ttl=64 time=0.521 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=6 ttl=64 time=0.495 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=7 ttl=64 time=0.743 ms -... Disconnecting patch cable, thus losing packets -... and reconnecting again. Connectivity resumes. -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=16 ttl=64 time=0.961 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=17 ttl=64 time=0.513 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=18 ttl=64 time=0.794 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=19 ttl=64 time=0.755 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=20 ttl=64 time=0.779 ms -^C ---- ff02::1%eth1 ping statistics --- -20 packets transmitted, 12 received, 40% packet loss, time 19432ms -rtt min/avg/max/mdev = 0.448/0.634/0.961/0.156 ms -~ $ -``` - -#### Add IP Address on Switch - -The configuration so far does not provide a means to connect to the -switch management via SSH or NETCONF, as the switch has no IP address. -The example below shows how to add the switch to VLAN 10 (as used for -ports e1 and e2) and enables IPv6. - -``` -admin@example:/config/> edit interface vlan10 -admin@example:/config/interface/vlan10/> set vlan lower-layer-if br0 -admin@example:/config/interface/vlan10/> set ipv6 enabled -admin@example:/config/interface/vlan10/> show -type vlan; -ipv6 { - enabled true; -} -vlan { - tag-type c-vlan; - id 10; - lower-layer-if br0; -} -admin@example:/config/interface/vlan10/> -admin@example:/config/interface/vlan10/> end -admin@example:/config/> edit interface br0 bridge vlans -admin@example:/config/interface/br0/bridge/vlans/> set vlan 10 tagged br0 -admin@example:/config/interface/br0/bridge/vlans/> leave -admin@example:/> -``` - -Interface *vlan10* with an auto-configured IPv6 address should appear. - -``` -admin@example:/> show interfaces -INTERFACE PROTOCOL STATE DATA -br0 bridge vlan:10t -│ ethernet UP 00:53:00:06:11:01 -├ e1 bridge FORWARDING vlan:10u pvid:10 -├ e2 bridge FORWARDING vlan:10u pvid:10 -├ e3 bridge FORWARDING vlan:20u pvid:20 -├ e4 bridge FORWARDING vlan:20u pvid:20 -├ e5 bridge FORWARDING vlan:30u pvid:30 -├ e6 bridge FORWARDING vlan:30u pvid:30 -├ e7 bridge FORWARDING vlan:40u pvid:40 -├ e8 bridge FORWARDING vlan:40u pvid:40 -├ e9 bridge FORWARDING vlan:50u pvid:50 -└ e10 bridge FORWARDING vlan:50u pvid:50 -lo ethernet UP 00:00:00:00:00:00 - ipv4 127.0.0.1/8 (static) - ipv6 ::1/128 (static) -vlan10 ethernet UP 00:53:00:06:11:01 -│ ipv6 fe80::0053:00ff:fe06:1101/64 (link-layer) -└ br0 ethernet UP 00:53:00:06:11:01 -admin@example:/> -``` - -When pinging "IPv6 all hosts" from the PC, there should be two -responses for every ping, one from the switch and one from the PC -attached to e10. - -``` -~ $ ping -L ff02::1%eth1 -PING ff02::1%eth1(ff02::1%eth1) 56 data bytes -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=1 ttl=64 time=0.508 ms -64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=1 ttl=64 time=0.968 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=2 ttl=64 time=0.866 ms -64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=2 ttl=64 time=0.867 ms -64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=3 ttl=64 time=0.467 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=3 ttl=64 time=0.469 ms -64 bytes from fe80::488a:a35f:9d41:ac9c%eth1: icmp_seq=4 ttl=64 time=0.452 ms -64 bytes from fe80::0053:00ff:fe06:1101%eth1: icmp_seq=4 ttl=64 time=0.453 ms -^C ---- ff02::1%eth1 ping statistics --- -4 packets transmitted, 4 received, +4 duplicates, 0% packet loss, time 3031ms -rtt min/avg/max/mdev = 0.452/0.631/0.968/0.211 ms -~ $ -``` - -It should now be possible to access the switch from the PC via SSH (or NETCONF). - -``` -~ $ ssh admin@fe80::0053:00ff:fe06:1101%eth1 -admin@fe80::0053:00ff:fe06:1101%eth1's password: -.-------. -| . . | Infix OS — Immutable.Friendly.Secure -|-. v .-| https://kernelkit.org -'-'---'-' - -Run the command 'cli' for interactive OAM - -admin@example:~$ exit -~ $ -``` - -See previous sections on [backup](#backup) and [restore](#restore) of -the created configuration. +[^1]: Press Win-r to bring up the Run dialog, enter `cmd.exe` and press + enter. Then type in `ipconfig /all` to list all interfaces, their + status, as well as interface index. [1]: discovery.md [2]: https://rauc.io/ [3]: boot.md#system-upgrade -[4]: https://netopeer.liberouter.org/doc/sysrepo/libyang1/html/sysrepocfg.html -[5]: vpd.md [6]: https://docs.kernel.org/leds/leds-class.html [7]: https://docs.kernel.org/power/power_supply_class.html -[8]: networking.md#bridging -[9]: networking.md#vlan-filtering-bridge diff --git a/mkdocs.yml b/mkdocs.yml index 61a7aef6..00372ef9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -36,7 +36,11 @@ nav: - Docker Containers: container.md - Hardware Info & Status: hardware.md - Network Discovery: discovery.md - - Scripting Infix: scripting.md + - Scripting Infix: + - Introduction: scripting.md + - Advanced Usage: scripting-sysrepocfg.md + - Remote RESTCONF: scripting-restconf.md + - Production Testing: scripting-prod.md - Tunneling (L2/L3): tunnels.md - Quality of Service: qos.md - RMON Counters: eth-counters.md