Repository navigation
Add IP Infusion OcNOS device (containerlab/vrnetlab) #3960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| - name: "ocnos_config: deploying {{ netsim_action }} from {{ config_template }}" | ||
| ipinfusion.ocnos.ocnos_config: | ||
| src: "{{ config_template }}" | ||
| save_when: "{{ 'modified' if netlab_save_config|default(True) else 'never' }}" | ||
| tags: [ print_action, always ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # fetch IP Infusion OcNOS configuration with ocnos_command | ||
| # | ||
| --- | ||
| - ipinfusion.ocnos.ocnos_command: | ||
| commands: [ show running-config ] | ||
| register: ocnos_running_config | ||
|
|
||
| - set_fact: | ||
| ansible_net_config: "{{ ocnos_running_config.stdout[0] }}" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| {% import "ocnos.macro.j2" as bgpcfg %} | ||
| {# | ||
| Legacy bgp.originate (IPv4 prefixes): OcNOS advertises a "network" prefix only when it | ||
| is in the routing table, so add a discard route for each originated prefix | ||
| #} | ||
| {% for pfx in bgp.originate|default([]) %} | ||
| ip route {{ pfx }} null | ||
| {% endfor %} | ||
| ! | ||
| router bgp {{ bgp.as }} | ||
| {% if bgp.router_id is defined %} | ||
| bgp router-id {{ bgp.router_id }} | ||
| {% endif %} | ||
| {% if bgp.rr|default(False) and bgp.rr_cluster_id|default(False) %} | ||
| bgp cluster-id {{ bgp.rr_cluster_id }} | ||
| {% endif %} | ||
| {% for n in bgp.neighbors %} | ||
| {% for af in ['ipv4','ipv6'] if n[af] is defined %} | ||
| {{ bgpcfg.neighbor_global(n,n[af]) }} | ||
| {% endfor %} | ||
| {% endfor %} | ||
| {% for af in ['ipv4','ipv6'] if bgp[af] is defined %} | ||
| address-family {{ af }} unicast | ||
| {% for pfx in bgp.advertise|default([]) if af in pfx %} | ||
| network {{ pfx[af] }} | ||
| {% endfor %} | ||
| {% for n in bgp.neighbors if n.activate[af]|default(false) %} | ||
| {{ bgpcfg.neighbor_af(n,n[af],bgp) }} | ||
| {% endfor %} | ||
| exit-address-family | ||
| {% endfor %} | ||
| ! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| {# | ||
| Global BGP neighbor definition. OcNOS sends standard and extended communities by default | ||
| ("send-community" on an enabled type is rejected), and advertisement-interval is a | ||
| router-level neighbor setting. | ||
| #} | ||
| {% macro neighbor_global(n,ip) %} | ||
| neighbor {{ ip }} remote-as {{ n.as }} | ||
| neighbor {{ ip }} description {{ n.name }} | ||
| neighbor {{ ip }} advertisement-interval 0 | ||
| {% if n._source_intf is defined %} | ||
| neighbor {{ ip }} update-source {{ n._source_intf.ifname }} | ||
| {% endif %} | ||
| {%- endmacro %} | ||
| {# | ||
| Address family BGP neighbor definition | ||
| #} | ||
| {% macro neighbor_af(n,ip,bgp) %} | ||
| neighbor {{ ip }} activate | ||
| {% if n.next_hop_self|default(False) %} | ||
| neighbor {{ ip }} next-hop-self | ||
| {% endif %} | ||
| {% if n.rr_client|default(False) %} | ||
| neighbor {{ ip }} route-reflector-client | ||
| {% endif %} | ||
| {% set c_list = bgp.community[n.type]|default([]) %} | ||
| {% for c_type in ['standard','extended'] if c_type not in c_list %} | ||
| no neighbor {{ ip }} send-community {{ c_type }} | ||
| {% endfor %} | ||
| {%- endmacro %} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| hostname {{ inventory_hostname.replace("_","-") }} | ||
| ! | ||
| {% for l in netlab_interfaces %} | ||
| interface {{ l.ifname }} | ||
| {% if l.name is defined %} | ||
| description {{ l.name|replace('"','') }}{{ " [" + l.role + "]" if l.role is defined else "" }} | ||
| {% elif l.type|default("") == "stub" %} | ||
| description Stub interface | ||
| {% endif %} | ||
| {% if l.mtu is defined and l.type|default("") != "loopback" %} | ||
| mtu {{ l.mtu }} | ||
| {% endif %} | ||
| {% if 'ipv4' in l and l.ipv4 is string %} | ||
| {# "lo" already has 127.0.0.1/8 as its primary address #} | ||
| ip address {{ l.ipv4 }}{{ " secondary" if l.ifname == "lo" else "" }} | ||
| {% endif %} | ||
| {% if 'ipv6' in l and l.ipv6 is string %} | ||
| ipv6 address {{ l.ipv6 }} | ||
| {% endif %} | ||
| {% if l.type|default("") != "loopback" %} | ||
| {{ "shutdown" if l.shutdown|default(False) else "no shutdown" }} | ||
| {% endif %} | ||
| ! | ||
| {% endfor %} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| {# | ||
| OcNOS uses "level-2-only" where netlab uses "level-2", and "isis metric" takes narrow | ||
| metrics only (1-63); wide metrics are set with "isis wide-metric". | ||
| #} | ||
| {% set lvl = { 'level-1': 'level-1', 'level-2': 'level-2-only', 'level-1-2': 'level-1-2' } %} | ||
| {% set mt_lvl = { 'level-1': 'level-1', 'level-2': 'level-2', 'level-1-2': 'level-1-2' } %} | ||
| {% set wide = isis.wide_metrics|default(True) %} | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| ! | ||
| router isis {{ isis.instance }} | ||
| is-type {{ lvl[isis.type]|default(isis.type) }} | ||
| net {{ isis.net }} | ||
| metric-style {{ 'wide' if wide else 'narrow' }} | ||
| dynamic-hostname | ||
| {% for l in netlab_interfaces if l.isis.passive|default(False) and 'vrf' not in l %} | ||
| passive-interface {{ l.ifname }} | ||
| {% endfor %} | ||
| {% if isis.af.ipv6 is defined %} | ||
| address-family ipv6 unicast | ||
| multi-topology {{ mt_lvl[isis.type]|default('level-1-2') }} | ||
| exit-address-family | ||
| {% endif %} | ||
| ! | ||
| {% for l in netlab_interfaces if 'isis' in l and 'vrf' not in l %} | ||
| interface {{ l.ifname }} | ||
| {% if 'ipv4' in l and isis.af.ipv4 is defined %} | ||
| ip router isis {{ isis.instance }} | ||
| {% endif %} | ||
| {% if 'ipv6' in l and isis.af.ipv6 is defined %} | ||
| ipv6 router isis {{ isis.instance }} | ||
| {% endif %} | ||
| {% if l.isis.network_type is defined %} | ||
| isis network {{ l.isis.network_type }} | ||
| {% endif %} | ||
| {% if l.isis.type is defined %} | ||
| isis circuit-type {{ lvl[l.isis.type]|default(l.isis.type) }} | ||
| {% endif %} | ||
| {% if l.isis.metric is defined %} | ||
| isis {{ 'wide-metric' if wide else 'metric' }} {{ l.isis.metric }} | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to deal with both (unless you want to have extra flexibility) |
||
| {% endif %} | ||
| ! | ||
| {% endfor %} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| {# | ||
| OcNOS assigns OSPF areas with "network" statements in the router configuration, | ||
| not with interface commands. A host prefix (interface address) is accepted and | ||
| normalized to the subnet. | ||
| #} | ||
| {% set ospf_pid = ospf.process|default(1) %} | ||
| {% if ospf.af.ipv4 is defined %} | ||
| router ospf {{ ospf_pid }} | ||
| {% if ospf.router_id is defined %} | ||
| ospf router-id {{ ospf.router_id }} | ||
| {% endif %} | ||
| {% if ospf.reference_bandwidth is defined %} | ||
| auto-cost reference-bandwidth {{ ospf.reference_bandwidth }} | ||
| {% endif %} | ||
| {% for l in netlab_interfaces if 'ospf' in l and l.ipv4 is string and 'vrf' not in l %} | ||
| network {{ l.ipv4 }} area {{ l.ospf.area }} | ||
| {% endfor %} | ||
| {% for l in netlab_interfaces if l.ospf.passive|default(False) and 'vrf' not in l %} | ||
| passive-interface {{ l.ifname }} enable | ||
| {% endfor %} | ||
| ! | ||
| {% for l in netlab_interfaces if 'ospf' in l and l.ipv4 is string and 'vrf' not in l %} | ||
| interface {{ l.ifname }} | ||
| {% if l.ospf.network_type is defined %} | ||
| ip ospf network {{ l.ospf.network_type }} | ||
| {% endif %} | ||
| {% if l.ospf.cost is defined %} | ||
| ip ospf cost {{ l.ospf.cost }} | ||
| {% endif %} | ||
| {% if l.ospf.timers.hello is defined %} | ||
| ip ospf hello-interval {{ l.ospf.timers.hello }} | ||
| {% endif %} | ||
| {% if l.ospf.timers.dead is defined %} | ||
| ip ospf dead-interval {{ l.ospf.timers.dead }} | ||
| {% endif %} | ||
| {% if l.ospf.priority is defined %} | ||
| ip ospf priority {{ l.ospf.priority }} | ||
| {% endif %} | ||
| {% if l.ospf.password is defined %} | ||
| ip ospf authentication | ||
| ip ospf authentication-key {{ l.ospf.password }} | ||
| {% endif %} | ||
| ! | ||
| {% endfor %} | ||
| {% endif %} | ||
| {# | ||
| OSPFv3: the process tag is the OSPF process ID; interfaces join an area with | ||
| "ipv6 router ospf area <area> tag <tag>" | ||
| #} | ||
| {% if ospf.af.ipv6 is defined %} | ||
| router ipv6 ospf {{ ospf_pid }} | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add the reference bandwidth if it's available for OSPFv3, otherwise just ignore this comment. It's a best-effort attribute anyway. |
||
| {% if ospf.router_id is defined %} | ||
| router-id {{ ospf.router_id }} | ||
| {% endif %} | ||
| {% for l in netlab_interfaces if l.ospf.passive|default(False) and 'ipv6' in l and 'vrf' not in l %} | ||
| passive-interface {{ l.ifname }} enable | ||
| {% endfor %} | ||
| ! | ||
| {% for l in netlab_interfaces if 'ospf' in l and 'ipv6' in l and 'vrf' not in l %} | ||
| interface {{ l.ifname }} | ||
| ipv6 router ospf area {{ l.ospf.area }} tag {{ ospf_pid }} | ||
| {% if l.ospf.network_type is defined %} | ||
| ipv6 ospf network {{ l.ospf.network_type }} | ||
| {% endif %} | ||
| {% if l.ospf.cost is defined %} | ||
| ipv6 ospf cost {{ l.ospf.cost }} | ||
| {% endif %} | ||
| {% if l.ospf.timers.hello is defined %} | ||
| ipv6 ospf hello-interval {{ l.ospf.timers.hello }} | ||
| {% endif %} | ||
| {% if l.ospf.timers.dead is defined %} | ||
| ipv6 ospf dead-interval {{ l.ospf.timers.dead }} | ||
| {% endif %} | ||
| {% if l.ospf.priority is defined %} | ||
| ipv6 ospf priority {{ l.ospf.priority }} | ||
| {% endif %} | ||
| ! | ||
| {% endfor %} | ||
| {% endif %} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's perfectly OK. Configuration keywords are device-specific in many cases.