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
Exemple #2
0
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)
Exemple #3
0
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)
Exemple #4
0
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