diff --git a/netsim/validate/ospf/eos.py b/netsim/validate/ospf/eos.py index 3b54baacdd..df604786d0 100644 --- a/netsim/validate/ospf/eos.py +++ b/netsim/validate/ospf/eos.py @@ -29,7 +29,7 @@ def get_ospf_neighbor_data(data: Box, *, id: str, proto: str, vrf: str = 'defaul ngb_list = [ ngb for ngb in ngb_list if ngb.routerId == id ] return ngb_list -def show_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default') -> str: +def show_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default', bfd: bool = False) -> str: try: ipaddress.IPv4Address(id) except: @@ -41,7 +41,8 @@ def valid_ospf_neighbor( present: bool = True, vrf: str = 'default',*, proto: str='ospf', - proto_name: str = 'OSPFv2') -> bool: + proto_name: str = 'OSPFv2', + bfd: bool = False) -> bool: _result = global_vars.get_result_dict('_result') ngb_list = get_ospf_neighbor_data(_result,id=id,proto=proto,vrf=vrf) @@ -54,9 +55,15 @@ def valid_ospf_neighbor( if not present: raise Exception(f'Unexpected {proto_name} neighbor {id} in state {n_state.adjacencyState}') - _common.report_state( - exit_msg=f'{proto_name} neighbor {id} is in state {n_state.adjacencyState}', - OK=n_state.adjacencyState.startswith('full')) + exit_msg = f'{proto_name} neighbor {id} is in state {n_state.adjacencyState}' + if not n_state.adjacencyState.startswith('full'): + raise Exception(exit_msg) + + if not bfd: + raise log.Result(exit_msg) + + exit_msg = f'{proto_name} neighbor {id} is in BFD state {n_state.details.bfdState}' + _common.report_state(exit_msg,n_state.details.bfdState == "up") def show_ospf6_neighbor(id: str, present: bool = True, vrf: str = 'default', **kwargs: typing.Any) -> str: try: diff --git a/netsim/validate/ospf/frr.py b/netsim/validate/ospf/frr.py index eb3e8f0fb0..6b5aa86215 100644 --- a/netsim/validate/ospf/frr.py +++ b/netsim/validate/ospf/frr.py @@ -14,14 +14,14 @@ from . import OSPF_PREFIX_NAMES -def show_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default') -> str: +def show_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default', bfd: bool = False) -> str: try: ipaddress.IPv4Address(id) 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' + return f'ip ospf vrf {vrf} neighbor {id} detail json' -def valid_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default') -> bool: +def valid_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default', bfd: bool = False) -> bool: _result = global_vars.get_result_dict('_result') if vrf in _result: @@ -36,12 +36,21 @@ def valid_ospf_neighbor(id: str, present: bool = True, vrf: str = 'default') -> if not present: raise Exception(f'Unexpected OSPFv2 neighbor {id} in state {n_state.nbrState}') + exit_msg = f'OSPFv2 neighbor {id} is in state {n_state.nbrState}' if not n_state.nbrState.startswith('Full'): raise Exception(exit_msg) - else: + + if not bfd: raise log.Result(exit_msg) + exit_msg = f'OSPFv2 neighbor {id} is in BFD state {n_state.peerBfdInfo.status}' + if not n_state.peerBfdInfo.status == "Up": + raise Exception(exit_msg) + + raise log.Result(exit_msg) + + def show_ospf6_neighbor(id: str, present: bool = True, vrf: str = 'default', **kwargs: typing.Any) -> str: try: ipaddress.IPv4Address(id) @@ -49,7 +58,7 @@ def show_ospf6_neighbor(id: str, present: bool = True, vrf: str = 'default', **k 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, vrf: str = 'default') -> bool: +def valid_ospf6_neighbor(id: str, present: bool = True, vrf: str = 'default', bfd: bool = False) -> bool: _result = global_vars.get_result_dict('_result') vrf_name = '' if vrf == 'default' else f' in VRF {vrf}' @@ -68,10 +77,15 @@ def valid_ospf6_neighbor(id: str, present: bool = True, vrf: str = 'default') -> if not present: raise Exception(f'Unexpected OSPFv3 neighbor {id}{vrf_name} in state {n_state.neighborState}') + ngb_msg = f'OSPFv3 neighbor {id}{vrf_name} is in state {n_state.neighborState}' if n_state.neighborState != 'Full': - raise Exception(f'OSPFv3 neighbor {id}{vrf_name} is in state {n_state.neighborState}') + raise Exception(ngb_msg) + + if not bfd: + raise log.Result(ngb_msg) - return True + exit_msg = f'OSPFv3 neighbor {id} is in BFD state {n_state.peerBfdInfo.status}' + _common.report_state(exit_msg,n_state.peerBfdInfo and n_state.peerBfdInfo.status == "Up") def show_ospf_prefix(pfx: str, **kwargs: typing.Any) -> str: return 'ip ospf route json' diff --git a/tests/integration/ospf/ospfv2/42-bfd.yml b/tests/integration/ospf/ospfv2/42-bfd.yml new file mode 100644 index 0000000000..0d65cb090f --- /dev/null +++ b/tests/integration/ospf/ospfv2/42-bfd.yml @@ -0,0 +1,47 @@ +message: | + This topology tests the OSPFv2 with BFD + + * Multiple OSPF areas on ABR + * BFD enabled on all interfaces + +defaults.sources.extra: [ ../../wait_times.yml, ../../warnings.yml ] +module: [ ospf, bfd ] + +ospf.bfd.ipv4: True + +groups: + probes: + device: frr + provider: clab + members: [ bb, r1 ] + mtu: 1500 + +nodes: + dut: + bb: + r1: + ospf.area: 1 + +links: +- dut-bb +- dut: + r1: + ospf: + area: 1 + cost: 42 + network_type: broadcast +- dut: + +validate: + adj: + description: Check OSPF adjacencies + wait: ospfv2_adj_lan + wait_msg: Waiting for OSPF adjacency process to complete + nodes: [ r1, bb ] + plugin: ospf_neighbor(nodes.dut.ospf.router_id) + ospf_bfd: + description: Check OSPF BFD adjacencies + wait: ospfv2_adj_p2p + wait_msg: Waiting for OSPF BFD adjacency process to complete + nodes: [ r1, bb ] + plugin: ospf_neighbor(nodes.dut.ospf.router_id,bfd=True) diff --git a/tests/integration/ospf/ospfv2/bfd.yml b/tests/integration/ospf/ospfv2/bfd.yml deleted file mode 100644 index 3d75caf319..0000000000 --- a/tests/integration/ospf/ospfv2/bfd.yml +++ /dev/null @@ -1,26 +0,0 @@ -message: | - This topology tests the OSPFv2 with BFD - - * Multiple OSPF areas on ABR - * BFD enabled on all interfaces - -module: [ ospf, bfd ] - -ospf.bfd.ipv4: True - -nodes: - bb: - ospf.router_id: 10.42.42.1 - abr: - r1: - ospf.area: 1 - -links: -- bb-abr -- abr: - r1: - ospf: - area: 1 - cost: 42 - network_type: broadcast -- abr: diff --git a/tests/integration/ospf/ospfv3/42-bfd.yml b/tests/integration/ospf/ospfv3/42-bfd.yml new file mode 100644 index 0000000000..16606d6e0c --- /dev/null +++ b/tests/integration/ospf/ospfv3/42-bfd.yml @@ -0,0 +1,47 @@ +message: | + This topology tests the OSPFv2 with BFD + + * Multiple OSPF areas on ABR + * BFD enabled on all interfaces + +defaults.sources.extra: [ ../../wait_times.yml, ../../warnings.yml ] +module: [ ospf, bfd ] + +ospf.bfd.ipv6: True + +groups: + probes: + device: frr + provider: clab + members: [ bb, r1 ] + mtu: 1500 + +nodes: + dut: + bb: + r1: + ospf.area: 1 + +links: +- dut-bb +- dut: + r1: + ospf: + area: 1 + cost: 42 + network_type: broadcast +- dut: + +validate: + adj: + description: Check OSPFv3 adjacencies + wait: ospfv3_adj_lan + wait_msg: Waiting for OSPFv3 adjacency process to complete + nodes: [ r1, bb ] + plugin: ospf6_neighbor(nodes.dut.ospf.router_id) + ospf_bfd: + description: Check OSPFv3 BFD adjacencies + wait: ospfv2_adj_p2p + wait_msg: Waiting for OSPFv3 BFD adjacency process to complete + nodes: [ r1, bb ] + plugin: ospf6_neighbor(nodes.dut.ospf.router_id,bfd=True) diff --git a/tests/integration/ospf/ospfv3/bfd.yml b/tests/integration/ospf/ospfv3/bfd.yml deleted file mode 100644 index 0bb5bc01bd..0000000000 --- a/tests/integration/ospf/ospfv3/bfd.yml +++ /dev/null @@ -1,37 +0,0 @@ -message: | - This topology tests the OSPFv3 with BFD - - * Multiple OSPF areas on ABR - * BFD enabled on all interfaces - -addressing: - loopback: - ipv4: False - ipv6: 2001:db8:1::/48 - lan: - ipv4: False - ipv6: 2001:db8:2::/48 - p2p: - ipv4: False - ipv6: 2001:db8:3::/48 - -module: [ ospf, bfd ] - -ospf.bfd.ipv6: True - -nodes: - bb: - ospf.router_id: 10.42.42.1 - abr: - r1: - ospf.area: 1 - -links: -- bb-abr -- abr: - r1: - ospf: - area: 1 - cost: 42 - network_type: broadcast -- abr: