Skip to content
Draft
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
51 changes: 51 additions & 0 deletions netsim/validate/bgp/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,57 @@ def valid_bgp_neighbor(

return f'Neighbor {n_addr} ({n_id}) is in state {data[n_addr].peerState}'

def show_bgp_neighbor_details(ngb: list, n_id: str, af: str='ipv4', *, activate: str = '', **kwargs: typing.Any) -> str:
n_addr = _common.get_bgp_neighbor_id(ngb,n_id,af)
global af_lookup
if not activate:
return f'bgp neighbors {n_addr} | json'

if activate not in af_lookup:
raise Exception(f'Unsupported address family {activate}')

return f'bgp {af_lookup[activate]} neighbors {n_addr} | json'

def valid_bgp_neighbor_details(
ngb: list,
n_id: str,
af: str = 'ipv4',
state: str = 'Established',
vrf: str = 'default',
activate: str = '',
intf: str = '',
bfd: bool = False) -> str:
_result = global_vars.get_result_dict('_result')
n_addr = _common.get_bgp_neighbor_id(ngb,n_id,af)

data = check_vrf_data(_result,vrf,'peerList','BGP peers')

act_err = f' in address family {activate}' if activate else ''
found = next(item for item in data if item.peerAddress == n_addr)

if not found:
result = f'The router has no BGP neighbor with {af} address {n_addr} ({n_id}){act_err}'
if state == 'missing':
return result
else:
raise Exception(result)

if not state == found.state:
result = f'The neighbor {n_addr} ({n_id}){act_err} is in state {found.state}'
if state == 'missing' and data[0].state != 'Established':
return result
else:
raise Exception(f'{result} (expected {state})')

if not bfd:
return result

result = f'The neighbor {n_addr} ({n_id}){act_err} is in BFD state {found.bfdState}'
if not found.bfdState == 3:
raise Exception(f'{result} (expected 3 - Up)')

return result

"""
BGP prefix checks, starting with 'get a BGP prefix from JSON results'
"""
Expand Down
11 changes: 10 additions & 1 deletion netsim/validate/bgp/frr.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ def show_bgp_neighbor_details(ngb: list, n_id: str, af: str = 'ipv4', **kwargs:
def valid_bgp_neighbor_details(
ngb: list,
n_id: str,
af: str = 'ipv4',**kwargs: typing.Any) -> str:
af: str = 'ipv4',
bfd: bool = False,
**kwargs: typing.Any) -> str:
_result = global_vars.get_result_dict('_result')

n_addr = _common.get_bgp_neighbor_id(ngb,n_id,af)
Expand All @@ -101,6 +103,13 @@ def valid_bgp_neighbor_details(
if data[k] != v:
raise Exception(f'{k} expected value {v} actual {data[k]}')

if bfd:
if data.peerBfdInfo:
if data.peerBfdInfo.status != 'Up':
raise Exception(f'BGP {k} expected value UP actual {data.peerBfdInfo.status}')
else:
raise Exception(f'No BFD information for BGP peer {n_id}')

return f'All specified BGP neighbor parameters have the expected values'

"""
Expand Down
45 changes: 43 additions & 2 deletions tests/integration/bgp.session/13-bfd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ message: |
This lab tests the BGP BFD functionality. The EBGP session between the probe
and the lab device should trigger a BFD session between them.

The final test disables BFD on the probe to verify that the BGP session is
promptly torn down when BFD fails. It catches the FRR 10.5.1 regression that
kept BGP sessions with default timers Established for 30 seconds after BFD
failure. To run the test against FRR 10.5.1:

netlab up tests/integration/bgp.session/13-bfd.yml --validate \
--set defaults.devices.frr.clab.image=quay.io/frrouting/frr:10.5.1

plugin: [ bgp.session ]
module: [ bgp, bfd ]

Expand All @@ -16,13 +24,13 @@ groups:
nodes:
dut:
bgp.as: 65000
config: [ static_bfd ]
x1:
bgp.as: 65100
config: [ static_bfd ]
bgp.bfd: True

links:
- dut:
bgp.bfd: True
x1:
pool: p2p # Force addressing to come from the p2p pool, else with host devices like bird it becomes a lan

Expand All @@ -34,13 +42,46 @@ validate:
nodes: [ x1 ]
plugin: bgp_neighbor(node.bgp.neighbors,'dut')

bgp_bfd_v4:
description: Check IPv4 EBGP sessions with DUT
wait_msg: Waiting for BFD EBGP session data
wait: ebgp_session
nodes: [ x1 ]
plugin: bgp_neighbor_details(node.bgp.neighbors,'dut',bfd='True')

bfd_v4:
description: Check BFD peer on X1
wait_msg: Waiting for BFD to start
wait: bfd_init
nodes: [ x1 ]
show:
eos: "bfd peers | json"
frr: "bfd peers json"
valid:
eos: >-
vrfs.default.ipv4Neighbors["10.1.0.1"].peers.Ethernet1.types.normal.peerStats["10.1.0.2"].status == "up"
frr: >-
result[0].status == "up"

drop_bfd_x1:
description: Disable BFD on X1 BGP neighbor
nodes: [ x1 ]
devices: [ frr ]
exec: >-
vtysh -c "configure terminal" -c "router bgp 65100" -c "no neighbor 10.1.0.1 bfd"
pass: BFD disabled on X1 BGP neighbor

bfd_bgp_down:
description: BGP session should go down promptly after BFD failure
wait_msg: Waiting for BFD failure to tear down BGP
wait: bfd_init
nodes: [ x1 ]
plugin: bgp_neighbor(node.bgp.neighbors,'dut',state=['Idle','Active','Connect'])

restore_bfd_x1:
description: Restore BFD on X1 BGP neighbor
nodes: [ x1 ]
devices: [ frr ]
exec: >-
vtysh -c "configure terminal" -c "router bgp 65100" -c "neighbor 10.1.0.1 bfd"
pass: BFD restored on X1 BGP neighbor