def storm_setup(self, init=False): """ Prepare fanout for the storm generation Args: init(bool): if the storm class needs to be initialized or not """ # new peer device if not self.peer_dev_list or self.peer_device not in self.peer_dev_list: peer_info = {'peerdevice': self.peer_device, 'hwsku': self.fanout_info[self.peer_device]['device_info']['HwSku'], 'pfc_fanout_interface': self.neighbors[self.pfc_wd['test_port']]['peerport'] } self.peer_dev_list[self.peer_device] = peer_info['hwsku'] # get pfc storm handle if init: self.storm_hndle = PFCStorm(self.dut, self.fanout_info, self.fanout, pfc_queue_idx=self.pfc_wd['queue_index'], pfc_frames_number=self.pfc_wd['frames_number'], peer_info=peer_info) self.storm_hndle.update_peer_info(peer_info) self.storm_hndle.deploy_pfc_gen() # peer device already exists. only interface changes else: peer_info = {'peerdevice': self.peer_device, 'hwsku': self.peer_dev_list[self.peer_device], 'pfc_fanout_interface': self.neighbors[self.pfc_wd['test_port']]['peerport'] } self.storm_hndle.update_peer_info(peer_info)
def storm_setup(self, port, queue, storm_defer=False): """ Prepare fanout for the storm generation Args: port(string) : DUT port queue(int): The queue on the DUT port which will get stormed storm_defer(bool): if the storm needs to be deferred, default: False """ peer_info = {'peerdevice': self.peer_device, 'hwsku': self.fanout_info[self.peer_device]['device_info']['HwSku'], 'pfc_fanout_interface': self.neighbors[port]['peerport'] } if storm_defer: self.storm_handle[port][queue] = PFCStorm(self.dut, self.fanout_info, self.fanout, pfc_queue_idx=queue, pfc_frames_number=self.pfc_wd['frames_number'], peer_info=peer_info, pfc_storm_defer_time=self.pfc_wd['storm_start_defer'], pfc_storm_stop_defer_time=self.pfc_wd['storm_stop_defer']) else: self.storm_handle[port][queue] = PFCStorm(self.dut, self.fanout_info, self.fanout, pfc_queue_idx=queue, pfc_frames_number=self.pfc_wd['frames_number'], peer_info=peer_info) # new peer device if not self.peer_dev_list or self.peer_device not in self.peer_dev_list: self.peer_dev_list[self.peer_device] = peer_info['hwsku'] self.storm_handle[port][queue].deploy_pfc_gen()
def set_storm_params(dut, fanout_info, fanout, peer_params): """ Setup storm parameters Args: dut (AnsibleHost): DUT instance fanout_info (fixture): fanout graph info fanout (AnsibleHost): fanout instance peer_params (dict): all PFC params needed for fanout for storm generation Returns: storm_handle (PFCStorm): class PFCStorm intance """ logger.info("Setting up storm params") pfc_queue_index = 4 pfc_frames_count = 300000 storm_handle = PFCStorm(dut, fanout_info, fanout, pfc_queue_idx=pfc_queue_index, pfc_frames_number=pfc_frames_count, peer_info=peer_params) storm_handle.deploy_pfc_gen() return storm_handle
class SetupPfcwdFunc(object): """ Test setup per port """ def setup_test_params(self, port, vlan, init=False): """ Sets up test parameters associated with a DUT port Args: port(string) : DUT port vlan(dict) : DUT vlan info init(bool) : If the fanout needs to be initialized or not """ logger.info("--- Setting up test params for port {} ---".format(port)) self.setup_port_params(port, init=init) self.resolve_arp(vlan) if not self.pfc_wd['fake_storm']: self.storm_setup(init=init) def setup_port_params(self, port, init=False): """ Gather all the parameters needed for storm generation and ptf test based off the DUT port Args: port(string) : DUT port """ self.pfc_wd = dict() self.pfc_wd['fake_storm'] = False if init else self.fake_storm self.pfc_wd['test_pkt_count'] = 100 self.pfc_wd['queue_index'] = 4 self.pfc_wd['frames_number'] = 100000000 self.pfc_wd['test_port_ids'] = list() self.peer_device = self.ports[port]['peer_device'] self.pfc_wd['test_port'] = port self.pfc_wd['rx_port'] = self.ports[port]['rx_port'] self.pfc_wd['test_neighbor_addr'] = self.ports[port]['test_neighbor_addr'] self.pfc_wd['rx_neighbor_addr'] = self.ports[port]['rx_neighbor_addr'] self.pfc_wd['test_port_id'] = self.ports[port]['test_port_id'] self.pfc_wd['rx_port_id'] = self.ports[port]['rx_port_id'] self.pfc_wd['port_type'] = self.ports[port]['test_port_type'] if self.pfc_wd['port_type'] == "portchannel": self.pfc_wd['test_port_ids'] = self.ports[port]['test_portchannel_members'] elif self.pfc_wd['port_type'] in ["vlan", "interface"]: self.pfc_wd['test_port_ids'] = self.pfc_wd['test_port_id'] self.queue_oid = PfcCmd.get_queue_oid(self.dut, port, self.pfc_wd['queue_index']) def resolve_arp(self, vlan): """ Populate ARP info for the DUT vlan port Args: vlan(dict) : DUT vlan info """ if self.pfc_wd['port_type'] == "vlan": self.ptf.script("./scripts/remove_ip.sh") self.ptf.command("ifconfig eth{} {}".format(self.pfc_wd['test_port_id'], self.pfc_wd['test_neighbor_addr'])) self.ptf.command("ping {} -c 10".format(vlan['addr'])) self.dut.command("docker exec -i swss arping {} -c 5".format(self.pfc_wd['test_neighbor_addr'])) def storm_setup(self, init=False): """ Prepare fanout for the storm generation Args: init(bool): if the storm class needs to be initialized or not """ # new peer device if not self.peer_dev_list or self.peer_device not in self.peer_dev_list: peer_info = {'peerdevice': self.peer_device, 'hwsku': self.fanout_info[self.peer_device]['device_info']['HwSku'], 'pfc_fanout_interface': self.neighbors[self.pfc_wd['test_port']]['peerport'] } self.peer_dev_list[self.peer_device] = peer_info['hwsku'] # get pfc storm handle if init: self.storm_hndle = PFCStorm(self.dut, self.fanout_info, self.fanout, pfc_queue_idx=self.pfc_wd['queue_index'], pfc_frames_number=self.pfc_wd['frames_number'], peer_info=peer_info) self.storm_hndle.update_peer_info(peer_info) self.storm_hndle.deploy_pfc_gen() # peer device already exists. only interface changes else: peer_info = {'peerdevice': self.peer_device, 'hwsku': self.peer_dev_list[self.peer_device], 'pfc_fanout_interface': self.neighbors[self.pfc_wd['test_port']]['peerport'] } self.storm_hndle.update_peer_info(peer_info)
class SetupPfcwdFunc(object): """ Test setup per port """ def setup_test_params(self, port, vlan, init=False, mmu_params=False): """ Sets up test parameters associated with a DUT port Args: port(string) : DUT port vlan(dict) : DUT vlan info init(bool) : If the fanout needs to be initialized or not """ logger.info("--- Setting up test params for port {} ---".format(port)) self.setup_port_params(port, init=init) if mmu_params: self.setup_mmu_params(port) self.resolve_arp(vlan) if not self.pfc_wd['fake_storm']: self.storm_setup(init=init) def setup_port_params(self, port, init=False): """ Gather all the parameters needed for storm generation and ptf test based off the DUT port Args: port(string) : DUT port """ self.pfc_wd = dict() self.pfc_wd['fake_storm'] = False if init else self.fake_storm self.pfc_wd['test_pkt_count'] = 100 self.pfc_wd['queue_index'] = 4 self.pfc_wd['frames_number'] = 100000000 self.pfc_wd['test_port_ids'] = list() self.peer_device = self.ports[port]['peer_device'] self.pfc_wd['test_port'] = port self.pfc_wd['rx_port'] = self.ports[port]['rx_port'] self.pfc_wd['test_neighbor_addr'] = self.ports[port]['test_neighbor_addr'] self.pfc_wd['rx_neighbor_addr'] = self.ports[port]['rx_neighbor_addr'] self.pfc_wd['test_port_id'] = self.ports[port]['test_port_id'] self.pfc_wd['rx_port_id'] = self.ports[port]['rx_port_id'] self.pfc_wd['port_type'] = self.ports[port]['test_port_type'] if self.pfc_wd['port_type'] == "portchannel": self.pfc_wd['test_port_ids'] = self.ports[port]['test_portchannel_members'] elif self.pfc_wd['port_type'] in ["vlan", "interface"]: self.pfc_wd['test_port_ids'] = self.pfc_wd['test_port_id'] self.queue_oid = self.dut.get_queue_oid(port, self.pfc_wd['queue_index']) def update_queue(self, port): """ Switch between queue 3 and 4 during the test Args: port(string) : DUT port """ if self.pfc_wd['queue_index'] == 4: self.pfc_wd['queue_index'] = self.pfc_wd['queue_index'] - 1 else: self.pfc_wd['queue_index'] = self.pfc_wd['queue_index'] + 1 logger.info("Current queue: {}".format(self.pfc_wd['queue_index'])) self.queue_oid = self.dut.get_queue_oid(port, self.pfc_wd['queue_index']) def setup_mmu_params(self, port): """ Retrieve the pg profile and alpha values of the port under test Args: port(string) : DUT port """ self.pg_profile, self.alpha = PfcCmd.get_mmu_params(self.dut, port) def update_mmu_params(self, mmu_action, port): """ Update dynamic threshold value Args: mmu_action(string): for value "change", update within -6 and 3 for value "restore", set back to original threshold port(string) : port name """ if int(self.alpha) <= -6: new_alpha = -5 elif int(self.alpha) >= 3: new_alpha = 2 else: new_alpha = int(self.alpha) + 1 if mmu_action == "change": PfcCmd.update_alpha(self.dut, port, self.pg_profile, new_alpha) elif mmu_action == "restore": PfcCmd.update_alpha(self.dut, port, self.pg_profile, self.alpha) time.sleep(2) def resolve_arp(self, vlan): """ Populate ARP info for the DUT vlan port Args: vlan(dict) : DUT vlan info """ if self.pfc_wd['port_type'] == "vlan": self.ptf.script("./scripts/remove_ip.sh") self.ptf.command("ifconfig eth{} {}".format(self.pfc_wd['test_port_id'], self.pfc_wd['test_neighbor_addr'])) self.ptf.command("ping {} -c 10".format(vlan['addr'])) self.dut.command("docker exec -i swss arping {} -c 5".format(self.pfc_wd['test_neighbor_addr'])) def storm_setup(self, init=False): """ Prepare fanout for the storm generation Args: init(bool): if the storm class needs to be initialized or not """ # new peer device if not self.peer_dev_list or self.peer_device not in self.peer_dev_list: peer_info = {'peerdevice': self.peer_device, 'hwsku': self.fanout_info[self.peer_device]['device_info']['HwSku'], 'pfc_fanout_interface': self.neighbors[self.pfc_wd['test_port']]['peerport'] } self.peer_dev_list[self.peer_device] = peer_info['hwsku'] # get pfc storm handle if init: self.storm_hndle = PFCStorm(self.dut, self.fanout_info, self.fanout, pfc_queue_idx=self.pfc_wd['queue_index'], pfc_frames_number=self.pfc_wd['frames_number'], peer_info=peer_info) self.storm_hndle.update_queue_index(self.pfc_wd['queue_index']) self.storm_hndle.update_peer_info(peer_info) self.storm_hndle.deploy_pfc_gen() # peer device already exists. only interface changes else: peer_info = {'peerdevice': self.peer_device, 'hwsku': self.peer_dev_list[self.peer_device], 'pfc_fanout_interface': self.neighbors[self.pfc_wd['test_port']]['peerport'] } self.storm_hndle.update_queue_index(self.pfc_wd['queue_index']) self.storm_hndle.update_peer_info(peer_info)
def run_test(pfc_test_setup, fanouthosts, duthost, ptfhost, conn_graph_facts, fanout_info, traffic_params, pause_prio=None, queue_paused=True, send_pause=True, pfc_pause=True, max_test_intfs_count=128): """ Run the test Args: pfc_test_setup(fixture) : setup fixture fanouthosts(AnsibleHost) : fanout instance duthost(AnsibleHost) : dut instance ptfhost(AnsibleHost) : ptf instance conn_graph_facts(fixture) : Testbed topology fanout_info(fixture) : fanout graph info traffic_params(dict) : dict containing the dscp of test dscp and background dscp pause_prio(string) : priority of PFC franme queue_paused(bool) : if the queue is expected to be paused send_pause(bool) : send pause frames or not pfc_pause(bool) : send PFC pause frames or not max_test_intfs_count(int) : maximum count of interfaces to test. By default, it is a very large value to cover all the interfaces Return: Number of iterations and number of passed iterations for each tested interface. """ setup = pfc_test_setup dut_intfs = setup['vlan_members'] ptf_intfs = setup['ptf_intfs'] ptf_ip_addrs = setup['vlan_ip_addrs'] ptf_mac_addrs = setup['vlan_mac_addrs'] """ Clear DUT's PFC counters """ duthost.sonic_pfc_counters(method="clear") results = dict() all_peer_dev = set() storm_handle = None for i in range(min(max_test_intfs_count, len(ptf_intfs))): src_index = i dst_index = (i + 1) % len(ptf_intfs) src_intf = ptf_intfs[src_index] dst_intf = ptf_intfs[dst_index] src_ip = ptf_ip_addrs[src_index] dst_ip = ptf_ip_addrs[dst_index] src_mac = ptf_mac_addrs[src_index] dst_mac = ptf_mac_addrs[dst_index] """ DUT interface to pause """ dut_intf_paused = dut_intfs[dst_index] """ Clear MAC table in DUT """ duthost.shell('sonic-clear fdb all') time.sleep(2) if send_pause: peer_device = conn_graph_facts['device_conn'][ duthost.hostname][dut_intf_paused]['peerdevice'] peer_port = conn_graph_facts['device_conn'][ duthost.hostname][dut_intf_paused]['peerport'] peer_info = { 'peerdevice': peer_device, 'pfc_fanout_interface': peer_port } if not pfc_pause: pause_prio = None if not storm_handle: storm_handle = PFCStorm(duthost, fanout_info, fanouthosts, pfc_queue_idx=pause_prio, pfc_frames_number=PFC_PKT_COUNT, peer_info=peer_info) storm_handle.update_peer_info(peer_info) if not all_peer_dev or peer_device not in all_peer_dev: storm_handle.deploy_pfc_gen() all_peer_dev.add(peer_device) storm_handle.start_storm() """ Wait for PFC pause frame generation """ time.sleep(1) """ Run PTF test """ logger.info("Running test: src intf: {} dest intf: {}".format( dut_intfs[src_index], dut_intfs[dst_index])) intf_info = '--interface %d@%s --interface %d@%s' % ( src_index, src_intf, dst_index, dst_intf) test_params = ("mac_src=\'%s\';" % src_mac + "mac_dst=\'%s\';" % dst_mac + "ip_src=\'%s\';" % src_ip + "ip_dst=\'%s\';" % dst_ip + "dscp=%d;" % traffic_params['dscp'] + "dscp_bg=%d;" % traffic_params['dscp_bg'] + "pkt_count=%d;" % PTF_PKT_COUNT + "pkt_intvl=%f;" % PTF_PKT_INTVL_SEC + "port_src=%d;" % src_index + "port_dst=%d;" % dst_index + "queue_paused=%s;" % queue_paused + "dut_has_mac=False") cmd = 'ptf --test-dir %s pfc_pause_test %s --test-params="%s"' % ( os.path.dirname(PTF_FILE_REMOTE_PATH), intf_info, test_params) print cmd stdout = ansible_stdout_to_str(ptfhost.shell(cmd)['stdout']) words = stdout.split() """ Expected format: "Passes: a / b" where a is # of passed iterations and b is total # of iterations """ if len(words) != 4: print 'Unknown PTF test result format' results[dut_intf_paused] = [0, 0] else: results[dut_intf_paused] = [int(words[1]), int(words[3])] time.sleep(1) if send_pause: """ Stop PFC / FC storm """ storm_handle.stop_storm() time.sleep(1) return results