14
14
from tests .common import constants
15
15
16
16
pytestmark = [
17
- pytest .mark .topology ('t0' , 't1' , 't1-lag ' )
17
+ pytest .mark .topology ('t1 ' )
18
18
]
19
19
20
- def skip_201911_and_older (duthost ):
21
- """ Skip the current test if the DUT version is 201911 or older.
22
- """
23
- if parse_version (duthost .kernel_version ) <= parse_version ('4.9.0' ):
24
- pytest .skip ("Test not supported for 201911 images or older. Skipping the test" )
25
-
20
+ BFD_RESPONDER_SCRIPT_SRC_PATH = '../ansible/roles/test/files/helpers/bfd_responder.py'
21
+ BFD_RESPONDER_SCRIPT_DEST_PATH = '/opt/bfd_responder.py'
26
22
27
23
def is_dualtor (tbinfo ):
28
24
"""Check if the testbed is dualtor."""
@@ -96,6 +92,47 @@ def get_neighbors(duthost, tbinfo, ipv6=False, count=1):
96
92
return [t1_ipv4_pattern .format (idx * 2 ) for idx in indices ], 31 , [t1_ipv4_pattern .format (idx * 2 + 1 ) for idx in indices ], [t0_intfs [_ ] for _ in indices ], [ptf_ports [_ ] for _ in indices ]
97
93
98
94
95
+ def get_loopback_intf (mg_facts , ipv6 ):
96
+ ipv6idx = 0 if mg_facts ['minigraph_lo_interfaces' ][0 ]['prefixlen' ] == 128 else 1
97
+ if ipv6 :
98
+ return mg_facts ['minigraph_lo_interfaces' ][ipv6idx ]['addr' ]
99
+ else :
100
+ return mg_facts ['minigraph_lo_interfaces' ][(ipv6idx + 1 ) % 2 ]['addr' ]
101
+
102
+ def get_neighbors_multihop (duthost , tbinfo , ipv6 = False , count = 1 ):
103
+ mg_facts = duthost .get_extended_minigraph_facts (tbinfo )
104
+ t0_ipv4_pattern = '4.{}.{}.1'
105
+ t0_ipv6_pattern = '3000:3000:{:x}::3000'
106
+ t0_intfs = get_t0_intfs (mg_facts )
107
+ ptf_ports = [mg_facts ['minigraph_ptf_indices' ][port ] for port in t0_intfs ]
108
+ loopback_addr = get_loopback_intf ( mg_facts , ipv6 )
109
+
110
+ index = random .sample (list (range (len (t0_intfs ))), k = 1 )[0 ]
111
+ port_intf = t0_intfs [index ]
112
+ ptf_intf = ptf_ports [index ]
113
+ nexthop_ip = ""
114
+ neighbour_dev_name = mg_facts ['minigraph_neighbors' ][port_intf ]['name' ]
115
+ for bgpinfo in mg_facts ['minigraph_bgp' ]:
116
+ if bgpinfo ['name' ] == neighbour_dev_name :
117
+ nexthop_ip = bgpinfo ['addr' ]
118
+ if ipv6 and ":" not in nexthop_ip :
119
+ nexthop_ip = ""
120
+ continue
121
+ break
122
+ if nexthop_ip == "" :
123
+ assert False
124
+ neighbor_addrs = []
125
+ idx2 = 0
126
+ for idx in range (1 , count ):
127
+ if idx % 250 == 0 :
128
+ idx2 += 1
129
+ if ipv6 :
130
+ neighbor_addrs .append (t0_ipv6_pattern .format (idx ))
131
+ else :
132
+ neighbor_addrs .append (t0_ipv4_pattern .format ((idx % 250 ),idx2 ))
133
+
134
+ return loopback_addr , ptf_intf , nexthop_ip , neighbor_addrs
135
+
99
136
def init_ptf_bfd (ptfhost ):
100
137
ptfhost .shell ("bfdd-beacon" )
101
138
@@ -117,7 +154,13 @@ def del_ipaddr(ptfhost, neighbor_addrs, prefix_len, neighbor_interfaces, ipv6=Fa
117
154
if ipv6 :
118
155
ptfhost .shell ("ip -6 addr del {}/{} dev eth{}" .format (neighbor_addrs [idx ], prefix_len , neighbor_interfaces [idx ]), module_ignore_errors = True )
119
156
else :
120
- ptfhost .shell ("ip addr del {}/{} dev eth{}" .format (neighbor_addrs [idx ], prefix_len , neighbor_interfaces [idx ]), module_ignore_errors = True )
157
+ cmd_buffer += "ip addr del {}/{} dev eth{} ;" .format (neighbor_addrs [idx ], prefix_len ,
158
+ neighbor_interfaces [idx ])
159
+ if idx % 50 == 0 :
160
+ ptfhost .shell (cmd_buffer , module_ignore_errors = True )
161
+ cmd_buffer = ""
162
+ if cmd_buffer != "" :
163
+ ptfhost .shell (cmd_buffer , module_ignore_errors = True )
121
164
122
165
123
166
def check_ptf_bfd_status (ptfhost , neighbor_addr , local_addr , expected_state ):
@@ -157,8 +200,51 @@ def create_bfd_sessions(ptfhost, duthost, local_addrs, neighbor_addrs):
157
200
if result ['rc' ] != 0 :
158
201
pytest .fail ('Failed to apply BFD session configuration file: {}' .format (result ['stderr' ]))
159
202
203
+ def create_bfd_sessions_multihop (ptfhost , duthost , loopback_addr , ptf_intf , neighbor_addrs ):
204
+ # Create a tempfile for BFD sessions
205
+ bfd_file_dir = duthost .shell ('mktemp' )['stdout' ]
206
+ ptf_file_dir = ptfhost .shell ('mktemp' )['stdout' ]
207
+ bfd_config = []
208
+ ptf_config = []
209
+ for neighbor_addr in neighbor_addrs :
210
+ bfd_config .append ({
211
+ "BFD_SESSION_TABLE:default:default:{}" .format (neighbor_addr ): {
212
+ "local_addr" : loopback_addr ,
213
+ "multihop" : "true"
214
+ },
215
+ "OP" : "SET"
216
+ })
217
+ ptf_config .append (
218
+ {
219
+ "neighbor_addr" : loopback_addr ,
220
+ "local_addr" : neighbor_addr ,
221
+ "multihop" : "true" ,
222
+ "ptf_intf" : "eth{}" .format (ptf_intf )
223
+ }
224
+ )
225
+
226
+ # Copy json file to DUT
227
+ duthost .copy (content = json .dumps (bfd_config , indent = 4 ), dest = bfd_file_dir , verbose = False )
228
+
229
+ # Apply BFD sessions with swssconfig
230
+ result = duthost .shell ('docker exec -i swss swssconfig /dev/stdin < {}' .format (bfd_file_dir ),
231
+ module_ignore_errors = True )
232
+ if result ['rc' ] != 0 :
233
+ pytest .fail ('Failed to apply BFD session configuration file: {}' .format (result ['stderr' ]))
234
+ # Copy json file to PTF
235
+ ptfhost .copy (content = json .dumps (ptf_config , indent = 4 ), dest = ptf_file_dir , verbose = False )
160
236
161
- def remove_bfd_sessions (duthost , local_addrs , neighbor_addrs ):
237
+ ptfhost .copy (src = BFD_RESPONDER_SCRIPT_SRC_PATH , dest = BFD_RESPONDER_SCRIPT_DEST_PATH )
238
+
239
+ extra_vars = {"bfd_responder_args" : "-c {}" .format (ptf_file_dir )}
240
+ ptfhost .host .options ["variable_manager" ].extra_vars .update (extra_vars )
241
+
242
+ ptfhost .template (src = 'templates/bfd_responder.conf.j2' , dest = '/etc/supervisor/conf.d/bfd_responder.conf' )
243
+ ptfhost .command ('supervisorctl reread' )
244
+ ptfhost .command ('supervisorctl update' )
245
+ ptfhost .command ('supervisorctl start bfd_responder' )
246
+
247
+ def remove_bfd_sessions (duthost , neighbor_addrs ):
162
248
# Create a tempfile for BFD sessions
163
249
bfd_file_dir = duthost .shell ('mktemp' )['stdout' ]
164
250
bfd_config = []
@@ -167,7 +253,6 @@ def remove_bfd_sessions(duthost, local_addrs, neighbor_addrs):
167
253
duthost .shell ("sonic-db-cli APPL_DB hmset 'BFD_SESSION_TABLE:default:default:{}' local_addr {}" .format (neighbor_addr , local_addrs [idx ]))
168
254
bfd_config .append ({
169
255
"BFD_SESSION_TABLE:default:default:{}" .format (neighbor_addr ): {
170
- "local_addr" : local_addrs [idx ]
171
256
},
172
257
"OP" : "DEL"
173
258
})
@@ -218,10 +303,9 @@ def test_bfd(rand_selected_dut, ptfhost, tbinfo, toggle_all_simulator_ports_to_r
218
303
check_ptf_bfd_status (ptfhost , neighbor_addr , local_addrs [idx ], "Up" )
219
304
finally :
220
305
stop_ptf_bfd (ptfhost )
221
- del_ipaddr (ptfhost , neighbor_addrs , prefix_len , neighbor_interfaces , ipv6 = False )
222
- remove_bfd_sessions (duthost , local_addrs , neighbor_addrs )
223
- if 't1' in tbinfo ['topo' ]['name' ]:
224
- remove_dut_ip (duthost , neighbor_devs , local_addrs , prefix_len )
306
+ del_ipaddr (ptfhost , neighbor_addrs , prefix_len , neighbor_interfaces , ipv6 )
307
+ remove_bfd_sessions (duthost , neighbor_addrs )
308
+ remove_dut_ip (duthost , neighbor_devs , local_addrs , prefix_len )
225
309
226
310
227
311
@pytest .mark .skip (reason = "Test may currently fail due to lack of hardware support" )
@@ -238,11 +322,12 @@ def test_bfd_ipv6(rand_selected_dut, ptfhost, tbinfo, toggle_all_simulator_ports
238
322
add_ipaddr (ptfhost , neighbor_addrs , prefix_len , neighbor_interfaces , ipv6 = True )
239
323
create_bfd_sessions (ptfhost , duthost , local_addrs , neighbor_addrs )
240
324
241
- time .sleep (1 )
242
-
243
- for idx , neighbor_addr in enumerate (neighbor_addrs ):
244
- check_dut_bfd_status (duthost , neighbor_addr , "Up" )
245
- check_ptf_bfd_status (ptfhost , neighbor_addr , local_addrs [idx ], "Up" )
325
+ time .sleep (10 )
326
+ bfd_state = ptfhost .shell ("bfdd-control status" )
327
+ dut_state = duthost .shell ("show bfd summary" )
328
+ for itr in local_addrs :
329
+ assert itr in bfd_state ['stdout' ]
330
+ assert itr in dut_state ['stdout' ]
246
331
247
332
update_idx = random .choice (range (bfd_session_cnt ))
248
333
update_bfd_session_state (ptfhost , neighbor_addrs [update_idx ], local_addrs [idx ], "down" )
@@ -256,7 +341,34 @@ def test_bfd_ipv6(rand_selected_dut, ptfhost, tbinfo, toggle_all_simulator_ports
256
341
check_ptf_bfd_status (ptfhost , neighbor_addr , local_addrs [idx ], "Up" )
257
342
finally :
258
343
stop_ptf_bfd (ptfhost )
259
- del_ipaddr (ptfhost , neighbor_addrs , prefix_len , neighbor_interfaces , ipv6 = True )
260
- remove_bfd_sessions (duthost , local_addrs , neighbor_addrs )
261
- if 't1' in tbinfo ['topo' ]['name' ]:
262
- remove_dut_ip (duthost , neighbor_devs , local_addrs , prefix_len )
344
+ del_ipaddr (ptfhost , neighbor_addrs , prefix_len , neighbor_interfaces , ipv6 )
345
+ remove_bfd_sessions (duthost , neighbor_addrs )
346
+ remove_dut_ip (duthost , neighbor_devs , local_addrs , prefix_len )
347
+
348
+
349
+ @pytest .mark .parametrize ('ipv6' , [False , True ], ids = ['ipv4' , 'ipv6' ])
350
+ def test_bfd_multihop (request , rand_selected_dut , ptfhost , tbinfo , toggle_all_simulator_ports_to_rand_selected_tor_m , ipv6 ):
351
+ duthost = rand_selected_dut
352
+
353
+ bfd_session_cnt = int (request .config .getoption ('--num_sessions' ))
354
+ loopback_addr , ptf_intf , nexthop_ip , neighbor_addrs = get_neighbors_multihop (duthost , tbinfo , ipv6 , count = bfd_session_cnt )
355
+ try :
356
+ cmd_buffer = ""
357
+ for neighbor in neighbor_addrs :
358
+ cmd_buffer += 'sudo ip route add {} via {} ;' .format (neighbor , nexthop_ip )
359
+ duthost .shell (cmd_buffer )
360
+
361
+ create_bfd_sessions_multihop (ptfhost , duthost , loopback_addr , ptf_intf , neighbor_addrs )
362
+
363
+ time .sleep (1 )
364
+ for neighbor_addr in neighbor_addrs :
365
+ check_dut_bfd_status (duthost , neighbor_addr , "Up" )
366
+
367
+ finally :
368
+ remove_bfd_sessions (duthost , neighbor_addrs )
369
+ cmd_buffer = ""
370
+ for neighbor in neighbor_addrs :
371
+ cmd_buffer += 'sudo ip route delete {} via {} ;' .format (neighbor , nexthop_ip )
372
+ duthost .shell (cmd_buffer )
373
+ ptfhost .command ('supervisorctl stop bfd_responder' )
374
+ ptfhost .file (path = BFD_RESPONDER_SCRIPT_DEST_PATH , state = "absent" )
0 commit comments