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: 1 addition & 14 deletions docs/caveats.md
Original file line number Diff line number Diff line change
Expand Up @@ -703,20 +703,7 @@ Other caveats you might encounter:

Other caveats (shared with Nokia SR-SIM):

* We use the `nokia.grpc` Ansible Galaxy collection to configure SR-OS. The latest version of that collection has to be installed from the git repo:

```
ansible-galaxy collection install git+https://github.com/nokia/ansible-networking-collections.git#/grpc/
python3 -m pip install grpcio protobuf==3.20.1
```

You can also use the **netlab install grpc** command to install the `nokia.grpc` collection and prerequisite Python modules.
* As of May 2024, the `nokia.grpc` collection crashes Ansible versions between 4.10.0 and 9.5.1. We recommend upgrading to Ansible release 9.5.1 or later (also included as part of the **netlab install grpc** script):

```
sudo pip3 install --upgrade 'ansible>=9.5.1'
```

* We use the `nokia.openconfig` Ansible Galaxy collection (`>= 2.0.0`) to configure SR-OS via gNMI (`nokia.openconfig.grpc`). Use the **netlab install grpc** command to install the `nokia.openconfig` collection and prerequisite Python gRPC modules (`grpcio` and `protobuf`).
* We implemented inter-VRF route leaking only for MPLS/VPN deployments.
* The SR OS configuration templates do not support additional routing policies on routing protocol route imports
* An SR OS interface cannot use an unnumbered IPv4 address in combination with IPv6 GUA
Expand Down
4 changes: 2 additions & 2 deletions docs/dev/config/srv6.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ router bgp {{ bgp.as }}
{% set srv6_interfaces = interfaces | selectattr('isis','defined') | list %}
updates:
- path: configure/router[router-name=Base]/segment-routing/segment-routing-v6
val:
value:
locator:
- locator-name: JvB
prefix:
Expand All @@ -190,7 +190,7 @@ updates:

{% if 'isis' in srv6.igp %}
- path: configure/router[router-name=Base]/isis[isis-instance=0]
val:
value:
segment-routing-v6:
admin-state: enable
locator:
Expand Down
4 changes: 2 additions & 2 deletions docs/netlab/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Ubuntu 26.04 introduced the Hardware Enablement (`-hwe`) version of `qemu-system
* The *netmiko* script installs *paramiko* and *netmiko* libraries. While the same libraries are installed with the *ansible* script, this script helps you enable [netmiko-based configuration](platform-config-mode) on supported devices
* The *ansible* script uses **pip3** to install the latest version of Ansible, networking libraries (*netaddr, paramiko, netmiko*), text parsing libraries (*testfsm, ttp, ntc-templates*), and a few other utility libraries (*jmespath, yamllint, yq*)
* The *graph* script installs GraphViz and D2 software needed to generate graphs from _netlab_ topologies
* The *grpc* script installs gRPC Python libraries needed to configure Nokia SR Linux and Nokia SR OS.
* The *grpc* script installs gRPC Python libraries and Nokia Ansible collections (`nokia.srlinux` and `nokia.openconfig`) needed to configure Nokia SR Linux and Nokia SR OS.
* The *podman* script installs *podman*, its Docker-compatible CLI, and *containerlab*.

[^UT]: Tested on Ubuntu 22.04, 24.04, and 26.04
Expand All @@ -64,7 +64,7 @@ $ netlab install
│ containerlab │ Docker and containerlab │
│ netmiko │ Netmiko and Paramiko Python libraries │
│ ansible │ Ansible and prerequisite Python libraries │
│ grpc │ GRPC libraries and Nokia GRPC Ansible collection │
│ grpc │ GRPC libraries and Nokia Ansible collections │
│ graph │ GraphViz and D2 software │
│ podman │ Podman and containerlab │
└──────────────┴───────────────────────────────────────────────────┘
Expand Down
21 changes: 12 additions & 9 deletions netsim/ansible/tasks/deploy-config/sros.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
---
- name: Generate gNMI YAML configuration
set_fact: yaml_config={{ lookup('template',config_template) }}
set_fact:
yaml_config: "{{ lookup('template',config_template) }}"

- name: Update {{ netsim_action }} node configuration from gNMI template {{ config_template }}
when: d|default([],True) != [] or u|default([],True) != [] or r|default([],True) != []
when: d != [] or u != [] or r != []
vars:
cfg: "{{ yaml_config | from_yaml }}"
d: "{{ cfg.delete if 'delete' in cfg and cfg.delete is not string else [] }}"
u: "{{ cfg.updates if 'updates' in cfg and cfg.updates is not string else [] }}"
r: "{{ cfg.replace if 'replace' in cfg and cfg.replace is not string else [] }}"
ansible_connection: nokia.grpc.gnmi
raw_cfg: "{{ yaml_config | from_yaml }}"
cfg: "{{ raw_cfg if raw_cfg is mapping else {} }}"
d: "{{ (cfg.get('delete') or cfg.get('deletes')) | default([], true) }}"
u: "{{ (cfg.get('updates') or cfg.get('update')) | default([], true) }}"
r: "{{ (cfg.get('replace') or cfg.get('replaces')) | default([], true) }}"
ansible_connection: nokia.openconfig.grpc
ansible_gnmi_encoding: JSON
ansible_port: "{{ sros_grpc_port }}"
nokia.grpc.gnmi_config:
# prefix: configure
nokia.openconfig.gnmi_set:
prefix: "{{ cfg.get('prefix') | default(omit, true) }}"
origin: "{{ cfg.get('origin') if cfg.get('origin') is not none else omit }}"
delete: "{{ d }}"
replace: "{{ r }}"
update: "{{ u }}"
Expand Down
5 changes: 3 additions & 2 deletions netsim/ansible/tasks/fetch-config/sros.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
#
- name: Backup SR OS node config user={{ ansible_user }}
vars:
ansible_connection: nokia.grpc.gnmi
ansible_connection: nokia.openconfig.grpc
ansible_gnmi_encoding: JSON
ansible_port: "{{ sros_grpc_port }}" # Uses gNMI over this port

nokia.grpc.gnmi_config:
nokia.openconfig.gnmi_set:
backup: yes
backup_options:
dir_path: "{{ config_dir }}"
Expand Down
18 changes: 12 additions & 6 deletions netsim/ansible/tasks/readiness-check/sros.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
- name: Check that required plugin exists, use 'netlab install grpc' to install it
vars:
ansible_connection: nokia.grpc.gnmi
nokia.grpc.gnmi_config:
prefix: test-plugin

---
- name: Wait up to 180s for gNMI(TCP {{sros_grpc_port}}) to be ready on {{ ansible_host }}
local_action:
module: wait_for
Expand All @@ -12,3 +7,14 @@
connect_timeout: 60
timeout: 180
sleep: 5

- name: Verify gNMI capabilities (use 'netlab install grpc' to install required plugin)
vars:
ansible_connection: nokia.openconfig.grpc
ansible_gnmi_encoding: JSON
ansible_port: "{{ sros_grpc_port }}"
nokia.openconfig.gnmi_capabilities:
register: gnmi_caps
until: gnmi_caps is succeeded
retries: 5
delay: 3
4 changes: 2 additions & 2 deletions netsim/ansible/tasks/readiness-check/srsim-hardware.j2
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
updates:
{% for card in netlab_srsim_hw %}
{% for card in netlab_srsim_hw | default([], true) %}
- path: configure/card[slot-number={{ card['slot-number'] }}]
val:
value:
{{ card|to_nice_yaml(indent=2)|indent(4,first=True) }}
{% endfor %}
11 changes: 6 additions & 5 deletions netsim/ansible/tasks/readiness-check/srsim.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@

- vars:
hw_config: "{{ lookup('template','srsim-hardware.j2')|from_yaml }}"
ansible_connection: nokia.grpc.gnmi
ansible_connection: nokia.openconfig.grpc
ansible_gnmi_encoding: JSON
ansible_port: "{{ sros_grpc_port }}"
tags: [ print_action, always ]
block:
- name: Update SR-SIM hardware configuration
nokia.grpc.gnmi_config:
update: "{{ hw_config.updates }}"
when: netlab_srsim_hw | default([], true) | length > 0
nokia.openconfig.gnmi_set:
update: "{{ hw_config['updates'] }}"
- name: Get port {{ netlab_srsim_first_port }} status
nokia.grpc.gnmi_get:
nokia.openconfig.gnmi_get:
type: STATE
prefix: /state
path:
- port[port-id={{ netlab_srsim_first_port }}]
register: result
until: >-
'ghost' not in result.output
result is succeeded and 'ghost' not in result.output
retries: 10
delay: 3
4 changes: 2 additions & 2 deletions netsim/ansible/templates/bfd/sros.j2
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
{% set bfd_v6 = l.isis.bfd.ipv6|default(False) or l.ospf.bfd|default(False) or l.bgp.bfd|default(False) or l.bfd|default(False) %}
{% if l.ipv4|default(False) and bfd_v4 %}
- path: configure/router[router-name=Base]/interface[interface-name={{ifname}}]/ipv4/bfd
val:
value:
{{ bfd_params( 'bfd' not in l or l.bfd ) }}
{% endif %}
{% if l.ipv6|default(False) and bfd_v6 %}
- path: configure/router[router-name=Base]/interface[interface-name={{ifname}}]/ipv6/bfd
val:
value:
{{ bfd_params( 'bfd' not in l or l.bfd ) }}
{% endif %}
{% endmacro %}
Expand Down
12 changes: 6 additions & 6 deletions netsim/ansible/templates/bgp/sros.gnmi.macro.j2
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

{% macro bgp_export_prefix(vrf,prefix) %}
- path: configure/policy-options/prefix-list[name=bgp_{{vrf}}_advertise]
val:
value:
prefix:
- ip-prefix: {{ prefix }}
type: exact
Expand All @@ -12,11 +12,11 @@

{# Create route export policies #}
- path: configure/policy-options/prefix-list[name=bgp_{{vrf}}_advertise]
val:
value:
prefix: [] # Make sure it exists

- path: configure/policy-options/policy-statement[name=bgp_{{vrf}}_export]
val:
value:
default-action:
action-type: reject
entry:
Expand All @@ -42,7 +42,7 @@

{% set path = "router[router-name=Base]" if vrf=="default" else "service/vprn[service-name="+vrf+"]" %}
- path: configure/{{ path }}
val:
value:
router-id: "{{ vrf_bgp.router_id|default(bgp.router_id) }}"
autonomous-system: {{ bgp.as }}
bgp:
Expand Down Expand Up @@ -77,7 +77,7 @@

{% macro bgp_peer_group(name,type,neighbor,transport_ip) %}
- path: configure/{{ path }}/bgp/group[group-name={{name}}]
val:
value:
admin-state: enable
{{ bgp_families(neighbor) }}
import:
Expand Down Expand Up @@ -117,7 +117,7 @@
{{ bgp_peer_group(peer_group,'ibgp' if 'ibgp' in n.type else 'ebgp',n,transport_ip) }}

- path: configure/{{ path }}/bgp
val:
value:
neighbor:
- ip-address: "{{ n[af] }}"
description: "{{ n.name }}"
Expand Down
4 changes: 2 additions & 2 deletions netsim/ansible/templates/bgp/sros.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
updates:

- path: configure/policy-options/policy-statement[name=accept_all]
val:
value:
default-action:
action-type: accept

{% if bgp.next_hop_self|default(False) %}
- path: configure/policy-options/policy-statement[name=next-hop-self-ebgp-routes-only]
val:
value:
entry:
- entry-id: 10
from:
Expand Down
8 changes: 4 additions & 4 deletions netsim/ansible/templates/evpn/sros.j2
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
updates:
{# Configure EVPN AF on BGP neighbors #}
- path: configure/router[router-name=Base]
val:
value:
bgp:
rapid-withdrawal: True
rapid-update:
Expand Down Expand Up @@ -78,7 +78,7 @@ updates:
{% if vlans is defined %}
{% for vname,vdata in vlans.items() if vdata.evpn.evi is defined %}
- path: configure/service/vpls[service-name=vlan{{ vdata.id }}]
val:
value:
{% if vdata.mode|default('irb') == 'irb' %}
routed-vpls:
vxlan-ipv4-tep-ecmp: True # Enable ECMP for routed VXLAN
Expand Down Expand Up @@ -118,7 +118,7 @@ updates:
{% if vrfs is defined %}
{% for vname,vdata in vrfs.items() if vdata.evpn.transit_vni is defined %}
- path: configure/service/vprn[service-name={{ vname }}]
val:
value:
bgp-evpn:
{% if evpn.transport|default('vxlan') == 'mpls' %}
# TODO if evpn.transport == 'mpls'
Expand Down Expand Up @@ -148,7 +148,7 @@ updates:
{% for proto in ['bgp','ospf','isis','ripv2'] if proto in vdata %}
#
- path: configure/policy-options/policy-statement[name={{ proto }}_{{ vname }}_export]
val:
value:
entry:
- entry-id: 2000
from:
Expand Down
2 changes: 1 addition & 1 deletion netsim/ansible/templates/gateway/sros.j2
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
updates:
{% for intf in interfaces if intf.gateway.protocol is defined %}
{{ declare_interface(intf) }}
val:
value:
{% for af in ('ipv4','ipv6') if intf.gateway.protocol in ['anycast','vrrp'] and af in intf.gateway %}
{{ af }}:
{% if af=='ipv6' and intf.ipv6 is string %}
Expand Down
18 changes: 9 additions & 9 deletions netsim/ansible/templates/initial/sros.j2
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
{# Minimal service config must exist #}
{% if not in_base and vrf_config %}
- path: configure/{{ base_path }}
val:
value:
customer: "1"
admin-state: enable
service-id: {{ vrfs[i.vrf].vrfidx if i.vrf is defined else 1 }}
Expand Down Expand Up @@ -81,7 +81,7 @@

{% macro interface(name,desc,ip_v4,ip_v6,port,l,vlan=0) -%}
{{ declare_interface(l,name) }}
val:
value:
admin-state: {{ "disable" if l.shutdown|default(False) else "enable" }}
description: "{{ desc }}{{ 'vlan= '+vlan|string if vlan else '' }}"
{% if l.mtu is defined %}
Expand Down Expand Up @@ -115,7 +115,7 @@
{% endif %}
{% if ip_v6 and l.type != 'loopback' and role|default('router') == 'router' %}
{{ declare_router(l) }}
val:
value:
ipv6:
router-advertisement:
interface:
Expand Down Expand Up @@ -153,14 +153,14 @@
{% if l.type in ['p2p','lan','vlan_member','stub'] %}
{% if 'c' in portname %}
- path: configure/port[port-id={{portname}}]
val:
value:
admin-state: enable
connector:
breakout: "c1-100g"
{% set portname = portname + '/1' %}
{% endif %}
- path: configure/port[port-id={{ portname }}]
val:
value:
admin-state: enable
ethernet:
{% set eth_header = 14 + (4 if tagged else 0) %}
Expand Down Expand Up @@ -188,7 +188,7 @@
updates:
{% if 'ixr' in clab.type %}
- path: configure/system/resource
val:
value:
ecmp-profile:
- profile-id: 1
type: ip # or mpls
Expand All @@ -206,15 +206,15 @@ updates:
want to use a different hardware configuration
#}
{% if 'srsim' in clab.kind %}
{% for card in netlab_srsim_hw %}
{% for card in netlab_srsim_hw | default([], true) %}
- path: configure/card[slot-number={{ card['slot-number'] }}]
val:
value:
{{ card|to_nice_yaml(indent=2)|indent(4,first=True) }}
{% endfor %}
{% endif %}
{# Enable ECMP=64 by default #}
- path: configure/router[router-name=Base]
val:
value:
ecmp: {{ 1 if 'ixr' in clab.type else 64 }}

{% for l in netlab_interfaces if l.vlan is not defined and l.subif_index is not defined %}
Expand Down
Loading
Loading