ptf/saihash.py (2,233 lines of code) (raw):

# Copyright 2021-present Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Thrift SAI interface HASH tests """ import binascii from ptf.testutils import * from sai_base_test import * ROUTER_MAC = '00:77:66:55:44:00' MAX_ITRS = 50 L3_MAX_ITRS = 200 LAG_MAX_ITRS = 120 DEBUG = False # Default hash seeds values. TEST_ECMP_SEED = 211 # test default ECMP seed value TEST_ECMP_SEED1 = 411 # ecmp seed tests second value TEST_LAG_SEED = 2557 # test default LAG seed value TEST_LAG_SEED1 = 411 # LAG seed tests second value # accepted LB minumum count level per port. # as min = LB avrg * 0.5 # e.g for 3 ports and 50 iterations # avrg = 13 # min = 13 * 0.5 = 6.5 # value reduced to 0.4 due to high chance of test failing TEST_HASH_CHECK_BASE = 0.4 SEED_TEST_CHECK_BASE = 0.2 def test_header(test_name, module=None): """ Prints test header Args: test_name (str): test case name module (str): module name """ if module is None: print("\n\n**** TEST - %s ****\n" % (test_name)) else: print("\n\n**** TEST - %s.%s ****\n" % (module, test_name)) def hash_to_hash_fields(hash_dict): """ Creates hash fields list Args: hash_dict (dict): dictionary with variables that defines the list of hash test fields and traffic header hashed fields Returns: list: hash fields list """ hash_fields = [] if ('hash_src_ip' in hash_dict) and \ (hash_dict['hash_src_ip'] is not None): hash_fields.append(SAI_NATIVE_HASH_FIELD_SRC_IP) if ('hash_dst_ip' in hash_dict) and (hash_dict['hash_dst_ip'] is not None): hash_fields.append(SAI_NATIVE_HASH_FIELD_DST_IP) if ('hash_dst_mac' in hash_dict) and \ (hash_dict['hash_dst_mac'] is not None): hash_fields.append(SAI_NATIVE_HASH_FIELD_DST_MAC) if ('hash_src_mac' in hash_dict) and \ (hash_dict['hash_src_mac'] is not None): hash_fields.append(SAI_NATIVE_HASH_FIELD_SRC_MAC) if ('hash_udp_dport' in hash_dict) and \ (hash_dict['hash_udp_dport'] is not None): hash_fields.append(SAI_NATIVE_HASH_FIELD_L4_DST_PORT) if ('hash_udp_sport' in hash_dict) and \ (hash_dict['hash_udp_sport'] is not None): hash_fields.append(SAI_NATIVE_HASH_FIELD_L4_SRC_PORT) if ('hash_ether_type' in hash_dict) and \ (hash_dict['hash_ether_type'] is not None): hash_fields.append(SAI_NATIVE_HASH_FIELD_ETHERTYPE) if ('hash_flow_label' in hash_dict) and \ (hash_dict['hash_flow_label'] is not None): hash_fields.append(SAI_NATIVE_HASH_FIELD_IPV6_FLOW_LABEL) return hash_fields def hash_fields_to_hash_names(hash_list): """ Converts hash fields list to hash names list Args: hash_list (list): list of hash fields Returns: list: hash names list """ hash_names = [] for hash_from_list in hash_list: if hash_from_list == SAI_NATIVE_HASH_FIELD_L4_DST_PORT: hash_names.append("L4_DST_PORT") elif hash_from_list == SAI_NATIVE_HASH_FIELD_L4_SRC_PORT: hash_names.append("L4_SRC_PORT") elif hash_from_list == SAI_NATIVE_HASH_FIELD_SRC_IP: hash_names.append("SRC_IP") elif hash_from_list == SAI_NATIVE_HASH_FIELD_DST_IP: hash_names.append("DST_IP") elif hash_from_list == SAI_NATIVE_HASH_FIELD_DST_MAC: hash_names.append("DST_MAC") elif hash_from_list == SAI_NATIVE_HASH_FIELD_SRC_MAC: hash_names.append("SRC_MAC") elif hash_from_list == SAI_NATIVE_HASH_FIELD_ETHERTYPE: hash_names.append("ETHER_TYPE") else: hash_names.append("ALL") return hash_names def verify_equaly_balanced(ecmp_count, pkt_count=MAX_ITRS, expected_base=TEST_HASH_CHECK_BASE): """ Verifies if ecmp paths are egualy balanced Args: ecmp_count (list): ecmp hashed port count list pkt_count (int): traffic number expected_base (int): percentage minimum accepted value of the port count for the equally balanced traffic Returns: boolean: True if traffic considerd equally balanced, False otherwise """ base = ((pkt_count / len(ecmp_count)) * expected_base) for count in ecmp_count: if count < base: # "Ecmp paths are not equally balanced" print("verify_equaly_balanced: ecmp_count=", ecmp_count, "count=", count, "expected count min=", base) return False return True def verify_similary_balanced(ecmp_count1, ecmp_count2): """ Checks if two results of LB are similar Args: ecmp_count1 (list): ecmp count list for the first LB result ecmp_count2 (list): ecmp count list for the second LB result Returns: boolean: True if traffic considerd similary balanced, False otherwise """ if len(ecmp_count1) != len(ecmp_count2): # list must have equal len return False diff = 0 for count, value in enumerate(ecmp_count1): print(count, value) diff += abs(ecmp_count1[count] - ecmp_count2[count]) if diff == 0: # value 0 indicate the hashing did not change return False # value other then 0 means detected hasing change return True def verify_lb_active_ports(lb_counts): """ Counts how mamy ports were balanced Args: lb_counts (list): load balancing counts list Returns: int: balanced ports counter """ cnt = 0 for port_cnt in lb_counts: if port_cnt != 0: cnt += 1 return cnt def verify_no_lb(lb_counts, max_iters=MAX_ITRS): """ Verifies if LB has no effect and all traffic is directed to single port only Args: lb_counts (list): load balancing counts list max_iters (int): maximum number of iterations Returns: boolean: True if load balancing has no effect, False otherwise """ cnt = 0 for port_cnt in lb_counts: if port_cnt != 0: if port_cnt != max_iters: # should be 0 or max_iters only return False cnt += 1 if cnt > 1: return False return True def hash_dict_negation(hash_dict): """ Negates the content of the input hash dictionary Args: hash_dict (dict): input dictionary Returns: dict: input dictionary negation """ hash_dict_not = {} for key in hash_dict: if hash_dict[key] is not None: hash_dict_not[key] = None else: hash_dict_not[key] = True return hash_dict_not @group("draft") class SAIHashTestBase(SaiHelper): """ Sets base configuration for tests """ def setUp(self): super(SAIHashTestBase, self).setUp() self.ipv4_hash_id = 0 self.ipv6_hash_id = 0 self.lag_hash_ipv4 = 0 self.lag_hash_ipv6 = 0 # set default ECMP and LAG hash seeds # this has an effect only if hash is not reconfigured later self.setupECMPSeed(seed=TEST_ECMP_SEED) self.setupLagSeed(seed=TEST_LAG_SEED) def tearDown(self): try: if self.ipv6_hash_id != 0: sai_thrift_set_switch_attribute( self.client, ecmp_hash_ipv6=0) sai_thrift_remove_hash(self.client, self.ipv6_hash_id) self.ipv6_hash_id = 0 if self.ipv4_hash_id != 0: sai_thrift_set_switch_attribute( self.client, ecmp_hash_ipv4=0) sai_thrift_remove_hash(self.client, self.ipv4_hash_id) self.ipv4_hash_id = 0 if self.lag_hash_ipv4 != 0: sai_thrift_set_switch_attribute( self.client, lag_hash_ipv4=0) sai_thrift_remove_hash(self.client, self.lag_hash_ipv4) self.lag_hash_ipv4 = 0 if self.lag_hash_ipv6 != 0: sai_thrift_set_switch_attribute( self.client, lag_hash_ipv6=0) sai_thrift_remove_hash(self.client, self.lag_hash_ipv6) self.lag_hash_ipv6 = 0 finally: super(SAIHashTestBase, self).tearDown() def setupNonIPECMPHash(self, hash_fields_list=None): """ Sets base configuration for the non IP ECMP case Args: hash_fields_list (list): hash fields list """ attr_list = sai_thrift_get_switch_attribute( self.client, ecmp_hash=True, lag_hash=True) lag_hash_id = attr_list['SAI_SWITCH_ATTR_LAG_HASH'] self.assertNotEqual(lag_hash_id, 0) if hash_fields_list is None: hash_fields_list = [SAI_NATIVE_HASH_FIELD_SRC_MAC, SAI_NATIVE_HASH_FIELD_DST_MAC, SAI_NATIVE_HASH_FIELD_ETHERTYPE] hash_attr_list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_id, native_hash_field_list=hash_attr_list) self.assertEqual(status, SAI_STATUS_SUCCESS) # verify if the hash_fields_list saved correctly self.assertEqual( True, self.verifyHashFieldsList( lag_hash_id, hash_fields_list)) def setupFGECMPIPv4Hash(self, hash_fields_list=None, p_ipv4_mask=None): ''' Sets base configuration for the FG ECMP IPv4 case Args: hash_fields_list (list): hash fields list p_ipv4_mask (string): ip mask to use Fine Grained ECMP IPV4 Hash configuraton is Three Step process. Step 1: Create object list for each hash field. [This step is create only, hence each time we have to create with field name, mask and sequence] Step 2: Creating the Hash object. This is both create/Set If not created before then we have to create a new hash object using the object list created in step 1. We can use set opertation if already created before. Step 3: Assigning a switch hash type with the above hash object id. ''' if hash_fields_list is None: hash_fields_list = [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT] attr_list = sai_thrift_get_switch_attribute( self.client, ecmp_hash_ipv4=True) ipv4_hash_id = attr_list['SAI_SWITCH_ATTR_ECMP_HASH_IPV4'] order = 1 hash_filed_id_list = [] for hash_field in hash_fields_list: if((hash_field == SAI_NATIVE_HASH_FIELD_SRC_IP) or (hash_field == SAI_NATIVE_HASH_FIELD_DST_IP)): hash_field = sai_thrift_create_fine_grained_hash_field( self.client, native_hash_field=hash_field, sequence_id=order, ipv4_mask=p_ipv4_mask) else: hash_field = sai_thrift_create_fine_grained_hash_field( self.client, native_hash_field=hash_field, sequence_id=order) hash_filed_id_list.append(hash_field) fg_hash_obj_list = sai_thrift_object_list_t( count=len(hash_filed_id_list), idlist=hash_filed_id_list) if ipv4_hash_id == 0: self.ipv4_hash_id = sai_thrift_create_hash( self.client, fine_grained_hash_field_list=fg_hash_obj_list) sai_thrift_set_switch_attribute( self.client, ecmp_hash_ipv4=self.ipv4_hash_id) else: # update existing hash status = sai_thrift_set_hash_attribute( self.client, ipv4_hash_id, fine_grained_hash_field_list=fg_hash_obj_list) self.assertEqual(status, SAI_STATUS_SUCCESS) def setupECMPIPv4Hash(self, hash_fields_list=None, seed=None): """ Sets base configuration for the ECMP IPv4 case Args: hash_fields_list (list): hash fields list seed (int): hash seed value """ if hash_fields_list is None: hash_fields_list = [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT] attr_list = sai_thrift_get_switch_attribute( self.client, ecmp_hash_ipv4=True) ipv4_hash_id = attr_list['SAI_SWITCH_ATTR_ECMP_HASH_IPV4'] if ipv4_hash_id == 0: # create new hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) self.ipv4_hash_id = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( self.ipv4_hash_id != 0, "Failed to create IPv4 hash") sai_thrift_set_switch_attribute( self.client, ecmp_hash_ipv4=self.ipv4_hash_id) # verify if the hash_fields_list saved correctly self.assertEqual( True, self.verifyHashFieldsList( self.ipv4_hash_id, hash_fields_list)) else: # update existing hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, ipv4_hash_id, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) if seed is not None: self.setupECMPSeed(seed=seed) def setupECMPIPv6Hash(self, hash_fields_list=None, seed=None): """ Sets base configuration for the ECMP IPv6 case Args: hash_fields_list (list): hash fields list seed (int): hash seed value """ print("Setting the ECMP IPv6 hash fields") if hash_fields_list is None: hash_fields_list = [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT, SAI_NATIVE_HASH_FIELD_IPV6_FLOW_LABEL] attr_list = sai_thrift_get_switch_attribute( self.client, ecmp_hash_ipv6=True, ecmp_hash_ipv4=True) ipv6_hash_id_old = attr_list['SAI_SWITCH_ATTR_ECMP_HASH_IPV6'] if ipv6_hash_id_old == 0: # create new hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) self.ipv6_hash_id = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( self.ipv6_hash_id != 0, "Failed to create IPv6 hash") status = sai_thrift_set_switch_attribute( self.client, ecmp_hash_ipv6=self.ipv6_hash_id) self.assertEqual(status, SAI_STATUS_SUCCESS) # verify if the hash_fields_list saved correctly self.assertEqual( True, self.verifyHashFieldsList( self.ipv6_hash_id, hash_fields_list)) else: # update existing hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, ipv6_hash_id_old, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) if seed is not None: self.setupECMPSeed(seed=seed) def setupLAGIPv6Hash(self, hash_fields_list=None, seed=None): """ Sets base configuration for the LAG IPv6 case Args: hash_fields_list (list): hash fields list seed (int): hash seed value """ if hash_fields_list is None: hash_fields_list = [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT, SAI_NATIVE_HASH_FIELD_IPV6_FLOW_LABEL] attr_list = sai_thrift_get_switch_attribute( self.client, lag_hash_ipv6=True) lag_hash_ipv6 = attr_list['SAI_SWITCH_ATTR_LAG_HASH_IPV6'] if lag_hash_ipv6 == 0: # create new hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) self.lag_hash_ipv6 = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( self.lag_hash_ipv6 != 0, "Failed to create IPv6 lag hash") sai_thrift_set_switch_attribute( self.client, lag_hash_ipv6=self.lag_hash_ipv6) # verify if the hash_fields_list saved correctly print("setupLAGIPv6Hash=", hash_fields_list) self.assertEqual( True, self.verifyHashFieldsList( self.lag_hash_ipv6, hash_fields_list)) else: # update existing hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_ipv6, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) if seed is not None: self.setupLagSeed(seed=seed) def setupLAGIPv4Hash(self, hash_fields_list=None, seed=None): """ Sets base configuration for the LAG IPv4 case Args: hash_fields_list (list): hash fields list seed (int): hash seed value """ if hash_fields_list is None: hash_fields_list = [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT] attr_list = sai_thrift_get_switch_attribute( self.client, lag_hash_ipv4=True) lag_hash_ipv4 = attr_list['SAI_SWITCH_ATTR_LAG_HASH_IPV4'] if lag_hash_ipv4 == 0: # create new hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) self.lag_hash_ipv4 = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( self.lag_hash_ipv4 != 0, "Failed to create IPv4 lag hash") sai_thrift_set_switch_attribute( self.client, lag_hash_ipv4=self.lag_hash_ipv4) # verify if the hash_fields_list saved correctly self.assertEqual( True, self.verifyHashFieldsList( self.lag_hash_ipv4, hash_fields_list)) else: # update existing hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_ipv4, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) if seed is not None: self.setupLagSeed(seed=seed) def setupECMPSeed(self, seed=200): """ Sets ECMP seed Args: seed (int): seed value """ sai_thrift_set_switch_attribute( self.client, ecmp_default_hash_seed=seed) def setupLagSeed(self, seed=200): """ Sets Lag seed Args: seed (int): seed value """ sai_thrift_set_switch_attribute( self.client, lag_default_hash_seed=seed) def verifyHashFieldsList(self, hash_id, fields_list): """ Verifies hash fields list Args: hash_id (int): hash id value fields_list (list): hash fields list Returns: boolean: True if hw saved hash_id field list equals fields_list False if field lists not equal """ hash_fields_list = [] s32list = sai_thrift_s32_list_t(count=100, int32list=hash_fields_list) hash_data = sai_thrift_get_hash_attribute( self.client, hash_id, native_hash_field_list=s32list) hash_fields_list = hash_data['native_hash_field_list'].int32list if len(hash_fields_list) != len(fields_list): return False # compare two hash field lists test_fields_list and hash_fields_list of # the given hash id for field1 in fields_list: found = False for field2 in hash_fields_list: if field1 == field2: found = True if found is not True: return False return True def setupLagAlgorithm(self, algo=SAI_HASH_ALGORITHM_CRC): """ Sets lag algorithm Args: algo (int): hash algorithm id """ print("setup Lag Algorithm algorithm=%d" % algo) sai_thrift_set_switch_attribute( self.client, lag_default_hash_algorithm=algo) def setupECMPAlgorithm(self, algo=SAI_HASH_ALGORITHM_CRC): """ Sets ECMP algorithm Args: algo (int): hash algorithm id """ print("setup ECMP Algorithm algorithm=%d" % algo) sai_thrift_set_switch_attribute( self.client, ecmp_default_hash_algorithm=algo) @group("draft") class SAIHashTest(SAIHashTestBase): """ Runs hash test cases """ def setUp(self): super(SAIHashTest, self).setUp() dmac1 = '00:11:11:11:11:11' dmac2 = '00:22:22:22:22:22' dmac3 = '00:33:33:33:33:33' dmac4 = '00:44:44:44:44:44' dmac5 = '00:55:55:55:55:55' dmac6 = '00:66:66:66:66:66' dmac7 = '00:77:77:77:77:77' nhop_ip1 = '11.11.11.11' nhop_ip2 = '22.22.22.22' nhop_ip3 = '33.33.33.33' nhop_ip4 = '44.44.44.44' nhop_ip5 = '44.55.55.55' nhop_ip6 = '44.66.66.66' nhop_ip7 = '44.77.77.77' # set switch src mac address sai_thrift_set_switch_attribute( self.client, src_mac_address=ROUTER_MAC) self.lag1_rif = sai_thrift_create_router_interface( self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, virtual_router_id=self.default_vrf, port_id=self.lag1, admin_v4_state=True) self.lag2_rif = sai_thrift_create_router_interface( self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, virtual_router_id=self.default_vrf, port_id=self.lag2, admin_v4_state=True) self.port15_rif = sai_thrift_create_router_interface( self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, virtual_router_id=self.default_vrf, port_id=self.port15, admin_v4_state=True) # create vlan 200 with port0 and lag1 self.vlan200 = sai_thrift_create_vlan(self.client, vlan_id=200) self.assertNotEqual(self.vlan200, 0) self.vlan200_member1 = sai_thrift_create_vlan_member( self.client, vlan_id=self.vlan200, bridge_port_id=self.port0_bp, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) self.vlan200_member2 = sai_thrift_create_vlan_member( self.client, vlan_id=self.vlan200, bridge_port_id=self.lag1_bp, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) sai_thrift_set_port_attribute( self.client, self.port0, port_vlan_id=200) sai_thrift_set_lag_attribute(self.client, self.lag1, port_vlan_id=200) # test neighbor creation self.neighbor_entry10 = sai_thrift_neighbor_entry_t( self.switch_id, self.port10_rif, sai_ipaddress(nhop_ip1)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry10, dst_mac_address=dmac1) self.neighbor_entry11 = sai_thrift_neighbor_entry_t( self.switch_id, self.port11_rif, sai_ipaddress(nhop_ip2)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry11, dst_mac_address=dmac2) self.neighbor_entry12 = sai_thrift_neighbor_entry_t( self.switch_id, self.port12_rif, sai_ipaddress(nhop_ip3)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry12, dst_mac_address=dmac3) self.neighbor_entry13 = sai_thrift_neighbor_entry_t( self.switch_id, self.port13_rif, sai_ipaddress(nhop_ip4)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry13, dst_mac_address=dmac4) self.neighbor_entry15 = sai_thrift_neighbor_entry_t( self.switch_id, self.lag1_rif, sai_ipaddress(nhop_ip5)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry15, dst_mac_address=dmac5) self.neighbor_entry16 = sai_thrift_neighbor_entry_t( self.switch_id, self.lag2_rif, sai_ipaddress(nhop_ip6)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry16, dst_mac_address=dmac6) self.neighbor_entry17 = sai_thrift_neighbor_entry_t( self.switch_id, self.lag1_rif, sai_ipaddress(nhop_ip7)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry17, dst_mac_address=dmac7) self.nhop1 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.port10_rif, ip=sai_ipaddress(nhop_ip1)) self.nhop2 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.port11_rif, ip=sai_ipaddress(nhop_ip2)) self.nhop3 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.port12_rif, ip=sai_ipaddress(nhop_ip3)) self.nhop4 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.port13_rif, ip=sai_ipaddress(nhop_ip4)) self.nhop3_lag1 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.lag1_rif, ip=sai_ipaddress(nhop_ip7)) self.nhop4_lag2 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.lag2_rif, ip=sai_ipaddress(nhop_ip4)) self.nhop5_lag1 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.lag1_rif, ip=sai_ipaddress(nhop_ip5)) self.nhop6_lag2 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.lag2_rif, ip=sai_ipaddress(nhop_ip6)) self.nhop_group1 = sai_thrift_create_next_hop_group( self.client, type=SAI_NEXT_HOP_GROUP_TYPE_ECMP) self.nh_group1_member1 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group1, next_hop_id=self.nhop1) self.nh_group1_member2 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group1, next_hop_id=self.nhop2) self.nh_group1_member3 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group1, next_hop_id=self.nhop3) self.nh_group1_member4 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group1, next_hop_id=self.nhop4) self.route0 = sai_thrift_route_entry_t( switch_id=self.switch_id, destination=sai_ipprefix('10.10.10.1/16'), vr_id=self.default_vrf) status = sai_thrift_create_route_entry( self.client, self.route0, next_hop_id=self.nhop_group1) self.assertEqual(status, SAI_STATUS_SUCCESS) self.nhop_group2 = sai_thrift_create_next_hop_group( self.client, type=SAI_NEXT_HOP_GROUP_TYPE_ECMP) self.nh_group2_member1 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group2, next_hop_id=self.nhop5_lag1) self.nh_group2_member2 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group2, next_hop_id=self.nhop6_lag2) # create route entry for nhop_group2 self.route1 = sai_thrift_route_entry_t( switch_id=self.switch_id, destination=sai_ipprefix('20.20.20.1/16'), vr_id=self.default_vrf) status = sai_thrift_create_route_entry( self.client, self.route1, next_hop_id=self.nhop_group2) self.assertEqual(status, SAI_STATUS_SUCCESS) # create route entry for nhop_group3 Lag1 only self.nhop_group3 = sai_thrift_create_next_hop_group( self.client, type=SAI_NEXT_HOP_GROUP_TYPE_ECMP) self.nh_group3_member1 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group3, next_hop_id=self.nhop3_lag1) self.route2 = sai_thrift_route_entry_t( switch_id=self.switch_id, destination=sai_ipprefix('10.70.70.1/16'), vr_id=self.default_vrf) status = sai_thrift_create_route_entry( self.client, self.route2, next_hop_id=self.nhop_group3) self.assertEqual(status, SAI_STATUS_SUCCESS) def tearDown(self): try: # retrieve original settings sai_thrift_flush_fdb_entries( self.client, entry_type=SAI_FDB_FLUSH_ENTRY_TYPE_ALL) sai_thrift_set_port_attribute( self.client, self.port0, port_vlan_id=0) sai_thrift_set_lag_attribute( self.client, self.lag1, port_vlan_id=0) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry10) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry11) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry12) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry13) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry15) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry16) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry17) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group1_member1) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group1_member2) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group1_member3) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group1_member4) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group2_member1) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group2_member2) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group3_member1) sai_thrift_remove_route_entry(self.client, self.route0) sai_thrift_remove_route_entry(self.client, self.route1) sai_thrift_remove_route_entry(self.client, self.route2) sai_thrift_remove_next_hop_group(self.client, self.nhop_group1) sai_thrift_remove_next_hop_group(self.client, self.nhop_group2) sai_thrift_remove_next_hop_group(self.client, self.nhop_group3) sai_thrift_remove_next_hop(self.client, self.nhop1) sai_thrift_remove_next_hop(self.client, self.nhop2) sai_thrift_remove_next_hop(self.client, self.nhop3) sai_thrift_remove_next_hop(self.client, self.nhop4) sai_thrift_remove_next_hop(self.client, self.nhop3_lag1) sai_thrift_remove_next_hop(self.client, self.nhop4_lag2) sai_thrift_remove_next_hop(self.client, self.nhop5_lag1) sai_thrift_remove_next_hop(self.client, self.nhop6_lag2) sai_thrift_remove_vlan_member(self.client, self.vlan200_member1) sai_thrift_remove_vlan_member(self.client, self.vlan200_member2) sai_thrift_remove_vlan(self.client, self.vlan200) sai_thrift_remove_router_interface(self.client, self.lag1_rif) sai_thrift_remove_router_interface(self.client, self.lag2_rif) sai_thrift_remove_router_interface(self.client, self.port15_rif) finally: super(SAIHashTest, self).tearDown() def l3IPv4LagPacketTest(self, hash_dict, traffic=True, max_itrs=MAX_ITRS): """ Function that performs the IPv4 LAG hash test with L3 hashed traffic Args: hash_dict (dict): dictionary with variables that defines the list of hash test fields and traffic header hashed fields traffic (boolean): informs if traffic is expected on egress ports max_itrs (int): maximum number of iterations Returns: list: list of numbers of packet egressed on specific test member """ count = [0, 0, 0] src_mac_start = '00:22:22:22:{0}:{1}' dst_mac_start = '00:99:99:99:{0}:{1}' dst_mac = '00:99:99:99:99:99' src_mac = '00:22:22:22:22:22' dst_ip = int(binascii.hexlify(socket.inet_aton('10.70.70.1')), 16) src_ip = int(binascii.hexlify(socket.inet_aton('192.168.8.1')), 16) udp_sport = 7 udp_dport = 7 for i in range(0, max_itrs): dst_ip_addr = socket.inet_ntoa( binascii.unhexlify(hex(dst_ip)[2:].zfill(8))) src_ip_addr = socket.inet_ntoa( binascii.unhexlify(hex(src_ip)[2:].zfill(8))) if ('hash_dst_ip' in hash_dict) and (hash_dict['hash_dst_ip']): dst_ip += i * 7 if ('hash_src_ip' in hash_dict) and (hash_dict['hash_src_ip']): src_ip += i * 17 if ('hash_src_mac' in hash_dict) and (hash_dict['hash_src_mac']): src_mac = src_mac_start.format( str(i).zfill(4)[:2], str(i).zfill(4)[2:]) if ('hash_dst_mac' in hash_dict) and (hash_dict['hash_dst_mac']): dst_mac = dst_mac_start.format( str(i).zfill(4)[:2], str(i).zfill(4)[2:]) if ('hash_udp_sport' in hash_dict) and \ (hash_dict['hash_udp_sport']): udp_sport += 13 if ('hash_udp_dport' in hash_dict) and \ (hash_dict['hash_udp_dport']): udp_dport += 13 pkt = simple_udp_packet(eth_dst=ROUTER_MAC, eth_src=src_mac, ip_dst=dst_ip_addr, ip_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ip_id=106, ip_ttl=64) exp_pkt = simple_udp_packet(eth_dst='00:77:77:77:77:77', eth_src=ROUTER_MAC, ip_dst=dst_ip_addr, ip_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ip_id=106, ip_ttl=63) send_packet(self, self.dev_port4, pkt) if traffic: exp_ports = [self.dev_port4, self.dev_port5, self.dev_port6] rcv_idx = verify_any_packet_any_port( self, [exp_pkt], exp_ports) count[rcv_idx] += 1 if DEBUG: print("idx:", rcv_idx, "dst_ip:", dst_ip_addr, " src_ip:", src_ip_addr, " smac:", src_mac, " dmac: ", dst_mac, " dport", udp_dport, " sport", udp_sport) else: verify_no_other_packets(self) return count def l3IPv4EcmpPacketTest(self, hash_dict, traffic=True, max_itrs=MAX_ITRS): """ Function that performs the IPv4 ECMP test with L3 hashed traffic Args: hash_dict (dict): dictionary with variables that defines the list of hash test fields and traffic header hashed fields traffic (boolean): informs if traffic is expected on egress ports max_itrs (int): maximum number of iterations Returns: list: list of numbers of packet egressed on specific test port """ count = [0, 0, 0, 0] src_mac_start = '00:22:22:22:{0}:{1}' dst_mac_start = '00:99:99:99:{0}:{1}' dst_mac = ROUTER_MAC src_mac = '00:22:22:22:22:22' dst_ip = int(binascii.hexlify(socket.inet_aton('10.10.10.1')), 16) src_ip = int(binascii.hexlify(socket.inet_aton('192.168.8.1')), 16) udp_sport = 7 udp_dport = 7 for i in range(0, max_itrs): dst_ip_addr = socket.inet_ntoa( binascii.unhexlify(hex(dst_ip)[2:].zfill(8))) src_ip_addr = socket.inet_ntoa( binascii.unhexlify(hex(src_ip)[2:].zfill(8))) if ('hash_dst_ip' in hash_dict) and (hash_dict['hash_dst_ip']): dst_ip += i * 7 if ('hash_src_ip' in hash_dict) and (hash_dict['hash_src_ip']): src_ip += i * 7 if ('hash_src_mac' in hash_dict) and (hash_dict['hash_src_mac']): src_mac = src_mac_start.format( str(i).zfill(4)[:2], str(i).zfill(4)[2:]) if ('hash_dst_mac' in hash_dict) and (hash_dict['hash_dst_mac']): dst_mac = dst_mac_start.format( str(i).zfill(4)[:2], str(i).zfill(4)[2:]) if ('hash_udp_sport' in hash_dict) and \ (hash_dict['hash_udp_sport']): udp_sport += 13 if ('hash_udp_dport' in hash_dict) and \ (hash_dict['hash_udp_dport']): udp_dport += 13 pkt = simple_udp_packet(eth_dst=ROUTER_MAC, eth_src=src_mac, ip_dst=dst_ip_addr, ip_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ip_id=106, ip_ttl=64) exp_pkt1 = simple_udp_packet(eth_dst='00:11:11:11:11:11', eth_src=ROUTER_MAC, ip_dst=dst_ip_addr, ip_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ip_id=106, ip_ttl=63) exp_pkt2 = simple_udp_packet(eth_dst='00:22:22:22:22:22', eth_src=ROUTER_MAC, ip_dst=dst_ip_addr, ip_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ip_id=106, ip_ttl=63) exp_pkt3 = simple_udp_packet(eth_dst='00:33:33:33:33:33', eth_src=ROUTER_MAC, ip_dst=dst_ip_addr, ip_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ip_id=106, ip_ttl=63) exp_pkt4 = simple_udp_packet(eth_dst='00:44:44:44:44:44', eth_src=ROUTER_MAC, ip_dst=dst_ip_addr, ip_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ip_id=106, ip_ttl=63) send_packet(self, self.dev_port15, pkt) if traffic: ports_to_verify = [ self.dev_port10, self.dev_port11, self.dev_port12, self.dev_port13] rcv_idx = verify_any_packet_any_port(self, [exp_pkt1, exp_pkt2, exp_pkt3, exp_pkt4], ports_to_verify) count[rcv_idx] += 1 if DEBUG: print("idx:", rcv_idx, "dst_ip:", dst_ip_addr, " src_ip:", src_ip_addr, " smac:", src_mac, " dmac: ", dst_mac, " dport", udp_dport, " sport", udp_sport) else: verify_no_other_packets(self) return count def l2hashTraffic(self, hash_dst_mac=False, hash_src_mac=False, hash_ether_type=False): """ Function that performs the LAG hash test with L2 hashed traffic Args: hash_dst_mac (boolean): indicates if test uses dst mac hashed traffic hash_src_mac (boolean): indicates if test uses src mac hashed traffic hash_ether_type (boolean): indicates if test uses ether type hashed traffic Returns: list: list of number of packet egressed on specific test port """ src_mac_start = '00:11:11:11:11:' dst_mac_start = '00:22:22:22:22:' src_mac = '00:11:11:11:11:11' dst_mac = '00:22:22:22:22:00' eth_type = 0x88cc pkt = simple_eth_packet(eth_dst=dst_mac, eth_src=src_mac, eth_type=eth_type, pktlen=100) fdb_entries = [] try: for i in range(0, MAX_ITRS): dst_mac = dst_mac_start + hex(i)[2:] fdb_entry = sai_thrift_fdb_entry_t( switch_id=self.switch_id, mac_address=dst_mac, bv_id=self.vlan200) fdb_entries.append(fdb_entry) sai_thrift_create_fdb_entry( self.client, fdb_entry, type=SAI_FDB_ENTRY_TYPE_STATIC, bridge_port_id=self.lag1_bp) count = [0, 0, 0] for i in range(0, MAX_ITRS): if hash_src_mac: pkt['Ethernet'].src = src_mac_start + hex(i)[2:] if hash_dst_mac: dst_mac = dst_mac_start + hex(i)[2:] pkt['Ethernet'].dst = dst_mac if hash_ether_type: pkt['Ethernet'].type = eth_type + i send_packet(self, self.dev_port0, pkt) ports_to_verify = [ self.dev_port4, self.dev_port5, self.dev_port6] rcv_idx = verify_any_packet_any_port( self, [pkt, pkt, pkt], ports_to_verify) count[rcv_idx] += 1 return count finally: for fdb_entry in fdb_entries: sai_thrift_remove_fdb_entry(self.client, fdb_entry) def ecmpIPv4HashSaveRestoreTest(self): """ Verfies modification of the switch ECMP IPv4 hash fields """ test_header("ecmpIPv4HashSaveRestoreTest") hash_fields_list = [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT] attr_list = sai_thrift_get_switch_attribute( self.client, ecmp_hash_ipv4=True) ipv4_hash_id = attr_list['SAI_SWITCH_ATTR_ECMP_HASH_IPV4'] if ipv4_hash_id == 0: if self.ipv4_hash_id != 0: ipv4_hash_id = self.ipv4_hash_id else: s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) ipv4_hash_id = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( ipv4_hash_id != 0, "Failed to create IPv4 hash") status = sai_thrift_set_switch_attribute( self.client, ecmp_hash_ipv4=ipv4_hash_id) self.assertEqual(status, SAI_STATUS_SUCCESS) attr_list = sai_thrift_get_switch_attribute( self.client, ecmp_hash_ipv4=True) ipv4_hash_id = attr_list['SAI_SWITCH_ATTR_ECMP_HASH_IPV4'] self.assertTrue( ipv4_hash_id != 0, "failed to get the switch IPv4 ecmp hash") self.ipv4_hash_id = ipv4_hash_id s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, ipv4_hash_id, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) # vefify the native hash fields list self.assertEqual( True, self.verifyHashFieldsList( ipv4_hash_id, hash_fields_list)) # verify new hash create test_fields_list = [[SAI_NATIVE_HASH_FIELD_SRC_IP], [SAI_NATIVE_HASH_FIELD_DST_IP], [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP], [SAI_NATIVE_HASH_FIELD_IP_PROTOCOL], [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT]] for field_list in test_fields_list: s32list = sai_thrift_s32_list_t( count=len(field_list), int32list=field_list) new_ipv4_hash_id = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( new_ipv4_hash_id != 0, "Failed to create IPv4 hash") self.assertEqual( True, self.verifyHashFieldsList( new_ipv4_hash_id, field_list)) status = sai_thrift_remove_hash(self.client, new_ipv4_hash_id) self.assertEqual(status, SAI_STATUS_SUCCESS) def lagIPv6HashSaveRestoreTest(self): """ Verfies modification of the switch lag IPv6 hash fields """ test_header("lagIPv6HashSaveRestoreTest") hash_fields_list = [ SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT] attr_list = sai_thrift_get_switch_attribute( self.client, lag_hash_ipv6=True) lag_hash_ipv6 = attr_list['SAI_SWITCH_ATTR_LAG_HASH_IPV6'] if lag_hash_ipv6 == 0: if self.lag_hash_ipv6 != 0: lag_hash_ipv6 = self.lag_hash_ipv6 else: s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) lag_hash_ipv6 = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( lag_hash_ipv6 != 0, "Failed to create IPv6 hash") status = sai_thrift_set_switch_attribute( self.client, lag_hash_ipv6=lag_hash_ipv6) self.assertEqual(status, SAI_STATUS_SUCCESS) sai_thrift_get_switch_attribute( self.client, lag_hash_ipv6=True) self.assertTrue( lag_hash_ipv6 != 0, "failed to restore the switch IPv6 LAG hash") self.lag_hash_ipv6 = lag_hash_ipv6 s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_ipv6, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) # vefify the native hash fields list self.assertEqual( True, self.verifyHashFieldsList( lag_hash_ipv6, hash_fields_list)) # verify new hash create test_fields_list = [[SAI_NATIVE_HASH_FIELD_SRC_IP], [SAI_NATIVE_HASH_FIELD_DST_IP], [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP], [SAI_NATIVE_HASH_FIELD_IP_PROTOCOL], [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT]] for field_list in test_fields_list: s32list = sai_thrift_s32_list_t( count=len(field_list), int32list=field_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_ipv6, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) self.assertEqual( True, self.verifyHashFieldsList( lag_hash_ipv6, field_list)) def lagIPv4HashSaveRestoreTest(self): """ Verfies modification of the switch lag IPv4 hash fields """ test_header("lagIPv4HashSaveRestoreTest") hash_fields_list = [ SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT] attr_list = sai_thrift_get_switch_attribute( self.client, lag_hash_ipv4=True) lag_hash_ipv4 = attr_list['SAI_SWITCH_ATTR_LAG_HASH_IPV4'] if lag_hash_ipv4 == 0: if self.lag_hash_ipv4 != 0: lag_hash_ipv4 = self.lag_hash_ipv4 else: s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) lag_hash_ipv4 = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( lag_hash_ipv4 != 0, "Failed to create IPv4 hash") status = sai_thrift_set_switch_attribute( self.client, lag_hash_ipv4=lag_hash_ipv4) self.assertEqual(status, SAI_STATUS_SUCCESS) attr_list = sai_thrift_get_switch_attribute( self.client, lag_hash_ipv4=True) lag_hash_ipv4 = attr_list['SAI_SWITCH_ATTR_LAG_HASH_IPV4'] self.assertTrue( lag_hash_ipv4 != 0, "failed to restore the switch IPv4 LAG hash") self.lag_hash_ipv4 = lag_hash_ipv4 s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_ipv4, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) # vefify the native hash fields list self.assertEqual( True, self.verifyHashFieldsList( lag_hash_ipv4, hash_fields_list)) # verify new hash create test_fields_list = [[SAI_NATIVE_HASH_FIELD_SRC_IP], [SAI_NATIVE_HASH_FIELD_DST_IP], [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP], [SAI_NATIVE_HASH_FIELD_IP_PROTOCOL], [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT]] for field_list in test_fields_list: s32list = sai_thrift_s32_list_t( count=len(field_list), int32list=field_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_ipv4, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) self.assertEqual( True, self.verifyHashFieldsList( lag_hash_ipv4, field_list)) def lagHashSaveRestoreTest(self): """ Verfies modification of the switch lag hash fields """ test_header("lagHashSaveRestoreTest") hash_fields_list = [ SAI_NATIVE_HASH_FIELD_SRC_MAC, SAI_NATIVE_HASH_FIELD_DST_MAC, SAI_NATIVE_HASH_FIELD_ETHERTYPE, SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT] attr_list = sai_thrift_get_switch_attribute( self.client, lag_hash=True) lag_hash_id = attr_list['SAI_SWITCH_ATTR_LAG_HASH'] self.assertTrue( lag_hash_id != 0, "switch lag hash not configured correctly") s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_id, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) # vefify the native hash fields list self.assertEqual( True, self.verifyHashFieldsList( lag_hash_id, hash_fields_list)) # verify new hash create test_fields_list = [[SAI_NATIVE_HASH_FIELD_SRC_MAC], [SAI_NATIVE_HASH_FIELD_SRC_MAC, SAI_NATIVE_HASH_FIELD_DST_MAC], [SAI_NATIVE_HASH_FIELD_SRC_MAC, SAI_NATIVE_HASH_FIELD_DST_MAC, SAI_NATIVE_HASH_FIELD_ETHERTYPE], [SAI_NATIVE_HASH_FIELD_ETHERTYPE]] for field_list in test_fields_list: s32list = sai_thrift_s32_list_t( count=len(field_list), int32list=field_list) status = sai_thrift_set_hash_attribute( self.client, lag_hash_id, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) self.assertEqual( True, self.verifyHashFieldsList( lag_hash_id, field_list)) def ecmpIPv4BasicHashNoLBTest(self): """ Verfies ECMP IPv4 hash defined for single not modified IPv4 hash field with traffic and no load balancing """ test_header("ecmpIPv4BasicHashNoLBTest") hash_dict = {'hash_src_ip': True, 'hash_dst_ip': True, 'hash_src_mac': True} self.setupECMPIPv4Hash([SAI_NATIVE_HASH_FIELD_DST_MAC]) print("Verify no load balancing when packet fields changes" "do not match hash fields.") # should NOT ballance ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict) print("ECMP count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 1) def fgEcmpIPv4HashTest(self, hash_src_ip=None, hash_dst_ip=None, hash_udp_sport=None, hash_udp_dport=None): """ Verifies traffic distribution using all the fields selected for ECMP IPv4 Hash Args: hash_src_ip (boolean): indicates if test uses src ip hashed traffic hash_dst_ip (boolean): indicates if test uses dst ip hashed traffic hash_udp_sport (boolean): indicates if test uses udp sport hashed traffic hash_udp_dport (boolean): indicates if test uses udp dport hashed traffic """ hash_dict = {'hash_src_ip': hash_src_ip, 'hash_dst_ip': hash_dst_ip, 'hash_udp_dport': hash_udp_dport, 'hash_udp_sport': hash_udp_sport} hash_fields = hash_to_hash_fields(hash_dict) print("Verify IPv4 ECMP load balancing for hash fields: %s" % (hash_fields_to_hash_names(hash_fields))) # setup IPv4 hash fields for all fields self.setupFGECMPIPv4Hash(hash_fields) # should ballance equally ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict) print("ECMP LB count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 4) equaly_balanced = verify_equaly_balanced(ecmp_count) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced") ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict_negation( hash_dict)) print("ECMP LB count (LB NOT expected):", ecmp_count) no_lb = verify_no_lb(ecmp_count, max_iters=MAX_ITRS) self.assertTrue(no_lb, "Not expected to balance") # Few bits of IP is masked self.setupFGECMPIPv4Hash(hash_fields, p_ipv4_mask='255.255.255.0') ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict) print("ECMP LB count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 4) equaly_balanced = verify_equaly_balanced(ecmp_count) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced") def ecmpIPv4HashTest(self, hash_src_ip=None, hash_dst_ip=None, hash_udp_sport=None, hash_udp_dport=None): """ Verifies traffic distribution using all the fields selected for ECMP IPv4 Hash Args: hash_src_ip (boolean): indicates if test uses src ip hashed traffic hash_dst_ip (boolean): indicates if test uses dst ip hashed traffic hash_udp_sport (boolean): indicates if test uses udp sport hashed traffic hash_udp_dport (boolean): indicates if test uses udp dport hashed traffic """ hash_dict = {'hash_src_ip': hash_src_ip, 'hash_dst_ip': hash_dst_ip, 'hash_udp_dport': hash_udp_dport, 'hash_udp_sport': hash_udp_sport} hash_fields = hash_to_hash_fields(hash_dict) print("Verify IPv4 ECMP load balancing for hash fields: %s" % (hash_fields_to_hash_names(hash_fields))) # setup IPv4 hash fields for all fields self.setupECMPIPv4Hash(hash_fields) # should ballance equally ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict) print("ECMP LB count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 4) equaly_balanced = verify_equaly_balanced(ecmp_count) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced") ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict_negation( hash_dict)) print("ECMP LB count (LB NOT expected):", ecmp_count) no_lb = verify_no_lb(ecmp_count, max_iters=MAX_ITRS) self.assertTrue(no_lb, "Not expected to balance") def ecmpIPv4vsIPv6HashTest(self): """ Verifies IPv6 hash does not impact IPv4 hashing """ test_header("ecmpIPv4vsIPv6HashTest") hash_dict_src = {'hash_src_ip': True} hash_dict_dst = {'hash_dst_ip': True} self.setupECMPIPv4Hash([SAI_NATIVE_HASH_FIELD_SRC_IP]) # verify if IPv6 hash affects IPv4 hash self.setupECMPIPv6Hash([SAI_NATIVE_HASH_FIELD_DST_IP]) print("Verify load balancing equaly for all next_hops when" "packet fields changes and do match hash fields.") # IPV4 should ballance equally independently of IPv6 hash ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict_src) print("ECMP count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 4) equaly_balanced = verify_equaly_balanced(ecmp_count) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced") # IPv4 should not ballance ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict_dst) print("ECMP count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertTrue(nbr_active_ports == 1, "LB not expected") def l3EcmpIPv4HashSeedTest(self): """ Verifies IPv4 ECMP with varing seed values """ test_header("l3EcmpIPv4HashSeedTest") hash_dict = {'hash_src_ip': True, 'hash_dst_ip': True, 'hash_udp_dport': True, 'hash_udp_sport': True} hash_fields = hash_to_hash_fields(hash_dict) self.setupECMPIPv4Hash(hash_fields, seed=TEST_ECMP_SEED) print("Verify load balancing equaly for all next_hops when" "all packets fields changes") ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict) print("ECMP count seed=%d:" % (TEST_ECMP_SEED), ecmp_count) equaly_balanced = verify_equaly_balanced( ecmp_count, expected_base=SEED_TEST_CHECK_BASE) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced with seed=17") nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 4) # set the ecmp hash seed self.setupECMPSeed(seed=TEST_ECMP_SEED1) ecmp_count_seed1 = self.l3IPv4EcmpPacketTest(hash_dict) print("ECMP count seed=%d:" % (TEST_ECMP_SEED1), ecmp_count_seed1) equaly_balanced = verify_equaly_balanced( ecmp_count_seed1, expected_base=SEED_TEST_CHECK_BASE) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced with seed=%d" % (TEST_ECMP_SEED)) nbr_active_ports = verify_lb_active_ports(ecmp_count_seed1) self.assertEqual(nbr_active_ports, 4) # vefiry if LB factor changed similary_balanced = verify_similary_balanced( ecmp_count, ecmp_count_seed1) self.assertTrue(similary_balanced, "ECMP Seed change has no effect on LB") def ecmpHashAlgorithmTest(self): """ Verifies ECMP hash algorithm """ test_header("ecmpHashAlgorithmTest") hash_dict = {'hash_src_ip': True} try: # configure ECMP hash for all fields self.setupECMPIPv4Hash() print("Verify L3 load balancing for ECMP members" "for all fields hashing") self.setupECMPSeed(seed=0) self.setupECMPAlgorithm() hash_attr_get = sai_thrift_get_switch_attribute( self.client, ecmp_default_hash_algorithm=True) self.assertEqual(hash_attr_get[ 'SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM'], SAI_HASH_ALGORITHM_CRC) print('Read value of algorithm: ', hash_attr_get) # should ballance equally ecmp_count = self.l3IPv4EcmpPacketTest(hash_dict, max_itrs=L3_MAX_ITRS) print("\nECMP count: %s \n" % (ecmp_count)) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 4) equaly_balanced = verify_equaly_balanced( ecmp_count, pkt_count=L3_MAX_ITRS, expected_base=0.6) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced") # Setting the ECMP default hash algorithm to RANDOM self.setupECMPSeed(seed=0) self.setupECMPAlgorithm(SAI_HASH_ALGORITHM_RANDOM) hash_attr_get = sai_thrift_get_switch_attribute( self.client, ecmp_default_hash_algorithm=True) print('Read value of algorithm: ', hash_attr_get) self.assertEqual(hash_attr_get[ 'SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM'], SAI_HASH_ALGORITHM_RANDOM) ecmp_random_count = self.l3IPv4EcmpPacketTest(hash_dict, max_itrs=L3_MAX_ITRS) print("\nECMP count: %s \n" % (ecmp_random_count)) nbr_active_ports_rd = verify_lb_active_ports( ecmp_random_count) self.assertEqual(nbr_active_ports_rd, 4) equaly_balanced_rd = verify_equaly_balanced( ecmp_random_count, pkt_count=L3_MAX_ITRS, expected_base=0.6) self.assertTrue(equaly_balanced_rd, "Ecmp paths are not equally balanced") similary_balanced = verify_similary_balanced( ecmp_count, ecmp_random_count) self.assertTrue(similary_balanced, "ECMP Algoritm change has no effect on LB") finally: self.setupECMPSeed(seed=0) self.setupECMPAlgorithm() def nonIpHashTest(self, hash_dst_mac=None, hash_src_mac=None, hash_ether_type=None): """ Verifies the hashing on LAG members for L2 traffic Args: hash_dst_mac (boolean): indicates if test uses dst mac hashed traffic hash_src_mac (boolean): indicates if test uses src mac hashed traffic hash_ether_type (boolean): indicates if test uses ether type hashed traffic """ hash_dict = {'hash_dst_mac': hash_dst_mac, 'hash_src_mac': hash_src_mac, 'hash_ether_type': hash_ether_type} try: hash_fields = hash_to_hash_fields(hash_dict) self.setupNonIPECMPHash(hash_fields) print("Setting Non-IP hash object with hash fields: %s" % ( hash_fields_to_hash_names(hash_fields))) lb_count = self.l2hashTraffic( hash_dst_mac=hash_dst_mac, hash_src_mac=hash_src_mac, hash_ether_type=hash_ether_type) print('NonIP-pkt-count:', lb_count) nbr_active_ports = verify_lb_active_ports(lb_count) self.assertEqual(nbr_active_ports, 3) equaly_balanced = verify_equaly_balanced(lb_count) self.assertTrue(equaly_balanced, "paths are not equally balanced") lb_count = self.l2hashTraffic(hash_src_mac=not hash_src_mac, hash_dst_mac=not hash_dst_mac, hash_ether_type=not hash_ether_type) print('NonIP-pkt-count:', lb_count) nbr_active_ports = verify_lb_active_ports(lb_count) self.assertTrue( nbr_active_ports == 1, "Expected no LB, traffic on single port only") finally: sai_thrift_flush_fdb_entries( self.client, entry_type=SAI_FDB_FLUSH_ENTRY_TYPE_ALL) def l3LagIPv4HashTest(self, hash_src_ip=None, hash_dst_ip=None, hash_udp_sport=None, hash_udp_dport=None): """ Verfies L3 IPv4 traffic distribution using all the field selected for IPv4 LAG Hash Args: hash_src_ip (boolean): indicates if test uses src ip hashed traffic hash_dst_ip (boolean): indicates if test uses dst ip hashed traffic hash_udp_sport (boolean): indicates if test uses udp sport hashed traffic hash_udp_dport (boolean): indicates if test uses udp dport hashed traffic """ hash_dict = {'hash_src_ip': hash_src_ip, 'hash_dst_ip': hash_dst_ip, 'hash_udp_dport': hash_udp_dport, 'hash_udp_sport': hash_udp_sport} hash_fields = hash_to_hash_fields(hash_dict) print("Verify IPv4 LAG load balancing for hash fields: %s" % (hash_fields_to_hash_names(hash_fields))) self.setupLAGIPv4Hash(hash_fields) lag_hashing_counts = self.l3IPv4LagPacketTest(hash_dict) print("LAG hash LB count (LB expected):", lag_hashing_counts) nbr_active_ports = verify_lb_active_ports(lag_hashing_counts) self.assertEqual(nbr_active_ports, 3) equaly_balanced = verify_equaly_balanced(lag_hashing_counts) self.assertTrue(equaly_balanced, "LAG members are not equally balanced") lag_hashing_counts = self.l3IPv4LagPacketTest( hash_dict_negation(hash_dict)) print("LAG hash LB count (LB NOT expected):", lag_hashing_counts) no_lb = verify_no_lb(lag_hashing_counts, max_iters=MAX_ITRS) self.assertTrue(no_lb, "Not expected to balance") def lagHashAlgorithmTest(self): """ Verifies lag hash algorithm """ test_header("lagHashAlgorithmTest") try: print("Verify L3 load balancing for all LAG members " "for all fields hashing") self.setupLAGIPv4Hash() self.setupLagSeed(seed=0) self.setupLagAlgorithm() hash_attr_get = sai_thrift_get_switch_attribute( self.client, lag_default_hash_algorithm=True) self.assertEqual(hash_attr_get[ 'SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_ALGORITHM'], SAI_HASH_ALGORITHM_CRC) print('Read value of algorithm: ', hash_attr_get) hash_dict = {'hash_src_ip': True, 'hash_udp_dport': True, 'hash_udp_sport': True} lag_pkt_count = self.l3IPv4LagPacketTest(hash_dict, max_itrs=LAG_MAX_ITRS) print("\nPacket count: %s \n" % (lag_pkt_count)) nbr_active_ports = verify_lb_active_ports(lag_pkt_count) self.assertEqual(nbr_active_ports, 3) equaly_balanced = verify_equaly_balanced( lag_pkt_count, pkt_count=LAG_MAX_ITRS, expected_base=0.6) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced") # Setting the ECMP default hash algorithm to RANDOM self.setupLagSeed(seed=0) self.setupLagAlgorithm(SAI_HASH_ALGORITHM_RANDOM) hash_attr_get = sai_thrift_get_switch_attribute( self.client, lag_default_hash_algorithm=True) self.assertEqual(hash_attr_get[ 'SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_ALGORITHM'], SAI_HASH_ALGORITHM_RANDOM) print('Read value of algorithm: ', hash_attr_get) pkt_count_random = self.l3IPv4LagPacketTest(hash_dict, max_itrs=LAG_MAX_ITRS) print("\nPacket count: %s \n" % (pkt_count_random)) nbr_active_ports_rd = verify_lb_active_ports(pkt_count_random) self.assertEqual(nbr_active_ports_rd, 3) equaly_balanced_rd = verify_equaly_balanced( pkt_count_random, pkt_count=LAG_MAX_ITRS, expected_base=0.6) self.assertTrue(equaly_balanced_rd, "Ecmp paths are not equally balanced") similary_balanced = verify_similary_balanced( lag_pkt_count, pkt_count_random) self.assertTrue(similary_balanced, "LAG Algoritm change has no effect on LB") finally: self.setupLagAlgorithm() self.setupLagSeed(seed=0) def l2LagHashSeedTest(self): """ Verifies basic L2 Lag configuration with varing seed values """ test_header("l2LagHashSeedTest") hash_dict = {'hash_dst_mac': True, 'hash_src_mac': True, 'hash_ether_type': True} print("Verify L2 load balancing for all LAG members " "for all fields hashing") hash_fields = hash_to_hash_fields(hash_dict) self.setupNonIPECMPHash(hash_fields) self.setupLagSeed(seed=TEST_LAG_SEED1) lb_count = self.l2hashTraffic( hash_dst_mac=True, hash_src_mac=True, hash_ether_type=True) print("LAG count seed=%d:" % (TEST_LAG_SEED1), lb_count) nbr_active_ports = verify_lb_active_ports(lb_count) self.assertEqual(nbr_active_ports, 3) new_seed = TEST_LAG_SEED1 * 2 self.setupLagSeed(seed=new_seed) lb_count_seed1 = self.l2hashTraffic( hash_dst_mac=True, hash_src_mac=True, hash_ether_type=True) print("LAG count seed=%d:" % (new_seed), lb_count_seed1) nbr_active_ports = verify_lb_active_ports(lb_count_seed1) self.assertEqual(nbr_active_ports, 3) # verify that changing seed changes modifies the LB # vefiry if LB factor changed similary_balanced = verify_similary_balanced( lb_count, lb_count_seed1) self.assertTrue(similary_balanced, "LAG Seed change has no effect on LB") def l3LagIPv4HashSeedTest(self): """ Verifies basic L3 Lag configuration with varing seed values """ hash_dict = {'hash_src_ip': True, 'hash_dst_ip': True, 'hash_udp_dport': True, 'hash_udp_sport': True} hash_fields = hash_to_hash_fields(hash_dict) print("Verify IPv4 LAG load balancing for hash fields: %s" % (hash_fields_to_hash_names(hash_fields))) self.setupLAGIPv4Hash(hash_fields) self.setupLagSeed(seed=TEST_LAG_SEED) ecmp_count = self.l3IPv4LagPacketTest(hash_dict) print("ECMP count seed=%d:" % (TEST_LAG_SEED), ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 3) equaly_balanced = verify_equaly_balanced( ecmp_count, expected_base=SEED_TEST_CHECK_BASE) self.assertTrue(equaly_balanced, "LAG paths are not equally balanced") self.setupLagSeed(seed=TEST_LAG_SEED1) print("Verify load balancing for IPv4 hash seed = %d" % (TEST_LAG_SEED1)) ecmp_count_seed1 = self.l3IPv4LagPacketTest(hash_dict) print("ECMP count seed=%d:" % (TEST_LAG_SEED1), ecmp_count_seed1) nbr_active_ports = verify_lb_active_ports(ecmp_count_seed1) self.assertEqual(nbr_active_ports, 3) equaly_balanced = verify_equaly_balanced( ecmp_count_seed1, expected_base=SEED_TEST_CHECK_BASE) self.assertTrue(equaly_balanced, "LAG paths are not equally balanced") # verify if LB distribution has changed similary_balanced = verify_similary_balanced( ecmp_count, ecmp_count_seed1) self.assertTrue(similary_balanced, "LAG Seed change has no effect on LB") @group("draft") class SAIIPv6HashTest(SAIHashTestBase): """ Runs IPv6 hash test cases """ def setUp(self): super(SAIIPv6HashTest, self).setUp() self.ipv4_hash_id = 0 self.ipv6_hash_id = 0 dmac5 = '00:55:55:55:55:55' dmac6 = '00:66:66:66:66:66' dmac7 = '00:77:77:77:77:77' dmac8 = '00:88:88:88:88:88' nhop_ip5 = '5000:1:1:0:0:0:0:1' nhop_ip6 = '6000:1:1:0:0:0:0:1' nhop_ip7 = '7000:1:1:0:0:0:0:1' nhop_ip8 = '0001:1:1:0:0:0:0:1' # set switch src mac address sai_thrift_set_switch_attribute( self.client, src_mac_address=ROUTER_MAC) self.port25_rif = sai_thrift_create_router_interface( self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, virtual_router_id=self.default_vrf, port_id=self.port25, admin_v6_state=True) self.port26_rif = sai_thrift_create_router_interface( self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, virtual_router_id=self.default_vrf, port_id=self.port26, admin_v6_state=True) self.port27_rif = sai_thrift_create_router_interface( self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, virtual_router_id=self.default_vrf, port_id=self.port27, admin_v6_state=True) self.lag1_rif = sai_thrift_create_router_interface( self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, virtual_router_id=self.default_vrf, port_id=self.lag1, admin_v6_state=True) self.neighbor_entry25 = sai_thrift_neighbor_entry_t( self.switch_id, self.port25_rif, sai_ipaddress(nhop_ip5)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry25, dst_mac_address=dmac5) self.neighbor_entry26 = sai_thrift_neighbor_entry_t( self.switch_id, self.port26_rif, sai_ipaddress(nhop_ip6)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry26, dst_mac_address=dmac6) self.neighbor_entry27 = sai_thrift_neighbor_entry_t( self.switch_id, self.port27_rif, sai_ipaddress(nhop_ip7)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry27, dst_mac_address=dmac7) self.neighbor_entry_lag1 = sai_thrift_neighbor_entry_t( self.switch_id, self.lag1_rif, sai_ipaddress(nhop_ip8)) sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry_lag1, dst_mac_address=dmac8) self.nhop5 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.port25_rif, ip=sai_ipaddress(nhop_ip5)) self.nhop6 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.port26_rif, ip=sai_ipaddress(nhop_ip6)) self.nhop7 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.port27_rif, ip=sai_ipaddress(nhop_ip7)) self.lag1_nhop1 = sai_thrift_create_next_hop( self.client, type=SAI_NEXT_HOP_TYPE_IP, router_interface_id=self.lag1_rif, ip=sai_ipaddress(nhop_ip8)) self.nhop_group1 = sai_thrift_create_next_hop_group( self.client, type=SAI_NEXT_HOP_GROUP_TYPE_ECMP) self.nh_group1_member1 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group1, next_hop_id=self.nhop5) self.nh_group1_member2 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group1, next_hop_id=self.nhop6) self.nh_group1_member3 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group1, next_hop_id=self.nhop7) self.nhop_group2 = sai_thrift_create_next_hop_group( self.client, type=SAI_NEXT_HOP_GROUP_TYPE_ECMP) self.nh_group2_member1 = sai_thrift_create_next_hop_group_member( self.client, next_hop_group_id=self.nhop_group2, next_hop_id=self.lag1_nhop1) # create route entries self.route0 = sai_thrift_route_entry_t(switch_id=self.switch_id, destination=sai_ipprefix( '1000:1:1:0:0:0:0:0/65'), vr_id=self.default_vrf) status = sai_thrift_create_route_entry( self.client, self.route0, next_hop_id=self.nhop_group1) self.assertEqual(status, SAI_STATUS_SUCCESS) # create route entries for IPv6 Lag test self.route1 = sai_thrift_route_entry_t(switch_id=self.switch_id, destination=sai_ipprefix( '8000:1:1:0:0:0:0:0/65'), vr_id=self.default_vrf) status = sai_thrift_create_route_entry( self.client, self.route1, next_hop_id=self.nhop_group2) self.assertEqual(status, SAI_STATUS_SUCCESS) def tearDown(self): try: sai_thrift_flush_fdb_entries( self.client, entry_type=SAI_FDB_FLUSH_ENTRY_TYPE_ALL) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry25) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry26) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry27) sai_thrift_remove_neighbor_entry( self.client, self.neighbor_entry_lag1) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group1_member1) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group1_member2) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group1_member3) sai_thrift_remove_next_hop_group_member( self.client, self.nh_group2_member1) sai_thrift_remove_route_entry(self.client, self.route0) sai_thrift_remove_route_entry(self.client, self.route1) sai_thrift_remove_next_hop_group(self.client, self.nhop_group1) sai_thrift_remove_next_hop_group(self.client, self.nhop_group2) sai_thrift_remove_next_hop(self.client, self.nhop5) sai_thrift_remove_next_hop(self.client, self.nhop6) sai_thrift_remove_next_hop(self.client, self.nhop7) sai_thrift_remove_next_hop(self.client, self.lag1_nhop1) sai_thrift_remove_router_interface(self.client, self.port25_rif) sai_thrift_remove_router_interface(self.client, self.port26_rif) sai_thrift_remove_router_interface(self.client, self.port27_rif) sai_thrift_remove_router_interface(self.client, self.lag1_rif) finally: super(SAIIPv6HashTest, self).tearDown() def l3IPv6EcmpPacketTest(self, hash_dict): """ Function that performs the IPv6 ECMP test with L3 hashed traffic Args: hash_dict (dict): dictionary with variables that defines the list of hash test fields and traffic header hashed fields Returns: list: list of numbers of packet egressed on specific test port """ ecmp_count = [0, 0, 0] src_mac_start = '00:22:22:22:{0}:{1}' src_mac = '00:22:22:22:22:22' dst_mac = ROUTER_MAC udp_sport = 7 udp_dport = 7 dst_ip = socket.inet_pton(socket.AF_INET6, '1000:1:1:0:0:0:0:1') dst_ip_arr = list(dst_ip) src_ip = socket.inet_pton(socket.AF_INET6, '6000:1:1:0:0:0:0:100') src_ip_arr = list(src_ip) for i in range(0, MAX_ITRS): if ('hash_src_mac' in hash_dict) and (hash_dict['hash_src_mac']): src_mac = src_mac_start.format( str(0xFF & (i * 117)).zfill(4)[:2], str(0xFF & (i * 13)).zfill(4)[2:]) if ('hash_dst_ip' in hash_dict) and (hash_dict['hash_dst_ip']): dst_ip_arr[15] = 0xFF & (dst_ip_arr[15] + 17) dst_ip = binascii.unhexlify(''.join( '%02x' % x for x in dst_ip_arr)) if ('hash_src_ip' in hash_dict) and (hash_dict['hash_src_ip']): src_ip_arr[15] = 0xFF & (src_ip_arr[15] + 13) src_ip = binascii.unhexlify(''.join( '%02x' % x for x in src_ip_arr)) dst_ip_addr = socket.inet_ntop(socket.AF_INET6, dst_ip) src_ip_addr = socket.inet_ntop(socket.AF_INET6, src_ip) if ('hash_udp_sport' in hash_dict) and \ (hash_dict['hash_udp_sport']): udp_sport += 13 if ('hash_udp_dport' in hash_dict) and \ (hash_dict['hash_udp_dport']): udp_dport += 13 pkt = simple_udpv6_packet(eth_dst=ROUTER_MAC, eth_src=src_mac, ipv6_dst=dst_ip_addr, ipv6_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ipv6_hlim=64) exp_pkt1 = simple_udpv6_packet(eth_dst='00:55:55:55:55:55', eth_src=ROUTER_MAC, ipv6_dst=dst_ip_addr, ipv6_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ipv6_hlim=63) exp_pkt2 = simple_udpv6_packet(eth_dst='00:66:66:66:66:66', eth_src=ROUTER_MAC, ipv6_dst=dst_ip_addr, ipv6_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ipv6_hlim=63) exp_pkt3 = simple_udpv6_packet(eth_dst='00:77:77:77:77:77', eth_src=ROUTER_MAC, ipv6_dst=dst_ip_addr, ipv6_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ipv6_hlim=63) send_packet(self, self.dev_port11, pkt) ports_to_verify = [ self.dev_port25, self.dev_port26, self.dev_port27] rcv_idx = verify_any_packet_any_port( self, [exp_pkt1, exp_pkt2, exp_pkt3], ports_to_verify) if DEBUG: print("idx:", rcv_idx, "dst_ip:", dst_ip_addr, " src_ip:", src_ip_addr, " smac:", src_mac, " dmac: ", dst_mac) ecmp_count[rcv_idx] += 1 return ecmp_count def lagIPv6PacketTest(self, hash_dict): """ Function that performs the IPv6 Lag test with L3 hashed traffic Args: hash_dict (dict): dictionary with variables that defines the list of hash test fields and traffic header hashed fields Returns: list: list of numbers of packet egressed on specific ecmp group member """ ecmp_count = [0, 0, 0] src_mac_start = '00:22:22:22:{0}:{1}' src_mac = '00:22:22:22:22:22' dst_mac = ROUTER_MAC udp_sport = 7 udp_dport = 7 dst_ip = socket.inet_pton(socket.AF_INET6, '8000:1:1:0:0:0:0:1') dst_ip_arr = list(dst_ip) src_ip = socket.inet_pton(socket.AF_INET6, '6000:1:1:0:0:0:0:100') src_ip_arr = list(src_ip) ipv6_flow_label = 0 if ('hash_flow_label' in hash_dict) and (hash_dict['hash_flow_label']): ipv6_flow_label = 10 for i in range(0, MAX_ITRS): if ('hash_src_mac' in hash_dict) and (hash_dict['hash_src_mac']): src_mac = src_mac_start.format( str(0xFF & (i * 117)).zfill(4)[:2], str(0xFF & (i * 13)).zfill(4)[2:]) if ('hash_dst_ip' in hash_dict) and (hash_dict['hash_dst_ip']): dst_ip_arr[15] = 0xFF & (dst_ip_arr[15] + 17) dst_ip = binascii.unhexlify(''.join( '%02x' % x for x in dst_ip_arr)) if ('hash_src_ip' in hash_dict) and (hash_dict['hash_src_ip']): src_ip_arr[15] = 0xFF & (src_ip_arr[15] + 13) src_ip = binascii.unhexlify(''.join( '%02x' % x for x in src_ip_arr)) dst_ip_addr = socket.inet_ntop(socket.AF_INET6, dst_ip) src_ip_addr = socket.inet_ntop(socket.AF_INET6, src_ip) if ('hash_udp_sport' in hash_dict) and \ (hash_dict['hash_udp_sport']): udp_sport += 13 if ('hash_udp_dport' in hash_dict) and \ (hash_dict['hash_udp_dport']): udp_dport += 13 pkt = simple_udpv6_packet(eth_dst=ROUTER_MAC, eth_src=src_mac, ipv6_dst=dst_ip_addr, ipv6_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ipv6_hlim=64, ipv6_fl=ipv6_flow_label) exp_pkt = simple_udpv6_packet(eth_dst='00:88:88:88:88:88', eth_src=ROUTER_MAC, ipv6_dst=dst_ip_addr, ipv6_src=src_ip_addr, udp_sport=udp_sport, udp_dport=udp_dport, ipv6_hlim=63, ipv6_fl=ipv6_flow_label) send_packet(self, self.dev_port4, pkt) ports_to_verify = [ self.dev_port4, self.dev_port5, self.dev_port6] rcv_idx = verify_any_packet_any_port( self, [exp_pkt], ports_to_verify) if DEBUG: print("idx:", rcv_idx, "dst_ip:", dst_ip_addr, " src_ip:", src_ip_addr, " smac:", src_mac, " dmac: ", dst_mac, "ipv6_flow_label: ", ipv6_flow_label) ecmp_count[rcv_idx] += 1 return ecmp_count def lagIPv6HashTest(self, hash_dict): """ Verifies IPv6 LAG load balancing for hash fields Args: hash_dict (dict): dictionary with variables that defines the list """ hash_fields = hash_to_hash_fields(hash_dict) print("Verify IPv6 LAG load balancing for hash fields: %s" % (hash_fields_to_hash_names(hash_fields))) self.setupLAGIPv6Hash(hash_fields) ecmp_count = self.lagIPv6PacketTest(hash_dict) print("ECMP count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertTrue( nbr_active_ports == 3, "Expected to balance equally on all next hops.") equaly_balanced = verify_equaly_balanced(ecmp_count) self.assertTrue(equaly_balanced, "Ecmp paths are not equally" "balanced for Lag IPv6 hashed traffic") print("Verify no load balancing for traffic " "with hash fields unchanged.") ecmp_count = self.lagIPv6PacketTest(hash_dict_negation(hash_dict)) print("ECMP count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertTrue( nbr_active_ports == 1, "Does not expect to balance on other hash fields.") def lagIPv6FlowLabelHashTest(self, hash_dict): """ Verifies IPv6 LAG load balancing for hash fields Args: hash_dict (dict): dictionary with variables that defines the list """ try: hash_fields = hash_to_hash_fields(hash_dict) print("Verify IPv6 Flow Label LAG load balancing " "for hash fields: %s" % (hash_fields_to_hash_names(hash_fields))) self.setupLAGIPv6Hash(hash_fields) packet_count = self.lagIPv6PacketTest(hash_dict) print("Packet count:", packet_count) no_lb = verify_no_lb(packet_count, max_iters=MAX_ITRS) self.assertTrue(no_lb, "Not expected to balance") finally: pass def lagIPv6HashSeedTest(self): """ Verfies L3 IPv6 Lag basic case with varing seed values """ hash_dict = {'hash_src_ip': True, 'hash_dst_ip': True, 'hash_udp_dport': True, 'hash_udp_sport': True} hash_fields = hash_to_hash_fields(hash_dict) print("Verify IPv6 LAG load balancing for hash fields: %s" % (hash_fields_to_hash_names(hash_fields))) self.setupLAGIPv6Hash(hash_fields) self.setupLagSeed(seed=TEST_LAG_SEED) ecmp_count = self.lagIPv6PacketTest(hash_dict) print("ECMP count seed=%d:" % (TEST_LAG_SEED), ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertTrue( nbr_active_ports == 3, "Expected to balance equally on all next hops.") equaly_balanced = verify_equaly_balanced( ecmp_count, expected_base=SEED_TEST_CHECK_BASE) self.assertTrue(equaly_balanced, "Ecmp paths are not equally" "balanced for Lag IPv6 hashed traffic") self.setupLagSeed(seed=TEST_LAG_SEED1) print("Verify load balancing for IPv6 hash seed = %d" % (TEST_LAG_SEED1)) ecmp_count_seed1 = self.lagIPv6PacketTest(hash_dict) print("ECMP count seed=%d:" % (TEST_LAG_SEED1), ecmp_count_seed1) nbr_active_ports = verify_lb_active_ports(ecmp_count_seed1) self.assertEqual(nbr_active_ports, 3) equaly_balanced = verify_equaly_balanced( ecmp_count_seed1, expected_base=SEED_TEST_CHECK_BASE) self.assertTrue(equaly_balanced, "LAG paths are not equally balanced") # verify if LB distribution has changed similary_balanced = verify_similary_balanced( ecmp_count, ecmp_count_seed1) self.assertTrue(similary_balanced, "LAG Seed change has no effect on LB") def ecmpIPv6HashTest(self, hash_src_ip=None, hash_dst_ip=None, hash_udp_sport=None, hash_udp_dport=None): """ Verifies traffic distribution using all the fields selected for ECMP IPv6 Hash Args: hash_src_ip (boolean): indicates if test uses src ip hashed traffic hash_dst_ip (boolean): indicates if test uses dst ip hashed traffic hash_udp_sport (boolean): indicates if test uses udp sport hashed traffic hash_udp_dport (boolean): indicates if test uses udp dport hashed traffic """ hash_dict = {'hash_src_ip': hash_src_ip, 'hash_dst_ip': hash_dst_ip, 'hash_udp_dport': hash_udp_dport, 'hash_udp_sport': hash_udp_sport} hash_fields = hash_to_hash_fields(hash_dict) print("Verify IPv6 ECMP load balancing for hash fields: %s" % (hash_fields_to_hash_names(hash_fields))) # setup IPv6 hash fields for all fields self.setupECMPIPv6Hash(hash_fields) ecmp_count = self.l3IPv6EcmpPacketTest(hash_dict) print("ECMP LB count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertTrue( nbr_active_ports == 3, "Expected to balance equally on all next hops.") equaly_balanced = verify_equaly_balanced(ecmp_count) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced") print("Verify no load balancing for non hashed traffic.") ecmp_count = self.l3IPv6EcmpPacketTest(hash_dict_negation( hash_dict)) print("ECMP no LB count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertTrue( nbr_active_ports == 1, "Does not expect to balance on other hash fields.") def l3EcmpIPv6HashSeedTest(self): """ Verifies IPv6 ECMP with varing seed values """ test_header("l3EcmpIPv6HashSeedTest") hash_dict = {'hash_src_ip': True, 'hash_dst_ip': True, 'hash_udp_dport': True, 'hash_udp_sport': True} hash_fields = hash_to_hash_fields(hash_dict) self.setupECMPIPv6Hash(hash_fields) self.setupECMPSeed(seed=TEST_ECMP_SEED) print("Verify load balancing equaly for all next_hops when " "all packets fields changes") ecmp_count = self.l3IPv6EcmpPacketTest(hash_dict) print("ECMP count seed=%d:" % (TEST_ECMP_SEED), ecmp_count) equaly_balanced = verify_equaly_balanced( ecmp_count, expected_base=SEED_TEST_CHECK_BASE) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced with seed=%d" % (TEST_ECMP_SEED1)) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 3) # set the ecmp hash seed self.setupECMPSeed(seed=TEST_ECMP_SEED1) ecmp_count_seed1 = self.l3IPv6EcmpPacketTest(hash_dict) print("ECMP count seed=%d:" % (TEST_ECMP_SEED1), ecmp_count_seed1) equaly_balanced = verify_equaly_balanced( ecmp_count_seed1, expected_base=SEED_TEST_CHECK_BASE) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced with seed=1") nbr_active_ports = verify_lb_active_ports(ecmp_count_seed1) self.assertEqual(nbr_active_ports, 3) # vefiry if LB factor changed similary_balanced = verify_similary_balanced( ecmp_count, ecmp_count_seed1) self.assertTrue(similary_balanced, "ECMP Seed change has no effect on LB") def ecmpIPv6HashSaveRestoreTest(self): """ Verfies modification of the switch ECMP IPv6 hash fields """ test_header("ecmpIPv6HashSaveRestoreTest") hash_fields_list = [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT] attr_list = sai_thrift_get_switch_attribute( self.client, ecmp_hash_ipv6=True) ipv6_hash_id = attr_list['SAI_SWITCH_ATTR_ECMP_HASH_IPV6'] if ipv6_hash_id == 0: if self.ipv6_hash_id != 0: ipv6_hash_id = self.ipv6_hash_id else: s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) ipv6_hash_id = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( ipv6_hash_id != 0, "Failed to create IPv6 hash") status = sai_thrift_set_switch_attribute( self.client, ecmp_hash_ipv6=ipv6_hash_id) self.assertEqual(status, SAI_STATUS_SUCCESS) attr_list = sai_thrift_get_switch_attribute( self.client, ecmp_hash_ipv6=True) ipv6_hash_id = attr_list['SAI_SWITCH_ATTR_ECMP_HASH_IPV6'] self.assertTrue( ipv6_hash_id != 0, "failed to restore the switch IPv6 ecmp hash") self.ipv6_hash_id = ipv6_hash_id # update existing IPv6 hash s32list = sai_thrift_s32_list_t( count=len(hash_fields_list), int32list=hash_fields_list) status = sai_thrift_set_hash_attribute( self.client, ipv6_hash_id, native_hash_field_list=s32list) self.assertEqual(status, SAI_STATUS_SUCCESS) # verify the native hash fields list self.assertEqual( True, self.verifyHashFieldsList( ipv6_hash_id, hash_fields_list)) # verify new hash create test_fields_list = [[SAI_NATIVE_HASH_FIELD_SRC_IP], [SAI_NATIVE_HASH_FIELD_DST_IP], [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP], [SAI_NATIVE_HASH_FIELD_IP_PROTOCOL], [SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_DST_IP, SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, SAI_NATIVE_HASH_FIELD_L4_DST_PORT, SAI_NATIVE_HASH_FIELD_L4_SRC_PORT]] for field_list in test_fields_list: s32list = sai_thrift_s32_list_t( count=len(field_list), int32list=field_list) new_ipv6_hash_id = sai_thrift_create_hash( self.client, native_hash_field_list=s32list) self.assertTrue( new_ipv6_hash_id != 0, "Failed to create IPv6 hash") self.assertEqual( True, self.verifyHashFieldsList( new_ipv6_hash_id, field_list)) status = sai_thrift_remove_hash(self.client, new_ipv6_hash_id) self.assertEqual(status, SAI_STATUS_SUCCESS) def ecmpIPv6vsIPv4HashTest(self): """ Verifies IPv4 hash does not impact IPv6 hashing """ test_header("ecmpIPv6vsIPv4HashTest") hash_dict_src = {'hash_src_ip': True} hash_dict = {'hash_dst_ip': True, 'hash_udp_dport': True, 'hash_udp_sport': True} self.setupECMPIPv6Hash([SAI_NATIVE_HASH_FIELD_SRC_IP]) # verify if IPv4 hash update overwrites IPv6 hash self.setupECMPIPv4Hash([SAI_NATIVE_HASH_FIELD_DST_IP]) print("Verify load balancing equaly for all next_hops when " "packet fields changes and do match hash fields.") # should ballance equally ecmp_count = self.l3IPv6EcmpPacketTest(hash_dict_src) print("ECMP count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertEqual(nbr_active_ports, 3) equaly_balanced = verify_equaly_balanced(ecmp_count) self.assertTrue(equaly_balanced, "Ecmp paths are not equally balanced") # should not ballance ecmp_count = self.l3IPv6EcmpPacketTest(hash_dict) print("ECMP count:", ecmp_count) nbr_active_ports = verify_lb_active_ports(ecmp_count) self.assertTrue(nbr_active_ports == 1, "LB not expected") @group("draft") class NonIPSrcMacHashTest(SAIHashTest): """ Verfies traffic distribution using src MAC selection for Non-IP Hash """ def runTest(self): test_header("NonIPSrcMacHashTest") self.nonIpHashTest(hash_src_mac=True) @group("draft") class NonIPDstMacHashTest(SAIHashTest): """ Verfies traffic distribution using dst MAC selection for Non-IP Hash """ def runTest(self): test_header("NonIPDstMacHashTest") self.nonIpHashTest(hash_dst_mac=True) @group("draft") class L2LagHashEtherTypeTest(SAIHashTest): """ Verfies traffic distribution using the Ether type selection for L2 Lag Hash """ def runTest(self): test_header("L2LagHashEtherTypeTest") self.nonIpHashTest(hash_ether_type=True) @group("draft") class L2LagHashSrcMACTest(SAIHashTest): ''' Verfies traffic distribution using the src MAC selection for L2 Lag Hash ''' def runTest(self): test_header("L2LagHashSrcMACTest") self.nonIpHashTest(hash_src_mac=True) @group("draft") class L2LagHashDstMACTest(SAIHashTest): ''' Verfies traffic distribution using the dst MAC selection for L2 Lag Hash ''' def runTest(self): test_header("L2LagHashDstMACTest") self.nonIpHashTest(hash_dst_mac=True) @group("draft") class L2LagHashTest(SAIHashTest): ''' Verfies traffic distribution using all fields selection for L2 Lag Hash ''' def runTest(self): test_header("L2LagHashTest") self.nonIpHashTest(hash_dst_mac=True, hash_src_mac=True, hash_ether_type=True) @group("draft") class NonIpHashTest(SAIHashTest): """ Verfies traffic distribution using all fields selection for Non-IP Hash """ def runTest(self): test_header("nonIpHashTest") self.nonIpHashTest(hash_dst_mac=True, hash_src_mac=True, hash_ether_type=True) @group("draft") class L2LagHashSeedTest(SAIHashTest): """ Verfies L2 Lag basic case with varing seed values """ def runTest(self): self.l2LagHashSeedTest() @group("draft") class EcmpIPv4SrcIPHashTest(SAIHashTest): """ Verfies traffic distribution using src IP selection for ECMP IPv4 Hash """ def runTest(self): test_header("EcmpIPv4SrcIPHashTest") self.ecmpIPv4HashTest(hash_src_ip=True) @group("draft") class FGEcmpIPv4SrcIPHashTest(SAIHashTest): """ Verfies traffic distribution using src IP selection for Fine-Grained ECMP IPv4 Hash """ def runTest(self): test_header("FGEcmpIPv4SrcIPHashTest") self.fgEcmpIPv4HashTest(hash_src_ip=True) @group("draft") class EcmpIPv4DstIPHashTest(SAIHashTest): """ Verfies traffic distribution using dst IP selection for ECMP IPv4 Hash """ def runTest(self): test_header("EcmpIPv4DstIPHashTest") self.ecmpIPv4HashTest(hash_dst_ip=True) @group("draft") class EcmpIPv4DstPortHashTest(SAIHashTest): """ Verfies L3 IPv4 traffic distribution using dst port selection for ECMP hash """ def runTest(self): test_header("EcmpIPv4DstPortHashTest") self.ecmpIPv4HashTest(hash_udp_dport=True) @group("draft") class EcmpIPv4SrcPortHashTest(SAIHashTest): """ Verfies L3 IPv4 traffic distribution using src port selection for ECMP Hash """ def runTest(self): test_header("EcmpIPv4SrcPortHashTest") self.ecmpIPv4HashTest(hash_udp_sport=True) @group("draft") class EcmpIPv4BasicHashNoLBTest(SAIHashTest): """ Verfies ECMP IPv4 hash defined for single not modified IPv4 hash field with traffic and no load balancing """ def runTest(self): self.ecmpIPv4BasicHashNoLBTest() @group("draft") class EcmpIPv4HashTest(SAIHashTest): """ Verfies traffic distribution using all the fields selected for ECMP IPv4 Hash """ def runTest(self): test_header("EcmpIPv4HashTest") self.ecmpIPv4HashTest( hash_src_ip=True, hash_dst_ip=True, hash_udp_sport=True, hash_udp_dport=True) @group("draft") class EcmpIPv4vsIPv6HashTest(SAIHashTest): """ Verifies if IPv6 hash does not impact IPv4 hashing """ def runTest(self): self.ecmpIPv4vsIPv6HashTest() @group("draft") class L3EcmpIPv4HashSeedTest(SAIHashTest): """ Verfies IPv4 ECMP seed case with varing values """ def runTest(self): self.l3EcmpIPv4HashSeedTest() @group("draft") class EcmpIPv4HashSaveRestoreTest(SAIHashTest): """ Verfies ECMP for IPv4 standard creates, modifies and removes ECMP hash fields """ def runTest(self): self.ecmpIPv4HashSaveRestoreTest() @group("draft") class EcmpHashAlgorithmTest(SAIHashTest): """ Verfies ECMP hash algorithm """ def runTest(self): self.ecmpHashAlgorithmTest() @group("draft") class L3LagIPv4HashTest(SAIHashTest): """ Verfies L3 IPv4 traffic distribution using all the fields selected for IPv4 LAG Hash """ def runTest(self): test_header("l3LagIPv4HashTest") self.l3LagIPv4HashTest( hash_src_ip=True, hash_dst_ip=True, hash_udp_sport=True, hash_udp_dport=True) @group("draft") class LagHashAlgorithmTest(SAIHashTest): """ Verfies lag hash algorithm """ def runTest(self): self.lagHashAlgorithmTest() @group("draft") class L3LagIPv4SrcIPHashTest(SAIHashTest): """ Verfies L3 IPv4 traffic distribution using src IP selection for IPv4 LAG Hash """ def runTest(self): test_header("L3LagIPv4SrcIPHashTest") self.l3LagIPv4HashTest(hash_src_ip=True) @group("draft") class L3LagIPv4DstIPHashTest(SAIHashTest): """ Verfies L3 IPv4 traffic distribution using dst IP selection for IPv4 LAG Hash """ def runTest(self): test_header("L3LagIPv4DstIPHashTest") self.l3LagIPv4HashTest(hash_dst_ip=True) @group("draft") class L3LagIPv4SrcPortHashTest(SAIHashTest): """ Verfies L3 IPv4 traffic distribution using src port selection for LAG Hash """ def runTest(self): test_header("L3LagIPv4SrcPortHashTest") self.l3LagIPv4HashTest(hash_udp_sport=True) @group("draft") class L3LagIPv4DstPortHashTest(SAIHashTest): """ Verifies L3 IPv4 traffic distribution using dst port selection for IPv4 LAG Hash """ def runTest(self): test_header("L3LagIPv4DstPortHashTest") self.l3LagIPv4HashTest(hash_udp_dport=True) @group("draft") class L3LagIPv4HashSeedTest(SAIHashTest): """ Verfies L3 Lag basic case with varing seed values """ def runTest(self): test_header("l3LagIPv4HashSeedTest") self.l3LagIPv4HashSeedTest() @group("draft") class LagHashSaveRestoreTest(SAIHashTest): """ Verfies modification of the switch lag hash fields """ def runTest(self): self.lagHashSaveRestoreTest() @group("draft") class LagIPv4HashSaveRestoreTest(SAIHashTest): """ Verfies modification of the switch lag IPv4 hash fields """ def runTest(self): self.lagIPv4HashSaveRestoreTest() @group("draft") class LagIPv6HashSaveRestoreTest(SAIHashTest): """ Varifies modification of the switch lag IPv6 hash fields """ def runTest(self): self.lagIPv6HashSaveRestoreTest() @group("draft") class L3LagIPv6HashSeedTest(SAIIPv6HashTest): """ Verfies L3 IPv6 Lag basic case with varing seed values """ def runTest(self): test_header("L3LagIPv6HashSeedTest") self.lagIPv6HashSeedTest() @group("draft") class L3LagIPv6HashTest(SAIIPv6HashTest): """ Verfies L3 IPv6 traffic distribution using all the fields selected for LAG Hash """ def runTest(self): hash_dict = {'hash_src_ip': True, 'hash_dst_ip': True, 'hash_src_mac': True, 'hash_udp_dport': True, 'hash_udp_sport': True} test_header("L3LagIPv6HashTest") self.lagIPv6HashTest(hash_dict) @group("draft") class L3LagIPv6FlowLabelHashTest(SAIIPv6HashTest): """ Verfies L3 IPv6 traffic distribution using all ipv6 flow label fields selected for LAG Hash """ def runTest(self): hash_dict = {'hash_flow_label': True} test_header("L3LagIPv6FlowLabelHashTest") self.lagIPv6FlowLabelHashTest(hash_dict) @group("draft") class L3LagIPv6SrcIPHashTest(SAIIPv6HashTest): """ Verfies L3 IPv6 traffic distribution using src IP selection for LAG Hash """ def runTest(self): hash_dict = {'hash_src_ip': True} test_header("L3LagIPv6SrcIPHashTest") self.lagIPv6HashTest(hash_dict) @group("draft") class L3LagIPv6DstIPHashTest(SAIIPv6HashTest): """ Verfies L3 IPv6 traffic distribution using dst IP selection for LAG Hash """ def runTest(self): hash_dict = {'hash_dst_ip': True} test_header("L3LagIPv6DstIPHashTest") self.lagIPv6HashTest(hash_dict) @group("draft") class L3LagIPv6SrcPortHashTest(SAIIPv6HashTest): """ Verfies L3 IPv6 traffic distribution using src port selection for LAG Hash """ def runTest(self): hash_dict = {'hash_udp_sport': True} test_header("L3LagIPv6SrcPortHashTest") self.lagIPv6HashTest(hash_dict) @group("draft") class L3LagIPv6DstPortHashTest(SAIIPv6HashTest): """ Verfies L3 IPv6 traffic distribution using dst port selection for LAG Hash """ def runTest(self): hash_dict = {'hash_udp_dport': True} test_header("L3LagIPv6DstPortHashTest") self.lagIPv6HashTest(hash_dict) @group("draft") class EcmpIPv6HashSaveRestoreTest(SAIIPv6HashTest): """ Verfies ECMP for IPv6 standard creates, modifies and removes ECMP hash fields """ def runTest(self): self.ecmpIPv6HashSaveRestoreTest() @group("draft") class L3EcmpIPv6HashSeedTest(SAIIPv6HashTest): """ Verfies IPv6 ECMP seed case with varing values """ def runTest(self): self.l3EcmpIPv6HashSeedTest() @group("draft") class EcmpIPv6HashTest(SAIIPv6HashTest): """ Verfies traffic distribution using all the field selected for ECMP IPv6 Hash """ def runTest(self): test_header("EcmpIPv6HashTest") self.ecmpIPv6HashTest( hash_src_ip=True, hash_dst_ip=True, hash_udp_sport=True, hash_udp_dport=True) @group("draft") class EcmpIPv6DstIPHashTest(SAIIPv6HashTest): """ Verfies traffic distribution using dst IP selection for ECMP IPv6 Hash """ def runTest(self): test_header("EcmpIPv6DstIPHashTest") self.ecmpIPv6HashTest(hash_dst_ip=True) @group("draft") class EcmpIPv6SrcIPHashTest(SAIIPv6HashTest): """ Verfies traffic distribution using src IP selection for ECMP IPv6 Hash """ def runTest(self): test_header("EcmpIPv6SrcIPHashTest") self.ecmpIPv6HashTest(hash_src_ip=True) @group("draft") class EcmpIPv6SrcPortHashTest(SAIIPv6HashTest): """ Verfies L3 IPv6 traffic distribution using src port selection for ECMP Hash """ def runTest(self): test_header("EcmpIPv6SrcPortHashTest") self.ecmpIPv6HashTest(hash_udp_sport=True) @group("draft") class EcmpIPv6DstPortHashTest(SAIIPv6HashTest): """ Verfies L3 IPv6 traffic distribution using dst port selection for ECMP Hash """ def runTest(self): test_header("EcmpIPv6DstPortHashTest") self.ecmpIPv6HashTest(hash_udp_dport=True) @group("draft") class EcmpIPv6vsIPv4HashTest(SAIIPv6HashTest): """ Verifies if IPv4 hash does not impact IPv6 hashing """ def runTest(self): self.ecmpIPv6vsIPv4HashTest()