ptf/saisanity.py (246 lines of code) (raw):

# Copyright (c) 2021 Microsoft Open Technologies, Inc. # # 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 # # THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR # CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT # LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS # FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. # # See the Apache Version 2.0 License for specific language governing # permissions and limitations under the License. # # Microsoft would like to thank the following companies for their review and # assistance with these files: Intel Corporation, Mellanox Technologies Ltd, # Dell Products, L.P., Facebook, Inc., Marvell International Ltd. """ This file contains some Test classes which are used to the basic functionality of the switch. """ from sai_thrift.sai_headers import * from sai_base_test import * mac1 = '00:11:11:11:11:11' mac2 = '00:22:22:22:22:22' mac3 = '00:33:33:33:33:33' mac4 = '00:12:12:12:12:13' class L2TrunkToTrunkVlanTest(PlatformSaiHelper): """ Test for L2 Vlan Trunk to Trunk transport. """ def setUp(self): #this process contains the switch_init process SaiHelperBase.setUp(self) self.create_bridge_ports() print("Sending L2 packet port 1 -> port 2 [access vlan=10])") self.vlan_id = 10 mac_action = SAI_PACKET_ACTION_FORWARD self.vlan_oid = sai_thrift_create_vlan(self.client, vlan_id=self.vlan_id) self.assertNotEqual(self.vlan_oid, 0) self.vlan_member1 = sai_thrift_create_vlan_member( self.client, vlan_id=self.vlan_oid, bridge_port_id=self.port0_bp, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) self.vlan_member2 = sai_thrift_create_vlan_member( self.client, vlan_id=self.vlan_oid, bridge_port_id=self.port1_bp, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) sai_thrift_set_port_attribute(self.client, port_oid=self.port0, port_vlan_id=self.vlan_id) sai_thrift_set_port_attribute(self.client, port_oid=self.port1, port_vlan_id=self.vlan_id) self.fdb_entry1 = sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1, bv_id=self.vlan_oid) self.fdb_entry2 = sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac2, bv_id=self.vlan_oid) #need the bridge port inactually sai_thrift_create_fdb_entry(self.client, fdb_entry=self.fdb_entry1, bridge_port_id=self.port0_bp, packet_action=mac_action) sai_thrift_create_fdb_entry(self.client, fdb_entry=self.fdb_entry2, bridge_port_id=self.port1_bp, packet_action=mac_action) def runTest(self): pkt = simple_tcp_packet(eth_dst='00:22:22:22:22:22', eth_src=mac4, ip_dst='10.0.0.1', ip_id=101, ip_ttl=64) try: time.sleep(5) send_packet(self, self.dev_port0, pkt) verify_packet(self, pkt, self.dev_port1) finally: pass def tearDown(self): sai_thrift_remove_fdb_entry(self.client, self.fdb_entry1) sai_thrift_remove_fdb_entry(self.client, self.fdb_entry2) sai_thrift_set_port_attribute(self.client, port_oid=self.port0, port_vlan_id=1) sai_thrift_set_port_attribute(self.client, port_oid=self.port1, port_vlan_id=1) sai_thrift_remove_vlan_member(self.client,self.vlan_member1) sai_thrift_remove_vlan_member(self.client,self.vlan_member2) sai_thrift_remove_vlan(self.client, self.vlan_oid) self.remove_bridge_port() #TODO resove the error for fdb entry not equals to init one SaiHelperBase.tearDown(self) class L2TrunkToAccessVlanTest(PlatformSaiHelper): """ Test for L2 Vlan Trunk to Access transport. """ def setUp(self): #this process contains the switch_init process SaiHelperBase.setUp(self) self.create_bridge_ports() print("Sending L2 packet port 1 -> port 2 [trunk vlan=10])") self.vlan_id = 10 mac_action = SAI_PACKET_ACTION_FORWARD self.vlan_oid = sai_thrift_create_vlan(self.client, vlan_id=self.vlan_id) self.assertNotEqual(self.vlan_oid, 0) self.vlan_member1 = sai_thrift_create_vlan_member( self.client, vlan_id=self.vlan_oid, bridge_port_id=self.port0_bp, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_TAGGED) self.vlan_member2 = sai_thrift_create_vlan_member( self.client, vlan_id=self.vlan_oid, bridge_port_id=self.port1_bp, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) sai_thrift_set_port_attribute(self.client, port_oid=self.port0, port_vlan_id=self.vlan_id) sai_thrift_set_port_attribute(self.client, port_oid=self.port1, port_vlan_id=self.vlan_id) self.fdb_entry1 = sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1, bv_id=self.vlan_oid) self.fdb_entry2 = sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac2, bv_id=self.vlan_oid) #need the bridge port inactually sai_thrift_create_fdb_entry(self.client, fdb_entry=self.fdb_entry1, bridge_port_id=self.port0_bp, packet_action=mac_action) sai_thrift_create_fdb_entry(self.client, fdb_entry=self.fdb_entry2, bridge_port_id=self.port1_bp, packet_action=mac_action) def runTest(self): pkt = simple_udp_packet(eth_dst=mac2, eth_src=mac4, dl_vlan_enable=True, vlan_vid=10, ip_dst='172.16.0.1', ip_id=102, ip_ttl=64) exp_pkt = simple_udp_packet(eth_dst=mac2, eth_src=mac4, ip_dst='172.16.0.1', ip_id=102, ip_ttl=64, pktlen=96) try: time.sleep(5) send_packet(self, self.dev_port0, pkt) verify_packet(self, exp_pkt, self.dev_port1) finally: pass def tearDown(self): sai_thrift_remove_fdb_entry(self.client, self.fdb_entry1) sai_thrift_remove_fdb_entry(self.client, self.fdb_entry2) sai_thrift_set_port_attribute(self.client, port_oid=self.port0, port_vlan_id=1) sai_thrift_set_port_attribute(self.client, port_oid=self.port1, port_vlan_id=1) sai_thrift_remove_vlan_member(self.client,self.vlan_member1) sai_thrift_remove_vlan_member(self.client,self.vlan_member2) sai_thrift_remove_vlan(self.client, self.vlan_oid) self.remove_bridge_port() #TODO resove the error for fdb entry not equals to init one SaiHelperBase.tearDown(self) class L2SanityTest(PlatformSaiHelper): """ Test for L2 trunk and access port access, all ports scanning. """ def gen_mac(self): #Gets self.portX objects for all active ports for index in range(0, len(self.port_list)): mac = "00" if index < 9 : section = ":" + "0" + str(index+1) else: section= ":" + str(index+1) mac += (section*5) setattr(self, 'mac%s' % index, mac) def create_vlan_ports(self, vlanid, vlan_oid): for index in range(0, len(self.port_list)): port_bp = getattr(self, 'port%s_bp' % index) if index%2 == 0: vlan_member = sai_thrift_create_vlan_member( self.client, vlan_id=self.vlan_oid, bridge_port_id=port_bp, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) else: vlan_member = sai_thrift_create_vlan_member( self.client, vlan_id=self.vlan_oid, bridge_port_id=port_bp, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_TAGGED) setattr(self, 'vlan%s_member%s' % (vlanid, index), vlan_member) def set_port_vlan(self, vlan_id): for index in range(0, len(self.port_list)): port_id=getattr(self, 'port%s' % index) sai_thrift_set_port_attribute(self.client, port_id, port_vlan_id=vlan_id) def create_port_fdb(self, vlan_id, vlan_oid, mac_action): for index in range(0, len(self.port_list)): mac=getattr(self, 'mac%s' % index) port_bp = getattr(self, 'port%s_bp' % index) fdb_entry = sai_thrift_fdb_entry_t( switch_id=self.switch_id, mac_address=mac, bv_id=vlan_oid) sai_thrift_create_fdb_entry( self.client, fdb_entry, type=SAI_FDB_ENTRY_TYPE_STATIC, bridge_port_id=port_bp, packet_action=mac_action) setattr(self, 'fdb_entry%s' % index, fdb_entry) def create_pkt(self, vlan_id): for index in range(0, len(self.port_list)): target_mac = getattr(self, 'mac%s' % index) if index%2 == 0: pkt = simple_tcp_packet(eth_src=self.src_mac, eth_dst=target_mac, ip_dst='172.16.0.1', ip_id=101, ip_ttl=64) else: pkt = simple_tcp_packet(eth_dst=target_mac, eth_src=self.src_mac, dl_vlan_enable=True, vlan_vid=vlan_id, ip_dst='172.16.0.1', ip_id=102, ip_ttl=64) setattr(self, 'pkt%s' % index, pkt) def create_exp_pkt(self, vlan_id): for index in range(0, len(self.port_list)): target_mac = getattr(self, 'mac%s' % index) if index%2 == 0: exp_pkt = getattr(self, 'pkt%s' % index) else: exp_pkt = simple_tcp_packet(eth_dst=target_mac, eth_src=self.src_mac, ip_dst='172.16.0.1', ip_id=102, dl_vlan_enable=True, vlan_vid=vlan_id, ip_ttl=64) setattr(self, 'exp_pkt%s' % index, exp_pkt) def setUp(self): #Init switch SaiHelperBase.setUp(self) mac4= '00:55:55:55:55:55' self.vlan_id = 10 self.gen_mac() self.src_mac=mac4 mac_action = SAI_PACKET_ACTION_FORWARD self.src_port = self.port0 self.dst_port = self.port1 self.create_bridge_ports() # create vlan 10 with ports self.vlan_oid = sai_thrift_create_vlan(self.client, vlan_id=self.vlan_id) self.assertNotEqual(self.vlan_oid, 0) self.create_vlan_ports(self.vlan_id, self.vlan_oid) #set port vlan attribute self.set_port_vlan(self.vlan_id) #set fdb self.create_port_fdb(self.vlan_id, self.vlan_oid, mac_action) #create send pkt and rcv pkt self.create_pkt(self.vlan_id) self.create_exp_pkt(self.vlan_id) def runTest(self): self.test_flooding_to_ports() # A protential bug here # Although the port is up, cannot use it immediately. time.sleep(5) self.test_forwad_to_each_port() def test_forwad_to_each_port(self): try: for index in range(2, len(self.port_list), 2): self.dataplane.flush() print("Check port{} forwarding...".format(index)) # example for debug with pdb and open a sai shell # import pdb # pdb.set_trace() # note, this method to open the shell # is not support on diff platform, diff asic # in some cases, the shell might need to be # opened from cmd line. # Then, just set the break point by pdb.set_trace() # and open shell in CLI, then start debugging with sai shell. # self.shell() target_pkt = getattr(self, 'pkt%s' % index) exp_pkt = getattr(self, 'exp_pkt%s' % index) send_packet(self, self.dev_port0, target_pkt) verify_packet(self, exp_pkt, index) #verify_packet_any_port(self, exp_pkt, range(1,len(self.port_list))) finally: pass def test_flooding_to_ports(self): """ Test fdb forwarding """ unknown_mac1 = "00:01:01:99:99:99" unknown_mac2 = "00:01:02:99:99:99" pkt = simple_udp_packet(eth_dst=unknown_mac1, eth_src=unknown_mac2, ip_id=101, ip_ttl=64) try: # Unknown mac, flooding to all the other ports. print("Sanity test, check all the ports be flooded.") self.dataplane.flush() send_packet( self, 1, pkt) received_index = verify_each_packet_on_multiple_port_lists( self, [pkt], [range(2, len(self.port_list))]) finally: pass def tearDown(self): #reset port vlan id #?reset to 0 or 1? self.reset_port_vlan(1) #remove fdb self.remove_fdb() #remove vlan member self.remove_vlan_member(self.vlan_id) #remove bridge port self.remove_bridge_port() sai_thrift_remove_vlan(self.client, self.vlan_oid) SaiHelperBase.tearDown(self) def reset_port_vlan(self, reset_vlan_id): for index in range(0, len(self.port_list)): port_id=getattr(self, 'port%s' % index) sai_thrift_set_port_attribute(self.client, port_id, port_vlan_id=reset_vlan_id) def remove_fdb(self): for index in range(0, len(self.port_list)): fdb_entry=getattr(self, 'fdb_entry%s' % index) sai_thrift_remove_fdb_entry(self.client, fdb_entry) def remove_vlan_member(self, vlan_id): for index in range(0, len(self.port_list)): vlan_member=getattr(self, 'vlan%s_member%s' % (vlan_id, index)) sai_thrift_remove_vlan_member(self.client, vlan_member) def set_vlan_data(vlan_id=0, ports=None, untagged=None, large_port=0): """ Creates dictionary with vlan data Args: vlan_id (int): VLAN ID number ports (list): ports numbers untagged (list): list of untagged ports large_port (int): the largest port in vlan Return: dictionary: vlan_data_dict """ vlan_data_dict = { "vlan_id": vlan_id, "ports": ports, "untagged": untagged, "large_port": large_port } return vlan_data_dict