Skip to content

Commit fdc92eb

Browse files
authored
Fix bgp_neighbor validation plugin implementations (#3580)
* Make EOS and FRR implementations VRF-aware * Fix the FRR check when state=missing Also: * Added integration test
1 parent 2de4181 commit fdc92eb

4 files changed

Lines changed: 161 additions & 15 deletions

File tree

netsim/validate/bgp/eos.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,21 @@ def check_vrf_data(data: Box, vrf: str, key: str, missing_data: str) -> Box:
3131
'vpnv6': 'vpn-ipv6'
3232
}
3333

34-
def show_bgp_neighbor(ngb: list, n_id: str, af: str='ipv4', *, activate: str = '', **kwargs: typing.Any) -> str:
34+
def show_bgp_neighbor(
35+
ngb: list,
36+
n_id: str,
37+
af: str='ipv4', *,
38+
vrf: str = 'default',
39+
activate: str = '', **kwargs: typing.Any) -> str:
3540
global af_lookup
36-
if not activate:
37-
return 'bgp summary | json'
38-
39-
if activate not in af_lookup:
41+
if not activate:
42+
bgp_cmd = 'bgp summary'
43+
elif activate not in af_lookup:
4044
raise Exception(f'Unsupported address family {activate}')
45+
else:
46+
bgp_cmd = f'bgp {af_lookup[activate]} summary'
4147

42-
return f'bgp {af_lookup[activate]} summary | json'
48+
return f'{bgp_cmd} vrf {vrf} | json'
4349

4450
def valid_bgp_neighbor(
4551
ngb: list,
@@ -59,7 +65,6 @@ def valid_bgp_neighbor(
5965
# n_addr = intf
6066

6167
data = check_vrf_data(_result,vrf,'peers','BGP peers')
62-
6368
act_err = f' in address family {activate}' if activate else ''
6469
if not n_addr in data:
6570
result = f'The router has no BGP neighbor with {af} address {n_addr} ({n_id}){act_err}'

netsim/validate/bgp/frr.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,27 @@
2929
'vpnv6': 'ipv6 vpn summary'
3030
}
3131

32-
def show_bgp_neighbor(ngb: list, n_id: str, af: str='ipv4', activate: str = '', **kwargs: typing.Any) -> str:
32+
def show_bgp_neighbor(
33+
ngb: list,
34+
n_id: str,
35+
af: str='ipv4', *,
36+
vrf: str = 'default',
37+
activate: str = '', **kwargs: typing.Any) -> str:
3338
global af_lookup
3439

3540
if not activate:
36-
return "bgp summary json"
41+
return f"bgp vrf {vrf} summary json"
3742

3843
if activate not in af_lookup:
39-
raise Exception(f'Unsupport address family {activate}')
44+
raise Exception(f'Unsupported address family {activate}')
4045

41-
return f"bgp {af_kw[activate]} json"
46+
return f"bgp vrf {vrf} {af_kw[activate]} json"
4247

4348
def valid_bgp_neighbor(
4449
ngb: list,
4550
n_id: str,
46-
af: str = 'ipv4',
51+
af: str = 'ipv4', *,
52+
vrf: str = 'default',
4753
state: str = 'Established',
4854
activate: str = '',
4955
intf: str = '') -> str:
@@ -77,8 +83,13 @@ def valid_bgp_neighbor(
7783
else:
7884
raise Exception(result)
7985

80-
if data[n_addr].state not in state:
81-
raise Exception(f'The neighbor {n_addr} ({n_id}) {act_err} is in state {data[n_addr].state} (expected {state})')
86+
p_state = data[n_addr].state
87+
if p_state not in state:
88+
result = f'The neighbor {n_addr} ({n_id}) {act_err} is in state {p_state}'
89+
if state == 'missing' and p_state != 'Established':
90+
return result
91+
else:
92+
raise Exception(f'{result} (expected {state})')
8293

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

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
message: |
2+
Check the 'bgp_neighbor' validation plugin
3+
4+
defaults.sources.extra: [ ../../integration/wait_times.yml ]
5+
6+
module: [ bgp, vrf ]
7+
groups:
8+
probes:
9+
members: [ r1, r2, r3, vr1, vr2 ]
10+
module: [ bgp ]
11+
device: frr
12+
13+
vrfs:
14+
tenant:
15+
links:
16+
- interfaces: [ dut_eos, dut_frr, vr1, vr3 ]
17+
prefix.ipv4: 172.16.2.0/24
18+
- interfaces: [ dut_eos, dut_frr, vr2, vr3 ]
19+
prefix.ipv6: 2001:db8:0:2::/64
20+
21+
# Node device type for DUT devices set via default groups
22+
#
23+
nodes:
24+
dut_eos.bgp.as: 65001
25+
dut_frr.bgp.as: 65002
26+
r1.bgp.as: 65101
27+
r2.bgp.as: 65102
28+
r3:
29+
bgp.as: 65103
30+
skip_config: [ bgp ]
31+
vr1.bgp.as: 65201
32+
vr2.bgp.as: 65202
33+
vr3:
34+
bgp.as: 65203
35+
skip_config: [ bgp ]
36+
37+
links:
38+
- interfaces: [ dut_eos, dut_frr, r1, r3 ]
39+
prefix.ipv4: 172.16.1.0/24
40+
- interfaces: [ dut_eos, dut_frr, r2, r3 ]
41+
prefix.ipv6: 2001:db8:0:1::/64
42+
43+
validate:
44+
# Check BGP sessions that are expected to be up (global + VRF)
45+
#
46+
bgp_ipv4:
47+
nodes: [ dut_eos, dut_frr ]
48+
wait: ebgp_session
49+
plugin: bgp_neighbor(node.bgp.neighbors,'r1')
50+
bgp_ipv6:
51+
nodes: [ dut_eos, dut_frr ]
52+
wait: ebgp_session
53+
plugin: bgp_neighbor(node.bgp.neighbors,'r2',af='ipv6')
54+
vrf_bgp_ipv4:
55+
nodes: [ dut_eos, dut_frr ]
56+
wait: ebgp_session
57+
plugin: bgp_neighbor(node.vrfs.tenant.bgp.neighbors,'vr1',vrf='tenant')
58+
vrf_bgp_ipv6:
59+
nodes: [ dut_eos, dut_frr ]
60+
wait: ebgp_session
61+
plugin: bgp_neighbor(node.vrfs.tenant.bgp.neighbors,'vr2',af='ipv6',vrf='tenant')
62+
63+
# Check the activation of BGP address families
64+
#
65+
act_ipv4:
66+
nodes: [ dut_eos, dut_frr ]
67+
wait: ebgp_session
68+
plugin: bgp_neighbor(node.bgp.neighbors,'r1',activate='ipv4')
69+
act_ipv6:
70+
nodes: [ dut_eos, dut_frr ]
71+
wait: ebgp_session
72+
plugin: bgp_neighbor(node.bgp.neighbors,'r2',af='ipv6',activate='ipv6')
73+
vrf_act_ipv4:
74+
nodes: [ dut_eos, dut_frr ]
75+
plugin: bgp_neighbor(node.vrfs.tenant.bgp.neighbors,'vr1',activate='ipv4',vrf='tenant')
76+
vrf_act_ipv6:
77+
nodes: [ dut_eos, dut_frr ]
78+
plugin: bgp_neighbor(node.vrfs.tenant.bgp.neighbors,'vr2',af='ipv6',activate='ipv6',vrf='tenant')
79+
80+
# Check that 'state=missing' matches BGP session that is not established or missing AFs
81+
#
82+
miss_ipv4:
83+
nodes: [ dut_eos, dut_frr ]
84+
plugin: bgp_neighbor(node.bgp.neighbors,'r3',af='ipv4',state='missing')
85+
miss_ipv6:
86+
nodes: [ dut_eos, dut_frr ]
87+
plugin: bgp_neighbor(node.bgp.neighbors,'r3',af='ipv6',state='missing')
88+
miss_act_ipv4:
89+
nodes: [ dut_eos, dut_frr ]
90+
wait: ebgp_session
91+
plugin: bgp_neighbor(node.bgp.neighbors,'r1',activate='ipv6',state='missing')
92+
miss_act_ipv6:
93+
nodes: [ dut_eos, dut_frr ]
94+
wait: ebgp_session
95+
plugin: bgp_neighbor(node.bgp.neighbors,'r2',af='ipv6',activate='ipv4',state='missing')
96+
97+
# Check matching explicit states
98+
#
99+
state_ipv4:
100+
nodes: [ dut_eos, dut_frr ]
101+
wait: 3
102+
plugin: bgp_neighbor(node.bgp.neighbors,'r3',af='ipv4',state=['Idle','Active'])
103+
state_ipv6:
104+
nodes: [ dut_eos, dut_frr ]
105+
wait: 3
106+
plugin: bgp_neighbor(node.bgp.neighbors,'r3',af='ipv6',state=['Idle','Active'])
107+
108+
# Check that bgp_neighbor with no extra parameters fails as expected on missing BGP session
109+
#
110+
fail_ipv4:
111+
nodes: [ dut_eos, dut_frr ]
112+
plugin: bgp_neighbor(node.bgp.neighbors,'r3',af='ipv4')
113+
_expect_fail: True
114+
fail_ipv6:
115+
nodes: [ dut_eos, dut_frr ]
116+
plugin: bgp_neighbor(node.bgp.neighbors,'r3',af='ipv6')
117+
_expect_fail: True
118+
119+
# Check missing BGP AFs
120+
#
121+
fail_act_ipv6:
122+
nodes: [ dut_eos, dut_frr ]
123+
plugin: bgp_neighbor(node.bgp.neighbors,'r1',activate='ipv6')
124+
_expect_fail: True
125+
fail_act_ipv4:
126+
nodes: [ dut_eos, dut_frr ]
127+
plugin: bgp_neighbor(node.bgp.neighbors,'r2',af='ipv6',activate='ipv4')
128+
_expect_fail: True

tests/platform-integration/validate/topology-defaults.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@ groups:
1414
members: [ h1, h2, h3 ]
1515
device: linux
1616
grp_frr_probes:
17-
members: [ r1, r2, r3 ]
17+
members: [ r1, r2, r3, r4 ]
1818
device: frr
19+
probes:
20+
members: [ grp_linux_probes, grp_frr_probes ]

0 commit comments

Comments
 (0)