33import logging
44import tempfile
55import re
6+ import allure
67
78from datetime import datetime
89
2829VXLAN_PORT = 13330
2930DUT_VXLAN_PORT_JSON_FILE = '/tmp/vxlan.switch.json'
3031
32+ T0_VLAN = "1000"
3133IP_VERSIONS_LIST = ["ipv4" , "ipv6" ]
3234OUTER_ENCAP_FORMATS = ["vxlan" , "nvgre" ]
3335TABLE_NAME = "pbh_table"
4244V6_ETHER_TYPE = "0x86dd"
4345VXLAN_IP_PROTOCOL = "0x11"
4446NVGRE_IP_PROTOCOL = "0x2f"
47+ GRE_KEY = "0x2500"
48+ NVGRE_TNI = 0x25
49+ GRE_MASK = "0xffffff00"
4550VXLAN_L4_DST_PORT = "0x3412"
4651VXLAN_L4_DST_PORT_OPTION = " --l4-dst-port {}" .format (VXLAN_L4_DST_PORT )
52+ NVGRE_GRE_KEY_OPTION = " --gre-key {}/{}" .format (GRE_KEY , GRE_MASK )
4753ADD_PBH_TABLE_CMD = "sudo config pbh table add '{}' --interface-list '{}' --description '{}'"
4854DEL_PBH_TABLE_CMD = "sudo config pbh table delete '{}'"
55+ ADD_PBH_RULE_BASE_CMD = "sudo config pbh rule add '{}' '{}' --priority '{}' --ether-type {}" \
56+ " --inner-ether-type '{}' --hash '{}' --packet-action '{}' --flow-counter 'ENABLED'"
4957ADD_PBH_RULE_BASE_CMD = "sudo config pbh rule add '{}' '{}' --priority '{}' --ether-type {}" \
5058 " --inner-ether-type '{}' --hash '{}' --packet-action '{}' --flow-counter 'ENABLED'"
5159DEL_PBH_RULE_CMD = "sudo config pbh rule delete '{}' '{}'"
@@ -181,6 +189,59 @@ def vlan_ptf_ports(config_facts, tbinfo, duthost):
181189 return ports
182190
183191
192+ @pytest .fixture (scope = 'module' )
193+ def lag_port_map (duthost , config_facts , vlan_ptf_ports , tbinfo ):
194+ '''
195+ Create lag-port map for vlan ptf ports
196+ '''
197+ portchannels = config_facts .get ('PORTCHANNEL' , {}).keys ()
198+ mg_facts = duthost .get_extended_minigraph_facts (tbinfo )
199+ port_list_idx = 0
200+ lag_port_map = {}
201+ port_key_list = list (mg_facts ['minigraph_ptf_indices' ].keys ())
202+ port_val_list = list (mg_facts ['minigraph_ptf_indices' ].values ())
203+
204+ for portchannel_idx in range (1 , 10000 ): # Max len of PortChannel index can be '9999'
205+ lag_port = 'PortChannel{}' .format (portchannel_idx )
206+
207+ if lag_port not in portchannels :
208+ port_idx_value = vlan_ptf_ports [port_list_idx ]
209+ position = port_val_list .index (port_idx_value )
210+ port_name = port_key_list [position ]
211+ lag_port_map [lag_port ] = port_name
212+ port_list_idx += 1
213+
214+ if len (lag_port_map ) == len (vlan_ptf_ports ):
215+ break
216+
217+ return lag_port_map
218+
219+
220+ @pytest .fixture (scope = 'module' )
221+ def lag_ip_map (lag_port_map ):
222+ index = 1
223+ base_ipv4_addr = '100.0.{}.1/31'
224+ base_ipv6_addr = 'fc00:{}::1/126'
225+ lag_ip_map = {}
226+
227+ for lag_port , _ in lag_port_map .items ():
228+ ipv4_addr = base_ipv4_addr .format (index )
229+ ipv6_addr = base_ipv6_addr .format (index )
230+ lag_ip_map [lag_port ] = {'ipv4' : ipv4_addr , 'ipv6' : ipv6_addr }
231+ index += 1
232+
233+ return lag_ip_map
234+
235+
236+ @pytest .fixture (scope = 'module' )
237+ def config_lag_ports (duthost , lag_port_map , lag_ip_map ):
238+ add_lag_config (duthost , lag_port_map , lag_ip_map )
239+
240+ yield
241+
242+ remove_lag_config (duthost , lag_port_map , lag_ip_map )
243+
244+
184245@pytest .fixture (scope = 'module' )
185246def router_mac (duthosts , rand_one_dut_hostname ):
186247 duthost = duthosts [rand_one_dut_hostname ]
@@ -214,8 +275,23 @@ def inner_ipver(request):
214275 return request .param
215276
216277
278+ @pytest .fixture (scope = "module" )
279+ def config_pbh_table_lag (duthost , lag_port_map ):
280+ logging .info ("Create PBH table: {}" .format (TABLE_NAME ))
281+ test_intfs_str = "," .join (lag_port_map .keys ())
282+
283+ duthost .command (ADD_PBH_TABLE_CMD .format (TABLE_NAME ,
284+ test_intfs_str ,
285+ TABLE_DESCRIPTION ))
286+
287+ yield
288+
289+ duthost .command (DEL_PBH_TABLE_CMD .format (TABLE_NAME ))
290+
291+
217292@pytest .fixture (scope = "module" )
218293def config_pbh_table (duthost , vlan_ptf_ports , tbinfo ):
294+ logging .info ("Create PBH table: {}" .format (TABLE_NAME ))
219295 test_intfs_str = get_dut_test_intfs_str (duthost , vlan_ptf_ports , tbinfo )
220296
221297 duthost .command (ADD_PBH_TABLE_CMD .format (TABLE_NAME ,
@@ -239,6 +315,7 @@ def get_dut_test_intfs_str(duthost, vlan_ptf_ports, tbinfo):
239315
240316@pytest .fixture (scope = "module" )
241317def config_hash_fields (duthost ):
318+ logging .info ("Create PBH hash-fields" )
242319 for hash_field , hash_field_params_dict in HASH_FIELD_CONFIG .items ():
243320 cmd = get_hash_field_add_cmd (hash_field , hash_field_params_dict )
244321 duthost .command (cmd )
@@ -260,6 +337,7 @@ def get_hash_field_add_cmd(hash_field_name, hash_field_params_dict):
260337
261338@pytest .fixture (scope = "module" )
262339def config_hash (duthost ):
340+ logging .info ("Create PBH hash: {}" .format (HASH_NAME ))
263341 duthost .command (ADD_PBH_HASH_CMD .format (HASH_NAME , PBH_HASH_FIELD_LIST ))
264342
265343 yield
@@ -291,6 +369,7 @@ def config_ipv6_rules(duthost, inner_ipver):
291369
292370
293371def config_vxlan_rule (duthost , ip_ver_option , ether_type , outer_ipver , inner_ipver ):
372+ logging .info ("Create PBH rule: {}" .format (VXLAN_RULE_NAME .format (outer_ipver , inner_ipver )))
294373 inner_ether_type = V4_ETHER_TYPE if inner_ipver == "ipv4" else V6_ETHER_TYPE
295374 duthost .command ((ADD_PBH_RULE_BASE_CMD + ip_ver_option + VXLAN_L4_DST_PORT_OPTION )
296375 .format (TABLE_NAME ,
@@ -305,8 +384,9 @@ def config_vxlan_rule(duthost, ip_ver_option, ether_type, outer_ipver, inner_ipv
305384
306385
307386def config_nvgre_rule (duthost , ip_ver_option , ether_type , outer_ipver , inner_ipver ):
387+ logging .info ("Create PBH rule: {}" .format (NVGRE_RULE_NAME .format (outer_ipver , inner_ipver )))
308388 inner_ether_type = V4_ETHER_TYPE if inner_ipver == "ipv4" else V6_ETHER_TYPE
309- duthost .command ((ADD_PBH_RULE_BASE_CMD + ip_ver_option )
389+ duthost .command ((ADD_PBH_RULE_BASE_CMD + ip_ver_option + NVGRE_GRE_KEY_OPTION )
310390 .format (TABLE_NAME ,
311391 NVGRE_RULE_NAME .format (outer_ipver , inner_ipver ),
312392 NVGRE_RULE_PRIO ,
@@ -341,16 +421,40 @@ def get_src_dst_ip_range(ipver):
341421
342422
343423def check_pbh_counters (duthost , outer_ipver , inner_ipver , balancing_test_times , symmetric_hashing , hash_keys ):
344- symmetric_multiplier = 2 if symmetric_hashing else 1
345- exp_port_multiplier = 4 # num of POs in t0 topology
346- hash_keys_multiplier = len (hash_keys )
347- # for hash key "ip-proto", the traffic sends always in one way
348- exp_count = str ((balancing_test_times * symmetric_multiplier * exp_port_multiplier * (hash_keys_multiplier - 1 ))
349- + (balancing_test_times * exp_port_multiplier ))
350- pbh_statistic_output = duthost .shell ("show pbh statistic" )['stdout' ]
351- for outer_encap_format in OUTER_ENCAP_FORMATS :
352- regex = r'{}\s+{}_{}_{}\s+(\d+)\s+\d+' .format (TABLE_NAME , outer_encap_format , outer_ipver , inner_ipver )
353- current_count = re .search (regex , pbh_statistic_output ).group (1 )
354- assert current_count == exp_count ,\
355- "PBH counters are different from expected for {}, outer ipver {}, inner ipver {}. Expected: {}, " \
356- "Current: {}" .format (outer_encap_format , outer_ipver , inner_ipver , exp_count , current_count )
424+ logging .info ('Verify PBH counters' )
425+ with allure .step ('Verify PBH counters' ):
426+ symmetric_multiplier = 2 if symmetric_hashing else 1
427+ exp_port_multiplier = 4 # num of POs in t0 topology
428+ hash_keys_multiplier = len (hash_keys )
429+ # for hash key "ip-proto", the traffic sends always in one way
430+ exp_count = str ((balancing_test_times * symmetric_multiplier * exp_port_multiplier * (hash_keys_multiplier - 1 ))
431+ + (balancing_test_times * exp_port_multiplier ))
432+ pbh_statistic_output = duthost .shell ("show pbh statistic" )['stdout' ]
433+ for outer_encap_format in OUTER_ENCAP_FORMATS :
434+ regex = r'{}\s+{}_{}_{}\s+(\d+)\s+\d+' .format (TABLE_NAME , outer_encap_format , outer_ipver , inner_ipver )
435+ current_count = re .search (regex , pbh_statistic_output ).group (1 )
436+ assert current_count == exp_count ,\
437+ "PBH counters are different from expected for {}, outer ipver {}, inner ipver {}. Expected: {}, " \
438+ "Current: {}" .format (outer_encap_format , outer_ipver , inner_ipver , exp_count , current_count )
439+
440+
441+ def add_lag_config (duthost , lag_port_map , lag_ip_map ):
442+ logging .info ('Add LAG configuration' )
443+ with allure .step ('Add LAG configuration' ):
444+ for lag_port , port_name in lag_port_map .items ():
445+ duthost .shell ('sudo config vlan member del {} {}' .format (T0_VLAN , port_name ))
446+ duthost .shell ('sudo config portchannel add {} --fallback enable' .format (lag_port ))
447+ duthost .shell ('sudo config portchannel member add {} {}' .format (lag_port , port_name ))
448+ duthost .shell ('config interface ip add {} {}' .format (lag_port , lag_ip_map [lag_port ]['ipv4' ]))
449+ duthost .shell ('config interface ip add {} {}' .format (lag_port , lag_ip_map [lag_port ]['ipv6' ]))
450+
451+
452+ def remove_lag_config (duthost , lag_port_map , lag_ip_map ):
453+ logging .info ('Remove LAG configuration' )
454+ with allure .step ('Remove LAG configuration' ):
455+ for lag_port , port_name in lag_port_map .items ():
456+ duthost .shell ('config interface ip remove {} {}' .format (lag_port , lag_ip_map [lag_port ]['ipv4' ]))
457+ duthost .shell ('config interface ip remove {} {}' .format (lag_port , lag_ip_map [lag_port ]['ipv6' ]))
458+ duthost .shell ('sudo config portchannel member del {} {}' .format (lag_port , port_name ))
459+ duthost .shell ('sudo config portchannel del {}' .format (lag_port ))
460+ duthost .shell ('sudo config vlan member add {} {} --untagged' .format (T0_VLAN , port_name ))
0 commit comments