From 6f523a2f05b850cae5b501489697f06e0516315f Mon Sep 17 00:00:00 2001 From: Seb d'Argoeuves Date: Wed, 7 Oct 2026 15:21:04 +0000 Subject: [PATCH 1/2] ASAv: static routes --- docs/caveats.md | 2 ++ netsim/ansible/templates/routing/asa.j2 | 22 ++++++++++++++++++++++ netsim/devices/asav.yml | 5 +++++ 3 files changed, 29 insertions(+) create mode 100644 netsim/ansible/templates/routing/asa.j2 diff --git a/docs/caveats.md b/docs/caveats.md index f628ad5506..8e62da1f72 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -167,6 +167,8 @@ and validation. Configuration is deployed with a bash script executed within the * The ASAv IS-IS configuration templates were not tested, as all IS-IS integration tests include at least one point-to-point circuit * ASAv implements OSPFv2 point-to-point links with the `point-to-point non-broadcast` network type. *netlab* configures static OSPF neighbors on these links. * We did not implement OSPFv3 for ASAv +* ASAv static routes require an outgoing interface. *netlab* does not configure static routes with indirect next hops on ASAv. +* ASAv does not support equal-cost static routes over multiple interfaces. *netlab* configures only the first next hop of a static route. (caveats-cat8000v)= ## Cisco Catalyst 8000v diff --git a/netsim/ansible/templates/routing/asa.j2 b/netsim/ansible/templates/routing/asa.j2 new file mode 100644 index 0000000000..b43e7ab17e --- /dev/null +++ b/netsim/ansible/templates/routing/asa.j2 @@ -0,0 +1,22 @@ +{# + ASA static routes need the outgoing interface (nameif == ifname in the initial template), + so only directly-connected next hops and discard routes can be configured +#} +{% for sr_data in routing.static|default([]) if 'intf' in sr_data.nexthop or 'discard' in sr_data.nexthop %} +{% if loop.first %} +! +! Static routes +! +{% endif %} +{% set sr_intf = 'Null0' if 'discard' in sr_data.nexthop else sr_data.nexthop.intf %} +{% if 'ipv4' in sr_data %} +route {{ sr_intf }} {{ + sr_data.ipv4|ansible.utils.ipaddr('network') }} {{ + sr_data.ipv4|ansible.utils.ipaddr('netmask') }}{{ + '' if 'discard' in sr_data.nexthop else ' ' + sr_data.nexthop.ipv4 }} +{% endif %} +{% if 'ipv6' in sr_data %} +ipv6 route {{ sr_intf }} {{ sr_data.ipv6 }}{{ + '' if 'discard' in sr_data.nexthop else ' ' + sr_data.nexthop.ipv6 }} +{% endif %} +{% endfor %} diff --git a/netsim/devices/asav.yml b/netsim/devices/asav.yml index 25bc7eb787..00b14a4170 100644 --- a/netsim/devices/asav.yml +++ b/netsim/devices/asav.yml @@ -34,6 +34,11 @@ features: password: true priority: true timers: true + routing: + static: + caveats: true + discard: true + max_nexthop: 1 libvirt: image: cisco/asav create_template: asav.xml.j2 From fa55126962f986852f9288d1da85b490b75e16fc Mon Sep 17 00:00:00 2001 From: Seb d'Argoeuves Date: Sun, 11 Oct 2026 00:15:40 +0000 Subject: [PATCH 2/2] ASAv: Quirk for indirect routing --- netsim/devices/asav.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netsim/devices/asav.py b/netsim/devices/asav.py index efa92b3fff..897c4e366a 100644 --- a/netsim/devices/asav.py +++ b/netsim/devices/asav.py @@ -5,6 +5,7 @@ from ..utils import log from . import _Quirks, report_quirk +from ._common import check_indirect_static_routes def check_isis_p2p_interfaces(node: Box, topology: Box, igp: str = 'isis') -> None: @@ -24,6 +25,7 @@ class ASA(_Quirks): @classmethod def device_quirks(self, node: Box, topology: Box) -> None: + check_indirect_static_routes(node) mods = node.get('module', []) for igp in ('isis'): if igp in mods: