Ejemplo n.º 1
0
    def __init__(self, crb, serializer, name, alt_session=True, dut_id=0):
        self.dut_id = dut_id
        self.crb = crb
        self.read_cache = False
        self.skip_setup = False
        self.serializer = serializer
        self.ports_info = None
        self.sessions = []
        self.stage = 'pre-init'
        self.name = name

        self.logger = getLogger(name)
        self.session = SSHConnection(self.get_ip_address(), name,
                                     self.get_username(),
                                     self.get_password(), dut_id)
        self.session.init_log(self.logger)
        if alt_session:
            self.alt_session = SSHConnection(
                self.get_ip_address(),
                name + '_alt',
                self.get_username(),
                self.get_password(),
                dut_id)
            self.alt_session.init_log(self.logger)
        else:
            self.alt_session = None
Ejemplo n.º 2
0
 def init_host_session(self):
     if self.host_init_flag:
         pass
     else:
         self.host_session = SSHConnection(self.get_ip_address(),
                                           self.NAME + '_host',
                                           self.get_password())
         self.host_session.init_log(self.logger)
         self.host_init_flag = True
Ejemplo n.º 3
0
 def create_session(self, name=""):
     """
     Create new session for addtional useage. This session will not enable log.
     """
     logger = getLogger(name)
     session = SSHConnection(self.get_ip_address(), name,
                             self.get_username(), self.get_password())
     session.init_log(logger)
     self.sessions.append(session)
     return session
Ejemplo n.º 4
0
def main(argv):
  # Parse the username, hostname, and keyfile from the command line arguments
  username, hostname = argv[1].split('@')
  keyfile = argv[2]

  # Construct an SSH connection
  ssh = SSHConnection(hostname, username, keyfile)
  ssh.connect()

  # Run an interactive prompt, until the user enters an empty line or closes the input stream
  print colors.red(ssh.read())
  while True:
    try:
      command_to_run = raw_input('> ')
    except EOFError:
      command_to_run = ''

    if command_to_run.strip() == '':
      break
    ssh.send(command_to_run + '\n')
    print colors.red(ssh.read())

  # Cleanly close the SSH connection
  exit_status = ssh.disconnect()
  return exit_status
Ejemplo n.º 5
0
 def init_host_session(self, vm_name):
     """
     Create session for each VM, session will be handled by VM instance
     """
     self.host_session = SSHConnection(self.get_ip_address(),
                                       vm_name + '_host',
                                       self.get_username(),
                                       self.get_password())
     self.host_session.init_log(self.logger)
     self.logger.info("[%s] create new session for VM" %
                      (threading.current_thread().name))
Ejemplo n.º 6
0
 def __init__(self, crb, serializer, name):
     self.crb = crb
     self.skip_setup = False
     self.serializer = serializer
     self.ports_info = None
     self.sessions = []
     self.name = name
     self.logger = getLogger(name)
     self.session = SSHConnection(self.get_ip_address(), name,
                                  self.get_password())
     self.session.init_log(self.logger)
     self.alt_session = SSHConnection(self.get_ip_address(), name + '_alt',
                                      self.get_password())
     self.alt_session.init_log(self.logger)
Ejemplo n.º 7
0
def process_logs(info):
    from ssh_connection import SSHConnection
    import re

    for host, host_info in info.items():
        with SSHConnection(host, host_info["username"],
                           host_info["password"]) as conn:
            if "logfiles" in host_info:
                for path, regex in host_info["logfiles"]:
                    pattern = re.compile(regex)
                    with conn.open(path) as infile:
                        for line in infile:
                            matches = pattern.finditer(line)
                            if matches:
                                for m in matches:
                                    yield m

            if "logcommands" in host_info:
                for command, regex in host_info["logcommands"]:
                    pattern = re.compile(regex)
                    _, stdout, _ = conn.exec_command(command)
                    for line in stdout:
                        matches = pattern.finditer(line)
                        if matches:
                            for m in matches:
                                yield m
Ejemplo n.º 8
0
    def createConnection(self):
        """ Method to create connection

        @return httplib connection object
        """

        conn = ""
        context = ssl._create_unverified_context()
        if self.type == "https":
            conn = httplib.HTTPSConnection(self.ip, context=context)
            sock = socket.create_connection((conn.host, conn.port),
                                            conn.timeout, conn.source_address)
            conn.sock = ssl.wrap_socket(sock,
                                        conn.key_file,
                                        conn.cert_file,
                                        ssl_version=ssl.PROTOCOL_TLSv1)
        elif self.type == "ssh":
            conn = SSHConnection(self.ip, self.username, self.password)
        elif self.type == "scp":
            transport = paramiko.Transport((self.ip, 22))
            transport.connect(username="******", password=self.password)
            conn = paramiko.SFTPClient.from_transport(transport)
        elif self.type == "expect":
            conn = ExpectConnection(self.ip, self.username, self.password)
        else:
            conn = httplib.HTTPConnection(self.ip)
        return conn
Ejemplo n.º 9
0
 def __init__(self, crb, serializer):
     super(Dut, self).__init__(crb, serializer)
     self.NAME = 'dut'
     self.logger = getLogger(self.NAME)
     self.session = SSHConnection(self.get_ip_address(), self.NAME,
                                  self.get_password())
     self.session.init_log(self.logger)
     self.alt_session = SSHConnection(self.get_ip_address(), self.NAME + '_alt',
                                      self.get_password())
     self.alt_session.init_log(self.logger)
     self.number_of_cores = 0
     self.tester = None
     self.cores = []
     self.architecture = None
     self.ports_info = None
     self.conf = UserConf()
     self.ports_map = []
Ejemplo n.º 10
0
def _stop_project(ssh_host: str, ssh_user: str, ssh_password: str,
                  project_name: str) -> None:
    logging.info(f"[{ssh_host}] Stopping project")

    ssh: SSHConnection = SSHConnection(ssh_host, ssh_user, ssh_password)

    ssh.execute(f"screen -X -S {project_name} quit")

    ssh.close()
Ejemplo n.º 11
0
 def __init__(self, crb, serializer):
     super(Dut, self).__init__(crb, serializer)
     self.NAME = 'dut'
     self.logger = getLogger(self.NAME)
     self.session = SSHConnection(self.get_ip_address(), self.NAME,
                                  self.get_password())
     self.session.init_log(self.logger)
     self.alt_session = SSHConnection(self.get_ip_address(),
                                      self.NAME + '_alt',
                                      self.get_password())
     self.alt_session.init_log(self.logger)
     self.number_of_cores = 0
     self.tester = None
     self.cores = []
     self.architecture = None
     self.ports_info = None
     self.conf = UserConf()
     self.ports_map = []
Ejemplo n.º 12
0
    def __init__(self, crb, serializer):
        super(Tester, self).__init__(crb, serializer)
        self.NAME = 'tester'

        self.logger = getLogger(self.NAME)
        self.session = SSHConnection(self.get_ip_address(),
                                     self.NAME, self.get_password())
        self.session.init_log(self.logger)
        self.alt_session = SSHConnection(self.get_ip_address(),
                                         self.NAME + '_alt', self.get_password())
        self.alt_session.init_log(self.logger)

        self.bgProcIsRunning = False
        self.dut = None
        self.inBg = 0
        self.scapyCmds = []
        self.bgCmds = []
        self.bgItf = ''
Ejemplo n.º 13
0
    def reconnect_session(self, alt_session=False):
        """
        When session can't used anymore, recreate another one for replace
        """
        try:
            if alt_session:
                self.alt_session.close(force=True)
            else:
                self.session.close(force=True)
        except Exception as e:
            self.loggger.error("Session close failed for [%s]" % e)

        if alt_session:
            session = SSHConnection(
                self.get_ip_address(),
                self.name + '_alt',
                self.get_username(),
                self.get_password())
            self.alt_session = session
        else:
            session = SSHConnection(self.get_ip_address(), self.name,
                                    self.get_username(), self.get_password())
            self.session = session

        session.init_log(self.logger)
    def __init__(self, config_path: Path, experiment_path: Path,
                 skip_list: List[str], ssh_password: str, node_index: int):
        self.config: Configuration = Configuration.load(config_path)
        self.experiment: Experiment = Experiment.load(experiment_path)
        self._node_index: int = node_index
        self.node: str = self.config.nodes[node_index]
        self.skip_list: List[str] = skip_list
        self.ssh_password: str = ssh_password
        self.command: str = ExperimentEnvironment(self.config, self.experiment,
                                                  node_index).command

        self.ssh: SSHConnection = SSHConnection(self.node,
                                                self.config.ssh_user,
                                                ssh_password)
Ejemplo n.º 15
0
class Crb(object):
    """
    Get the information of NIC and setup for SPDK.
    """
    def __init__(self, crb, serializer, name):
        self.crb = crb
        self.skip_setup = False
        self.serializer = serializer
        self.ports_info = None
        self.sessions = []
        self.name = name
        self.logger = getLogger(name)
        self.session = SSHConnection(self.get_ip_address(), name,
                                     self.get_password())
        self.session.init_log(self.logger)
        self.alt_session = SSHConnection(self.get_ip_address(), name + '_alt',
                                         self.get_password())
        self.alt_session.init_log(self.logger)

    def send_expect(self,
                    cmds,
                    expected,
                    timeout=TIMEOUT,
                    alt_session=False,
                    verify=False):
        """
        Send commands to target and return string before expected string.
        If not, TimeoutException will be raised.
        """
        if alt_session:
            return self.alt_session.session.send_expect(
                cmds, expected, timeout, verify)
        return self.session.send_expect(cmds, expected, timeout, verify)

    def get_session_output(self, timeout=TIMEOUT):
        """
        Get session output message before timeout
        """
        return self.session.get_session_before(timeout)

    def set_speedup_options(self, skip_setup):
        """
        Configure skip network topology scan or skip SPDK packet setup.
        """
        self.skip_setup = skip_setup

    def set_directory(self, base_dir):
        """
        Set SPDK package folder name.
        """
        self.base_dir = base_dir

    def set_path(self, dpdk_dir):
        """
        Add DPDK package path name.
        """
        self.dpdk_dir = dpdk_dir

    def pci_devices_information(self):
        self.pci_devices_information_uncached()
        self.serializer.save(self.PCI_DEV_CACHE_KEY, self.pci_devices_info)

    def pci_devices_information_uncached(self):
        out = self.send_expect("lspci -Dnn | grep -i eth",
                               "# ",
                               alt_session=True)
        rexp = r"([\da-f]{4}:[\da-f]{2}:[\da-f]{2}.\d{1}) .*Eth.*?ernet .*?([\da-f]{4}:[\da-f]{4})"
        pattern = re.compile(rexp)
        match = pattern.findall(out)
        self.pci_devices_info = []
        for i in range(len(match)):
            self.pci_devices_info.append((match[i][0], match[i][1]))

    def get_pci_dev_driver(self, domain_id, bus_id, devfun_id):
        out = self.send_expect("cat /sys/bus/pci/devices/%s\:%s\:%s/uevent" %
                               (domain_id, bus_id, devfun_id),
                               "# ",
                               alt_session=True)
        rexp = r"DRIVER=(.+?)\r"
        pattern = re.compile(rexp)
        match = pattern.search(out)
        if not match:
            return None
        return match.group(1)

    def enable_ipv6(self, intf):
        """
        Enable ipv6 of of specified interface
        """
        if intf != 'N/A':
            self.send_expect("sysctl net.ipv6.conf.%s.disable_ipv6=0" % intf,
                             "# ",
                             alt_session=True)
Ejemplo n.º 16
0
class Dut(Crb):

    """
    A connection to the CRB under test.
    This class sends commands to the CRB and validates the responses. It is
    implemented using either ssh for linuxapp or the terminal server for
    baremetal.
    All operations are in fact delegated to an instance of either CRBLinuxApp
    or CRBBareMetal.
    """

    PORT_MAP_CACHE_KEY = 'dut_port_map'
    PORT_INFO_CACHE_KEY = 'dut_port_info'
    NUMBER_CORES_CACHE_KEY = 'dut_number_cores'
    CORE_LIST_CACHE_KEY = 'dut_core_list'
    PCI_DEV_CACHE_KEY = 'dut_pci_dev_info'

    def __init__(self, crb, serializer):
        super(Dut, self).__init__(crb, serializer)
        self.NAME = 'dut'
        self.logger = getLogger(self.NAME)
        self.session = SSHConnection(self.get_ip_address(), self.NAME,
                                     self.get_password())
        self.session.init_log(self.logger)
        self.alt_session = SSHConnection(self.get_ip_address(), self.NAME + '_alt',
                                         self.get_password())
        self.alt_session.init_log(self.logger)
        self.number_of_cores = 0
        self.tester = None
        self.cores = []
        self.architecture = None
        self.ports_info = None
        self.conf = UserConf()
        self.ports_map = []

    def change_config_option(self, target, parameter, value):
        """
        This function change option in the config file
        """
        self.send_expect("sed -i 's/%s=.*$/%s=%s/'  config/defconfig_%s" %
                         (parameter, parameter, value, target), "# ")

    def set_nic_type(self, nic):
        """
        Set CRB NICS ready to validated.
        """
        self.nic = nic
        if 'cfg' in nic:
            self.conf.load_ports_config(self.get_ip_address())

    def set_toolchain(self, target):
        """
        This looks at the current target and instantiates an attribute to
        be either a CRBLinuxApp or CRBBareMetal object. These latter two
        classes are private and should not be used directly by client code.
        """
        self.kill_all()
        self.target = target
        [arch, _, _, toolchain] = target.split('-')

        if toolchain == "icc":
            icc_vars = os.getenv('ICC_VARS', "/opt/intel/composer_xe_2013/bin/")
            icc_vars += "compilervars.sh"

            if arch == "x86_64":
                icc_arch = "intel64"
            elif arch == "i686":
                icc_arch = "ia32"
            self.send_expect("source " + icc_vars + " " + icc_arch, "# ")

        self.architecture = arch

    def mount_procfs(self):
        """
        Mount proc file system.
        """
        mount_procfs = getattr(self, 'mount_procfs_%s' % self.get_os_type())
        mount_procfs()

    def mount_procfs_linux(self):
        pass

    def mount_procfs_freebsd(self):
        """
        Mount proc file system in Freebsd.
        """
        self.send_expect('mount -t procfs proc /proc', '# ')

    def get_ip_address(self):
        """
        Get DUT's ip address.
        """
        return self.crb['IP']

    def get_password(self):
        """
        Get DUT's login password.
        """
        return self.crb['pass']

    def dut_prerequisites(self):
        """
        Prerequest function should be called before execute any test case.
        Will call function to scan all lcore's information which on DUT.
        Then call pci scan function to collect nic device information.
        At last setup DUT' environment for validation.
        """
        self.send_expect("cd %s" % self.base_dir, "# ")
        self.send_expect("alias ls='ls --color=none'", "#")

        if self.get_os_type() == 'freebsd':
            self.send_expect('alias make=gmake', '# ')
            self.send_expect('alias sed=gsed', '# ')

        self.init_core_list()
        self.pci_devices_information()
        # scan ports before restore interface
        self.scan_ports()
        # restore dut ports to kernel
        self.restore_interfaces()
        # rescan ports after interface up
        self.rescan_ports()
        # load port infor from config file
        self.load_portconf()
        self.mount_procfs()
        # auto detect network topology
        self.map_available_ports()
        # print latest ports_info
        self.logger.info(dts.pprint(self.ports_info))
        if self.ports_map is None or len(self.ports_map) == 0:
            raise ValueError("ports_map should not be empty, please check all links")

    def restore_interfaces(self):
        """
        Restore all ports's interfaces.
        """
        restore_interfaces = getattr(self, 'restore_interfaces_%s' % self.get_os_type())
        return restore_interfaces()

    def restore_interfaces_freebsd(self):
        """
        Restore FreeBSD interfaces.
        """
        self.send_expect("kldunload nic_uio.ko", "#")
        self.send_expect("kldunload contigmem.ko", "#")
        self.send_expect("kldload if_ixgbe.ko", "#", 20)

    def restore_interfaces_linux(self):
        """
        Restore Linux interfaces.
        """
        for port in self.ports_info:
            pci_bus = port['pci']
            pci_id = port['type']
            # get device driver
            driver = dts.get_nic_driver(pci_id)
            if driver is not None and self.isMellanox == False:
                # unbind device driver
                addr_array = pci_bus.split(':')
                bus_id = addr_array[0]
                devfun_id = addr_array[1]

                self.send_expect('echo 0000:%s > /sys/bus/pci/devices/0000\:%s\:%s/driver/unbind'
                                 % (pci_bus, bus_id, devfun_id), '# ')
                #bind to linux kernel driver
                self.send_expect('modprobe %s' % driver, '# ')
                self.send_expect('echo 0000:%s > /sys/bus/pci/drivers/%s/bind'
                                 % (pci_bus, driver), '# ')
                itf = self.get_interface_name(addr_array[0], addr_array[1])
                self.send_expect("ifconfig %s up" % itf, "# ")
            else:
                self.logger.info("NOT FOUND DRIVER FOR PORT (%s|%s)!!!" % (pci_bus, pci_id))

    def setup_memory(self, hugepages=-1):
        """
        Setup hugepage on DUT.
        """
        try:
            function_name = 'setup_memory_%s' % self.get_os_type()
            setup_memory = getattr(self, function_name)
            setup_memory(hugepages)
        except AttributeError:
            self.logger.error("%s is not implemented" % function_name)

    def setup_memory_linux(self, hugepages=-1):
        """
        Setup Linux hugepages.
        """
        hugepages_size = self.send_expect("awk '/Hugepagesize/ {print $2}' /proc/meminfo", "# ")

        if int(hugepages_size) < (1024 * 1024):
            if self.architecture == "x86_64":
                arch_huge_pages = hugepages if hugepages > 0 else 4096
            elif self.architecture == "i686":
                arch_huge_pages = hugepages if hugepages > 0 else 512
            # set huge pagesize for x86_x32 abi target
            elif self.architecture == "x86_x32":
                arch_huge_pages = hugepages if hugepages > 0 else 256

            total_huge_pages = self.get_total_huge_pages()

            self.mount_huge_pages()
            if total_huge_pages != arch_huge_pages:
                self.set_huge_pages(arch_huge_pages)

    def setup_memory_freebsd(self, hugepages=-1):
        """
        Setup Freebsd hugepages.
        """
        if hugepages is -1:
            hugepages = 2048

        num_buffers = hugepages / 1024
        if num_buffers:
            self.send_expect('kenv hw.contigmem.num_buffers=%d' % num_buffers, "#")

        self.send_expect("kldunload contigmem.ko", "#")
        self.send_expect("kldload ./%s/kmod/contigmem.ko" % self.target, "#")

    def taskset(self, core):
        if self.get_os_type() != 'linux':
            return ''

        return 'taskset %s ' % core

    def bind_interfaces_linux(self, driver='igb_uio', nics_to_bind=None):
        """
        Bind the interfaces to the selected driver. nics_to_bind can be None
        to bind all interfaces or an array with the port indexes
        """

        binding_list = '--bind=%s ' % driver

        current_nic = 0
        for (pci_bus, pci_id) in self.pci_devices_info:
            if dts.accepted_nic(pci_id):

                if nics_to_bind is None or current_nic in nics_to_bind:
                    binding_list += '%s ' % (pci_bus)

                current_nic += 1

        self.send_expect('tools/dpdk_nic_bind.py %s' % binding_list, '# ')

    def unbind_interfaces_linux(self, nics_to_bind=None):
        """
        Unbind the interfaces.
        """

        binding_list = '-u '

        current_nic = 0
        for (pci_bus, pci_id) in self.pci_devices_info:
            if dts.accepted_nic(pci_id):

                if nics_to_bind is None or current_nic in nics_to_bind:
                    binding_list += '%s ' % (pci_bus)

                current_nic += 1

        self.send_expect('tools/dpdk_nic_bind.py %s' % binding_list, '# ', 30)

    def get_ports(self, nic_type='any', perf=None, socket=None):
        """
        Return DUT port list with the filter of NIC type, whether run IXIA
        performance test, whether request specified socket.
        """
        ports = []
        candidates = []

        if perf is None:
            perf = self.want_perf_tests

        nictypes = []
        if nic_type == 'any':
            for portid in range(len(self.ports_info)):
                ports.append(portid)
            return ports
        elif nic_type == 'cfg':
            for portid in range(len(self.ports_info)):
                if self.ports_info[portid]['source'] == 'cfg':
                    ports.append(portid)
            return ports
        else:
            for portid in range(len(self.ports_info)):
                port_info = self.ports_info[portid]
                # match nic type
                if port_info['type'] == NICS[nic_type]:
                    # match numa or none numa awareness
                    if (socket is None or
                        port_info['numa'] == -1 or
                            socket == port_info['numa']):
                        # port has link,
                        if self.tester.get_local_port(portid) != -1:
                            ports.append(portid)
            return ports

    def get_ports_performance(self, nic_type='any', perf=None, socket=None,
                              force_same_socket=True,
                              force_different_nic=True):
        """
            Return the maximum available number of ports meeting the parameters.
            Focuses on getting ports with same/different NUMA node and/or
            same/different NIC.
        """

        available_ports = self.get_ports(nic_type, perf, socket)
        accepted_sets = []

        while len(available_ports) > 0:
            accepted_ports = []
            # first avaiable port is the reference port
            accepted_ports.append(available_ports[0])

            # check from second port according to parameter
            for port in available_ports[1:]:

                if force_same_socket and socket is None:
                    if self.ports_info[port]['numa'] != self.ports_info[accepted_ports[0]]['numa']:
                        continue
                if force_different_nic:
                    if self.ports_info[port]['pci'][:-1] == self.ports_info[accepted_ports[0]]['pci'][:-1]:
                        continue

                accepted_ports.append(port)

            for port in accepted_ports:
                available_ports.remove(port)

            accepted_sets.append(accepted_ports)

        biggest_set = max(accepted_sets, key=lambda s: len(s))

        return biggest_set

    def get_peer_pci(self, port_num):
        """
        return the peer pci address of dut port
        """
        if 'peer' not in self.ports_info[port_num]:
            return None
        else:
            return self.ports_info[port_num]['peer']

    def get_mac_address(self, port_num):
        """
        return the port mac on dut
        """
        return self.ports_info[port_num]['mac']

    def get_ipv6_address(self, port_num):
        """
        return the IPv6 address on dut
        """
        return self.ports_info[port_num]['ipv6']

    def get_numa_id(self, port_num):
        """
        return the Numa Id of port
        """
        if self.ports_info[port_num]['numa'] == -1:
            self.logger.warning('NUMA not supported')

        return self.ports_info[port_num]['numa']

    def get_port_info(self, pci):
        """
        return port info by pci id
        """
        for port_info in self.ports_info:
            if port_info['pci'] == pci:
                return port_info

    def lcore_table_print(self, horizontal=False):
        if not horizontal:
            dts.results_table_add_header(['Socket', 'Core', 'Thread'])

            for lcore in self.cores:
                dts.results_table_add_row([lcore['socket'], lcore['core'], lcore['thread']])
            dts.results_table_print()
        else:
            dts.results_table_add_header(['X'] + [''] * len(self.cores))
            dts.results_table_add_row(['Thread'] + [n['thread'] for n in self.cores])
            dts.results_table_add_row(['Core'] + [n['core'] for n in self.cores])
            dts.results_table_add_row(['Socket'] + [n['socket'] for n in self.cores])
            dts.results_table_print()

    def get_memory_channels(self):
        n = self.crb['memory channels']
        if n is not None and n > 0:
            return n
        else:
            return 1

    def check_ports_available(self, pci_bus, pci_id):
        """
        Check that whether auto scanned ports ready to use
        """
        pci_addr = "%s:%s" % (pci_bus, pci_id)
        if self.nic == 'any':
            return True
        elif self.nic == 'cfg':
            if self.conf.check_port_available(pci_bus) is True:
                return True
        elif self.nic not in NICS.keys():
            self.logger.warning("NOT SUPPORTED NIC TYPE: %s" % self.nic)
        else:
            codename = NICS[self.nic]
            if pci_id == codename:
                return True

        return False

    def rescan_ports(self):
        unknow_interface = dts.RED('Skipped: unknow_interface')

        for port_info in self.ports_info:
            pci_bus = port_info['pci']
            addr_array = pci_bus.split(':')
            bus_id = addr_array[0]
            devfun_id = addr_array[1]
            intf = self.get_interface_name(bus_id, devfun_id)
            if "No such file" in intf:
                self.logger.info("DUT: [0000:%s] %s" % (pci_bus, unknow_interface))
            out = self.send_expect("ip link show %s" % intf, "# ")
            if "DOWN" in out:
                self.send_expect("ip link set %s up" % intf, "# ")
                time.sleep(5)
            macaddr = self.get_mac_addr(intf, bus_id, devfun_id)
            out = self.send_expect("ip -family inet6 address show dev %s | awk '/inet6/ { print $2 }'"
                                   % intf, "# ")
            ipv6 = out.split('/')[0]
            # Unconnected ports don't have IPv6
            if ":" not in ipv6:
                ipv6 = "Not connected"

            port_info['mac'] = macaddr
            port_info['intf'] = intf
            port_info['ipv6'] = ipv6

    def scan_ports(self):
        """
        Scan ports information or just read it from cache file.
        """
        if self.read_cache:
            self.ports_info = self.serializer.load(self.PORT_INFO_CACHE_KEY)
            
        if not self.read_cache or self.ports_info is None:
            self.scan_ports_uncached()
            self.serializer.save(self.PORT_INFO_CACHE_KEY, self.ports_info)

    def scan_ports_uncached(self):
        """
        Scan ports and collect port's pci id, mac adress, ipv6 address.
        """
        scan_ports_uncached = getattr(self, 'scan_ports_uncached_%s' % self.get_os_type())
        return scan_ports_uncached()

    def scan_ports_uncached_linux(self):
        """
        Scan Linux ports and collect port's pci id, mac adress, ipv6 address.
        """
        self.ports_info = []

        skipped = dts.RED('Skipped: Unknown/not selected')
        unknow_interface = dts.RED('Skipped: unknow_interface')
        #RRR
        for (pci_bus, pci_id) in self.pci_devices_info:
            if self.check_ports_available(pci_bus, pci_id) is False:
                self.logger.info("DUT: [000:%s %s] %s" % (pci_bus, pci_id,
                                                          skipped))
                continue

            addr_array = pci_bus.split(':')
            bus_id = addr_array[0]
            devfun_id = addr_array[1]
            
            numa = self.get_device_numa(bus_id, devfun_id)
            # store the port info to port mapping
            self.check_Mellanox_pci(pci_bus,pci_id)
            if self.isMellanox :
                self.ports_info.append({'pci': pci_bus, 'type': pci_id, 'numa': numa})
            self.ports_info.append({'pci': pci_bus, 'type': pci_id, 'numa': numa})
        
    def scan_ports_uncached_freebsd(self):
        """
        Scan Freebsd ports and collect port's pci id, mac adress, ipv6 address.
        """
        self.ports_info = []

        skipped = dts.RED('Skipped: Unknown/not selected')

        for (pci_bus, pci_id) in self.pci_devices_info:

            if not dts.accepted_nic(pci_id):
                self.logger.info("DUT: [%s %s] %s" % (pci_bus, pci_id,
                                                      skipped))
                continue

            intf = self.get_interface_name(pci_bus)

            macaddr = self.get_mac_addr(intf)
            ipv6 = self.get_ipv6_addr(intf)

            if ipv6 is None:
                ipv6 = "Not available"

            self.logger.warning("NUMA not available on FreeBSD")

            self.logger.info("DUT: [%s %s] %s %s" % (pci_bus, pci_id, intf, ipv6))

            # convert bsd format to linux format
            pci_split = pci_bus.split(':')
            pci_bus_id = hex(int(pci_split[0]))[2:]
            if len(pci_split[1]) == 1:
                pci_dev_str = "0" + pci_split[1]
            else:
                pci_dev_str = pci_split[1]

            pci_str = "%s:%s.%s" % (pci_bus_id, pci_dev_str, pci_split[2])

            # store the port info to port mapping
            self.ports_info.append({'pci': pci_str, 'type': pci_id, 'intf':
                                    intf, 'mac': macaddr, 'ipv6': ipv6, 'numa': -1})

    def load_portconf(self):
        """
        Load port configurations for ports_info. If manually configured infor
        not same as auto scanned, still use infor in configuration file.
        """
        for port in self.ports_info:
            pci_bus = port['pci']
            ports_cfg = self.conf.get_ports_config()
            if pci_bus in ports_cfg:
                port_cfg = ports_cfg[pci_bus]
                port_cfg['source'] = 'cfg'
            else:
                port_cfg = {}

            for key in ['intf', 'mac', 'numa', 'peer', 'source']:
                if key in port_cfg:
                    if key in port and port_cfg[key] != port[key]:
                        self.logger.warning("CONFIGURED %s NOT SAME AS SCANNED!!!" % (key.upper()))

                    port[key] = port_cfg[key]

    def map_available_ports(self):
        """
        Load or generate network connection mapping list.
        """
        if self.read_cache:
            self.ports_map = self.serializer.load(self.PORT_MAP_CACHE_KEY)

        if not self.read_cache or self.ports_map is None:
            self.map_available_ports_uncached()
            self.serializer.save(self.PORT_MAP_CACHE_KEY, self.ports_map)

        self.logger.warning("DUT PORT MAP: " + str(self.ports_map))

    def map_available_ports_uncached(self):
        """
        Generate network connection mapping list.
        """
        nrPorts = len(self.ports_info)
        if nrPorts == 0:
            return

        remove = []
        self.ports_map = [-1] * nrPorts

        hits = [False] * len(self.tester.ports_info)
        
        for dutPort in range(nrPorts):
            peer = self.get_peer_pci(dutPort)
            dutpci = self.ports_info[dutPort]['pci']
            if peer is not None:
                
                for remotePort in range(len(self.tester.ports_info)):
                    if self.tester.ports_info[remotePort]['pci'] == peer:
                        hits[remotePort] = True
                        self.ports_map[dutPort] = remotePort
                        break
                if self.ports_map[dutPort] == -1:
                    self.logger.error("CONFIGURED TESTER PORT CANNOT FOUND!!!")
                else:
                    continue  # skip ping6 map

            for remotePort in range(len(self.tester.ports_info)):
                if hits[remotePort]:
                    continue

                # skip ping self port
                remotepci = self.tester.ports_info[remotePort]['pci']
                if (self.crb['IP'] == self.crb['tester IP']) and (dutpci == remotepci):
                    continue

                # skip ping those not connected port
                ipv6 = self.get_ipv6_address(dutPort)
                if ipv6 == "Not connected":
                    continue

                out = self.tester.send_ping6(remotePort, ipv6, self.get_mac_address(dutPort))

                if ('64 bytes from' in out):
                    self.logger.info("PORT MAP: [dut %d: tester %d]" % (dutPort, remotePort))
                    self.ports_map[dutPort] = remotePort
                    hits[remotePort] = True
                    if self.crb['IP'] == self.crb['tester IP']:
                        # remove dut port act as tester port
                        remove_port = self.get_port_info(remotepci)
                        if remove_port is not None:
                            remove.append(remove_port)
                        # skip ping from those port already act as dut port
                        testerPort = self.tester.get_local_index(dutpci)
                        if testerPort != -1:
                            hits[testerPort] = True
                    break

        for port in remove:
            self.ports_info.remove(port)
def process_server(host, info, out):
    from ssh_connection import SSHConnection
    with SSHConnection(host, info["username"], info["password"]) as ssh:
        parse_logfiles(ssh.sftp_client, host, info, out)
Ejemplo n.º 18
0
        uuid_set_list.append(uuid_set)

    uuid_set_str = ','.join(uuid_set_list)
    update_cmd = update_template % {'uuid': uuid_set_str, 'name': port}

    cmd_list.append(update_cmd)
    cmd_str = ','.join(cmd_list)

    cmd = "ovsdb-client transact '[\"Open_vSwitch\", %s]'" % cmd_str
    ssh.send_expect(cmd, '# ')


if __name__ == "__main__":
    from ssh_connection import SSHConnection

    ssh = SSHConnection('192.168.8.103', 'root', '111111')
    all_intf_uuid = get_ovs_all_interface_uuid(ssh)
    print "All interface uuids: ", all_intf_uuid
    ports = get_ovs_port_interface_uuid(ssh, 'bond0')
    print "ports uuid are: ", ports
    add_interface_to_port(ssh, 'bond0', *['eth1'])
    interfaces = ssh.send_expect(
        "ovsdb-client transact '[\"Open_vSwitch\", {\"op\":\"select\", \"table\":\"Interface\", \"columns\":[\"name\"], \"where\":[]}]'",
        '# ')
    print "Now interfaces: ", interfaces
    remove_interface_to_port(ssh, 'bond0', *['eth1'])
    interfaces = ssh.send_expect(
        "ovsdb-client transact '[\"Open_vSwitch\", {\"op\":\"select\", \"table\":\"Interface\", \"columns\":[\"name\"], \"where\":[]}]'",
        '# ')
    print "Now interfaces: ", interfaces
Ejemplo n.º 19
0
def rebase_image(ssh, baking_file, image, backend='qemu'):
    if backend == 'qemu':
        if command_exists(ssh, 'qemu-img'):
            pass
        else:
            raise Exception("Not support rebasing image with [qemu] backend!") 
    else:
        raise Exception("Not support rebasing image with [%s] backend!" % backend)

    cmd = "qemu-img rebase -b %s %s" % (baking_file, image)
    retcode, ret = ssh.send_expect(cmd, '# ', verify=True, timeout=None)
    return retcode, ret

if __name__ == "__main__":
    from ssh_connection import SSHConnection
    ssh = SSHConnection('192.168.10.16', 'root', '111111')
    import pdb
    pdb.set_trace()
    domainname = get_domain_name(ssh)
    ovs_bonds = get_bond_slaves(ssh, 'bond0') 
    print "OVS bond slaves: ", ovs_bonds
    host_bond_nics = get_host_nics(ssh, 'ovs_bond')
    print "OVS bonds: ", host_bond_nics
    host_free_nics = get_host_nics(ssh, 'free')
    print "OVS free nics: ", host_free_nics
    if kernel_module_is_loaded(ssh, 'zfs'):
        print "yes"
    else:
        print "no"
    free_disks = get_host_disks(ssh, 'free')
    print "Free Disks: ", free_disks
Ejemplo n.º 20
0
class Dut(Crb):
    """
    A connection to the CRB under test.
    This class sends commands to the CRB and validates the responses. It is
    implemented using either ssh for linuxapp or the terminal server for
    baremetal.
    All operations are in fact delegated to an instance of either CRBLinuxApp
    or CRBBareMetal.
    """

    PORT_MAP_CACHE_KEY = 'dut_port_map'
    PORT_INFO_CACHE_KEY = 'dut_port_info'
    NUMBER_CORES_CACHE_KEY = 'dut_number_cores'
    CORE_LIST_CACHE_KEY = 'dut_core_list'
    PCI_DEV_CACHE_KEY = 'dut_pci_dev_info'

    def __init__(self, crb, serializer):
        self.NAME = 'dut' + LOG_NAME_SEP + '%s' % crb['My IP']
        super(Dut, self).__init__(crb, serializer, self.NAME)

        self.host_init_flag = False
        self.number_of_cores = 0
        self.tester = None
        self.cores = []
        self.architecture = None
        self.ports_info = []
        self.conf = PortConf()
        self.ports_map = []
        self.virt_pool = None
        # hypervisor pid list, used for cleanup
        self.virt_pids = []

    def init_host_session(self):
        if self.host_init_flag:
            pass
        else:
            self.host_session = SSHConnection(self.get_ip_address(),
                                              self.NAME + '_host',
                                              self.get_username(),
                                              self.get_password())
            self.host_session.init_log(self.logger)
            self.host_init_flag = True

    def new_session(self, suite=""):
        """
        Create new session for dut instance. Session name will be unique.
        """
        session_name = self.NAME + '_' + str(uuid4())
        session = self.create_session(name=session_name)
        if suite != "":
            session.logger.config_suite(suite, self.NAME)
        else:
            session.logger.config_execution(self.NAME)
        session.send_expect("cd %s" % self.base_dir, "# ")
        return session

    def close_session(self, session):
        """
        close new session in dut instance
        """
        self.destroy_session(session)

    def change_config_option(self, target, parameter, value):
        """
        This function change option in the config file
        """
        self.send_expect(
            "sed -i 's/%s=.*$/%s=%s/'  config/defconfig_%s" %
            (parameter, parameter, value, target), "# ")

    def set_nic_type(self, nic_type):
        """
        Set CRB NICS ready to validated.
        """
        self.nic_type = nic_type
        if 'cfg' in nic_type:
            self.conf.load_ports_config(self.get_ip_address())

    def set_toolchain(self, target):
        """
        This looks at the current target and instantiates an attribute to
        be either a CRBLinuxApp or CRBBareMetal object. These latter two
        classes are private and should not be used directly by client code.
        """
        self.kill_all()
        self.target = target
        [arch, _, _, toolchain] = target.split('-')

        if toolchain == "icc":
            icc_vars = os.getenv('ICC_VARS',
                                 "/opt/intel/composer_xe_2013/bin/")
            icc_vars += "compilervars.sh"

            if arch == "x86_64":
                icc_arch = "intel64"
            elif arch == "i686":
                icc_arch = "ia32"
            self.send_expect("source " + icc_vars + " " + icc_arch, "# ")

        self.architecture = arch

    def mount_procfs(self):
        """
        Mount proc file system.
        """
        mount_procfs = getattr(self, 'mount_procfs_%s' % self.get_os_type())
        mount_procfs()

    def mount_procfs_linux(self):
        pass

    def mount_procfs_freebsd(self):
        """
        Mount proc file system in Freebsd.
        """
        self.send_expect('mount -t procfs proc /proc', '# ')

    def get_ip_address(self):
        """
        Get DUT's ip address.
        """
        return self.crb['IP']

    def get_password(self):
        """
        Get DUT's login password.
        """
        return self.crb['pass']

    def get_username(self):
        """
        Get DUT's login username.
        """
        return self.crb['user']

    def dut_prerequisites(self):
        """
        Prerequest function should be called before execute any test case.
        Will call function to scan all lcore's information which on DUT.
        Then call pci scan function to collect nic device information.
        At last setup DUT' environment for validation.
        """
        self.send_expect("cd %s" % self.base_dir, "# ")
        self.send_expect("alias ls='ls --color=none'", "#")

        if self.get_os_type() == 'freebsd':
            self.send_expect('alias make=gmake', '# ')

        self.init_core_list()
        self.pci_devices_information()
        # make sure ipv6 enable before scan
        self.enable_tester_ipv6()
        # scan ports before restore interface
        self.scan_ports()
        # restore dut ports to kernel
        self.restore_interfaces()
        # rescan ports after interface up
        self.rescan_ports()
        # load port infor from config file
        self.load_portconf()
        self.mount_procfs()
        # auto detect network topology
        self.map_available_ports()
        # disable tester port ipv6
        self.disable_tester_ipv6()
        # print latest ports_info
        for port_info in self.ports_info:
            self.logger.info(port_info)
        if self.ports_map is None or len(self.ports_map) == 0:
            self.logger.warning(
                "ports_map should not be empty, please check all links")

        # initialize virtualization resource pool
        self.virt_pool = VirtResource(self)

    def restore_interfaces(self):
        """
        Restore all ports's interfaces.
        """
        # no need to restore for all info has been recorded
        if self.read_cache:
            return

        restore_interfaces = getattr(
            self, 'restore_interfaces_%s' % self.get_os_type())
        return restore_interfaces()

    def restore_interfaces_freebsd(self):
        """
        Restore FreeBSD interfaces.
        """
        self.send_expect("kldunload nic_uio.ko", "#")
        self.send_expect("kldunload contigmem.ko", "#")
        self.send_expect("kldload if_ixgbe.ko", "#", 20)

    def stop_ports(self):
        """
        After all execution done, some special nic like fm10k should be stop
        """
        for (pci_bus, pci_id) in self.pci_devices_info:
            driver = settings.get_nic_driver(pci_id)
            if driver is not None:
                # unbind device driver
                addr_array = pci_bus.split(':')
                domain_id = addr_array[0]
                bus_id = addr_array[1]
                devfun_id = addr_array[2]
                port = GetNicObj(self, domain_id, bus_id, devfun_id)
                port.stop()

    def restore_interfaces_linux(self):
        """
        Restore Linux interfaces.
        """
        for port in self.ports_info:
            pci_bus = port['pci']
            pci_id = port['type']
            # get device driver
            driver = settings.get_nic_driver(pci_id)
            if driver is not None:
                # unbind device driver
                addr_array = pci_bus.split(':')
                domain_id = addr_array[0]
                bus_id = addr_array[1]
                devfun_id = addr_array[2]

                port = GetNicObj(self, domain_id, bus_id, devfun_id)

                self.send_expect(
                    'echo %s > /sys/bus/pci/devices/%s\:%s\:%s/driver/unbind' %
                    (pci_bus, domain_id, bus_id, devfun_id), '# ')
                # bind to linux kernel driver
                self.send_expect('modprobe %s' % driver, '# ')
                self.send_expect(
                    'echo %s > /sys/bus/pci/drivers/%s/bind' %
                    (pci_bus, driver), '# ')
                itf = port.get_interface_name()
                self.send_expect("ifconfig %s up" % itf, "# ")
            else:
                self.logger.info("NOT FOUND DRIVER FOR PORT (%s|%s)!!!" %
                                 (pci_bus, pci_id))

    def setup_memory(self, hugepages=-1):
        """
        Setup hugepage on DUT.
        """
        try:
            function_name = 'setup_memory_%s' % self.get_os_type()
            setup_memory = getattr(self, function_name)
            setup_memory(hugepages)
        except AttributeError:
            self.logger.error("%s is not implemented" % function_name)

    def setup_memory_linux(self, hugepages=-1):
        """
        Setup Linux hugepages.
        """
        if self.virttype == 'XEN':
            return
        hugepages_size = self.send_expect(
            "awk '/Hugepagesize/ {print $2}' /proc/meminfo", "# ")
        total_huge_pages = self.get_total_huge_pages()
        force_socket = False

        if int(hugepages_size) < (1024 * 1024):
            if self.architecture == "x86_64":
                arch_huge_pages = hugepages if hugepages > 0 else 4096
            elif self.architecture == "i686":
                arch_huge_pages = hugepages if hugepages > 0 else 512
                force_socket = True
            # set huge pagesize for x86_x32 abi target
            elif self.architecture == "x86_x32":
                arch_huge_pages = hugepages if hugepages > 0 else 256
                force_socket = True
            elif self.architecture == "ppc_64":
                arch_huge_pages = hugepages if hugepages > 0 else 512
            elif self.architecture == "arm64":
                if hugepages_size == "524288":
                    arch_huge_pages = hugepages if hugepages > 0 else 8
                else:
                    arch_huge_pages = hugepages if hugepages > 0 else 2048

            if total_huge_pages != arch_huge_pages:
                # before all hugepage average distribution  by all socket,
                # but sometimes create mbuf pool on socket 0 failed when setup testpmd,
                # so set all huge page on socket 0
                if force_socket:
                    self.set_huge_pages(arch_huge_pages, 0)
                else:
                    self.set_huge_pages(arch_huge_pages)

        self.mount_huge_pages()
        self.hugepage_path = self.strip_hugepage_path()

    def setup_memory_freebsd(self, hugepages=-1):
        """
        Setup Freebsd hugepages.
        """
        if hugepages is -1:
            hugepages = 4096

        num_buffers = hugepages / 1024
        if num_buffers:
            self.send_expect('kenv hw.contigmem.num_buffers=%d' % num_buffers,
                             "#")

        self.send_expect("kldunload contigmem.ko", "#")
        self.send_expect("kldload ./%s/kmod/contigmem.ko" % self.target, "#")

    def taskset(self, core):
        if self.get_os_type() != 'linux':
            return ''

        return 'taskset %s ' % core

    def is_ssh_session_port(self, pci_bus):
        """
        Check if the pci device is the dut SSH session port.
        """
        port = None
        for port_info in self.ports_info:
            if pci_bus == port_info['pci']:
                port = port_info['port']
                break
        if port and port.get_ipv4_addr() == crbs['IP'].strip():
            return True
        else:
            return False

    def get_dpdk_bind_script(self):
        op = self.send_command("ls")
        if "usertools" in op:
            res = 'usertools/dpdk-devbind.py'
        else:
            op = self.send_command("ls tools")
            if "dpdk_nic_bind.py" in op:
                res = 'tools/dpdk_nic_bind.py'
            else:
                res = 'tools/dpdk-devbind.py'
        return res

    def bind_interfaces_linux(self, driver='igb_uio', nics_to_bind=None):
        """
        Bind the interfaces to the selected driver. nics_to_bind can be None
        to bind all interfaces or an array with the port indexes
        """

        binding_list = '--bind=%s ' % driver

        current_nic = 0
        for (pci_bus, pci_id) in self.pci_devices_info:
            if settings.accepted_nic(pci_id):
                if self.is_ssh_session_port(pci_bus):
                    continue

                if nics_to_bind is None or current_nic in nics_to_bind:
                    binding_list += '%s ' % (pci_bus)

                current_nic += 1
        if current_nic == 0:
            self.logger.info("Not nic need bind driver: %s" % driver)
            return
        bind_script_path = self.get_dpdk_bind_script()
        self.send_expect('%s --force %s' % (bind_script_path, binding_list),
                         '# ')

    def unbind_interfaces_linux(self, nics_to_bind=None):
        """
        Unbind the interfaces.
        """

        binding_list = '-u '

        current_nic = 0
        for (pci_bus, pci_id) in self.pci_devices_info:
            if settings.accepted_nic(pci_id):
                if self.is_ssh_session_port(pci_bus):
                    continue

                if nics_to_bind is None or current_nic in nics_to_bind:
                    binding_list += '%s ' % (pci_bus)

                current_nic += 1

        if current_nic == 0:
            self.logger.info("Not nic need unbind driver")
            return

        bind_script_path = self.get_dpdk_bind_script()
        self.send_expect('%s --force %s' % (bind_script_path, binding_list),
                         '# ')

    def get_ports(self, nic_type='any', perf=None, socket=None):
        """
        Return DUT port list with the filter of NIC type, whether run IXIA
        performance test, whether request specified socket.
        """
        ports = []
        candidates = []

        nictypes = []
        if nic_type == 'any':
            for portid in range(len(self.ports_info)):
                ports.append(portid)
            return ports
        elif nic_type == 'cfg':
            for portid in range(len(self.ports_info)):
                if self.ports_info[portid]['source'] == 'cfg':
                    if (socket is None or self.ports_info[portid]['numa'] == -1
                            or socket == self.ports_info[portid]['numa']):
                        ports.append(portid)
            return ports
        else:
            for portid in range(len(self.ports_info)):
                port_info = self.ports_info[portid]
                # match nic type
                if port_info['type'] == NICS[nic_type]:
                    # match numa or none numa awareness
                    if (socket is None or port_info['numa'] == -1
                            or socket == port_info['numa']):
                        # port has link,
                        if self.tester.get_local_port(portid) != -1:
                            ports.append(portid)
            return ports

    def get_ports_performance(self,
                              nic_type='any',
                              perf=None,
                              socket=None,
                              force_same_socket=True,
                              force_different_nic=True):
        """
            Return the maximum available number of ports meeting the parameters.
            Focuses on getting ports with same/different NUMA node and/or
            same/different NIC.
        """

        available_ports = self.get_ports(nic_type, perf, socket)
        accepted_sets = []

        while len(available_ports) > 0:
            accepted_ports = []
            # first avaiable port is the reference port
            accepted_ports.append(available_ports[0])

            # check from second port according to parameter
            for port in available_ports[1:]:

                if force_same_socket and socket is None:
                    if self.ports_info[port]['numa'] != self.ports_info[
                            accepted_ports[0]]['numa']:
                        continue
                if force_different_nic:
                    if self.ports_info[port]['pci'][:-1] == self.ports_info[
                            accepted_ports[0]]['pci'][:-1]:
                        continue

                accepted_ports.append(port)

            for port in accepted_ports:
                available_ports.remove(port)

            accepted_sets.append(accepted_ports)

        biggest_set = max(accepted_sets, key=lambda s: len(s))

        return biggest_set

    def get_peer_pci(self, port_num):
        """
        return the peer pci address of dut port
        """
        if 'peer' not in self.ports_info[port_num]:
            return None
        else:
            return self.ports_info[port_num]['peer']

    def get_mac_address(self, port_num):
        """
        return the port mac on dut
        """
        return self.ports_info[port_num]['mac']

    def get_ipv6_address(self, port_num):
        """
        return the IPv6 address on dut
        """
        return self.ports_info[port_num]['ipv6']

    def get_numa_id(self, port_num):
        """
        return the Numa Id of port
        """
        if self.ports_info[port_num]['numa'] == -1:
            self.logger.warning('NUMA not supported')

        return self.ports_info[port_num]['numa']

    def lcore_table_print(self, horizontal=False):
        if not horizontal:
            result_table = ResultTable(['Socket', 'Core', 'Thread'])

            for lcore in self.cores:
                result_table.add_row(
                    [lcore['socket'], lcore['core'], lcore['thread']])
            result_table.table_print()
        else:
            result_table = ResultTable(['X'] + [''] * len(self.cores))
            result_table.add_row(['Thread'] +
                                 [n['thread'] for n in self.cores])
            result_table.add_row(['Core'] + [n['core'] for n in self.cores])
            result_table.add_row(['Socket'] +
                                 [n['socket'] for n in self.cores])
            result_table.table_print()

    def get_memory_channels(self):
        n = self.crb['memory channels']
        if n is not None and n > 0:
            return n
        else:
            return 1

    def check_ports_available(self, pci_bus, pci_id):
        """
        Check that whether auto scanned ports ready to use
        """
        pci_addr = "%s:%s" % (pci_bus, pci_id)
        if self.nic_type == 'any':
            return True
        elif self.nic_type == 'cfg':
            if self.conf.check_port_available(pci_bus) is True:
                return True
        elif self.nic_type not in NICS.keys():
            self.logger.warning("NOT SUPPORTED NIC TYPE: %s" % self.nic_type)
        else:
            codename = NICS[self.nic_type]
            if pci_id == codename:
                return True

        return False

    def rescan_ports(self):
        """
        Rescan ports information
        """
        if self.read_cache:
            return

        if self.ports_info:
            self.rescan_ports_uncached()
            self.save_serializer_ports()

    def rescan_ports_uncached(self):
        """
        rescan ports and update port's mac adress, intf, ipv6 address.
        """
        rescan_ports_uncached = getattr(
            self, 'rescan_ports_uncached_%s' % self.get_os_type())
        return rescan_ports_uncached()

    def rescan_ports_uncached_linux(self):
        unknow_interface = RED('Skipped: unknow_interface')

        for port_info in self.ports_info:
            port = port_info['port']
            intf = port.get_interface_name()
            port_info['intf'] = intf
            out = self.send_expect("ip link show %s" % intf, "# ")
            if "DOWN" in out:
                self.send_expect("ip link set %s up" % intf, "# ")
                time.sleep(5)
            port_info['mac'] = port.get_mac_addr()
            out = self.send_expect(
                "ip -family inet6 address show dev %s | awk '/inet6/ { print $2 }'"
                % intf, "# ")
            ipv6 = out.split('/')[0]
            # Unconnected ports don't have IPv6
            if ":" not in ipv6:
                ipv6 = "Not connected"

            out = self.send_expect(
                "ip -family inet address show dev %s | awk '/inet/ { print $2 }'"
                % intf, "# ")
            ipv4 = out.split('/')[0]

            port_info['ipv6'] = ipv6
            port_info['ipv4'] = ipv4

    def rescan_ports_uncached_freebsd(self):
        unknow_interface = RED('Skipped: unknow_interface')

        for port_info in self.ports_info:
            port = port_info['port']
            intf = port.get_interface_name()
            if "No such file" in intf:
                self.logger.info("DUT: [%s] %s" % (pci_bus, unknow_interface))
                continue
            self.send_expect("ifconfig %s up" % intf, "# ")
            time.sleep(5)
            macaddr = port.get_mac_addr()
            ipv6 = port.get_ipv6_addr()
            # Unconnected ports don't have IPv6
            if ipv6 is None:
                ipv6 = "Not connected"

            port_info['mac'] = macaddr
            port_info['intf'] = intf
            port_info['ipv6'] = ipv6

    def load_serializer_ports(self):
        cached_ports_info = self.serializer.load(self.PORT_INFO_CACHE_KEY)
        if cached_ports_info is None:
            return None

        self.ports_info = cached_ports_info

    def save_serializer_ports(self):
        cached_ports_info = []
        for port in self.ports_info:
            port_info = {}
            for key in port.keys():
                if type(port[key]) is str:
                    port_info[key] = port[key]
            cached_ports_info.append(port_info)
        self.serializer.save(self.PORT_INFO_CACHE_KEY, cached_ports_info)

    def scan_ports(self):
        """
        Scan ports information or just read it from cache file.
        """
        if self.read_cache:
            self.load_serializer_ports()
            self.scan_ports_cached()

        if not self.read_cache or self.ports_info is None:
            self.scan_ports_uncached()

    def scan_ports_cached(self):
        """
        Scan cached ports, instantiate tester port
        """
        scan_ports_cached = getattr(
            self, 'scan_ports_cached_%s' % self.get_os_type())
        return scan_ports_cached()

    def scan_ports_cached_linux(self):
        """
        Scan Linux ports and instantiate tester port
        """
        if self.ports_info is None:
            return

        for port_info in self.ports_info:
            addr_array = port_info['pci'].split(':')
            domain_id = addr_array[0]
            bus_id = addr_array[1]
            devfun_id = addr_array[2]

            port = GetNicObj(self, domain_id, bus_id, devfun_id)
            port_info['port'] = port

            self.logger.info(
                "DUT cached: [%s %s] %s" %
                (port_info['pci'], port_info['type'], port_info['intf']))

    def scan_ports_uncached(self):
        """
        Scan ports and collect port's pci id, mac adress, ipv6 address.
        """
        scan_ports_uncached = getattr(
            self, 'scan_ports_uncached_%s' % self.get_os_type())
        return scan_ports_uncached()

    def scan_ports_uncached_linux(self):
        """
        Scan Linux ports and collect port's pci id, mac adress, ipv6 address.
        """
        self.ports_info = []

        skipped = RED('Skipped: Unknown/not selected')
        unknow_interface = RED('Skipped: unknow_interface')

        for (pci_bus, pci_id) in self.pci_devices_info:
            if self.check_ports_available(pci_bus, pci_id) is False:
                self.logger.info("DUT: [%s %s] %s" %
                                 (pci_bus, pci_id, skipped))
                continue

            addr_array = pci_bus.split(':')
            domain_id = addr_array[0]
            bus_id = addr_array[1]
            devfun_id = addr_array[2]

            port = GetNicObj(self, domain_id, bus_id, devfun_id)
            intf = port.get_interface_name()
            if "No such file" in intf:
                self.logger.info("DUT: [%s] %s" % (pci_bus, unknow_interface))
                continue

            macaddr = port.get_mac_addr()
            if "No such file" in intf:
                self.logger.info("DUT: [%s] %s" % (pci_bus, unknow_interface))
                continue

            numa = port.socket
            # store the port info to port mapping
            self.ports_info.append({
                'port': port,
                'pci': pci_bus,
                'type': pci_id,
                'numa': numa,
                'intf': intf,
                'mac': macaddr
            })

            if not port.get_interface2_name():
                continue

            intf = port.get_interface2_name()
            macaddr = port.get_intf2_mac_addr()
            numa = port.socket
            # store the port info to port mapping
            self.ports_info.append({
                'port': port,
                'pci': pci_bus,
                'type': pci_id,
                'numa': numa,
                'intf': intf,
                'mac': macaddr
            })

    def scan_ports_uncached_freebsd(self):
        """
        Scan Freebsd ports and collect port's pci id, mac adress, ipv6 address.
        """
        self.ports_info = []

        skipped = RED('Skipped: Unknown/not selected')

        for (pci_bus, pci_id) in self.pci_devices_info:

            if not settings.accepted_nic(pci_id):
                self.logger.info("DUT: [%s %s] %s" %
                                 (pci_bus, pci_id, skipped))
                continue
            addr_array = pci_bus.split(':')
            domain_id = addr_array[0]
            bus_id = addr_array[1]
            devfun_id = addr_array[2]
            port = GetNicObj(self, domain_id, bus_id, devfun_id)
            intf = port.get_interface_name()

            macaddr = port.get_mac_addr()
            ipv6 = port.get_ipv6_addr()

            if ipv6 is None:
                ipv6 = "Not available"

            self.logger.warning("NUMA not available on FreeBSD")

            self.logger.info("DUT: [%s %s] %s %s" %
                             (pci_bus, pci_id, intf, ipv6))

            # convert bsd format to linux format
            pci_split = pci_bus.split(':')
            pci_bus_id = hex(int(pci_split[0]))[2:]
            if len(pci_split[1]) == 1:
                pci_dev_str = "0" + pci_split[1]
            else:
                pci_dev_str = pci_split[1]

            pci_str = "%s:%s.%s" % (pci_bus_id, pci_dev_str, pci_split[2])

            # store the port info to port mapping
            self.ports_info.append({
                'port': port,
                'pci': pci_str,
                'type': pci_id,
                'intf': intf,
                'mac': macaddr,
                'ipv6': ipv6,
                'numa': -1
            })

    def generate_sriov_vfs_by_port(self, port_id, vf_num, driver='default'):
        """
        Generate SRIOV VFs with default driver it is bound now or specifid driver.
        """
        port = self.ports_info[port_id]['port']
        port_driver = port.get_nic_driver()

        if driver == 'default':
            if not port_driver:
                self.logger.info(
                    "No driver on specified port, can not generate SRIOV VF.")
                return None
        else:
            if port_driver != driver:
                port.bind_driver(driver)
        port.generate_sriov_vfs(vf_num)

        # append the VF PCIs into the ports_info
        sriov_vfs_pci = port.get_sriov_vfs_pci()
        self.ports_info[port_id]['sriov_vfs_pci'] = sriov_vfs_pci

        # instantiate the VF
        vfs_port = []
        for vf_pci in sriov_vfs_pci:
            addr_array = vf_pci.split(':')
            domain_id = addr_array[0]
            bus_id = addr_array[1]
            devfun_id = addr_array[2]
            vf_port = GetNicObj(self, domain_id, bus_id, devfun_id)
            vfs_port.append(vf_port)
        self.ports_info[port_id]['vfs_port'] = vfs_port

        pci = self.ports_info[port_id]['pci']
        self.virt_pool.add_vf_on_pf(pf_pci=pci, vflist=sriov_vfs_pci)

    def destroy_sriov_vfs_by_port(self, port_id):
        port = self.ports_info[port_id]['port']
        vflist = []
        port_driver = port.get_nic_driver()
        if 'sriov_vfs_pci' in self.ports_info[port_id] and \
           self.ports_info[port_id]['sriov_vfs_pci']:
            vflist = self.ports_info[port_id]['sriov_vfs_pci']
        else:
            if not port.get_sriov_vfs_pci():
                return

        if not port_driver:
            self.logger.info(
                "No driver on specified port, skip destroy SRIOV VF.")
        else:
            sriov_vfs_pci = port.destroy_sriov_vfs()
        self.ports_info[port_id]['sriov_vfs_pci'] = []
        self.ports_info[port_id]['vfs_port'] = []

        pci = self.ports_info[port_id]['pci']
        self.virt_pool.del_vf_on_pf(pf_pci=pci, vflist=vflist)

    def destroy_all_sriov_vfs(self):

        if self.ports_info == None:
            return
        for port_id in range(len(self.ports_info)):
            self.destroy_sriov_vfs_by_port(port_id)

    def get_vm_core_list(self):
        return VMCORELIST[self.crb['VM CoreList']]

    def load_portconf(self):
        """
        Load port configurations for ports_info. If manually configured infor
        not same as auto scanned, still use infor in configuration file.
        """
        for port in self.ports_info:
            pci_bus = port['pci']
            ports_cfg = self.conf.get_ports_config()
            if pci_bus in ports_cfg:
                port_cfg = ports_cfg[pci_bus]
                port_cfg['source'] = 'cfg'
            else:
                port_cfg = {}

            for key in ['intf', 'mac', 'peer', 'source']:
                if key in port_cfg:
                    if key in port and port_cfg[key].lower(
                    ) != port[key].lower():
                        self.logger.warning(
                            "CONFIGURED %s NOT SAME AS SCANNED!!!" %
                            (key.upper()))
                    port[key] = port_cfg[key].lower()
            if 'numa' in port_cfg:
                if port_cfg['numa'] != port['numa']:
                    self.logger.warning(
                        "CONFIGURED NUMA NOT SAME AS SCANNED!!!")
                port['numa'] = port_cfg['numa']

    def map_available_ports(self):
        """
        Load or generate network connection mapping list.
        """
        if self.read_cache:
            self.ports_map = self.serializer.load(self.PORT_MAP_CACHE_KEY)

        if not self.read_cache or self.ports_map is None:
            self.map_available_ports_uncached()
            self.serializer.save(self.PORT_MAP_CACHE_KEY, self.ports_map)

        self.logger.warning("DUT PORT MAP: " + str(self.ports_map))

    def map_available_ports_uncached(self):
        """
        Generate network connection mapping list.
        """
        nrPorts = len(self.ports_info)
        if nrPorts == 0:
            return

        remove = []
        self.ports_map = [-1] * nrPorts

        hits = [False] * len(self.tester.ports_info)

        for dutPort in range(nrPorts):
            peer = self.get_peer_pci(dutPort)
            dutpci = self.ports_info[dutPort]['pci']
            if peer is not None:
                for remotePort in range(len(self.tester.ports_info)):
                    if self.tester.ports_info[remotePort]['pci'].lower(
                    ) == peer.lower():
                        hits[remotePort] = True
                        self.ports_map[dutPort] = remotePort
                        break
                if self.ports_map[dutPort] == -1:
                    self.logger.error("CONFIGURED TESTER PORT CANNOT FOUND!!!")
                else:
                    continue  # skip ping6 map

            for remotePort in range(len(self.tester.ports_info)):
                if hits[remotePort]:
                    continue

                # skip ping self port
                remotepci = self.tester.ports_info[remotePort]['pci']
                if (self.crb['IP']
                        == self.crb['tester IP']) and (dutpci == remotepci):
                    continue

                # skip ping those not connected port
                ipv6 = self.get_ipv6_address(dutPort)
                if ipv6 == "Not connected":
                    if self.tester.ports_info[remotePort].has_key('ipv4'):
                        out = self.tester.send_ping(
                            dutPort,
                            self.tester.ports_info[remotePort]['ipv4'],
                            self.get_mac_address(dutPort))
                    else:
                        continue
                else:
                    if getattr(self, 'send_ping6', None):
                        out = self.send_ping6(
                            dutPort,
                            self.tester.ports_info[remotePort]['ipv6'],
                            self.get_mac_address(dutPort))
                    else:
                        out = self.tester.send_ping6(
                            remotePort, ipv6, self.get_mac_address(dutPort))

                if ('64 bytes from' in out):
                    self.logger.info("PORT MAP: [dut %d: tester %d]" %
                                     (dutPort, remotePort))
                    self.ports_map[dutPort] = remotePort
                    hits[remotePort] = True
                    if self.crb['IP'] == self.crb['tester IP']:
                        # remove dut port act as tester port
                        remove_port = self.get_port_info(remotepci)
                        if remove_port is not None:
                            remove.append(remove_port)
                        # skip ping from those port already act as dut port
                        testerPort = self.tester.get_local_index(dutpci)
                        if testerPort != -1:
                            hits[testerPort] = True
                    break

        for port in remove:
            self.ports_info.remove(port)

    def disable_tester_ipv6(self):
        for tester_port in self.ports_map:
            if self.tester.ports_info[tester_port]['type'] != 'ixia':
                port = self.tester.ports_info[tester_port]['port']
                port.disable_ipv6()

    def enable_tester_ipv6(self):
        for tester_port in range(len(self.tester.ports_info)):
            if self.tester.ports_info[tester_port]['type'] != 'ixia':
                port = self.tester.ports_info[tester_port]['port']
                port.enable_ipv6()

    def check_port_occupied(self, port):
        out = self.alt_session.send_expect('lsof -i:%d' % port, '# ')
        if out == '':
            return False
        else:
            return True

    def get_maximal_vnc_num(self):
        out = self.send_expect("ps aux | grep '\-vnc' | grep -v grep", '# ')
        if out:
            ports = re.findall(r'-vnc .*?:(\d+)', out)
            for num in range(len(ports)):
                ports[num] = int(ports[num])
                ports.sort()
        else:
            ports = [
                0,
            ]
        return ports[-1]

    def close(self):
        """
        Close ssh session of DUT.
        """
        if self.session:
            self.session.close()
            self.session = None
        if self.alt_session:
            self.alt_session.close()
            self.alt_session = None
        if self.host_init_flag:
            self.host_session.close()

    def virt_exit(self):
        """
        Stop all unstopped hypervisors process
        """
        # try to kill all hypervisor process
        for pid in self.virt_pids:
            self.send_expect("kill -s SIGTERM %d" % pid,
                             "# ",
                             alt_session=True)
            time.sleep(3)
        self.virt_pids = []

    def crb_exit(self):
        """
        Recover all resource before crb exit
        """
        self.logger.logger_exit()
        self.enable_tester_ipv6()
        self.close()
Ejemplo n.º 21
0
class Crb(object):
    """
    Basic module for customer reference board. This module implement functions
    interact with CRB. With these function, we can get the information of
    CPU/PCI/NIC on the board and setup running environment for DPDK.
    """
    def __init__(self, crb, serializer, name):
        self.crb = crb
        self.read_cache = False
        self.skip_setup = False
        self.serializer = serializer
        self.ports_info = None
        self.sessions = []
        self.stage = 'pre-init'
        self.name = name

        self.logger = getLogger(name)
        self.session = SSHConnection(self.get_ip_address(), name,
                                     self.get_username(), self.get_password())
        self.session.init_log(self.logger)
        self.alt_session = SSHConnection(self.get_ip_address(), name + '_alt',
                                         self.get_username(),
                                         self.get_password())
        self.alt_session.init_log(self.logger)

    def send_expect(self,
                    cmds,
                    expected,
                    timeout=TIMEOUT,
                    alt_session=False,
                    verify=False):
        """
        Send commands to crb and return string before expected string. If
        there's no expected string found before timeout, TimeoutException will
        be raised.
        """

        if alt_session:
            return self.alt_session.session.send_expect(
                cmds, expected, timeout, verify)

        return self.session.send_expect(cmds, expected, timeout, verify)

    def create_session(self, name=""):
        """
        Create new session for addtional useage. This session will not enable log.
        """
        logger = getLogger(name)
        session = SSHConnection(self.get_ip_address(), name,
                                self.get_username(), self.get_password())
        session.init_log(logger)
        self.sessions.append(session)
        return session

    def destroy_session(self, session=None):
        """
        Destroy addtional session.
        """
        for save_session in self.sessions:
            if save_session == session:
                save_session.close()
                logger = getLogger(save_session.name)
                logger.logger_exit()
                self.sessions.remove(save_session)
                break

    def reconnect_session(self, alt_session=False):
        """
        When session can't used anymore, recreate another one for replace
        """
        try:
            if alt_session:
                self.alt_session.close(force=True)
            else:
                self.session.close(force=True)
        except Exception as e:
            self.loggger.error("Session close failed for [%s]" % e)

        if alt_session:
            session = SSHConnection(self.get_ip_address(), self.name + '_alt',
                                    self.get_username(), self.get_password())
            self.alt_session = session
        else:
            session = SSHConnection(self.get_ip_address(), self.name,
                                    self.get_username(), self.get_password())
            self.session = session

        session.init_log(self.logger)

    def send_command(self, cmds, timeout=TIMEOUT, alt_session=False):
        """
        Send commands to crb and return string before timeout.
        """

        if alt_session:
            return self.alt_session.session.send_command(cmds, timeout)

        return self.session.send_command(cmds, timeout)

    def get_session_output(self, timeout=TIMEOUT):
        """
        Get session output message before timeout
        """
        return self.session.get_session_before(timeout)

    def set_test_types(self, func_tests, perf_tests):
        """
        Enable or disable function/performance test.
        """
        self.want_func_tests = func_tests
        self.want_perf_tests = perf_tests

    def get_total_huge_pages(self):
        """
        Get the huge page number of CRB.
        """
        huge_pages = self.send_expect(
            "awk '/HugePages_Total/ { print $2 }' /proc/meminfo",
            "# ",
            alt_session=True)
        if huge_pages != "":
            return int(huge_pages)
        return 0

    def mount_huge_pages(self):
        """
        Mount hugepage file system on CRB.
        """
        self.send_expect(
            "umount `awk '/hugetlbfs/ { print $2 }' /proc/mounts`", '# ')
        out = self.send_expect("awk '/hugetlbfs/ { print $2 }' /proc/mounts",
                               "# ")
        # only mount hugepage when no hugetlbfs mounted
        if not len(out):
            self.send_expect('mkdir -p /mnt/huge', '# ')
            self.send_expect('mount -t hugetlbfs nodev /mnt/huge', '# ')

    def strip_hugepage_path(self):
        mounts = self.send_expect("cat /proc/mounts |grep hugetlbfs", "# ")
        infos = mounts.split()
        if len(infos) >= 2:
            return infos[1]
        else:
            return ''

    def set_huge_pages(self, huge_pages, numa=-1):
        """
        Set numbers of huge pages
        """
        page_size = self.send_expect(
            "awk '/Hugepagesize/ {print $2}' /proc/meminfo", "# ")

        if numa == -1:
            self.send_expect(
                'echo %d > /sys/kernel/mm/hugepages/hugepages-%skB/nr_hugepages'
                % (huge_pages, page_size), '# ', 5)
        else:
            # sometimes we set hugepage on kernel cmdline, so we need clear default hugepage
            self.send_expect(
                'echo 0 > /sys/kernel/mm/hugepages/hugepages-%skB/nr_hugepages'
                % (page_size), '# ', 5)
            # some platform not support numa, example vm dut
            try:
                self.send_expect(
                    'echo %d > /sys/devices/system/node/node%d/hugepages/hugepages-%skB/nr_hugepages'
                    % (huge_pages, numa, page_size), '# ', 5)
            except:
                self.logger.warning("set %d hugepage on socket %d error" %
                                    (huge_pages, numa))
                self.send_expect(
                    'echo %d > /sys/kernel/mm/hugepages/hugepages-%skB/nr_hugepages'
                    % (huge_pages.page_size), '# ', 5)

    def set_speedup_options(self, read_cache, skip_setup):
        """
        Configure skip network topology scan or skip DPDK packet setup.
        """
        self.read_cache = read_cache
        self.skip_setup = skip_setup

    def set_directory(self, base_dir):
        """
        Set DPDK package folder name.
        """
        self.base_dir = base_dir

    def set_virttype(self, virttype):
        self.virttype = virttype

    def admin_ports(self, port, status):
        """
        Force set port's interface status.
        """
        admin_ports_freebsd = getattr(
            self, 'admin_ports_freebsd_%s' % self.get_os_type())
        return admin_ports_freebsd()

    def admin_ports_freebsd(self, port, status):
        """
        Force set remote interface link status in FreeBSD.
        """
        eth = self.ports_info[port]['intf']
        self.send_expect("ifconfig %s %s" % (eth, status),
                         "# ",
                         alt_session=True)

    def admin_ports_linux(self, eth, status):
        """
        Force set remote interface link status in Linux.
        """
        self.send_expect("ip link set  %s %s" % (eth, status),
                         "# ",
                         alt_session=True)

    def pci_devices_information(self):
        """
        Scan CRB pci device information and save it into cache file.
        """
        if self.read_cache:
            self.pci_devices_info = self.serializer.load(
                self.PCI_DEV_CACHE_KEY)

        if not self.read_cache or self.pci_devices_info is None:
            self.pci_devices_information_uncached()
            self.serializer.save(self.PCI_DEV_CACHE_KEY, self.pci_devices_info)

    def pci_devices_information_uncached(self):
        """
        Scan CRB NIC's information on different OS.
        """
        pci_devices_information_uncached = getattr(
            self, 'pci_devices_information_uncached_%s' % self.get_os_type())
        return pci_devices_information_uncached()

    def pci_devices_information_uncached_linux(self):
        """
        Look for the NIC's information (PCI Id and card type).
        """
        out = self.send_expect("lspci -Dnn | grep -i eth",
                               "# ",
                               alt_session=True)
        rexp = r"([\da-f]{4}:[\da-f]{2}:[\da-f]{2}.\d{1}) .*Eth.*?ernet .*?([\da-f]{4}:[\da-f]{4})"
        pattern = re.compile(rexp)
        match = pattern.findall(out)
        self.pci_devices_info = []
        for i in range(len(match)):
            #check if device is cavium and check its linkspeed, append only if it is 10G
            if "177d:" in match[i][1]:
                linkspeed = "10000"
                nic_linkspeed = self.send_command(
                    "cat /sys/bus/pci/devices/%s/net/*/speed" % match[i][0])
                if nic_linkspeed == linkspeed:
                    self.pci_devices_info.append((match[i][0], match[i][1]))
            else:
                self.pci_devices_info.append((match[i][0], match[i][1]))

    def pci_devices_information_uncached_freebsd(self):
        """
        Look for the NIC's information (PCI Id and card type).
        """
        out = self.send_expect("pciconf -l", "# ", alt_session=True)
        rexp = r"pci0:([\da-f]{1,3}:[\da-f]{1,2}:\d{1}):\s*class=0x020000.*chip=0x([\da-f]{4})8086"
        pattern = re.compile(rexp)
        match = pattern.findall(out)

        self.pci_devices_info = []
        for i in range(len(match)):
            card_type = "8086:%s" % match[i][1]
            self.pci_devices_info.append((match[i][0], card_type))

    def get_pci_dev_driver(self, domain_id, bus_id, devfun_id):
        """
        Get the driver of specified pci device.
        """
        get_pci_dev_driver = getattr(
            self, 'get_pci_dev_driver_%s' % self.get_os_type())
        return get_pci_dev_driver(domain_id, bus_id, devfun_id)

    def get_pci_dev_driver_linux(self, domain_id, bus_id, devfun_id):
        """
        Get the driver of specified pci device on linux.
        """
        out = self.send_expect("cat /sys/bus/pci/devices/%s\:%s\:%s/uevent" %
                               (domain_id, bus_id, devfun_id),
                               "# ",
                               alt_session=True)
        rexp = r"DRIVER=(.+?)\r"
        pattern = re.compile(rexp)
        match = pattern.search(out)
        if not match:
            return None
        return match.group(1)

    def get_pci_dev_driver_freebsd(self, domain_id, bus_id, devfun_id):
        """
        Get the driver of specified pci device.
        """
        return True

    def get_pci_dev_id(self, domain_id, bus_id, devfun_id):
        """
        Get the pci id of specified pci device.
        """
        get_pci_dev_id = getattr(self,
                                 'get_pci_dev_id_%s' % self.get_os_type())
        return get_pci_dev_id(domain_id, bus_id, devfun_id)

    def get_pci_dev_id_linux(self, domain_id, bus_id, devfun_id):
        """
        Get the pci id of specified pci device on linux.
        """
        out = self.send_expect("cat /sys/bus/pci/devices/%s\:%s\:%s/uevent" %
                               (domain_id, bus_id, devfun_id),
                               "# ",
                               alt_session=True)
        rexp = r"PCI_ID=(.+)"
        pattern = re.compile(rexp)
        match = re.search(out)
        if not match:
            return None
        return match.group(1)

    def get_device_numa(self, domain_id, bus_id, devfun_id):
        """
        Get numa number of specified pci device.
        """
        get_device_numa = getattr(self,
                                  "get_device_numa_%s" % self.get_os_type())
        return get_device_numa(domain_id, bus_id, devfun_id)

    def get_device_numa_linux(self, domain_id, bus_id, devfun_id):
        """
        Get numa number of specified pci device on Linux.
        """
        numa = self.send_expect(
            "cat /sys/bus/pci/devices/%s\:%s\:%s/numa_node" %
            (domain_id, bus_id, devfun_id),
            "# ",
            alt_session=True)

        try:
            numa = int(numa)
        except ValueError:
            numa = -1
            self.logger.warning("NUMA not available")
        return numa

    def get_ipv6_addr(self, intf):
        """
        Get ipv6 address of specified pci device.
        """
        get_ipv6_addr = getattr(self, 'get_ipv6_addr_%s' % self.get_os_type())
        return get_ipv6_addr(intf)

    def get_ipv6_addr_linux(self, intf):
        """
        Get ipv6 address of specified pci device on linux.
        """
        out = self.send_expect(
            "ip -family inet6 address show dev %s | awk '/inet6/ { print $2 }'"
            % intf,
            "# ",
            alt_session=True)
        return out.split('/')[0]

    def get_ipv6_addr_freebsd(self, intf):
        """
        Get ipv6 address of specified pci device on Freebsd.
        """
        out = self.send_expect('ifconfig %s' % intf, '# ', alt_session=True)
        rexp = r"inet6 ([\da-f:]*)%"
        pattern = re.compile(rexp)
        match = pattern.findall(out)
        if len(match) == 0:
            return None

        return match[0]

    def disable_ipv6(self, intf):
        """
        Disable ipv6 of of specified interface
        """
        if intf != 'N/A':
            self.send_expect("sysctl net.ipv6.conf.%s.disable_ipv6=1" % intf,
                             "# ",
                             alt_session=True)

    def enable_ipv6(self, intf):
        """
        Enable ipv6 of of specified interface
        """
        if intf != 'N/A':
            self.send_expect("sysctl net.ipv6.conf.%s.disable_ipv6=0" % intf,
                             "# ",
                             alt_session=True)

            out = self.send_expect("ifconfig %s" % intf,
                                   "# ",
                                   alt_session=True)
            if "inet6" not in out:
                self.send_expect("ifconfig %s down" % intf,
                                 "# ",
                                 alt_session=True)
                self.send_expect("ifconfig %s up" % intf,
                                 "# ",
                                 alt_session=True)

    def create_file(self, contents, fileName):
        """
        Create file with contents and copy it to CRB.
        """
        with open(fileName, "w") as f:
            f.write(contents)
        self.session.copy_file_to(fileName, password=self.get_password())

    def kill_all(self, alt_session=True):
        """
        Kill all dpdk applications on CRB.
        """
        pids = []
        pid_reg = r'p(\d+)'
        cmd = 'lsof -Fp /var/run/.rte_config'
        out = self.send_expect(cmd, "# ", 20, alt_session)
        if len(out):
            lines = out.split('\r\n')
            for line in lines:
                m = re.match(pid_reg, line)
                if m:
                    pids.append(m.group(1))
        for pid in pids:
            self.send_expect('kill -9 %s' % pid, '# ', 20, alt_session)
            self.get_session_output(timeout=2)

        cmd = 'lsof -Fp /var/run/.rte_hugepage_info'
        out = self.send_expect(cmd, "# ", 20, alt_session)
        if len(out) and "No such file or directory" not in out:
            self.logger.warning(
                "There are some dpdk process not free hugepage")
            self.logger.warning("**************************************")
            self.logger.warning(out)
            self.logger.warning("**************************************")

    def close(self):
        """
        Close ssh session of CRB.
        """
        self.session.close()
        self.alt_session.close()

    def get_os_type(self):
        """
        Get OS type from execution configuration file.
        """
        from dut import Dut
        if isinstance(self, Dut) and 'OS' in self.crb:
            return str(self.crb['OS']).lower()

        return 'linux'

    def check_os_type(self):
        """
        Check real OS type whether match configured type.
        """
        from dut import Dut
        expected = 'Linux.*#'
        if isinstance(self, Dut) and self.get_os_type() == 'freebsd':
            expected = 'FreeBSD.*#'

        self.send_expect('uname', expected, 2, alt_session=True)

    def init_core_list(self):
        """
        Load or create core information of CRB.
        """
        if self.read_cache:
            self.number_of_cores = self.serializer.load(
                self.NUMBER_CORES_CACHE_KEY)
            self.cores = self.serializer.load(self.CORE_LIST_CACHE_KEY)

        if not self.read_cache or self.cores is None or self.number_of_cores is None:
            self.init_core_list_uncached()
            self.serializer.save(self.NUMBER_CORES_CACHE_KEY,
                                 self.number_of_cores)
            self.serializer.save(self.CORE_LIST_CACHE_KEY, self.cores)

    def init_core_list_uncached(self):
        """
        Scan cores on CRB and create core information list.
        """
        init_core_list_uncached = getattr(
            self, 'init_core_list_uncached_%s' % self.get_os_type())
        init_core_list_uncached()

    def init_core_list_uncached_freebsd(self):
        """
        Scan cores in Freebsd and create core information list.
        """
        self.cores = []

        import xml.etree.ElementTree as ET

        out = self.send_expect("sysctl -n kern.sched.topology_spec", "# ")

        cpu_xml = ET.fromstring(out)

        # WARNING: HARDCODED VALUES FOR CROWN PASS IVB
        thread = 0
        socket_id = 0

        sockets = cpu_xml.findall(".//group[@level='2']")
        for socket in sockets:
            core_id = 0
            core_elements = socket.findall(".//children/group/cpu")
            for core in core_elements:
                threads = [int(x) for x in core.text.split(",")]
                for thread in threads:
                    if thread != 0:
                        self.cores.append({
                            'socket': socket_id,
                            'core': core_id,
                            'thread': thread
                        })
                core_id += 1
            socket_id += 1
        self.number_of_cores = len(self.cores)

    def init_core_list_uncached_linux(self):
        """
        Scan cores in linux and create core information list.
        """
        self.cores = []

        cpuinfo = \
            self.send_expect(
                "lscpu -p|grep -v \#",
                "#", alt_session=True)

        cpuinfo = cpuinfo.split()
        # haswell cpu on cottonwood core id not correct
        # need addtional coremap for haswell cpu
        core_id = 0
        coremap = {}
        for line in cpuinfo:
            (thread, core, socket, unused) = line.split(',')[0:4]

            if core not in coremap.keys():
                coremap[core] = core_id
                core_id += 1

            if self.crb['bypass core0'] and core == '0' and socket == '0':
                self.logger.info("Core0 bypassed")
                continue
            self.cores.append({
                'thread': thread,
                'socket': socket,
                'core': coremap[core]
            })

        self.number_of_cores = len(self.cores)

    def get_all_cores(self):
        """
        Return core information list.
        """
        return self.cores

    def remove_hyper_core(self, core_list, key=None):
        """
        Remove hyperthread locre for core list.
        """
        found = set()
        for core in core_list:
            val = core if key is None else key(core)
            if val not in found:
                yield core
                found.add(val)

    def init_reserved_core(self):
        """
        Remove hyperthread cores from reserved list.
        """
        partial_cores = self.cores
        # remove hyper-threading core
        self.reserved_cores = list(
            self.remove_hyper_core(partial_cores,
                                   key=lambda d: (d['core'], d['socket'])))

    def remove_reserved_cores(self, core_list, args):
        """
        Remove cores from reserved cores.
        """
        indexes = sorted(args, reverse=True)
        for index in indexes:
            del core_list[index]
        return core_list

    def get_reserved_core(self, config, socket):
        """
        Get reserved cores by core config and socket id.
        """
        m = re.match("([1-9]+)C", config)
        nr_cores = int(m.group(1))
        if m is None:
            return []

        partial_cores = [
            n for n in self.reserved_cores if int(n['socket']) == socket
        ]
        if len(partial_cores) < nr_cores:
            return []

        thread_list = [
            self.reserved_cores[n]['thread'] for n in range(nr_cores)
        ]

        # remove used core from reserved_cores
        rsv_list = [n for n in range(nr_cores)]
        self.reserved_cores = self.remove_reserved_cores(
            partial_cores, rsv_list)

        # return thread list
        return map(str, thread_list)

    def get_core_list(self, config, socket=-1):
        """
        Get lcore array according to the core config like "all", "1S/1C/1T".
        We can specify the physical CPU socket by paramter "socket".
        """
        if config == 'all':
            cores = []
            if socket != -1:
                for core in self.cores:
                    if int(core['socket']) == socket:
                        cores.append(core['thread'])
            else:
                cores = [core['thread'] for core in self.cores]
            return cores

        m = re.match("([1234])S/([0-9]+)C/([12])T", config)

        if m:
            nr_sockets = int(m.group(1))
            nr_cores = int(m.group(2))
            nr_threads = int(m.group(3))

            partial_cores = self.cores

            # If not specify socket sockList will be [0,1] in numa system
            # If specify socket will just use the socket
            if socket < 0:
                sockList = set([int(core['socket']) for core in partial_cores])
            else:
                for n in partial_cores:
                    if (int(n['socket']) == socket):
                        sockList = [int(n['socket'])]

            sockList = list(sockList)[:nr_sockets]
            partial_cores = [
                n for n in partial_cores if int(n['socket']) in sockList
            ]
            core_list = set([int(n['core']) for n in partial_cores])
            core_list = list(core_list)
            thread_list = set([int(n['thread']) for n in partial_cores])
            thread_list = list(thread_list)

            # filter usable core to core_list
            temp = []
            for sock in sockList:
                core_list = set([
                    int(n['core']) for n in partial_cores
                    if int(n['socket']) == sock
                ])
                core_list = list(core_list)[:nr_cores]
                temp.extend(core_list)

            core_list = temp

            # if system core less than request just use all cores in in socket
            if len(core_list) < (nr_cores * nr_sockets):
                partial_cores = self.cores
                sockList = set([int(n['socket']) for n in partial_cores])

                sockList = list(sockList)[:nr_sockets]
                partial_cores = [
                    n for n in partial_cores if int(n['socket']) in sockList
                ]

                temp = []
                for sock in sockList:
                    core_list = list([
                        int(n['thread']) for n in partial_cores
                        if int(n['socket']) == sock
                    ])
                    core_list = core_list[:nr_cores]
                    temp.extend(core_list)

                core_list = temp

            partial_cores = [
                n for n in partial_cores if int(n['core']) in core_list
            ]
            temp = []
            if len(core_list) < nr_cores:
                return []
            if len(sockList) < nr_sockets:
                return []
            # recheck the core_list and create the thread_list
            i = 0
            for sock in sockList:
                coreList_aux = [
                    int(core_list[n])
                    for n in range((nr_cores * i), (nr_cores * i + nr_cores))
                ]
                for core in coreList_aux:
                    thread_list = list([
                        int(n['thread']) for n in partial_cores
                        if ((int(n['core']) == core) and (
                            int(n['socket']) == sock))
                    ])
                    thread_list = thread_list[:nr_threads]
                    temp.extend(thread_list)
                    thread_list = temp
                i += 1
            return map(str, thread_list)

    def get_lcore_id(self, config):
        """
        Get lcore id of specified core by config "C{socket.core.thread}"
        """

        m = re.match("C{([01]).(\d).([01])}", config)

        if m:
            sockid = m.group(1)
            coreid = int(m.group(2))
            threadid = int(m.group(3))

            perSocklCs = [_ for _ in self.cores if _['socket'] == sockid]
            coreNum = perSocklCs[coreid]['core']

            perCorelCs = [_ for _ in perSocklCs if _['core'] == coreNum]

            return perCorelCs[threadid]['thread']

    def get_port_info(self, pci):
        """
        return port info by pci id
        """
        for port_info in self.ports_info:
            if port_info['pci'] == pci:
                return port_info

    def get_port_pci(self, port_id):
        """
        return port pci address by port index
        """
        return self.ports_info[port_id]['pci']

    def enable_promisc(self, intf):
        if intf != 'N/A':
            self.send_expect("ifconfig %s promisc" % intf,
                             "# ",
                             alt_session=True)
Ejemplo n.º 22
0
class Tester(Crb):

    """
    Start the DPDK traffic generator on the machine `target`.
    A config file and pcap file must have previously been copied
    to this machine.
    """
    PORT_INFO_CACHE_KEY = 'tester_port_info'
    CORE_LIST_CACHE_KEY = 'tester_core_list'
    NUMBER_CORES_CACHE_KEY = 'tester_number_cores'
    PCI_DEV_CACHE_KEY = 'tester_pci_dev_info'

    def __init__(self, crb, serializer):
        super(Tester, self).__init__(crb, serializer)
        self.NAME = 'tester'

        self.logger = getLogger(self.NAME)
        self.session = SSHConnection(self.get_ip_address(),
                                     self.NAME, self.get_password())
        self.session.init_log(self.logger)
        self.alt_session = SSHConnection(self.get_ip_address(),
                                         self.NAME + '_alt', self.get_password())
        self.alt_session.init_log(self.logger)

        self.bgProcIsRunning = False
        self.dut = None
        self.inBg = 0
        self.scapyCmds = []
        self.bgCmds = []
        self.bgItf = ''

    def init_ext_gen(self):
        """
        Initialize tester packet generator object.
        """
        if self.it_uses_external_generator():
            self.ixia_packet_gen = IxiaPacketGenerator(self)
        self.packet_gen = SoftwarePacketGenerator(self)

    def get_ip_address(self):
        """
        Get ip address of tester CRB.
        """
        return self.crb['tester IP']

    def get_password(self):
        """
        Get tester login password of tester CRB.
        """
        return self.crb['tester pass']

    def has_external_traffic_generator(self):
        """
        Check whether performance test will base on IXIA equipment.
        """
        try:
            if self.crb[IXIA] is not None:
                return True
        except Exception as e:
            return False

        return False

    def get_external_traffic_generator(self):
        """
        Return IXIA object.
        """
        return self.crb[IXIA]

    def it_uses_external_generator(self):
        """
        Check whether IXIA generator is ready for performance test.
        """
        return self.want_perf_tests and self.has_external_traffic_generator()

    def tester_prerequisites(self):
        """
        Prerequest function should be called before execute any test case.
        Will call function to scan all lcore's information which on Tester.
        Then call pci scan function to collect nic device information.
        Then discovery the network topology and save it into cache file.
        At last setup DUT' environment for validation.
        """
        self.init_core_list()
        self.pci_devices_information()
        self.restore_interfaces()
        self.scan_ports()

    def get_local_port(self, remotePort):
        """
        Return tester local port connect to specified dut port.
        """
        return self.dut.ports_map[remotePort]

    def get_local_port_type(self, remotePort):
        """
        Return tester local port type connect to specified dut port.
        """
        return self.ports_info[self.get_local_port(remotePort)]['type']

    def get_local_index(self, pci):
        """
        Return tester local port index by pci id
        """
        index = -1
        for port in self.ports_info:
            index += 1
            if pci == port['pci']:
                return index

    def get_pci(self, localPort):
        """
        Return tester local port pci id.
        """
        return self.ports_info[localPort]['pci']

    def get_interface(self, localPort):
        """
        Return tester local port interface name.
        """
        return self.ports_info[localPort]['intf']

    def get_mac(self, localPort):
        """
        Return tester local port mac address.
        """
        if self.ports_info[localPort]['type'] == 'ixia':
            return "00:00:00:00:00:01"
        else:
            return self.ports_info[localPort]['mac']

    def get_port_status(self, port):
        """
        Return link status of ethernet.
        """
        eth = self.ports_info[port]['intf']
        out = self.send_expect("ethtool %s" % eth, "# ")

        status = re.search(r"Link detected:\s+(yes|no)", out)
        if not status:
            self.logger.error("ERROR: unexpected output")

        if status.group(1) == 'yes':
            return 'up'
        else:
            return 'down'

    def restore_interfaces(self):
        """
        Restore Linux interfaces.
        """
        self.send_expect("modprobe igb", "# ", 20)
        self.send_expect("modprobe ixgbe", "# ", 20)
        self.send_expect("modprobe e1000e", "# ", 20)
        self.send_expect("modprobe e1000", "# ", 20)

        try:
            for (pci_bus, pci_id) in self.pci_devices_info:
                addr_array = pci_bus.split(':')
                itf = self.get_interface_name(addr_array[0], addr_array[1])
                self.send_expect("ifconfig %s up" % itf, "# ")

        except Exception as e:
            self.logger.error("   !!! Restore ITF: " + e.message)

    def scan_ports(self):
        """
        Scan all ports on tester and save port's pci/mac/interface.
        """
        if self.read_cache:
            self.ports_info = self.serializer.load(self.PORT_INFO_CACHE_KEY)

        if not self.read_cache or self.ports_info is None:
            self.scan_ports_uncached()
            if self.it_uses_external_generator():
                self.ports_info.extend(self.ixia_packet_gen.get_ports())
            self.serializer.save(self.PORT_INFO_CACHE_KEY, self.ports_info)

        self.logger.info(self.ports_info)

    def scan_ports_uncached(self):
        """
        Return tester port pci/mac/interface information.
        """
        self.ports_info = []

        for (pci_bus, pci_id) in self.pci_devices_info:
            # ignore unknown card types
            if pci_id not in NICS.values():
                self.logger.info("Tester: [000:%s %s] %s" % (pci_bus, pci_id,
                                                             "unknow_nic"))
                continue

            addr_array = pci_bus.split(':')
            bus_id = addr_array[0]
            devfun_id = addr_array[1]

            intf = self.get_interface_name(bus_id, devfun_id)

            if "No such file" in intf:
                self.logger.info("Tester: [000:%s %s] %s" % (pci_bus, pci_id,
                                                             "unknow_interface"))
                continue

            self.logger.info("Tester: [000:%s %s] %s" % (pci_bus, pci_id, intf))
            macaddr = self.get_mac_addr(intf, bus_id, devfun_id)

            # store the port info to port mapping
            self.ports_info.append({'pci': pci_bus,
                                    'type': pci_id,
                                    'intf': intf,
                                    'mac': macaddr})

    def send_ping6(self, localPort, ipv6, mac):
        """
        Send ping6 packet from local port with destination ipv6 address.
        """
        if self.ports_info[localPort]['type'] == 'ixia':
            return self.ixia_packet_gen.send_ping6(self.ports_info[localPort]['pci'], mac, ipv6)
        else:
            return self.send_expect("ping6 -w 5 -c 5 -A -I %s %s" % (self.ports_info[localPort]['intf'], ipv6), "# ", 10)

    def get_port_numa(self, port):
        """
        Return tester local port numa.
        """
        pci = self.ports_info[port]['pci']
        out = self.send_expect("cat /sys/bus/pci/devices/0000:%s/numa_node" % pci, "#")
        return int(out)

    def check_port_list(self, portList, ftype='normal'):
        """
        Check specified port is IXIA port or normal port.
        """
        dtype = None
        plist = set()
        for txPort, rxPort, _ in portList:
            plist.add(txPort)
            plist.add(rxPort)

        plist = list(plist)
        if len(plist) > 0:
            dtype = self.ports_info[plist[0]]['type']

        for port in plist[1:]:
            if dtype != self.ports_info[port]['type']:
                return False

        if ftype == 'ixia' and dtype != ftype:
            return False

        return True

    def scapy_append(self, cmd):
        """
        Append command into scapy command list.
        """
        self.scapyCmds.append(cmd)

    def scapy_execute(self, timeout=60):
        """
        Execute scapy command list.
        """
        self.kill_all()

        self.send_expect("scapy", ">>> ")
        if self.bgProcIsRunning:
            self.send_expect('subprocess.call("scapy -c sniff.py &", shell=True)', ">>> ")
            self.bgProcIsRunning = False
        sleep(2)

        for cmd in self.scapyCmds:
            self.send_expect(cmd, ">>> ", timeout)

        sleep(2)
        self.scapyCmds = []
        self.send_expect("exit()", "# ")

    def scapy_background(self):
        """
        Configure scapy running in backgroud mode which mainly purpose is
        that save RESULT into scapyResult.txt.
        """
        self.inBg = True

    def scapy_foreground(self):
        """
        Running backgroup scapy and convert to foregroup mode.
        """
        self.send_expect("echo -n '' >  scapyResult.txt", "# ")
        if self.inBg:
            self.scapyCmds.append('f = open(\'scapyResult.txt\',\'w\')')
            self.scapyCmds.append('f.write(RESULT)')
            self.scapyCmds.append('f.close()')
            self.scapyCmds.append('exit()')

            outContents = "import os\n" + \
                'conf.color_theme=NoTheme()\n' + 'RESULT=""\n' + \
                "\n".join(self.scapyCmds) + "\n"
            self.create_file(outContents, 'sniff.py')

            self.logger.info('SCAPY Receive setup:\n' + outContents)

            self.bgProcIsRunning = True
            self.scapyCmds = []
        self.inBg = False

    def scapy_get_result(self):
        """
        Return RESULT which saved in scapyResult.txt.
        """
        out = self.send_expect("cat scapyResult.txt", "# ")
        self.logger.info('SCAPY Result:\n' + out + '\n\n\n')

        return out.rpartition('[')[0]

    def traffic_generator_throughput(self, portList, rate_percent=100, delay=5):
        """
        Run throughput performance test on specified ports.
        """
        if self.check_port_list(portList, 'ixia'):
            return self.ixia_packet_gen.throughput(portList, rate_percent, delay)
        if not self.check_port_list(portList):
            self.logger.warning("exception by mixed port types")
            return None
        return self.packet_gen.throughput(portList, rate_percent)

    def traffic_generator_loss(self, portList, ratePercent):
        """
        Run loss performance test on specified ports.
        """
        if self.check_port_list(portList, 'ixia'):
            return self.ixia_packet_gen.loss(portList, ratePercent)
        elif not self.check_port_list(portList):
            self.logger.warning("exception by mixed port types")
            return None
        return self.packet_gen.loss(portList, ratePercent)

    def traffic_generator_latency(self, portList, ratePercent=100, delay=5):
        """
        Run latency performance test on specified ports.
        """
        if self.check_port_list(portList, 'ixia'):
            return self.ixia_packet_gen.latency(portList, ratePercent, delay)
        else:
            return None

    def extend_external_packet_generator(self, clazz, instance):
        """
        Update packet generator function, will implement later.
        """
        if self.it_uses_external_generator():
            self.ixia_packet_gen.__class__ = clazz
            current_attrs = instance.__dict__
            instance.__dict__ = self.ixia_packet_gen.__dict__
            instance.__dict__.update(current_attrs)

    def kill_all(self, killall=False):
        """
        Kill all scapy process or DPDK application on tester.
        """
        if not self.has_external_traffic_generator():
            self.alt_session.send_expect('killall scapy 2>/dev/null; echo tester', '# ', 5)
        if killall:
            super(Tester, self).kill_all()

    def close(self):
        """
        Close ssh session and IXIA tcl session.
        """
        super(Tester, self).close()
        if self.it_uses_external_generator():
            self.ixia_packet_gen.close()
Ejemplo n.º 23
0
from ssh_connection import SSHConnection

with SSHConnection("192.168.56.101", "root", "welcome") as conn:
    conn.put("a.py", "/tmp/a.py")
    conn.chmod("/tmp/a.py", 0o755)
    stdin, stdout, stderr = conn.exec_command("/tmp/a.py")
    print(str(stdout.read(), "utf8"))
    conn.get("/etc/passwd", "localfile.txt")
Ejemplo n.º 24
0
class Dut(Crb):
    """
    A connection to the CRB under test.
    This class sends commands to the CRB and validates the responses. It is
    implemented using either ssh for linuxapp or the terminal server for
    baremetal.
    All operations are in fact delegated to an instance of either CRBLinuxApp
    or CRBBareMetal.
    """

    PORT_MAP_CACHE_KEY = 'dut_port_map'
    PORT_INFO_CACHE_KEY = 'dut_port_info'
    NUMBER_CORES_CACHE_KEY = 'dut_number_cores'
    CORE_LIST_CACHE_KEY = 'dut_core_list'
    PCI_DEV_CACHE_KEY = 'dut_pci_dev_info'

    def __init__(self, crb, serializer):
        super(Dut, self).__init__(crb, serializer)
        self.NAME = 'dut'
        self.logger = getLogger(self.NAME)
        self.session = SSHConnection(self.get_ip_address(), self.NAME,
                                     self.get_password())
        self.session.init_log(self.logger)
        self.alt_session = SSHConnection(self.get_ip_address(),
                                         self.NAME + '_alt',
                                         self.get_password())
        self.alt_session.init_log(self.logger)
        self.number_of_cores = 0
        self.tester = None
        self.cores = []
        self.architecture = None
        self.ports_info = None
        self.conf = UserConf()
        self.ports_map = []

    def change_config_option(self, target, parameter, value):
        """
        This function change option in the config file
        """
        self.send_expect(
            "sed -i 's/%s=.*$/%s=%s/'  config/defconfig_%s" %
            (parameter, parameter, value, target), "# ")

    def set_nic_type(self, nic):
        """
        Set CRB NICS ready to validated.
        """
        self.nic = nic
        if 'cfg' in nic:
            self.conf.load_ports_config(self.get_ip_address())

    def set_toolchain(self, target):
        """
        This looks at the current target and instantiates an attribute to
        be either a CRBLinuxApp or CRBBareMetal object. These latter two
        classes are private and should not be used directly by client code.
        """
        self.kill_all()
        self.target = target
        [arch, _, _, toolchain] = target.split('-')

        if toolchain == "icc":
            icc_vars = os.getenv('ICC_VARS',
                                 "/opt/intel/composer_xe_2013/bin/")
            icc_vars += "compilervars.sh"

            if arch == "x86_64":
                icc_arch = "intel64"
            elif arch == "i686":
                icc_arch = "ia32"
            self.send_expect("source " + icc_vars + " " + icc_arch, "# ")

        self.architecture = arch

    def mount_procfs(self):
        """
        Mount proc file system.
        """
        mount_procfs = getattr(self, 'mount_procfs_%s' % self.get_os_type())
        mount_procfs()

    def mount_procfs_linux(self):
        pass

    def mount_procfs_freebsd(self):
        """
        Mount proc file system in Freebsd.
        """
        self.send_expect('mount -t procfs proc /proc', '# ')

    def get_ip_address(self):
        """
        Get DUT's ip address.
        """
        return self.crb['IP']

    def get_password(self):
        """
        Get DUT's login password.
        """
        return self.crb['pass']

    def dut_prerequisites(self):
        """
        Prerequest function should be called before execute any test case.
        Will call function to scan all lcore's information which on DUT.
        Then call pci scan function to collect nic device information.
        At last setup DUT' environment for validation.
        """
        self.send_expect("cd %s" % self.base_dir, "# ")
        self.send_expect("alias ls='ls --color=none'", "#")

        if self.get_os_type() == 'freebsd':
            self.send_expect('alias make=gmake', '# ')
            self.send_expect('alias sed=gsed', '# ')

        self.init_core_list()
        self.pci_devices_information()
        # scan ports before restore interface
        self.scan_ports()
        # restore dut ports to kernel
        self.restore_interfaces()
        # rescan ports after interface up
        self.rescan_ports()
        # load port infor from config file
        self.load_portconf()
        self.mount_procfs()
        # auto detect network topology
        self.map_available_ports()
        #print latest ports_info
        print self.ports_info  # raslan
        self.logger.info(dts.pprint(self.ports_info))
        if self.ports_map is None or len(self.ports_map) == 0:
            raise ValueError(
                "ports_map should not be empty, please check all links")

    def restore_interfaces(self):
        """
        Restore all ports's interfaces.
        """
        restore_interfaces = getattr(
            self, 'restore_interfaces_%s' % self.get_os_type())
        return restore_interfaces()

    def restore_interfaces_freebsd(self):
        """
        Restore FreeBSD interfaces.
        """
        self.send_expect("kldunload nic_uio.ko", "#")
        self.send_expect("kldunload contigmem.ko", "#")
        self.send_expect("kldload if_ixgbe.ko", "#", 20)

    def restore_interfaces_linux(self):
        """
        Restore Linux interfaces.
        """
        for port in self.ports_info:
            pci_bus = port['pci']
            pci_id = port['type']
            # get device driver
            driver = dts.get_nic_driver(pci_id)
            if driver is not None:
                # unbind device driver
                addr_array = pci_bus.split(':')
                bus_id = addr_array[0]
                devfun_id = addr_array[1]
                #print addr_array
                #self.send_expect('echo 0000:%s > /sys/bus/pci/devices/0000\:%s\:%s/driver/unbind'
                #                 % (pci_bus, bus_id, devfun_id), '# ')
                # bind to linux kernel driver
                #self.send_expect('modprobe %s' % driver, '# ')
                #self.send_expect('echo 0000:%s > /sys/bus/pci/drivers/%s/bind'
                #                 % (pci_bus, driver), '# ')

                itf = self.get_interface_name(addr_array[0], addr_array[1])
                self.send_expect("ifconfig %s up" % itf, "# ")
            else:
                self.logger.info("NOT FOUND DRIVER FOR PORT (%s|%s)!!!" %
                                 (pci_bus, pci_id))

    def setup_memory(self, hugepages=-1):
        """
        Setup hugepage on DUT.
        """
        try:
            function_name = 'setup_memory_%s' % self.get_os_type()
            setup_memory = getattr(self, function_name)
            setup_memory(hugepages)
        except AttributeError:
            self.logger.error("%s is not implemented" % function_name)

    def setup_memory_linux(self, hugepages=-1):
        """
        Setup Linux hugepages.
        """
        hugepages_size = self.send_expect(
            "awk '/Hugepagesize/ {print $2}' /proc/meminfo", "# ")

        if int(hugepages_size) < (1024 * 1024):
            if self.architecture == "x86_64":
                arch_huge_pages = hugepages if hugepages > 0 else 4096
            elif self.architecture == "i686":
                arch_huge_pages = hugepages if hugepages > 0 else 512
            # set huge pagesize for x86_x32 abi target
            elif self.architecture == "x86_x32":
                arch_huge_pages = hugepages if hugepages > 0 else 256

            total_huge_pages = self.get_total_huge_pages()

            self.mount_huge_pages()
            if total_huge_pages != arch_huge_pages:
                self.set_huge_pages(arch_huge_pages)

    def setup_memory_freebsd(self, hugepages=-1):
        """
        Setup Freebsd hugepages.
        """
        if hugepages is -1:
            hugepages = 2048

        num_buffers = hugepages / 1024
        if num_buffers:
            self.send_expect('kenv hw.contigmem.num_buffers=%d' % num_buffers,
                             "#")

        self.send_expect("kldunload contigmem.ko", "#")
        self.send_expect("kldload ./%s/kmod/contigmem.ko" % self.target, "#")

    def taskset(self, core):
        if self.get_os_type() != 'linux':
            return ''

        return 'taskset %s ' % core

    def bind_interfaces_linux(self, driver='igb_uio', nics_to_bind=None):
        """
        Bind the interfaces to the selected driver. nics_to_bind can be None
        to bind all interfaces or an array with the port indexes
        """

        binding_list = '--bind=%s ' % driver

        current_nic = 0
        for (pci_bus, pci_id) in self.pci_devices_info:
            if dts.accepted_nic(pci_id):

                if nics_to_bind is None or current_nic in nics_to_bind:
                    binding_list += '%s ' % (pci_bus)

                current_nic += 1

        self.send_expect('tools/dpdk_nic_bind.py %s' % binding_list, '# ')

    def unbind_interfaces_linux(self, nics_to_bind=None):
        """
        Unbind the interfaces.
        """

        binding_list = '-u '

        current_nic = 0
        for (pci_bus, pci_id) in self.pci_devices_info:
            if dts.accepted_nic(pci_id):

                if nics_to_bind is None or current_nic in nics_to_bind:
                    binding_list += '%s ' % (pci_bus)

                current_nic += 1

        self.send_expect('tools/dpdk_nic_bind.py %s' % binding_list, '# ', 30)

    def get_ports(self, nic_type='any', perf=None, socket=None):
        """
        Return DUT port list with the filter of NIC type, whether run IXIA
        performance test, whether request specified socket.
        """
        ports = []
        candidates = []

        if perf is None:
            perf = self.want_perf_tests

        nictypes = []
        if nic_type == 'any':
            for portid in range(len(self.ports_info)):
                ports.append(portid)
            return ports
        elif nic_type == 'cfg':
            for portid in range(len(self.ports_info)):
                if self.ports_info[portid]['source'] == 'cfg':
                    ports.append(portid)
            return ports
        else:
            for portid in range(len(self.ports_info)):
                port_info = self.ports_info[portid]
                # match nic type
                if port_info['type'] == NICS[nic_type]:
                    # match numa or none numa awareness
                    if (socket is None or port_info['numa'] == -1
                            or socket == port_info['numa']):
                        # port has link,
                        if self.tester.get_local_port(portid) != -1:
                            ports.append(portid)
            return ports

    def get_ports_performance(self,
                              nic_type='any',
                              perf=None,
                              socket=None,
                              force_same_socket=True,
                              force_different_nic=True):
        """
            Return the maximum available number of ports meeting the parameters.
            Focuses on getting ports with same/different NUMA node and/or
            same/different NIC.
        """

        available_ports = self.get_ports(nic_type, perf, socket)
        accepted_sets = []

        while len(available_ports) > 0:
            accepted_ports = []
            # first avaiable port is the reference port
            accepted_ports.append(available_ports[0])

            # check from second port according to parameter
            for port in available_ports[1:]:

                if force_same_socket and socket is None:
                    if self.ports_info[port]['numa'] != self.ports_info[
                            accepted_ports[0]]['numa']:
                        continue
                if force_different_nic:
                    if self.ports_info[port]['pci'][:-1] == self.ports_info[
                            accepted_ports[0]]['pci'][:-1]:
                        continue

                accepted_ports.append(port)

            for port in accepted_ports:
                available_ports.remove(port)

            accepted_sets.append(accepted_ports)

        biggest_set = max(accepted_sets, key=lambda s: len(s))

        return biggest_set

    def get_peer_pci(self, port_num):
        """
        return the peer pci address of dut port
        """
        if 'peer' not in self.ports_info[port_num]:
            return None
        else:
            return self.ports_info[port_num]['peer']

    def get_mac_address(self, port_num):
        """
        return the port mac on dut
        """
        return self.ports_info[port_num]['mac']

    def get_ipv6_address(self, port_num):
        """
        return the IPv6 address on dut
        """
        return self.ports_info[port_num]['ipv6']

    def get_numa_id(self, port_num):
        """
        return the Numa Id of port
        """
        if self.ports_info[port_num]['numa'] == -1:
            self.logger.warning('NUMA not supported')

        return self.ports_info[port_num]['numa']

    def get_port_info(self, pci):
        """
        return port info by pci id
        """
        for port_info in self.ports_info:
            if port_info['pci'] == pci:
                return port_info

    def lcore_table_print(self, horizontal=False):
        if not horizontal:
            dts.results_table_add_header(['Socket', 'Core', 'Thread'])

            for lcore in self.cores:
                dts.results_table_add_row(
                    [lcore['socket'], lcore['core'], lcore['thread']])
            dts.results_table_print()
        else:
            dts.results_table_add_header(['X'] + [''] * len(self.cores))
            dts.results_table_add_row(['Thread'] +
                                      [n['thread'] for n in self.cores])
            dts.results_table_add_row(['Core'] +
                                      [n['core'] for n in self.cores])
            dts.results_table_add_row(['Socket'] +
                                      [n['socket'] for n in self.cores])
            dts.results_table_print()

    def get_memory_channels(self):
        n = self.crb['memory channels']
        if n is not None and n > 0:
            return n
        else:
            return 1

    def check_ports_available(self, pci_bus, pci_id):
        """
        Check that whether auto scanned ports ready to use
        """
        pci_addr = "%s:%s" % (pci_bus, pci_id)
        if self.nic == 'any':
            return True
        elif self.nic == 'cfg':
            if self.conf.check_port_available(pci_bus) is True:
                return True
        elif self.nic not in NICS.keys():
            self.logger.warning("NOT SUPPORTED NIC TYPE: %s" % self.nic)
        else:
            codename = NICS[self.nic]
            if pci_id == codename:
                return True

        return False

    def rescan_ports(self):
        unknow_interface = dts.RED('Skipped: unknow_interface')

        for port_info in self.ports_info:
            pci_bus = port_info['pci']
            addr_array = pci_bus.split(':')
            bus_id = addr_array[0]
            devfun_id = addr_array[1]
            intf = self.get_interface_name(bus_id, devfun_id)
            if "No such file" in intf:
                self.logger.info("DUT: [0000:%s] %s" %
                                 (pci_bus, unknow_interface))
            out = self.send_expect("ip link show %s" % intf, "# ")
            if "DOWN" in out:
                self.send_expect("ip link set %s up" % intf, "# ")
                time.sleep(5)
            macaddr = self.get_mac_addr(intf, bus_id, devfun_id)
            out = self.send_expect(
                "ip -family inet6 address show dev %s | awk '/inet6/ { print $2 }'"
                % intf, "# ")
            ipv6 = out.split('/')[0]
            # Unconnected ports don't have IPv6
            if ":" not in ipv6:
                ipv6 = "Not connected"

            port_info['mac'] = macaddr
            port_info['intf'] = intf
            port_info['ipv6'] = ipv6

    def scan_ports(self):
        """
        Scan ports information or just read it from cache file.
        """
        if self.read_cache:
            self.ports_info = self.serializer.load(self.PORT_INFO_CACHE_KEY)

        if not self.read_cache or self.ports_info is None:
            self.scan_ports_uncached()
            self.serializer.save(self.PORT_INFO_CACHE_KEY, self.ports_info)

    def scan_ports_uncached(self):
        """
        Scan ports and collect port's pci id, mac adress, ipv6 address.
        """
        scan_ports_uncached = getattr(
            self, 'scan_ports_uncached_%s' % self.get_os_type())
        return scan_ports_uncached()

    def scan_ports_uncached_linux(self):
        """
        Scan Linux ports and collect port's pci id, mac adress, ipv6 address.
        """
        self.ports_info = []
        skipped = dts.RED('Skipped: Unknown/not selected')
        unknow_interface = dts.RED('Skipped: unknow_interface')
        print self.pci_devices_info  #rrr

        for (pci_bus, pci_id) in self.pci_devices_info:
            if self.check_ports_available(pci_bus, pci_id) is False:
                self.logger.info("DUT: [000:%s %s] %s" %
                                 (pci_bus, pci_id, skipped))
                continue

            addr_array = pci_bus.split(':')
            bus_id = addr_array[0]
            devfun_id = addr_array[1]

            numa = self.get_device_numa(bus_id, devfun_id)
            # store the port info to port mapping
            self.ports_info.append({
                'pci': pci_bus,
                'type': pci_id,
                'numa': numa
            })

    def scan_ports_uncached_freebsd(self):
        """
        Scan Freebsd ports and collect port's pci id, mac adress, ipv6 address.
        """
        self.ports_info = []

        skipped = dts.RED('Skipped: Unknown/not selected')

        for (pci_bus, pci_id) in self.pci_devices_info:

            if not dts.accepted_nic(pci_id):
                self.logger.info("DUT: [%s %s] %s" %
                                 (pci_bus, pci_id, skipped))
                continue

            intf = self.get_interface_name(pci_bus)

            macaddr = self.get_mac_addr(intf)
            ipv6 = self.get_ipv6_addr(intf)

            if ipv6 is None:
                ipv6 = "Not available"

            self.logger.warning("NUMA not available on FreeBSD")

            self.logger.info("DUT: [%s %s] %s %s" %
                             (pci_bus, pci_id, intf, ipv6))

            # convert bsd format to linux format
            pci_split = pci_bus.split(':')
            pci_bus_id = hex(int(pci_split[0]))[2:]
            if len(pci_split[1]) == 1:
                pci_dev_str = "0" + pci_split[1]
            else:
                pci_dev_str = pci_split[1]

            pci_str = "%s:%s.%s" % (pci_bus_id, pci_dev_str, pci_split[2])

            # store the port info to port mapping
            self.ports_info.append({
                'pci': pci_str,
                'type': pci_id,
                'intf': intf,
                'mac': macaddr,
                'ipv6': ipv6,
                'numa': -1
            })

    def load_portconf(self):
        """
        Load port configurations for ports_info. If manually configured infor
        not same as auto scanned, still use infor in configuration file.
        """
        for port in self.ports_info:
            pci_bus = port['pci']
            ports_cfg = self.conf.get_ports_config()
            if pci_bus in ports_cfg:
                port_cfg = ports_cfg[pci_bus]
                port_cfg['source'] = 'cfg'
            else:
                port_cfg = {}

            for key in ['intf', 'mac', 'numa', 'peer', 'source']:
                if key in port_cfg:
                    if key in port and port_cfg[key] != port[key]:
                        self.logger.warning(
                            "CONFIGURED %s NOT SAME AS SCANNED!!!" %
                            (key.upper()))
                    port[key] = port_cfg[key]

    def map_available_ports(self):
        """
        Load or generate network connection mapping list.
        """
        if self.read_cache:
            self.ports_map = self.serializer.load(self.PORT_MAP_CACHE_KEY)

        if not self.read_cache or self.ports_map is None:
            self.map_available_ports_uncached()
            self.serializer.save(self.PORT_MAP_CACHE_KEY, self.ports_map)

        self.logger.warning("DUT PORT MAP: " + str(self.ports_map))

    def map_available_ports_uncached(self):
        """
        Generate network connection mapping list.
        """
        nrPorts = len(self.ports_info)
        if nrPorts == 0:
            return

        remove = []
        self.ports_map = [-1] * nrPorts

        hits = [False] * len(self.tester.ports_info)

        for dutPort in range(nrPorts):
            peer = self.get_peer_pci(dutPort)
            dutpci = self.ports_info[dutPort]['pci']
            print "peer  ", peer
            print "dutpci ", dutpci
            print self.tester.ports_info
            if peer is not None:
                for remotePort in range(len(self.tester.ports_info)):
                    if self.tester.ports_info[remotePort]['pci'] == peer:
                        hits[remotePort] = True
                        self.ports_map[dutPort] = remotePort
                        break
                if self.ports_map[dutPort] == -1:
                    self.logger.error("CONFIGURED TESTER PORT CANNOT FOUND!!!")
                else:
                    continue  # skip ping6 map

            for remotePort in range(len(self.tester.ports_info)):
                if hits[remotePort]:
                    continue

                # skip ping self port
                remotepci = self.tester.ports_info[remotePort]['pci']
                if (self.crb['IP']
                        == self.crb['tester IP']) and (dutpci == remotepci):
                    continue

                # skip ping those not connected port
                ipv6 = self.get_ipv6_address(dutPort)
                if ipv6 == "Not connected":
                    continue

                out = self.tester.send_ping6(remotePort, ipv6,
                                             self.get_mac_address(dutPort))

                if ('64 bytes from' in out):
                    self.logger.info("PORT MAP: [dut %d: tester %d]" %
                                     (dutPort, remotePort))
                    self.ports_map[dutPort] = remotePort
                    hits[remotePort] = True
                    if self.crb['IP'] == self.crb['tester IP']:
                        # remove dut port act as tester port
                        remove_port = self.get_port_info(remotepci)
                        if remove_port is not None:
                            remove.append(remove_port)
                        # skip ping from those port already act as dut port
                        testerPort = self.tester.get_local_index(dutpci)
                        if testerPort != -1:
                            hits[testerPort] = True
                    break

        for port in remove:
            self.ports_info.remove(port)