Skip to content
Merged
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
37 changes: 18 additions & 19 deletions netsim/validate/ospf/frr.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
def show_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default') -> str:
try:
ipaddress.IPv4Address(id)
except:
raise Exception(f'OSPF router ID {id} is not a valid IPv4 address')
return f'ip ospf ' + (f'vrf {vrf} ' if vrf != 'default' else '') + f'neighbor {id} json'
except Exception as exc:
raise Exception(f'OSPF router ID {id} is not a valid IPv4 address') from exc
return f'ip ospf vrf {vrf} neighbor {id} json'

def valid_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default') -> bool:
_result = global_vars.get_result_dict('_result')
Expand All @@ -31,7 +31,7 @@ def valid_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default') ->
if not present:
return True
raise Exception(f'There is no OSPFv2 neighbor {id}')

n_state = _result[id][0]
if not present:
raise Exception(f'Unexpected OSPFv2 neighbor {id} in state {n_state.nbrState}')
Expand All @@ -42,15 +42,16 @@ def valid_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default') ->
else:
raise log.Result(exit_msg)

def show_ospf6_neighbor(id: str, **kwargs: typing.Any) -> str:
def show_ospf6_neighbor(id: str, present: bool = True, vrf: str = 'default', **kwargs: typing.Any) -> str:
try:
ipaddress.IPv4Address(id)
except:
raise Exception(f'OSPF router ID {id} is not a valid IPv4 address')
return f'ipv6 ospf6 neighbor {id} json'
except Exception as exc:
raise Exception(f'OSPF router ID {id} is not a valid IPv4 address') from exc
return f'ipv6 ospf6 vrf {vrf} neighbor {id} json'

def valid_ospf6_neighbor(id: str, present: bool = True) -> bool:
def valid_ospf6_neighbor(id: str, present: bool = True, vrf: str = 'default') -> bool:
_result = global_vars.get_result_dict('_result')
vrf_name = '' if vrf == 'default' else f' in VRF {vrf}'

n_state = None
for n_idx in _result.keys():
Expand All @@ -62,18 +63,18 @@ def valid_ospf6_neighbor(id: str, present: bool = True) -> bool:
if n_state is None:
if not present:
return True
raise Exception(f'There is no OSPFv3 neighbor {id}')
else:
raise Exception(f'There is no OSPFv3 neighbor {id}{vrf_name}')
else:
if not present:
raise Exception(f'Unexpected OSPFv3 neighbor {id} in state {n_state.neighborState}')
raise Exception(f'Unexpected OSPFv3 neighbor {id}{vrf_name} in state {n_state.neighborState}')

if n_state.neighborState != 'Full':
raise Exception(f'OSPFv3 neighbor {id} is in state {n_state.neighborState}')
raise Exception(f'OSPFv3 neighbor {id}{vrf_name} is in state {n_state.neighborState}')

return True

def show_ospf_prefix(pfx: str, **kwargs: typing.Any) -> str:
return f'ip ospf route json'
return 'ip ospf route json'

def get_ospf_prefix(pfx: str, data: Box, **kwargs: typing.Any) -> typing.Optional[Box]:
return data.get(pfx,None)
Expand Down Expand Up @@ -108,7 +109,7 @@ def valid_ospf_prefix(
names = OSPF_PREFIX_NAMES)

def show_ospf6_prefix(pfx: str, **kwargs: typing.Any) -> str:
return f'ipv6 ospf6 route detail json'
return 'ipv6 ospf6 route detail json'

def get_ospf6_prefix(pfx: str, data: Box) -> typing.Optional[Box]:
return data.get('routes').get(pfx,None)
Expand All @@ -122,8 +123,6 @@ def check_ospf6_cost(data: list, value: typing.Any, **kwargs: typing.Any) -> lis

return m_value

return [ p for p in data if p.metricCost == value ]

def check_ospf6_rt(data: list, value: typing.Any, **kwargs: typing.Any) -> list:
return [ p for p in data if p.pathType == value ]

Expand Down Expand Up @@ -157,10 +156,10 @@ def valid_ipv6_route(

if not _result:
raise Exception(f'The routing table has no {proto} routes')

if not pfx in _result:
raise Exception(f'The prefix {pfx} is not in the routing table or not a {proto} route')

pfx_data = _result[pfx][0]
if cost is not None and cost != pfx_data.metric:
raise Exception(f'Invalid OSPF end-to-end cost for prefix {pfx}: expected {cost} actual {pfx_data.metric}')
Expand Down
94 changes: 67 additions & 27 deletions tests/integration/vlan/52-vlan-vrf-lite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
#
# * Routed VLAN interfaces
# * VRFs
# * OSPF in VRFs
# * OSPF and OSPFv3 in VRFs
#
---
message: |
VRF lite implementation with VLAN trunks
VRF lite implementation with dual-stack VLAN trunks

* h1, h2, and h5 should be able to ping each other
* h3 and h4 should be able to ping each other
* h1, h2, and h5 should be able to ping each other using IPv4 and IPv6
* h3 and h4 should be able to ping each other using IPv4 and IPv6

Please note it might take a while for the lab to work due to
STP and OSPF setup phase
STP, OSPF, and OSPFv3 setup phase

defaults.sources.extra: [ ../wait_times.yml, ../warnings.yml ]
defaults.sources.extra: [ ../vrf/defaults-ipv6-only.yml, ../wait_times.yml, ../warnings.yml ]

groups:
_auto_create: True
Expand Down Expand Up @@ -54,43 +54,83 @@ links:
vlan.trunk: [ red, blue ]

validate:
adj_r1_b:
description: Check OSPF adjacencies (R2-R1)
wait_msg: Waiting for OSPF adjacencies to form
adj_v2_r1_b:
description: Check OSPFv2 adjacencies (R2-R1)
wait_msg: Waiting for OSPFv2 adjacencies to form
wait: ospfv2_adj_stp
nodes: [ r2 ]
plugin: ospf_neighbor(nodes.r1.vrfs.blue.ospf.router_id,vrf='blue')
adj_r1_r:
description: Check OSPF adjacencies (R2-R1)
wait_msg: Waiting for OSPF adjacencies to form
adj_v2_r1_r:
description: Check OSPFv2 adjacencies (R2-R1)
wait_msg: Waiting for OSPFv2 adjacencies to form
wait: ospfv2_adj_lan
nodes: [ r2 ]
plugin: ospf_neighbor(nodes.r1.vrfs.red.ospf.router_id,vrf='red')
adj_r3_b:
description: Check OSPF adjacencies (R2-R3)
wait_msg: Waiting for OSPF adjacencies to form
adj_v2_r3_b:
description: Check OSPFv2 adjacencies (R2-R3)
wait_msg: Waiting for OSPFv2 adjacencies to form
wait: ospfv2_adj_lan
nodes: [ r2 ]
plugin: ospf_neighbor(nodes.r3.vrfs.blue.ospf.router_id,vrf='blue')
adj_r3_r:
description: Check OSPF adjacencies (R2-R3)
wait_msg: Waiting for OSPF adjacencies to form
adj_v2_r3_r:
description: Check OSPFv2 adjacencies (R2-R3)
wait_msg: Waiting for OSPFv2 adjacencies to form
wait: ospfv2_adj_lan
nodes: [ r2 ]
plugin: ospf_neighbor(nodes.r3.vrfs.red.ospf.router_id,vrf='red')
red:
description: Intra-VLAN reachability (red)
adj_v3_r1_b:
description: Check OSPFv3 adjacencies (R2-R1)
wait_msg: Waiting for OSPFv3 adjacencies to form
wait: ospfv3_adj_stp
nodes: [ r2 ]
plugin: ospf6_neighbor(nodes.r1.vrfs.blue.ospf.router_id,vrf='blue')
adj_v3_r1_r:
description: Check OSPFv3 adjacencies (R2-R1)
wait_msg: Waiting for OSPFv3 adjacencies to form
wait: ospfv3_adj_lan
nodes: [ r2 ]
plugin: ospf6_neighbor(nodes.r1.vrfs.red.ospf.router_id,vrf='red')
adj_v3_r3_b:
description: Check OSPFv3 adjacencies (R2-R3)
wait_msg: Waiting for OSPFv3 adjacencies to form
wait: ospfv3_adj_lan
nodes: [ r2 ]
plugin: ospf6_neighbor(nodes.r3.vrfs.blue.ospf.router_id,vrf='blue')
adj_v3_r3_r:
description: Check OSPFv3 adjacencies (R2-R3)
wait_msg: Waiting for OSPFv3 adjacencies to form
wait: ospfv3_adj_lan
nodes: [ r2 ]
plugin: ospf6_neighbor(nodes.r3.vrfs.red.ospf.router_id,vrf='red')
red_v4:
description: IPv4 intra-VLAN reachability (red)
wait_msg: Waiting for STP forwarding state
wait: ping_stp
nodes: [ h1, h2 ]
plugin: ping('h5')
blue:
description: Intra-VLAN reachability (blue)
plugin: ping('h5',af='ipv4')
red_v6:
description: IPv6 intra-VLAN reachability (red)
wait_msg: Waiting for STP forwarding state
wait: ping_stp
nodes: [ h1, h2 ]
plugin: ping('h5',af='ipv6')
blue_v4:
description: IPv4 intra-VLAN reachability (blue)
nodes: [ h3 ]
wait: ping_long
devices: [ linux ]
plugin: ping('h4',af='ipv4')
blue_v6:
description: IPv6 intra-VLAN reachability (blue)
nodes: [ h3 ]
wait: ping_long
devices: [ linux ]
plugin: ping('h4')
filter:
description: Inter-VLAN isolation (red - blue)
plugin: ping('h4',af='ipv6')
filter_v4:
description: IPv4 inter-VLAN isolation (red - blue)
nodes: [ h1, h2 ]
plugin: ping('h3',af='ipv4',expect='fail')
filter_v6:
description: IPv6 inter-VLAN isolation (red - blue)
nodes: [ h1, h2 ]
plugin: ping('h3',expect='fail')
plugin: ping('h3',af='ipv6',expect='fail')