Skip to content
1 change: 1 addition & 0 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
plugins/mlag.vtep.md
plugins/multilab.md
plugins/node.clone.md
plugins/ospf.stub.md
plugins/vrrp.version.md
plugins/firewall.zonebased.md
```
Expand Down
42 changes: 42 additions & 0 deletions docs/plugins/ospf.stub.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
(plugin-ospf-stub)=
# Fine-grained Control Over OSPF Area Route Propagation

The **ospf.stub** plugin extends OSPF topology modeling by adding native support for stub, totally stubby, NSSA,
and totally NSSA areas. These specialized OSPF area types are commonly used to simplify routing in enterprise networks
by reducing the number of LSAs exchanged and minimizing routing table size in remote or branch locations. With this
plugin, Netlab will automatically generate the correct configurations on all routers in the area, including the
appropriate ABR settings. This makes it easy to model and validate optimized OSPF designs in your lab topologies.

```eval_rst
.. contents:: Table of Contents
:depth: 2
:local:
:backlinks: none
```

## Platform support

| Operating system | Stub areas |
|---------------------|:----------:|
| Cumulus 5.x NVUE | ✅ |
| Dell OS10 | ✅ |
| FRR | ✅ |

## Using the Plugin

To use the plugin, add it to the **plugin** list in the lab topology:

```
plugin: [ ...., ospf.stub ]
```

This enables support for ospf.areas:

```
module: [ ospf ]

ospf.areas:
1:
kind: stub
no_summarize: True
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest to add also the param range as an array of subnets for area range config - to be applied only on ABR

10 changes: 10 additions & 0 deletions netsim/extra/ospf.stub/cumulus_nvue.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% for id,area in ospf.areas.items() %}
- set:
vrf:
default:
router:
ospf:
area:
{{ id | ipv4 }}:
type: {{ 'totally-' if area.get('no_summary') else '' }}{{ area.kind }}
{% endfor %}
23 changes: 23 additions & 0 deletions netsim/extra/ospf.stub/defaults.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
devices:
cumulus_nvue.features.ospf:
stub: True
dellos10.features.ospf:
stub: True
frr.features.ospf:
stub: True
none.features.ospf:
stub: True

ospf:
attributes:
global:
areas:
type: dict
_requires: [ ospf ]
_keytype: int
_subtype:
kind: { 'type': str, 'valid_values': [ stub, nssa ] }
no_summary: bool
node:
areas:
6 changes: 6 additions & 0 deletions netsim/extra/ospf.stub/dellos10.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% set pid = ospf.process|default(1) %}

router ospf {{ pid }}
{% for id,area in ospf.areas.items() %}
area {{ id }} {{ area.kind }}{{ ' no-summary' if area.get('no_summary') else '' }}
{% endfor %}
4 changes: 4 additions & 0 deletions netsim/extra/ospf.stub/frr.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
router ospf
{% for id,area in ospf.areas.items() %}
area {{ id }} {{ area.kind }}{{ ' no-summary' if area.get('no_summary') else '' }}
{% endfor %}
25 changes: 25 additions & 0 deletions netsim/extra/ospf.stub/plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import typing
from box import Box
from netsim import api
from netsim.augment import devices
from netsim.utils import log

_config_name = "ospf.stub"
_require = [ "ospf" ]

def post_transform(topology: Box) -> None:
for ndata in topology.nodes.values():
if not 'ospf' in ndata.get('module',[]):
continue
ospf_areas = ndata.get('ospf.areas',{})
if not ospf_areas:
continue
features = devices.get_device_features(ndata,topology.defaults)
if 'stub' not in features.ospf:
log.error(f"Node {ndata.name} (device {ndata.device}) not supported by the ospf.stub plugin")
continue
if ndata.get('ospf.area','0.0.0.0') != '0.0.0.0': # Check if node is an ABR
for _,area in ospf_areas.items():
area.pop('no_summary',None)
global _config_name
api.node_config(ndata,_config_name)
22 changes: 22 additions & 0 deletions tests/integration/ospf.stub/01-ospf-stub.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
plugin: [ ospf.stub ]

module: [ ospf ]

ospf.areas:
1:
kind: stub
no_summary: True

nodes:
r1:
r2:
ospf.area: 1
r3:

links:
- r1:
r2:
ospf.area: 1

- r1-r3