Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/caveats.md
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,21 @@ ansible_httpapi_port: 80
* An OSPFv3 ABR running FRR release 10.3 does not originate summary external routes from NSSA areas
* As of FRRouting release 10.6.0, the FRR implementation of EVPN for VXLAN-over-IPv6 is incompatible with the Arista EOS implementation due to different encodings of the PMSI_TUNNEL_ATTRIBUTE.

(caveats-ocnos)=
## IP Infusion OcNOS

* OcNOS ships a commercial NOS image; there is no public Vagrant/Containerlab box. Obtain the `vrnetlab/ipinfusion_ocnos` container image (or an equivalent OcNOS VM) from IP Infusion and build/import it yourself.
* OcNOS's CLI (`cmlsh`) is a restricted shell with **no non-interactive exec mode** -- a plain `ssh device 'show ...'` fails with `Try 'cmlsh --help'`. Configuration deploy and collection use the **ipinfusion.ocnos** Ansible collection (`ocnos_config` / `ocnos_facts`) over `ansible_connection: network_cli`, which drives `cmlsh` interactively through dedicated cliconf/terminal plugins. Install the collection with `ansible-galaxy collection install ipinfusion.ocnos`.
* Because of the `cmlsh` restriction above, *netlab*'s SSH and `docker exec` validation transports cannot issue `show` commands directly against an OcNOS node. OcNOS instead uses the **`ansible` validation action**, which fetches show output through the `ipinfusion.ocnos.ocnos_command` module (declared in `netsim/devices/ocnos.yml` as `netlab_validate.ansible_module`); `netlab validate` works against OcNOS on both the device under test and attached FRR/Linux probes.
* An OSPF (v2 or v3) network-membership change on an already-running process (a new area or network added to an existing `router ospf`/`router ipv6 ospf`) makes OcNOS's `commit` return a non-empty informational notice (`Use "clear ip[v6] ospf process" command to take effect`). The `ocnos_config` Ansible module treats any non-empty commit response as a failure, which aborts the rest of that node's play -- any modules queued after `ospf` in the same **netlab initial** run (for example `isis`, `bgp`, `vrf`) are silently skipped for that node. Run **netlab initial** a second time after the first OSPF network/area change on a node; the second pass re-sends the now-unchanged OSPF config (no new membership, no notice) and lets the remaining modules deploy normally. This is a one-time cost per fresh OSPF network change, not a per-boot cost.
* The main loopback interface name is `lo`; the kernel `lo` owns `127.0.0.1`, so *netlab*'s loopback address is configured as a `secondary` address. Additional *netlab* loopbacks become `loopback<N>` (OcNOS does not support `loopback0`).
* OcNOS declares DHCP client and relay support and renders the corresponding configuration (cross-checked against the OKF CLI reference), but the DHCP **relay datapath** is not exercised by the integration suite on a containerlab-only host -- the `dhcp/11-ipv4-relay` test needs a libvirt-based `dnsmasq` server probe. OcNOS is therefore intentionally omitted from the [DHCP support table](platform-services-support) until that end-to-end path is covered.
* GRE tunnel configuration renders for OcNOS, but the tunnel line protocol does not come up on the tested OcNOS 7.0 image, so OcNOS is not listed among the [tunnel.gre](plugin-tunnel-gre) supported platforms.
* VLANs use the Customer Bridge (VLAN-aware bridge) model: `bridge 1 protocol ieee vlan-bridge` + `vlan database`, with SVIs named `vlan1.<vlan-id>`.
* Per-VRF OSPF uses a positional VRF name, not a `vrf` keyword: `router ospf <process-id> <vrf-name>`.
* LACP aggregates are named `po<N>`; static (non-LACP) port channels are named `sa<N>`.
* OSPFv3 is not supported inside a VRF: the `router ipv6 vrf ospf <name>` command commits and the interface area binding is accepted, but the process never actually attaches to the VRF (`show ipv6 ospf` reports zero areas indefinitely). This is a proven NSM-level gap, not a template limitation.

(caveats-junos)=
## Common Junos caveats

Expand Down
116 changes: 116 additions & 0 deletions docs/install/ocnos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Installing IP Infusion OcNOS

netlab runs **IP Infusion OcNOS** as a [containerlab](clab.md)-provisioned device: a vrnetlab-packaged
OcNOS VM. Only the **clab** provider is supported (no Vagrant box).

## Container image

* Build the vrnetlab OcNOS container from the OcNOS `qcow2` using vrnetlab's `ipinfusion_ocnos` kind.
* Tag it `vrnetlab/ipinfusion_ocnos:<version>`. Verified against **7.0.0-262** (and 6.5.2-101).
* The device sets clab `kind: ipinfusion_ocnos`; point it at your image:

```
defaults.devices.ocnos.clab.image: vrnetlab/ipinfusion_ocnos:7.0.0-262
```

## Configuration deployment

OcNOS configuration is pushed with the **`ipinfusion.ocnos` Ansible collection** over `network_cli`
(the collection drives the interactive `cmlsh` shell). Install it once:

```
ansible-galaxy collection install ipinfusion.ocnos
```

The same collection is used to read device state during `netlab validate` (see the validation
note below). Device settings: `interface_name eth{ifindex}`, `mgmt_if eth0`, loopbacks
`lo`/`loopbackN`.

## Supported configuration modules

`initial`, `ospf` (+areas/NSSA), `bgp` (+plugins/policy/multihop), `isis`, `vrf` (+isis), `vlan`,
`lag` (+passive), `gateway`, `dhcp`/relay, `stp`, `mpls`, `sr` (SRGB), `vxlan`, `evpn` (MPLS), `bfd`,
`gre`. See `netsim/devices/ocnos.yml` `features:` for the authoritative list; support level is
**best-effort** (see `docs/caveats.md`).

## Validation with the `ansible` action (`netlab validate`)

OcNOS's `ocnos` user has a **restricted shell**: it drops into `cmlsh` only on an *interactive*
login. `ssh ocnos@node "show ..."` (and every `cmlsh -e/-c` variant) returns ``Try `cmlsh --help'`` --
there is **no non-interactive exec** -- and OcNOS emits CLI **text**, not JSON. netlab's SSH and
`docker exec` validation transports therefore cannot drive OcNOS show commands.

OcNOS uses the **`ansible` validation action** instead -- a validation data *source* (a peer of
`netsim/cli/validate/suzieq.py`, implemented in `netsim/cli/validate/ansible.py`), **not** a
connection-method change (`netsim/cli/connect.py` is unchanged). A validation test selects it with
an `ansible` action or a validation-plugin `ansible_<test>()` function that supplies the show
command; the device names the Ansible module to run it through in `netsim/devices/ocnos.yml`:

```
netlab_validate:
ansible_module: ipinfusion.ocnos.ocnos_command
```

`netlab validate` then runs the show command through `ipinfusion.ocnos.ocnos_command` against the
netlab-generated inventory. The result is parsed as JSON when the command emits it, otherwise the
CLI text is returned in `stdout`; the OcNOS validators (`netsim/validate/<module>/ocnos.py`,
re-exported from `netsim/validate/ocnos.py`) screen-scrape that text. The action is generic -- any
device whose CLI lacks a non-interactive SSH exec can opt in the same way.

Run the standard integration suite against an OcNOS device under test:

```
export NETLAB_DEVICE=ocnos NETLAB_PROVIDER=clab
netlab up tests/integration/ospf/ospfv2/01-network.yml
netlab validate
```

Verified live (vrnetlab `ipinfusion_ocnos:7.0.0-262`, FRR probes): the OSPF, BGP and IS-IS
integration tests pass with native `netlab validate`, and DUT-side neighbor/prefix checks pass
over the Ansible transport.

## Validated modules (native `netlab validate`)

Live-verified against vrnetlab `ipinfusion_ocnos:7.0.0-262` with FRR / cEOS / Linux probes,
using the `ansible` validation action described above. "Probe" = the check runs on the
adjacent probe (interop); "DUT" = the check runs on the OcNOS device via the `ansible` action.

| Module | Integration test | Result |
|---|---|---|
| ospf (v2) | `ospf/ospfv2/01-network` | PASS 4/4 (probe) + 3/3 (DUT: neighbor Full, route present) |
| bgp | `bgp/01-ebgp-session` | PASS 3/3 (probe) + 3/3 (DUT: sessions Established, prefix present) |
| isis | `isis/01-ipv4` | PASS 5/5 (probe) + 2/2 (DUT: adjacency L1, prefix present) — needed the `dynamic-hostname` fix |
| vlan | `vlan/01-vlan-bridge-single` | PASS 1/1 (host-to-host ping across the bridge) |
| lag | `lag/01-l3-lag` | PASS (LAG active on both EOS probes + IPv4 ping; one warning-level path-MTU check) |
| stp | `stp/01-stp-priority` | PASS 2/2 (link forwarding + root-bridge priority) — needed the bridge-priority fix |
| gateway | `gateway/02-vrrp` | IPv4 VRRP fully green (VIP ping, backup/master/preempt). IPv6 VRRP control-plane green (master election + backup/master/preempt) + steady-state datapath — needed the IPv6-VRRP fix. See exception for the v6-transit-on-failover gap. |
| vrf | `vrf/11-multi-vrf-ospf` | Single-area VRF fully green (per-VRF adjacency, routes, ping, inter-VRF isolation). See exception below for the multi-area sub-case. |

Three config-completeness fixes came out of this pass: IS-IS `dynamic-hostname` (peers can map the
DUT system-id to a name), the STP customer-bridge `priority` (was never rendered), and IPv6 VRRP
(the gateway template rendered IPv4 VRRP only; VRRPv3 needs a link-local primary virtual-ipv6).

## Documented exceptions

A "full" device may ship with clearly-documented exceptions; these are recorded rather than faked.

* **Multi-area OSPF inside a VRF** (`vrf/11` blue sub-case). OcNOS is a strict (Cisco-type) ABR: it
will not originate inter-area type-3 summaries when its backbone (area 0) is *inactive* — here the
VRF's only area-0 interface is a stub loopback, so two non-backbone areas connected only through the
DUT do not exchange routes. (OSPF-in-VRF also defaults to MPLS-VPN "superbackbone" mode;
`capability vrf-lite` clears that but not the inactive-backbone rule.) FRR/EOS are lenient ABRs and
summarize anyway. Single-area VRF OSPF is unaffected and passes.
* **gateway / VRRP — IPv6 transit forwarding on failover.** The module boots and validates on stock
clab (an earlier boot failure was a bug in a local `clab-render-mtu` change, not netlab core — MTU
is handled device-side). IPv4 VRRP is fully green; IPv6 VRRP is now configured (VRRPv3, link-local
primary virtual address) and control-plane-verified — the DUT wins/holds master and the probe sees
correct backup/master/preempt transitions, and the v6 datapath pings in steady state. The remaining
gap: after the VRRP peer's LAN link drops, IPv6 *transit* forwarding through the DUT fails even
though it is master and the client's neighbor cache holds the virtual MAC — an OcNOS v6-VRRP
failover-forwarding edge (IPv4 failover is unaffected).
* **dhcp relay** — the 3-piece OcNOS relay config generates and parser-checks correctly, but the
`dhcp/11-ipv4-relay` integration test needs a libvirt-based `dnsmasq` server probe, unavailable
on a clab-only host, so the end-to-end relay datapath is not covered by the integration suite.
* **EVPN datapath**, **GRE tunnel line-protocol**, **VRF-bound-interface ingress**, and
**per-VRF OSPFv3 + IPv6 VRF route-leak** — tracked platform/image limitations; config
generation is present where applicable.
11 changes: 11 additions & 0 deletions docs/platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
| Fortinet FortiOS [❗](caveats-fortios) | fortios | minimal |
| FRRouting (FRR) [❗](caveats-frr) | frr | full |
| [Generic Linux host](generic-linux-devices) | linux | full |
| IP Infusion OcNOS [❗](caveats-ocnos) | ocnos | best effort |
| Juniper cRPD | crpd | full |
| Juniper cSRX [❗](caveats-csrx) | csrx | minimal |
| Juniper vMX [❗](caveats-vmx) | vmx | best effort |
Expand Down Expand Up @@ -130,6 +131,7 @@ You cannot use all supported network devices with all virtualization providers.
| Fortinet FortiOS | [✅](build-fortios) | ✅ |
| FRR | [✅](build-frr)[❗](caveats-frr) | ✅ |
| Generic Linux (Ubuntu/Alpine) | [❗](labs/linux.md) | ✅ |
| IP Infusion OcNOS | ❌ | ✅[❗](clab-vrnetlab) |
| Juniper cRPD | ❌ | ✅ |
| Juniper cSRX | ❌ | ✅ |
| Juniper vMX | ❌ | ✅[❗](clab-vrnetlab) |
Expand Down Expand Up @@ -202,6 +204,7 @@ Ansible playbooks included with **netlab** can deploy and collect device configu
| Fortinet FortiOS | ✅ | ✅ |
| FRR | ✅ [❗](caveats-frr) | ✅[❗](caveats-frr) |
| Generic Linux | ✅ | ❌ |
| IP Infusion OcNOS [❗](caveats-ocnos) | ✅ | ✅ |
| Juniper cSRX | ✅ | ❌ |
| Junos[^Junos] | ✅ | ✅ |
| Mikrotik RouterOS 6 | ✅ | ✅ |
Expand Down Expand Up @@ -288,6 +291,7 @@ The following system-wide features are configured on supported network operating
| Fortinet FortiOS | ✅ | ❌ | ✅ | ✅ | ✅ |
| FRR | ✅ | ✅[^HIF] | ❌ | ✅ | ✅ |
| Generic Linux | ✅ | ✅[^HIF] | ✅[❗](linux-lldp) | ✅ | ✅ |
| IP Infusion OcNOS | ✅ | ❌ | ✅ | ✅ | ✅ |
| Juniper cSRX | ✅ | ✅ | ❌ | ❌ | ❌ |
| Junos[^Junos] | ✅ | ❌ | ✅ | ✅ | ✅ |
| Mikrotik RouterOS 6 | ✅ | ✅ | ✅[❗](caveats-routeros6) | ✅ | ✅ |
Expand Down Expand Up @@ -320,6 +324,7 @@ The following interface parameters are configured on supported network operating
| Fortinet FortiOS | ✅ | ✅ | ✅[❗](caveats-fortios) | ❌ |
| FRR | ✅ | ✅ | ✅ | ✅ |
| Generic Linux | ❌ | ❌ | ✅ | ❌ |
| IP Infusion OcNOS | ✅ | ❌ | ✅ | ✅ |
| Juniper cSRX | ✅ | ❌ | ✅ | ❌ |
| Junos[^Junos] | ✅ | ✅ | ✅ | ❌ |
| Mikrotik RouterOS 6 | ✅ | ❌ | ✅ | ❌ |
Expand Down Expand Up @@ -349,6 +354,7 @@ The following interface addresses are supported on various platforms; most daemo
| Fortinet FortiOS | ✅ | ✅ | ❌ | ❌ |
| FRR | ✅ | ✅ | ✅ | ✅ |
| Generic Linux | ✅ | ✅ | ❌ | ❌ |
| IP Infusion OcNOS | ✅ | ✅ | ❌ | ❌ |
| Juniper cSRX | ✅ | ✅ | ❌ | ❌ |
| Junos[^Junos] | ✅ | ✅ | ✅ | ❌ |
| Mikrotik RouterOS 6 | ✅ | ✅ | ❌ | ❌ |
Expand Down Expand Up @@ -397,6 +403,7 @@ Routing protocol [configuration modules](module-reference.md) are supported on t
| Extreme Networks EXOS | ✅ | ❌ | ❌ | ❌ | ❌ |
| Fortinet FortiOS | ✅ [❗](caveats-fortios) | ❌ | ❌ | ✅ | ❌ |
| FRR | ✅ | ✅ | ❌ | ✅ | ✅ |
| IP Infusion OcNOS [❗](caveats-ocnos) | ✅ | ✅ | ❌ | ✅ | ✅ |
| Junos[^Junos] | ✅ | ✅ | ❌ | ✅ | ❌ |
| Mikrotik RouterOS 6 | ✅ | ❌ | ❌ | ✅ | ❌ |
| Mikrotik RouterOS 7 | ✅ | ❌ | ❌ | ✅ | ❌ |
Expand All @@ -421,6 +428,7 @@ These devices support additional control-plane protocols or BGP address families
| Dell OS10 | ✅ | ✅ | ❌ | ❌ |
| Extreme Networks EXOS | ❌ | ❌ | ❌ | ✅ |
| FRR | ✅ | ✅ | ✅ | ❌ |
| IP Infusion OcNOS [❗](caveats-ocnos) | ✅ | ✅ | ✅ | ✅ |
| Juniper cRPD | ✅ | ❌ | ✅ | ❌ |
| Juniper vMX | ✅ | ❌ | ✅ | ✅ |
| Juniper vPTX | ✅ | ✅ | ✅ | ✅ |
Expand Down Expand Up @@ -449,6 +457,7 @@ The layer-2 control plane [configuration modules](module-reference.md) are suppo
| Dell OS10 | ✅ | ✅ |
| dnsmasq | ❌ | ✅ |
| FRR | ✅ | ✅ |
| IP Infusion OcNOS [❗](caveats-ocnos) | ✅ | ✅ |
| Linux | ❌ | ✅ |

(platform-dataplane-support)=
Expand All @@ -471,6 +480,7 @@ The data plane [configuration modules](module-reference.md) are supported on the
| Dell OS10 | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| Extreme Networks EXOS | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| FRR | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| IP Infusion OcNOS [❗](caveats-ocnos) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Juniper cRPD | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Juniper vMX | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
| Juniper vPTX | ✅ | ✅ | ✅ [❗](caveats-vptx) | ✅ | ✅ | ❌ |
Expand Down Expand Up @@ -518,6 +528,7 @@ Core *netlab* functionality and all multi-protocol routing protocol configuratio
| Extreme Networks EXOS | ✅ | ❌ | ❌ | ❌ | ❌ |
| Fortinet FortiOS | ✅ | ❌ | ❌ | ✅ | ❌ |
| FRR | ✅ | ✅ | ❌ | ✅ | ❌ |
| IP Infusion OcNOS [❗](caveats-ocnos) | ✅ | ✅ | ❌ | ✅ | ❌ |
| Junos[^Junos] | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| Mikrotik RouterOS 6 | ❌ | ❌ | ❌ | ✅ | ❌ |
| Mikrotik RouterOS 7 | ✅ | ❌ | ❌ | ✅ | ❌ |
Expand Down
2 changes: 2 additions & 0 deletions docs/release/26.07.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
* The [**WireGuard tunnel** plugin](plugin-tunnel-wireguard) supports WireGuard tunnels on FRR.
* The [**bgp.session** plugin](plugin-bgp-session) and the [OSPF module](module-ospf) support graceful restart on Arista EOS, BIRD, FortiOS, and FRR
* The [**bgp.policy** plugin](plugin-bgp-policy) supports the **bgp.role** attribute on FRR and BIRD.
* [IP Infusion OcNOS](https://www.ipinfusion.com/products/ocnos/) is now supported (best-effort) as a containerlab node, with configuration deployment and validation through the **ipinfusion.ocnos** Ansible collection.

**Minor changes and improvements**

* The **[netlab status](netlab-status)** command displays IPv6 management addresses.
* Validation plugins can check BFD state in BGP neighbor details, use platform-independent parameters, and mark expected failures.
* The new **ansible** validation action lets `netlab validate` fetch device state through an Ansible module, for platforms whose CLI cannot run non-interactive SSH commands (for example, IP Infusion OcNOS).
* Configuration templates can use directories in the `package:extra` template search path.
* Filter static route node next hops by link name

Expand Down
17 changes: 17 additions & 0 deletions netsim/ansible/tasks/deploy-config/ocnos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
# netlab config-deploy task for OcNOS. Pushes the rendered config file
# (config_template) to the node using the ipinfusion.ocnos Ansible collection over
# ansible.netcommon.network_cli -- OcNOS's cmlsh restricted shell has no
# non-interactive exec mode, so raw SSH command push (paramiko/netmiko) does not
# work; this collection ships the cliconf/terminal plugins that drive cmlsh
# interactively. Requires: ansible-galaxy collection install ipinfusion.ocnos
- name: "ocnos_config: deploying {{ netsim_action | default('config') }} from {{ config_template }}"
ipinfusion.ocnos.ocnos_config:
src: "{{ config_template }}"
# match: none -- send the rendered file verbatim in order. The default
# line-matching skips lines already present in running-config, including
# mode-exit lines like exit-address-family, which breaks mode tracking on
# re-deploys. Our templates are written to be re-runnable, so verbatim is
# correct.
match: none
tags: [ print_action, always ]
7 changes: 7 additions & 0 deletions netsim/ansible/tasks/fetch-config/ocnos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# fetch OcNOS running configuration for 'netlab collect', using the
# ipinfusion.ocnos_facts module (network_cli / cmlsh) -- raw SSH command exec
# ("show running-config" over paramiko) does not work against OcNOS's restricted
# cmlsh shell, see tasks/deploy-config/ocnos.yml.
---
- ipinfusion.ocnos.ocnos_facts:
gather_subset: config
17 changes: 17 additions & 0 deletions netsim/ansible/tasks/readiness-check/ocnos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#
# OcNOS device readiness check (triggered by netlab_ready: [ ansible ] in devices/ocnos.yml).
#
# OcNOS CLI (cmlsh) has no non-interactive exec mode, so the generic raw-SSH readiness probe
# (tasks/readiness-check/ssh.yml runs `ssh node "show version"`, which cmlsh rejects) never
# succeeds. Instead probe over the ipinfusion.ocnos connection -- the same transport config
# deploy uses -- retrying until the management CLI answers. The vrnetlab OcNOS VM takes ~9 min
# to boot, so the bound is netlab_check_retries x netlab_check_delay (default 60 x 12 = 720s).
#
---
- name: "Wait for OcNOS management CLI to become ready ({{ inventory_hostname }})"
ipinfusion.ocnos.ocnos_command:
commands: [ show version ]
register: _ocnos_ready
until: _ocnos_ready is succeeded
retries: "{{ netlab_check_retries | default(60) }}"
delay: "{{ netlab_check_delay | default(12) }}"
Loading