Example #1
0
class Petalinux(Basebuild):
    """This Petalinux class contains api's for all common petalinux options"""

    configs_dir = "project-spec/configs"
    meta_user = "******"
    recipes_apps = f"{meta_user}/recipes-apps"
    recipes_bsp = f"{meta_user}/recipes-bsp"
    project_config = f"{configs_dir}/config"
    rootfs_config = f"{configs_dir}/rootfs_config"
    user_rootfs_config = f"{meta_user}/conf/user-rootfsconfig"
    plnxbspconf_file = f"{meta_user}/conf/petalinuxbsp.conf"
    devicetree_dir = f"{recipes_bsp}/device-tree"
    fsbl_dir = f"{recipes_bsp}/fsbl"
    pmufw_dir = f"{recipes_bsp}/pmu-firmware"
    plm_dir = f"{recipes_bsp}/plm"
    psmfw_dir = f"{recipes_bsp}/psm-firmware"
    system_user_file = f"{devicetree_dir}/files/system-user.dtsi"
    kernel_dir = f"{meta_user}/recipes-kernel/linux/linux-xlnx"
    kernel_bbappend = f"{meta_user}/recipes-kernel/linux/linux-xlnx_%.bbappend"
    devicetree_append = f"{devicetree_dir}/device-tree.bbappend"
    fsbl_bbappend = f"{fsbl_dir}/fsbl-firmware_%.bbappend"
    atf_dir = f"{recipes_bsp}/arm-trusted-firmware"
    atf_bbappend = f"{atf_dir}/arm-trusted-firmware_%.bbappend"
    uboot_dir = f"{meta_user}/recipes-bsp/u-boot"
    uboot_bbappend = f"{uboot_dir}/u-boot-xlnx_%.bbappend"
    pmufw_bbappend = f"{pmufw_dir}/pmu-firmware_%.bbappend"
    plm_bbappend = f"{plm_dir}/plm-firmware_%.bbappend"
    psmfw_bbappend = f"{psmfw_dir}/psm-firmware_%.bbappend"
    openamp_dir = f"{meta_user}/recipes-openamp"
    libmetal_dir = openamp_dir
    openamp_bbappend = f"{openamp_dir}/open-amp/open-amp_%.bbappend"
    libmetal_bbappend = f"{openamp_dir}/libmetal/libmetal_%.bbappend"
    xen_dir = f"{meta_user}/recipes-extended/xen"
    xen_bbappend = f"{xen_dir}/xen_%.bbappend"
    recipesmm_dir = f"{meta_user}/recipes-multimedia/"
    gst_dir = f"{recipesmm_dir}/gstreamer/"
    vcu_dir = f"{recipesmm_dir}/vcu/"
    vcu_firmware_dir = f"{recipesmm_dir}/vcu/vcu-firmware"
    vcu_firmware_bbappend = f"{vcu_dir}/vcu-firmware.bbappend"
    vcu_omxil_dir = f"{recipesmm_dir}/vcu/libomxil-xlnx"
    vcu_omxil_bbappend = f"{vcu_dir}/libomxil-xlnx.bbappend"
    vcu_ctrlsw_dir = f"{recipesmm_dir}/vcu/libvcu-xlnx"
    vcu_ctrlsw_bbappend = f"{vcu_dir}/libvcu-xlnx.bbappend"
    vcu_modules_dir = f"{recipesmm_dir}/vcu/kernel-module-vcu"
    vcu_modules_bbappend = f"{vcu_dir}/kernel-module-vcu.bbappend"
    gstreamer_dir = f"{recipesmm_dir}/gstreamer/gstreamer1.0"
    gstreamer_bbappend = f"{gst_dir}/gstreamer1.0_%.bbappend"
    gst_plugins_bad_dir = f"{recipesmm_dir}/gstreamer/gstreamer1.0-plugins-bad"
    gst_plugins_bad_bbappend = f"{gst_dir}/gstreamer1.0-plugins-bad_%.bbappend"
    gst_plugins_base_dir = f"{recipesmm_dir}/gstreamer/gstreamer1.0-plugins-base"
    gst_plugins_base_bbappend = f"{gst_dir}/gstreamer1.0-plugins-base_%.bbappend"
    gst_plugins_good_dir = f"{recipesmm_dir}/gstreamer/gstreamer1.0-plugins-good"
    gst_plugins_good_bbappend = f"{gst_dir}/gstreamer1.0-plugins-good_%.bbappend"
    gst_omx_dir = f"{recipesmm_dir}/gstreamer/gstreamer1.0-omx"
    gst_omx_bbappend = f"{gst_dir}/gstreamer1.0-omx_%.bbappend"

    def __init__(self, config, setup: bool = True):
        super().__init__(config, setup)
        self.plnx_tool = config["PLNX_TOOL"]
        self.bsp_path = config["BSP_PATH"]
        self.plnx_pkg = None
        self.plnx_tmp = config["PLNX_TMP_PATH"]
        self.plnx_proj = config["plnx_proj"]

        self.workDir = config["workDir"]
        self.imagesDir = config["imagesDir"]
        self.wsDir = config["wsDir"]
        self.config["platform"] = config["platform"]

        self.proj_dir = f"{self.workDir}/{self.plnx_proj}"
        self.petalinux_images = f"{self.proj_dir}/images"
        self.qemu_boot = False
        # Acquire bash console.
        self.runner = Xexpect(log, exit_nzero_ret=True)
        atexit.register(self.__del__)
        myconfs = [
            "RECIPE_NAME",
            "RECIPE_NEW_NAME",
            "FETCHURI",
            "SOURCE_PATH",
            "RECIPE_DESTINATION",
            "IMAGE_RECIPE",
            "WORKSPACE_LAYERPATH",
            "EXISTING_RECIPENAME",
            "RECIPE_UPGRADE",
        ]
        for myconf in myconfs:
            if myconf in config:
                setattr(self, myconf.lower(), getattr(config, myconf))

    def source_tool(self, timeout: int = 120) -> None:
        """This Function source the petalinux tool.

        Parameters:
            PLNX_TOOL - by default set to petalinux daily_latest
        """
        if not is_file(self.plnx_tool):
            raise Exception(f"Error: ({self.plnx_tool}) is not a file")
        cmd = f"source {self.plnx_tool}"
        self.runner.runcmd(cmd=str(cmd), timeout=timeout)
        log.info(f"Petalinux Tool : {self.runner.runcmd(f'echo $PETALINUX')}")

    def create_project(self, timeout: int = 300) -> None:
        """This Function sources the creates petalinux project based on user configuration,

        Parameters:
           PLNX_TOOL : petalinux tool path
           platform  : versal, zynqMP, zynq, microblaze
           plnx_flow : BSP, template (by default BSP)
           BSP_PATH  : bsp path (default set to petalinux daily_latest)
           PLNX_BSP  : bsp name
           plnx_proj : project name
        """
        remove(f"{self.proj_dir}")

        self.source_tool()
        cmd = f"petalinux-create -t project "
        if self.config.get("plnx_flow") == "template":
            log.info("Using templete flow to create petalinux project...")
            cmd += f"--template {self.config['platform']}"
        else:
            log.info("Using bsp flow to create petalinux project...")
            self.plnx_bsp = self.config["PLNX_BSP"]
            self.plnx_bsp_path = get_original_path(
                f"{self.bsp_path}/{self.plnx_bsp}")
            if not is_file(self.plnx_bsp_path):
                log.error(f"Petalinux BSP {self.plnx_bsp_path} Not found")
                assert False, "Petalinux BSP Not found"
            cmd += f"-s {self.plnx_bsp_path} "

        if "plnx_proj" in self.config:
            cmd += f" -n {self.plnx_proj}"

        self.runner.runcmd(f"cd {self.workDir}")
        self.runner.runcmd(cmd=str(cmd), timeout=timeout)
        self.runner.runcmd(f"cd {self.plnx_proj}")
        os.chdir(self.proj_dir)
        if self.config.get("plnx_init_cmds"):
            self.runner.runcmd_list(self.config.plnx_init_cmds)

    def fetch_project(self):
        """This Function clones petalinux project from git,

        Parameters:
            PLNX_TOOL : petalinux tool path
            plnx_proj : project name
            bsp_src : bsp source
        >>> git.bsp.url : "https://gitenterprise.xilinx.com/bsp_src.git"
            git.bsp.branch : "master"
        """
        self.source_tool()
        if "git.bsp.url" in self.config:
            url = self.config.git.bsp.url
            if "git.bsp.branch" not in self.config:
                self.config.git.bsp.branch = "master"
            clone(
                self.config.git.bsp,
                self.proj_dir,
                recurse_submodules=self.config.git.bsp.recurse_submodules,
            )
            os.chdir(self.proj_dir)
            self.runner.runcmd(f"cd {self.proj_dir}")
        else:
            err_msg = "git.bsp.url not found in config"
            assert False, err_msg

    def create_apps(self, timeout: int = 300) -> None:
        """This Function creates user applications in petalinux project,

        Parameters:
            user_apps : it is dictionary
        >>> Usage:
            1. user_apps = { 'appname' : [ 'app files1', 'app file2' ] }
            2. user_apps = { 'appname' : [ 'app files' ],
                             'appname_bbfile' : 'userspecfic bbfile path'}
        """

        plnx_apps = self.config["user_apps"]
        if plnx_apps:
            for app_name, files in plnx_apps.items():
                app_name = app_name.lower()
                if "bbfile" not in app_name:
                    files = convert_list(files)
                    if self.config.get("plnx_flow") == "template":
                        create_apps_cmd = f"petalinux-create -t apps --template install -n {app_name.strip()} --enable"
                        self.runner.runcmd(cmd=str(create_apps_cmd),
                                           timeout=timeout)
                        remove_all_files(
                            f"{self.recipes_apps}/{app_name}/files/")
                    else:
                        create_apps_cmd = (
                            f"petalinux-create -t apps -n {app_name.strip()} --enable"
                        )
                        self.runner.runcmd(cmd=str(create_apps_cmd),
                                           timeout=timeout)
                    for data in files:
                        data = parse_config(self.config, data)
                        if is_dir(data):
                            copyDirectory(
                                data,
                                f"{self.proj_dir}/{self.recipes_apps}/{app_name}/files/",
                            )
                        else:
                            copy_file(
                                data,
                                f"{self.proj_dir}/{self.recipes_apps}/{app_name}/files/",
                            )
            for app_name, files in plnx_apps.items():
                app_name = app_name.lower()
                if "bbfile" in app_name:
                    files = parse_config(self.config, files)
                    app_name = os.path.splitext(os.path.basename(files))[0]
                    copy_file(
                        files,
                        f"{self.proj_dir}/{self.recipes_apps}/{app_name}/")
        else:
            log.warning("No user apps to create ")

    def set_tmp_path(self):
        """This Function to set temp path for petalinux project

        Parameters:
            PLNX_TMP_PATH : Default it set to '/tmp/petalinux'
        """

        if self.plnx_tmp:
            tmp_dir = (self.plnx_proj + "-" +
                       datetime.now().strftime("%Y.%m.%d-%H.%M.%S"))

            if os.getenv("JOB_NAME"):
                tmp_dir = f"{os.getenv('JOB_NAME')}/{tmp_dir}"

            self.plnx_tmp = os.path.join(self.plnx_tmp, tmp_dir)

            mkdir(self.plnx_tmp)
            os.chmod(self.plnx_tmp, 0o777)
            add_newline(f"{self.project_config}",
                        f'CONFIG_TMP_DIR_LOCATION="{self.plnx_tmp}"')

        if is_filesystem_nfs(self.proj_dir):
            self.plnx_tmp = self.get_tmp_path()

    def get_tmp_path(self):
        with open(f"{self.proj_dir}/{self.project_config}", "r") as read_obj:
            for line in read_obj:
                if "CONFIG_TMP_DIR_LOCATION" in line:
                    matchObj = re.search('CONFIG_TMP_DIR_LOCATION="(.*)"',
                                         line)
                    tmp_path = matchObj.group(1)
                    return tmp_path

    def silent_config(self, timeout: int = 600) -> None:
        """This Function apply the user configuration to petalinux project
        Parameter: plnx_config_component (optional)
        """

        plnx_silent_cmd = "yes | petalinux-config"
        if "plnx_config_component" in self.config:
            plnx_silent_cmd += f" -c {self.config['plnx_config_component']}"
        plnx_silent_cmd += " --silentconfig"

        self.runner.runcmd(cmd=str(plnx_silent_cmd), timeout=timeout)

    def get_hwdesign(self, timeout: int = 600) -> None:
        """This Function apply hardware design file(.xsa) on petalinux project

        Parameter:
            hw_design_path : .xsa file path
        """

        hw_design = get_original_path(self.config["hw_design_path"])
        hwdesign_cmd = (
            f"yes | petalinux-config --get-hw-description={hw_design} --silentconfig"
        )
        self.runner.runcmd(cmd=str(hwdesign_cmd), timeout=timeout)

    def plnx_build(self, timeout: int = 3600) -> None:
        """This Function runs petalinux build command on project
        Parameter: None
        """

        build_cmd = "petalinux-build"
        if self.config.get("plnx_build_timeout", ""):
            timeout = self.config.plnx_build_timeout

        self.runner.runcmd(cmd=str(build_cmd), timeout=timeout)

    def set_config(self):
        """This Function apply the user configs on petalinux project

        >>> Usage:
            plnx_configs = { rootfs :   [ 'CONFIG_xen=y',
                                          'CONFIG_open-amp_demo is not set' ],
                             project :  [ 'CONFIG_ROOTFS_INITRD=y' ],
                             kernel :   [ 'CONFIG_XILINX_ETHERNET=y'],
                             user-rootfs : ['CONFIG_kernel-module-hdmi'],
                             bspconf : ['IMAGE_INSTALL_append = "iperf3"']
                           }
        """

        component_map = {
            "user-rootfs": {
                "conf": f"{self.user_rootfs_config}"
            },
            "rootfs": {
                "conf": f"{self.rootfs_config}"
            },
            "project": {
                "conf": f"{self.project_config}"
            },
            "kernel": {
                "conf":
                f"{self.kernel_dir}/bsp.cfg",
                "conf_dir":
                f"{self.kernel_dir}",
                "bbappend": [
                    'FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"',
                    'SRC_URI += "file://bsp.cfg"',
                ],
            },
            "uboot": {
                "conf": f"{self.uboot_dir}/files/bsp.cfg",
                "conf_dir": f"{self.uboot_dir}",
                "bbappend": ['SRC_URI += "file://bsp.cfg"'],
            },
            "bspconf": {
                "conf": f"{self.plnxbspconf_file}"
            },
        }

        components = ("plm", "pmufw", "fsbl", "psmfw")

        for key, value in self.config["plnx_configs"].items():
            value = convert_list(value)
            if key in component_map:
                if "conf_dir" in component_map[key].keys():
                    mkdir(str(component_map[key]["conf_dir"]))
                if "bbappend" in component_map[key].keys():
                    append_list = convert_list(component_map[key]["bbappend"])
                    for val in append_list:
                        add_newline(getattr(self, f"{key}_bbappend"), str(val))
                for itr in value:
                    itr = parse_config(self.config, itr)
                    add_newline(str(component_map[key]["conf"]), str(itr))
            elif key in components:
                mkdir(getattr(self, f"{key}_dir"))
                for itr in value:
                    itr = parse_config(self.config, itr)
                    add_newline(getattr(self, f"{key}_bbappend"), str(itr))
            else:
                err_msg = f"Invalid arg {key} in plnx_configs"
                assert False, err_msg

    def apply_patch(self):
        components = ("atf", "pmufw", "fsbl", "uboot")
        for key, value in self.config["apply_patches"].items():
            value = convert_list(value)
            component_dir = f"{key}_dir"
            mycomponent_dir = getattr(self, component_dir)
            append_file = f"{key}_bbappend"
            myappend_file = getattr(self, append_file)
            mkdir(mycomponent_dir)
            if "kernel" in key:
                add_newline(f"{self.kernel_bbappend}",
                            'SRC_URI += "file://bsp.cfg"')
                add_newline(
                    myappend_file,
                    'FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"',
                )
            if key in components:
                add_newline(
                    myappend_file,
                    'FILESEXTRAPATHS_prepend := "${THISDIR}:"',
                )
            else:
                add_newline(
                    myappend_file,
                    'FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"',
                )
            for itr in value:
                if itr.endswith(".patch"):
                    if is_file(f"{itr}"):
                        copy_file(f"{itr}", mycomponent_dir)
                        itr = os.path.basename(f"{itr}")
                        add_newline(myappend_file,
                                    f'SRC_URI += "file://{itr}"')
                    else:
                        copy_file(f"{self.config['workDir']}/{itr}",
                                  mycomponent_dir)
                        add_newline(myappend_file,
                                    f'SRC_URI += "file://{itr}"')
                else:
                    log.info("Invalid patch...")

    def apply_external_component(self):
        """This function adds support to apply external src on petalinux project
            for kernel, uboot, atf, fsbl, xen, openamp components

        Parameters:
            url - component git url
            externalsrc - local src path
            srcrev - commid id/tag
            branch - git branch
            checksum - source checksum
        >>> Usage:
                plnx.component.uboot.url = "<git url>"
                plnx.component.uboot.branch = "master"
                plnx.component.uboot.srcrev = "12223434222"
                plnx.component.uboot.checksum = "<checksum>"
                plnx.component.xen.externalsrc= "<external source path>"
                plnx.component.openamp.url= "<source url>"
        """
        def _external_repo_setup(self, key):
            if key == "openamp":
                key = "open-amp"
            component = re.sub("-", "", key)
            comp = f"{component}_bbappend"
            comp_dir = f"{component}_dir"
            mycomp_dir = getattr(self, comp_dir)
            mkdir(f"{mycomp_dir}/{key}")
            bbappend = getattr(self, comp)
            return bbappend

        def _component_map(self):
            component_map = {}
            component_map["atf"] = "ARM__TRUSTED__FIRMWARE"
            component_map["uboot"] = "U__BOOT"
            component_map["kernel"] = "LINUX__KERNEL"
            return component_map

        for key, value in self.config.plnx.component.items():
            if key in ["kernel", "uboot", "atf"]:
                component_map = _component_map(self)
                if value["url"]:
                    add_newline(
                        f"{self.project_config}",
                        f"CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_REMOTE=y",
                    )
                    add_newline(
                        f"{self.project_config}",
                        f"# CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_EXT__LOCAL__SRC is not set",
                    )
                    add_newline(
                        f"{self.project_config}",
                        f"CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_REMOTE_DOWNLOAD_PATH=\"{value['url']};protocol=https\"",
                    )
                    if value["srcrev"]:
                        add_newline(
                            f"{self.project_config}",
                            f"CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_REMOTE_REFERENCE=\"{value['srcrev']}\"",
                        )
                    else:
                        add_newline(
                            f"{self.project_config}",
                            f'CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_REMOTE_REFERENCE="${{AUTOREV}}"',
                        )
                    if value["branch"]:
                        add_newline(
                            f"{self.project_config}",
                            f"CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_REMOTE_BRANCH=\"{value['branch']}\"",
                        )
                    if value["checksum"]:
                        add_newline(
                            f"{self.project_config}",
                            f"CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_LIC_FILES_CHKSUM_REMOTE=\"{value['checksum']}\"",
                        )
                else:
                    if value["externalsrc"]:
                        add_newline(
                            f"{self.project_config}",
                            f"# CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_REMOTE is not set",
                        )
                        add_newline(
                            f"{self.project_config}",
                            f"CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_EXT__LOCAL__SRC=y",
                        )
                        add_newline(
                            f"{self.project_config}",
                            f"CONFIG_SUBSYSTEM_COMPONENT_{component_map[key]}_NAME_EXT__LOCAL__SRC_PATH=\"{value['externalsrc']}\"",
                        )
            else:
                bbappend = _external_repo_setup(self, key)
                if value["externalsrc"]:
                    repo_name = get_base_name(value["externalsrc"])
                    self.runner.runcmd(
                        cmd=
                        f"rsync -av --exclude '.git*' {value['externalsrc']} {self.workDir}",
                        timeout=120,
                    )
                    add_newline(bbappend, f"inherit externalsrc")
                    add_newline(bbappend,
                                f'EXTERNALSRC = "{self.workDir}/{repo_name}"')
                    add_newline(
                        bbappend,
                        f'EXTERNALSRC_BUILD = "{self.workDir}/{repo_name}"')
                    if value["checksum"]:
                        add_newline(
                            bbappend,
                            f"LIC_FILES_CHKSUM = \"file://license.txt;md5={value['checksum']}\"",
                        )
                elif value["url"]:
                    if value["checksum"]:
                        add_newline(
                            bbappend,
                            f"LIC_FILES_CHKSUM = \"file://license.txt;md5={value['checksum']}\"",
                        )
                    add_newline(bbappend,
                                f"REPO = \"{value['url']};protocol=https\"")
                    if value["srcrev"]:
                        if value["srcrev"] == "AUTOREV":
                            add_newline(bbappend, 'SRCREV = "{AUTOREV}"')
                        else:
                            add_newline(bbappend,
                                        f"SRCREV = \"{value['srcrev']}\"")
                    if value["branch"]:
                        add_newline(bbappend,
                                    f"BRANCH = \"{value['branch']}\"")
                    # Add build dependency using this var, for the component being built
                    if value["depends"]:
                        add_newline(bbappend,
                                    f"DEPENDS += \"{value['depends']}\"")
                else:
                    log.info(
                        "Invalid external component src option.... using default petalinux sources"
                    )

    def update_dtsi_file(self):
        """This function adds user dtsi file to petalinux project

        Parameter:
            plnx_user_dtsi_files : user .dtsi file

        >>> Usage:
            plnx_user_dtsi_files = ['<path to dtsi file>']
        """

        mkdir(self.devicetree_dir)
        if "plnx_user_dtsi_files" in self.config:
            dt_files = convert_list(self.config["plnx_user_dtsi_files"])
            for file in dt_files:
                copy_file(file, f"{self.devicetree_dir}/files/")
                dt_file = os.path.basename(file)
                if dt_file.endswith(".dtsi"):
                    add_newline(f"{self.system_user_file}",
                                f'/include/ "{dt_file}"')
                    add_newline(f"{self.devicetree_append}",
                                f'SRC_URI += "file://{dt_file}"')
                else:
                    log.error("Invalid dtsi input")

    def link_dtsi_file(self):
        """This function softlink system-user.dtsi file with user provided dtsi file

        Parameter:
           plnx_user_dtsi_file : user .dtsi file

        >>> Usage:
            plnx_user_dtsi_file = 'path to user dtsi file'
        """
        if "plnx_user_dtsi_file" in self.config:
            plnx_user_dtsi_file = self.config["plnx_user_dtsi_file"]
            system_dt_file = os.path.basename(self.system_user_file)
            user_dt_file = os.path.basename(plnx_user_dtsi_file)
            if os.path.isabs(plnx_user_dtsi_file):
                if is_file(plnx_user_dtsi_file):
                    copy_file(plnx_user_dtsi_file,
                              f"{self.devicetree_dir}/files/")
                else:
                    err_msg = "ERROR: No {plnx_user_dtsi_file} exists"
                    assert False, err_msg
            os.chdir(f"{self.devicetree_dir}/files/")
            symlink(system_dt_file, user_dt_file)
            os.chdir(self.proj_dir)

    def pack_bsp(self, timeout: int = 300) -> None:
        """This Function packages the petalinux project into BSP"""

        self.plnx_pkg = self.config["plnx_pkg"]
        if not self.plnx_pkg.split():
            self.plnx_pkg = self.plnx_bsp

        pack_cmd = f"petalinux-package --bsp -p ./ -o {self.workDir}/{self.plnx_pkg}"
        self.runner.runcmd(cmd=str(pack_cmd), timeout=timeout)

    def run_user_script(self, timeout: int = 600) -> None:
        """This Function can be useful to run any user script after petalinux project creation.
        Parameters:
            user_script : supports .sh and .py
        >>> Usage:
            user_script = { "file_name" : "example.sh",
                            "args" : "<script args if any>",
                            "expected" : "<any script to match to know
                                        the script execution complete>"
            }

        """

        userSuite = self.config["user_script"]
        script = userSuite["file_name"]
        args = userSuite["args"]
        expected = userSuite["expected"]

        if is_file(f"{self.workDir}/{script}") == True:
            if script.endswith(".sh"):
                config_cmd = f"sh {self.workDir}/{script} {args}"
            elif script.endswith(".py"):
                config_cmd = f"python {self.workDir}/{script} {args}"
            else:
                log.error(f"{script} not supported to execute")
        else:
            raise Exception(f"ERROR: {self.workDir}/{script} not exist")
        self.runner.runcmd(cmd=str(config_cmd),
                           expected=expected,
                           timeout=timeout)

    def plnx_package_boot(self, timeout: int = 600) -> None:
        """This Function creates BOOT.BIN"""

        if self.config["platform"].strip().lower() == "zynqmp":
            plnx_bin_cmd = "petalinux-package --boot %s %s %s %s" % (
                "--fsbl images/linux/zynqmp_fsbl.elf",
                "--u-boot images/linux/u-boot.elf",
                "--pmufw images/linux/pmufw.elf",
                "--fpga images/linux/system.bit --force",
            )
        elif self.config["platform"].strip().lower() == "zynq":
            plnx_bin_cmd = "petalinux-package --boot %s %s %s" % (
                "--fsbl images/linux/zynq_fsbl.elf",
                "--u-boot images/linux/u-boot.elf",
                "--fpga images/linux/system.bit --force",
            )
        elif self.config["platform"].strip().lower() == "versal":
            plnx_bin_cmd = "petalinux-package --boot --force --u-boot"
        elif self.config["platform"].strip().lower() == "microblaze":
            plnx_bin_cmd = ""
        else:
            log.error(f"{(self.config['platform'])} not supported")
            raise Exception(
                f"Error: {(self.config['platform'])} not supported")
        self.runner.runcmd(cmd=str(plnx_bin_cmd), timeout=timeout)

    def build_sdk(self, timeout: int = 3600) -> None:
        """This Function runs petalinux sdk command on project"""

        build_sdk_cmd = "petalinux-build --sdk"
        self.runner.runcmd(cmd=str(build_sdk_cmd), timeout=timeout)

    def extract_sdk(self, timeout: int = 3600) -> None:
        """This Function extracts the sdk on project"""
        extract_sdk_cmd = "petalinux-package --sysroot"
        self.runner.runcmd(cmd=str(extract_sdk_cmd), timeout=timeout)

    # Fix me
    def plnx_package_wic(self, wic_args=None, timeout=600):
        """This Function can be useful to generate wic image to prepare sd card.
        Parameters:
            wic_args : None (or) --bootfiles "BOOT.BIN boot.scr system.dtb image.ub"
        """
        wic_cmd = "petalinux-package --wic"
        if wic_args:
            wic_cmd += f" {wic_args}"
        self.runner.runcmd(cmd=str(wic_cmd), timeout=timeout)

    def deploy(self):
        """This Function deploy the generated petalinux build images to specfic location
        Parameters:
            plnx_artifacts - to copy any specific files
            deploy_dir : to copy images to specific location
        >>> Usage:
            plnx_artifacts = ['image.ub', 'BOOT.BIN', 'Image', 'system.xsa' ]
            deploy_dir = "<path>"
        """
        ret = True
        if "deploy_dir" in self.config:
            deploy_dir = self.config["deploy_dir"]
            if not is_dir(deploy_dir):
                mkdir(deploy_dir)

            log.info(f"Checking petalinux artifacts in {self.proj_dir}")
            if "plnx_artifacts" in self.config:
                for image in self.config["plnx_artifacts"]:
                    image_file = find_file(image,
                                           f"{self.proj_dir}/images/linux")
                    if image_file:
                        if is_file(image_file):
                            copy_file(image_file, deploy_dir)
                        elif is_dir(image_file):
                            copyDirectory(image_file,
                                          f"{deploy_dir}/{image}",
                                          symlinks=True)
                    else:
                        log.error(f"{image} does not exist in {self.workDir}")
                        ret = False

        copyDirectory(f"{self.proj_dir}/images/linux",
                      self.imagesDir,
                      symlinks=True)
        return ret

    def deploy_bsp(self):
        """This Function deploys the petalinux bsp to specified location

        Parameter:
            deploy_dir : <path>
        """

        deploy_dir = self.config["deploy_dir"]
        if deploy_dir:
            if is_dir(deploy_dir) == False:
                mkdir(deploy_dir)
            else:
                remove(deploy_dir)
                mkdir(deploy_dir)
            log.info(f"Copying plnx packed bsp to {deploy_dir}")
            shutil.copy(f"{self.workDir}/{self.plnx_pkg}", deploy_dir)
        shutil.copy(f"{self.workDir}/{self.plnx_pkg}", self.imagesDir)

    def _run_boot(
        self,
        cmd: str,
        proj_path: Optional[str] = None,
        hwserver: Optional[str] = None,
        bitfile: Optional[str] = None,
        rootfs: Optional[str] = None,
    ) -> None:
        """This function create petalinux boot command"""

        if proj_path:
            self.proj_dir = proj_path
        if not bitfile:
            bitfile = f"{self.proj_dir}/pre-built/linux/images/system.bit"
        if bitfile.endswith(".bit"):
            if self.config.get("platform") != "versal":
                if self.config.get("plnx_no_rev_check"):
                    cmd += f' --after-connect "fpga -no-revision-check {bitfile}"'
                else:
                    cmd += f" --bitstream {bitfile}"
        if rootfs:
            cmd += f" --rootfs {rootfs}"
        if hwserver:
            cmd += f" --hw_server-url {hwserver}:3121"

        if not is_dir(self.proj_dir):
            log.error(f"Petalinux Project Directory {self.proj_dir} not found")
            assert False, "Petalinux project directory not found"

        self.runner.runcmd(f"cd {self.proj_dir}")
        self.runner.runcmd(cmd=str(cmd), timeout=3600)

    def _run_qemu_boot(self, cmd, proj_path=None, qemu_args=None, rootfs=None):
        """This function create petalinux qemu boot command"""
        if proj_path:
            self.proj_dir = proj_path
        if rootfs:
            cmd += f" --rootfs {rootfs}"
        if qemu_args:
            cmd += f" {qemu_args}"

        if not is_dir(self.proj_dir):
            log.error(f"Petalinux Project Directory {self.proj_dir} not found")
            assert False, "Petalinux project directory not found"
        self.runner.runcmd(f"cd {self.proj_dir}")
        self.qemu_boot = True
        self.runner.sendline(cmd=str(cmd))

    def plnx_boot(
        self,
        boottype=None,
        proj_path=None,
        hwserver=None,
        bitfile=None,
        qemu_args=None,
        rootfs=None,
    ):
        if boottype not in ("prebuilt 2", "prebuilt 3", "kernel", "uboot"):
            raise Exception("""Invalid petalinux boot type selected
            support types are: prebuilt 2, prebuilt 3, kernel, uboot""")

        if hwserver:
            cmd = f"petalinux-boot --jtag -v --{boottype}"
            self._run_boot(cmd, proj_path, hwserver, bitfile, rootfs)
        else:
            cmd = f"petalinux-boot --qemu --{boottype}"
            self._run_qemu_boot(cmd, proj_path, qemu_args, rootfs)

    def __del__(self):
        """This function deletes the petalinux project created under TEMP path.

        Parameters:
            PLNX_TMP_PATH : tmp path to to build petalinux project
            skip_clean_temp : to skip temp clean
        >>> skip_clean_temp = true

        """
        if self.config.get("skip_clean_temp"):
            log.info("Skipped petaliux project temp clean...")
        else:
            if self.plnx_tmp:
                log.info(
                    f"Petaliunx project temp clean successful on path : {self.plnx_tmp} ..."
                )
                remove(self.plnx_tmp)

        if self.qemu_boot:
            self.runner.sendcontrol("a")
            self.runner.sendline("x")

    def devtool(self, operation, timeout=12000):
        """This function performs petalinux-devtool options"""
        self.source_tool()
        self.create_project()
        if operation == "add":
            self.runner.runcmd(
                cmd=
                f" petalinux-devtool {operation} {self.recipe_name}  {self.fetchuri}",
                timeout=2000,
            )
        elif operation == "modify":
            self.runner.runcmd(
                cmd=
                f" petalinux-devtool {operation} {self.existing_recipename} ",
                timeout=1000,
            )
        elif operation == "upgrade":
            self.runner.runcmd(
                cmd=f" petalinux-devtool {operation} {self.recipe_upgrade}",
                timeout=2000,
            )
        elif operation in ("status", "export"):
            self.runner.runcmd_list(
                cmd_list=[
                    f"petalinux-devtool add {self.recipe_name} {self.fetchuri}",
                    f"petalinux-devtool {operation}",
                ],
                timeout=600,
            )
        elif operation in (
                "latest-version",
                "check-upgrade-status",
                "search",
                "build",
                "find-recipe",
                "configure-help",
                "update-recipe",
                "configure",
        ):
            self.runner.runcmd_list(
                cmd_list=[
                    f"petalinux-devtool add {self.recipe_name} {self.fetchuri}",
                    f"petalinux-devtool {operation} {self.recipe_name}",
                ],
                timeout=2000,
            )
        elif operation == "rename":
            self.runner.runcmd_list(
                cmd_list=[
                    f"petalinux-devtool add {self.recipe_name} {self.fetchuri}",
                    f"petalinux-devtool {operation} {self.recipe_name}  {self.recipe_new_name}",
                    f"petalinux-devtool search {self.recipe_new_name}",
                ],
                timeout=2000,
            )
        elif operation == "reset":
            self.runner.runcmd_list(
                cmd_list=[
                    f"petalinux-devtool add {self.recipe_name} {self.fetchuri}",
                    f" petalinux-devtool {operation}  {self.recipe_name} ",
                    f"cd {self.source_path} && rm -rf {self.recipe_name}",
                    f"cd && cd {self.workDir}/{self.plnx_proj}",
                ],
                timeout=2000,
            )
        elif operation == "finish":
            self.runner.runcmd_list(
                cmd_list=[
                    f"petalinux-devtool add {self.recipe_name} {self.fetchuri}",
                    f" petalinux-devtool {operation}  {self.recipe_name} {self.workDir}/{self.plnx_proj}/{self.recipe_destination}",
                    f"cd {self.source_path} && rm -rf {self.recipe_name}",
                    f"petalinux-devtool find-recipe {self.recipe_name}",
                    f"cd && cd {self.workDir}/{self.plnx_proj}",
                ],
                timeout=2000,
            )
        elif operation == "build-image":
            self.runner.runcmd(
                cmd=f" petalinux-devtool {operation} {self.image_recipe}",
                timeout=2000)
        elif operation == "create-workspace":
            self.runner.runcmd(
                cmd=
                f" petalinux-devtool {operation} {self.workspace_layerpath}",
                timeout=600,
            )
        elif operation == "import":
            self.plnx_bsp = self.config["PLNX_BSP"]
            self.runner.runcmd_list(
                cmd_list=[
                    f"petalinux-devtool add {self.recipe_name} {self.fetchuri}",
                    f" petalinux-devtool export && cd ..",
                    f"yes | petalinux-create -t project -s  {self.bsp_path}{self.plnx_bsp}",
                    f"cd {self.plnx_proj} && petalinux-devtool {operation} {self.workDir}/{self.plnx_proj}.old/build/workspace-export-*tar.gz -o",
                ],
                timeout=600,
            )
        elif operation == "extract":
            self.runner.runcmd(
                cmd=
                f"petalinux-devtool {operation} {self.existing_recipename} {self.workspace_layerpath}",
                timeout=2000,
            )
        elif operation == "--help":
            self.runner.runcmd(cmd=f"petalinux-devtool {operation} ")
Example #2
0
class Ethernet(BaseLinux):
    def __init__(self, console, config, eth_interface):
        super().__init__(console, config)
        self.platform = None
        self.client_ip = "10.10.70.101"
        self.client_mac = "2c:2b:59:cf:7c:00"
        self.board_ip = "10.10.70.1"
        self.ping_intervel = "1"
        self.ping_size = "45"
        self.ping_count = "10"
        self.file_size = "4096"
        self.pktgen_size = "200"
        self.pktgen_count = "1"
        self.pktgen_burst = "1"
        self.pktgen_delay = "0"
        self.pktgen_frags = "4"
        self.pktgen_vlan_id = "0"
        self.eth_interface = "eth0"
        self.host_interface = "enp9s0"
        self.updown_count = "3"
        self.mtu = "1500"
        self.udp_mtu = "1500"
        self.iperf3_binary = "iperf3"
        self.extra_iperf3_args = ""
        self.timeout = "60"
        self.client_user = None
        self.client_password = None
        self.client_sudo_login = None
        self.server_user = "******"
        self.server_password = "******"
        self.config = config
        self.terminal = console
        self.log = log
        self.eth_interface = eth_interface
        self.terminal.prompt = r"root(.*?)# "
        if self.config.get("client_user"):
            self.client_user = self.config.client_user
        if self.config.get("client_password"):
            self.client_password = self.config.client_password
        if self.config.get("client_sudo_login"):
            self.client_sudo_login = self.config.client_sudo_login
        if self.config.get("target_ip"):
            self.client_ip = self.config.target_ip
        if self.config.get("board_ip"):
            self.board_ip = self.config.board_ip
        if self.config.get("client_mac"):
            self.client_mac = self.config.client_mac

    def _setip_config(self, config):
        self.config = config

    def ping_test(self):
        cmd = f"ping {self.client_ip} -s {self.ping_size} -c {self.ping_count}"
        self.terminal.runcmd(cmd=str(cmd),
                             timeout=60,
                             expected=" 0% packet loss")

    def ping_flood(self):
        self.get_client_console()
        self.client_console.runcmd(
            cmd=f"ping -f {self.board_ip} -i 5 -c 5",
            timeout=60,
            expected=" 0% packet loss",
        )
        self.terminal.runcmd(cmd=f"ping {self.client_ip} -c 5",
                             timeout=30,
                             expected=" 0% packet loss")

    def ifupdown(self):
        for count in self.updown_count:
            self.terminal.runcmd(cmd=f"ifconfig {self.eth_interface} down",
                                 timeout=15)
            self.terminal.runcmd(
                cmd=f"ifconfig {self.eth_interface} up;sleep 5",
                timeout=15,
                expected_failures="link is not ready",
            )
            self.ping_test()

    def eth_pktgen(self):
        commands = [
            "echo 'stop' > /proc/net/pktgen/pgctrl",
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_0",
            f"echo 'add_device {self.eth_interface}' > /proc/net/pktgen/kpktgend_0",
            f"echo 'count {self.pktgen_count}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'clone_skb 100' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'pkt_size {self.pktgen_size}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'burst {self.pktgen_burst}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'delay {self.pktgen_delay}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'vlan_id {self.pktgen_vlan_id}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'vlan_p 0' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'vlan_cfi 0' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'frags {self.pktgen_frags}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'dst {self.client_ip}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'dst_mac {self.client_mac}' > /proc/net/pktgen/{self.eth_interface}",
            "echo 'start' > /proc/net/pktgen/pgctrl",
            f"cat /proc/net/pktgen/{self.eth_interface}",
            "paramsCount=$(grep -E 'Params: count' /proc/net/pktgen/eth0 | awk '{print substr($3,1)}')",
            "pktSofar=$(grep -E 'pkts-sofar' /proc/net/pktgen/eth0 | awk '{print substr($2,1)}')",
            '[ "$paramsCount" -eq "$pktSofar" ]',
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)

    def eth_scp(self):
        self.terminal.runcmd(cmd="scp_file=$(mktemp scp.XXXXXXXXX)")
        self.terminal.runcmd(
            cmd=
            f"dd if=/dev/zero of=$scp_file bs=1 count=0 seek={self.file_size}")
        scp_cmd = f"scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r $scp_file {self.client_user}@{self.client_ip}:/home/{self.client_user}"
        index = self.terminal.runcmd(
            cmd=scp_cmd,
            expected=["(y/n)", "password"],
            wait_for_prompt=False,
            timeout=120,
        )
        if index == "1":
            self.terminal.runcmd(cmd=f"{self.client_password}", timeout=120)
        else:
            self.terminal.runcmd(cmd="y",
                                 expected="password",
                                 wait_for_prompt=False,
                                 timeout=300)
            self.terminal.runcmd(cmd=f"{self.client_password}")
        self.terminal.runcmd(cmd="rm $scp_file")

    def iperf_tcp_host_client(self):
        self.log.info("Starting an iperf3 server on the client...")
        self.get_client_console()
        cmd = f"{self.iperf3_binary} -s &"
        self.client_console.runcmd(cmd=cmd,
                                   expected="Server listening",
                                   wait_for_prompt=False,
                                   timeout=60)
        self.log.info(f"Measuring {self.iperf3_binary} TCP throughput...")
        cmd = f"{self.iperf3_binary} -c {self.client_ip} -f m {self.extra_iperf3_args}"
        self.terminal.runcmd(cmd=cmd, timeout=60)
        time.sleep(5)
        self.client_console.runcmd(cmd=f"pkill {self.iperf3_binary}",
                                   timeout=60)

    def iperf_tcp_client_host(self):
        self.get_client_console()
        self.log.info("Starting an iperf3 server on the board...")
        self.terminal.runcmd(cmd=f"{self.iperf3_binary} -s &", timeout=60)
        time.sleep(15)
        self.log.info(f"Starting an iperf3 client...")
        self.client_console.runcmd(
            cmd=
            f"{self.iperf3_binary} -c {self.board_ip} -f m {self.extra_iperf3_args}",
            timeout=60,
        )
        time.sleep(5)
        self.terminal.runcmd(cmd=f"pkill {self.iperf3_binary}", timeout=60)

    def iperf_udp_host_client(self):
        self.log.info("Starting an iperf3 server on the client...")
        self.get_client_console()
        cmd = f"{self.iperf3_binary} -s &"
        self.client_console.runcmd(cmd=cmd,
                                   expected="Server listening",
                                   wait_for_prompt=False,
                                   timeout=60)
        time.sleep(15)
        self.log.info(f"Measuring {self.iperf3_binary} UDP throughput...")
        cmd = (
            f"{self.iperf3_binary} -c {self.client_ip} -f m -u {self.extra_iperf3_args}"
        )
        self.terminal.runcmd(cmd=cmd, timeout=60)
        time.sleep(5)
        self.client_console.runcmd(cmd=f"pkill {self.iperf3_binary}",
                                   timeout=60)

    def iperf_udp_client_host(self):
        self.get_client_console()
        self.log.info("Starting an iperf3 server on the board...")
        self.terminal.runcmd(cmd=f"{self.iperf3_binary} -s &", timeout=60)
        time.sleep(15)
        self.log.info(f"Starting an iperf3 client...")
        self.client_console.runcmd(
            cmd=
            f"{self.iperf3_binary} -c {self.board_ip} -f m -u {self.extra_iperf3_args}",
            timeout=60,
        )
        time.sleep(5)
        self.terminal.runcmd(cmd=f"pkill {self.iperf3_binary}", timeout=60)

    def netperf_tcp_host_client(self):
        self.log.info("Starting an netperf server on the client...")
        self.get_client_console()
        cmd = f"ps -ef | grep netserver || netserver -D -4 &"
        self.client_console.runcmd(cmd=cmd, timeout=20)
        if self.mtu != "1500":
            time.sleep(2)
            self.log.info(
                f"Updating MTU size on host and device... : {self.mtu}")
            self.terminal.runcmd(
                cmd=
                f"ifconfig {self.eth_interface} down; ifconfig {self.eth_interface} mtu {self.mtu} up; ifconfig"
            )
            time.sleep(5)
            self.client_console.runcmd(
                cmd=
                f"ifconfig {self.eth_interface} down; ifconfig {self.eth_interface} mtu {self.mtu} up; ifconfig"
            )
            time.sleep(5)
            self.udp_mtu = f"{self.mtu} - 28"
            time.sleep(5)
        self.log.info(
            f"Device Netperf Output for TCP(Tx Mode) with MTU size {self.mtu}")
        time.sleep(1)
        cmd = f"netperf -c -C -H {self.client_ip} -t TCP_STREAM"
        failures = ["No space left on device", "recv_response:"]
        self.terminal.runcmd(cmd=cmd, expected_failures=failures, timeout=60)
        time.sleep(5)

    def netperf_udp_host_client(self):
        self.log.info("Starting an netperf server on the client...")
        self.get_client_console()
        cmd = f"ps -ef | grep netserver || netserver -D -4 &"
        self.client_console.runcmd(cmd=cmd, timeout=20)
        if self.mtu != "1500":
            time.sleep(2)
            self.log.info(
                f"Updating MTU size on host and device... : {self.mtu}")
            self.terminal.runcmd(
                cmd=
                f"ifconfig {self.eth_interface} down; ifconfig {self.eth_interface} mtu {self.mtu} up; ifconfig"
            )
            time.sleep(5)
            self.client_console.runcmd(
                cmd=
                f"ifconfig {self.eth_interface} down; ifconfig {self.eth_interface} mtu {self.mtu} up; ifconfig"
            )
            time.sleep(5)
            self.udp_mtu = f"{self.mtu} - 28"
            time.sleep(5)
        self.log.info(
            f"Device Netperf Output for UDP(Tx Mode) with MTU Size: {self.mtu}"
        )
        time.sleep(1)
        cmd = f"netperf -c -C -H {self.client_ip} -t UDP_STREAM"
        failures = ["No space left on device", "recv_response:"]
        self.terminal.runcmd(cmd=cmd, expected_failures=failures, timeout=60)
        time.sleep(5)

    def netperf_tcp_client_host(self):
        self.get_client_console()
        failures = ["No space left on device", "recv_response:"]
        cmd = f"ps -ef | grep netserver || netserver -D -4 &"
        self.terminal.runcmd(cmd=cmd, timeout=20)
        time.sleep(5)
        cmd = f"netperf -c -C -H {self.board_ip} -t TCP_STREAM -- -m {self.mtu} -M {self.mtu}"
        self.client_console.runcmd(cmd=cmd,
                                   expected_failures=failures,
                                   timeout=50)

    def netperf_udp_client_host(self):
        self.get_client_console()
        failures = ["No space left on device", "recv_response:"]
        cmd = f"ps -ef | grep netserver || netserver -D -4 &"
        self.terminal.runcmd(cmd=cmd, timeout=20)
        time.sleep(5)
        self.log.info(
            f"Host Netperf Output for UDP(Rx Mode) with MTU Size: {self.udp_mtu}"
        )
        cmd = f"netperf -c -C -H {self.board_ip} -t UDP_STREAM -- -m {self.mtu} -M {self.udp_mtu}"
        self.client_console.runcmd(cmd=cmd, timeout=50)
        time.sleep(5)

    def eth_dhcp(self):
        cmd = f"udhcpc -i {self.eth_interface}"
        self.terminal.runcmd(cmd=cmd,
                             timeout=30,
                             expected_failures=["not found"])
        self.ping_test()

    def eth_speed(self):

        for speed in [1000, 10, 100]:
            cmd = f"ethtool -s {self.eth_interface} speed {speed} duplex full; sleep 15"
            self.terminal.runcmd(cmd=cmd)
            self.terminal.sendline("\r\n")
            self.terminal.runcmd(cmd=f"ethtool {self.eth_interface}")
            self.ping_test()
        cmd = f"ethtool -s {self.eth_interface} autoneg on; sleep 15"
        self.terminal.runcmd(cmd=cmd)
        self.terminal.sendline("\r\n")
        self.terminal.runcmd(cmd=f"ethtool {self.eth_interface}")
        self.ping_test()

    def eth_tftp(self):
        failures = [
            "server error:",
            "(2) Access violation",
            "No such file or directory",
            "ERROR",
        ]
        tftp_file = "system.bit"
        cmdd = f"tftp -g -r {tftp_file} {self.client_ip}"
        self.terminal.runcmd(cmd=cmdd, timeout=300, expected_failures=failures)

    def eth_telnet(self):
        self.terminal.runcmd(cmd="telnetd", timeout=20)
        self.get_client_console()
        self.client_console.runcmd(
            cmd=f"telnet {self.board_ip}",
            timeout=20,
            expected="Peta",
            wait_for_prompt=False,
        )
        self.client_console.sendline("root")
        self.client_console.sendline("root")
        time.sleep(1)
        self.client_console.sendline("root")
        self.client_console.runcmd(cmd=f"ls",
                                   timeout=20,
                                   expected=":~# ",
                                   wait_for_prompt=False)

    def eth_gravcat(self, **kwargs):
        self.get_client_console()
        cmd = f"gravecat -l 9999 &"
        self.terminal.sync()
        self.terminal.runcmd(cmd=cmd,
                             timeout=20,
                             expected_failures=["ommand", "failed"])
        self.client_console.runcmd(
            f"/usr/bin/gravecat_x86_64 -s {self.boardIp} 9999 4 1000 500",
            expected="using",
            timeout=10,
            wait_for_prompt=False,
        )
        time.sleep(600)
        self.client_console.sendline("\x03")
        self.client_console.runcmd(
            cmd="if pgrep gravecat;then kill -9 `pgrep -f gravecat`; fi")
        self.terminal.sync()
        self.ifupdown()

    def suspend_resume_eth_wkp(self, platform):
        eth_nodes = ["ff0b0000", "ff0c0000", "ff0d0000", "ff0e0000"]
        self.log.info("Starting an netperf server on the client...")
        self.terminal.runcmd("cat /proc/cpuinfo")
        self.terminal.runcmd("ifconfig -a")
        self.terminal.runcmd("echo 8 > /proc/sys/kernel/printk")
        self.terminal.runcmd(
            "echo 0 > /sys/module/printk/parameters/console_suspend")
        if platform == "versal":
            self.terminal.runcmd(
                f"echo disabled > {self.sys_axi}/ff000000.serial/tty/ttyAMA0/power/wakeup"
            )
            self.terminal.runcmd(
                f"echo enabled > {self.sys_axi}/ff0c0000.ethernet/net/eth0/power/wakeup"
            )
            self.terminal.runcmd(
                "echo mem > /sys/power/state",
                expected="CPU1 killed",
                wait_for_prompt=False,
            )
        else:
            self.terminal.runcmd(
                f"echo disabled > {self.sys_axi}/ff000000.serial/tty/ttyPS0/power/wakeup"
            )
            for node in eth_nodes:
                self.terminal.runcmd(
                    f"cat /proc/device-tree/axi/ethernet\@{node}/status",
                    expected="\r\n",
                )
                node_status = self.terminal.output()
                if node_status == "okay":
                    ethernet_node = node
            self.terminal.runcmd(
                f"echo enabled > {self.sys_axi}/{ethernet_node}.ethernet/net/eth0/power/wakeup"
            )
            self.terminal.runcmd(
                "echo mem > /sys/power/state",
                expected="CPU3 killed",
                wait_for_prompt=False,
            )
        self.get_client_console()
        self.client_console.runcmd(cmd=f"ping {self.board_ip} -c 5",
                                   expected_failures="0 received",
                                   retries=2)
        time.sleep(15)
        is_linux_cons(self.terminal)
        self.terminal.runcmd("pwd")
        if platform == "versal":
            self.terminal.runcmd(
                f"echo enabled > {self.sys_axi}/ff000000.serial/tty/ttyAMA0/power/wakeup"
            )
            self.terminal.runcmd('bootmode="sd_boot"')
        else:
            self.terminal.runcmd(
                f"echo enabled > {self.sys_axi}/ff000000.serial/tty/ttyPS0/power/wakeup"
            )

    def get_client_console(self):
        if self.config["eth_host_name"]:
            self.client_console = Xexpect(
                hostname=self.config["eth_host_name"],
                hostip=None,
                userid=None,
                password=None,
                non_interactive=False,
                log=log,
            )
        elif self.config["board_interface"] == "systest":
            client_ip = self.config["systest_host"]
            self.client_console = Xexpect(hostname=client_ip,
                                          non_interactive=False,
                                          log=log)
        else:
            client_ip = self.client_ip
            self.client_console = Xexpect(
                hostip=client_ip,
                userid=self.client_user,
                password=self.client_password,
                non_interactive=False,
                log=log,
            )
            self.client_console.prompt = "bash-"
            self.client_console.runcmd("/bin/bash --norc")

        def _sudo_login():
            self.client_console.prompt = r"root(.*?)# "
            self.client_console.sendline(cmd="sudo su -")
            index = self.client_console.expect(
                expected=["password", "root"],
                expected_failures="Permission denied",
                err_msg="fail to login with sudo",
                wait_for_prompt=False,
            )
            if index == 1:
                self.client_console.runcmd(
                    cmd=self.client_password,
                    expected="root",
                    expected_failures=[
                        "Permission denied", "Sorry", "not allowed"
                    ],
                    err_msg="fail to login with sudo",
                    wait_for_prompt=False,
                )

        def _set_status_init():
            self.client_console.sync()
            self.client_console._setup_init()
            self.client_console.exit_nzero_ret = True

        if self.client_sudo_login:
            _sudo_login()
        _set_status_init()

    def ifplugd(self):
        self.terminal.runcmd(cmd="ifplugd")
        cmd = f'pgrep -f ifplugd >/dev/null || echo "ifplugd demon not running"'
        self.terminal.runcmd(cmd=cmd,
                             timeout=30,
                             expected_failures=["ifplugd demon not running"])
        self.ifupdown()
        cmd = f"ifconfig {self.eth_interface} {self.board_ip} netmask 255.255.255.0"
        self.terminal.runcmd(cmd=cmd, timeout=self.timeout)

    def eth_nfs(self):
        self.log.info("Output test files and clean up..")
        cmd_list = [
            "out_dir=/tmp/nfs_temp_output",
            "mkdir -p ${out_dir} > /dev/null 2>&1",
            "out_prefix=${out_dir}/nfs_test",
            "out_mount=${out_prefix}.mount",
            "out_mount_prefix=${out_mount}/nfs_test",
            "unmount ${out_mount} && rm -rf ${out_prefix}*",
        ]

        self.terminal.runcmd_list(cmd_list=cmd_list, timeout=60)

        self.log.info("Mounting NFS...")
        cmd_list = [
            "mkdir -p ${out_mount}",
            f'rpcinfo "{self.client_ip}" | grep "nfs"',
            f"mount -o port=2049,nolock,proto=tcp,vers=2 {self.client_ip}:/exports/root $out_mount",
        ]
        self.terminal.runcmd_list(cmd_list=cmd_list, timeout=200)

        self.log.info("Creating large pattern data files..")
        cmd_list = [
            " [ -c /dev/urandom ] || mknod -m 777 /dev/urandom c 1 9 > /dev/null 2>&1;",
            "dd if=/dev/urandom of=${out_prefix}.r2m-pattern.bin bs=1024 count=4096;",
            "dd if=/dev/urandom of=${out_mount_prefix}.m2r-pattern.bin bs=1024 count=4096;",
            "cp ${out_mount_prefix}.m2r-pattern.bin ${out_prefix}.m2r-pattern.bin;",
            "cp ${out_prefix}.r2m-pattern.bin ${out_mount_prefix}.r2m-pattern.bin;",
        ]

        self.terminal.runcmd_list(cmd_list=cmd_list, timeout=200)
        self.log.info("Re-mounting the NFS.. Verifying the read back data...")
        cmd_list = [
            "umount ${out_mount};",
            f"mount -o port=2049,nolock,proto=tcp,vers=2 {self.client_ip}:/exports/root $out_mount;"
            "diff -q ${out_prefix}.m2r-pattern.bin ${out_mount_prefix}.m2r-pattern.bin",
            "diff -q ${out_mount_prefix}.r2m-pattern.bin ${out_prefix}.r2m-pattern.bin",
        ]
        self.terminal.runcmd_list(cmd_list=cmd_list, timeout=200)

    def vlan_test(self):
        cmd = "board_mac=$(ifconfig eth0 | awk '/HWaddr/ {print substr($5,1)}')"
        self.terminal.runcmd(cmd=cmd, timeout=60)
        self.BoardMac = self.terminal.output()
        time.sleep(2)
        self.log.info(f"Board HWaddr : {self.BoardMac}... ")
        cmd = 'tcpdump -i {self.eth_interface} "vlan and icmp" and ip host 10.10.70.2 and ether host "$board_mac" -n -ev &'
        self.terminal.runcmd(cmd=cmd, timeout=60)
        time.sleep(2)
        cmd_list = [
            "ip link set dev eth2.5 down &",
            "ip link del eth2.5 &",
            "modprobe 8021q &",
            "ip link add link eth2 name eth2.5 type vlan id 5 &",
            "ip addr add 10.10.70.2 brd 10.10.70.255 dev eth2.5 &",
            "ip link set dev eth2.5 up &",
            f"arp -s {self.client_ip} $board_mac dev eth2.5 &",
            f"{self.client_ip} -I eth2.5 -c 3 &",
        ]
        self.get_client_console()
        self.client_console.runcmd(cmd=cmd_list, timeout=120)
        time.sleep(10)
        self.log.info("=================== rx output ===================")
        self.terminal.runcmd(cmd="killall -s INT tcpdump &", timeout=60)
        time.sleep(2)
        cmd_list = [
            "ip link set dev eth2.5 down &",
            "ip link del eth2.5 &",
            f"route del {self.client_ip} &",
            f"route add {self.client_ip} dev eth2 &",
            f"tcpdump -n -i eth2 dst port 9 and ip host {self.client_ip} -e -v > ~/tx_tcpdump_vlan.txt &",
        ]
        self.client_console.runcmd(cmd=cmd_list, timeout=120)
        time.sleep(10)
        self.client_console.runcmd(cmd="gettest_hostmac", timeout=20)
        time.sleep(1)
        commands = [
            "echo 'stop' > /proc/net/pktgen/pgctrl",
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_0",
            "echo 'add_device eth0' > /proc/net/pktgen/kpktgend_0",
            "echo 'count 1' > /proc/net/pktgen/eth0",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0",
            "echo 'pkt_size 200' > /proc/net/pktgen/eth0",
            "echo 'delay 0' > /proc/net/pktgen/eth0",
            "echo 'frags 4' > /proc/net/pktgen/eth0",
            "echo 'vlan_id 0' > /proc/net/pktgen/eth0",
            "echo 'vlan_p 0' > /proc/net/pktgen/eth0",
            "echo 'vlan_cfi 0' > /proc/net/pktgen/eth0",
            f"echo 'dst {self.board_ip}' > /proc/net/pktgen/eth0",
            f"echo 'dst_mac {self.client_mac}' > /proc/net/pktgen/eth0",
            "echo 'start' > /proc/net/pktgen/pgctrl",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(4)
        self.log.info("=================== tx output ===================")
        cmd_list = [
            "killall -s INT tcpdump &",
            "cat ~/tx_tcpdump_vlan.txt",
            "rm ~/tx_tcpdump_vlan.txt",
        ]
        self.client_console.runcmd(cmd=cmd_list, timeout=120)
        time.sleep(10)

    def update_mtu(self, **kwargs):
        self.get_client_console()
        self.log.info(f"Updating MTU size on host and device... : {self.mtu}")
        self.terminal.runcmd_list(cmd_list=[
            f"ifconfig {self.eth_interface} down",
            "sleep 10",
            f"ifconfig {self.eth_interface} mtu {self.mtu} {self.boardIp}  up",
            "sleep 5",
            "ifconfig",
        ])
        time.sleep(5)
        self.client_console.runcmd_list(cmd_list=[
            f"sudo ifconfig {self.host_interface} down",
            "sleep 10",
            f"sudo ifconfig {self.host_interface} mtu {self.mtu} {self.clientIp} up",
            "sleep 5",
            "sudo ifconfig",
        ])
        time.sleep(5)
        self.terminal.sync()

    def ping_jumbo_frame(self, **kwargs):
        self.get_client_console()
        for mtu in [1500, 2048, 4096, 8192]:
            self.log.info(f"Updating MTU size on device... : {mtu}")
            self.mtu = mtu
            self.update_mtu()
            self.terminal.sync()
            time.sleep(3)
            self.terminal.runcmd(
                cmd=f"ping {self.clientIp} -s {mtu-28} -c 5",
                timeout=30,
                expected=" 0% packet loss",
            )
            time.sleep(2)
        self.mtu = 1500
        self.update_mtu()

    def mii_test(self, **kwargs):
        self.terminal.runcmd(cmd=f"mii-tool -v {self.eth_interface}",
                             expected="link ok")
        self.terminal.runcmd(
            cmd=f"mii-tool --force 10baseT-FD {self.eth_interface}",
            expected=" ")
        self.terminal.runcmd(cmd=f"mii-tool {self.eth_interface}",
                             expected=": 10 Mbit")
        self.terminal.runcmd(cmd=f"mii-tool --restart {self.eth_interface}",
                             expected=" ")
        self.terminal.sync()
        time.sleep(10)
        self.ping_test()
        self.terminal.sync()

    def eth_pqueue(self):
        self.client_console.runcmd(cmd="gettest_hostmac", timeout=20)
        self.client_console.runcmd(cmd="killall -s INT tcpdump &", timeout=20)
        self.client_console.runcmd(cmd="rm ~/priority.txt &", timeout=20)
        self.client_console.runcmd(
            cmd=
            f"tcpdump -n -i {self.host_interface} ip host {self.board_ip} -ev > ~/priority.txt &",
            timeout=20,
        )
        time.sleep(5)
        self.log.info(f"targetMac = {self.client_mac}")
        commands = [
            "echo 'stop' > /proc/net/pktgen/pgctrl",
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_0",
            "echo 'add_device eth0@0' > /proc/net/pktgen/kpktgend_0",
            "echo 'count 500' > /proc/net/pktgen/eth0@0",
            "echo 'burst 50' > /proc/net/pktgen/eth0@0",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0@0",
            "echo 'pkt_size 1500' > /proc/net/pktgen/eth0@0",
            "echo 'delay 0' > /proc/net/pktgen/eth0@0",
            "echo 'frags 0' > /proc/net/pktgen/eth0@0",
            f"echo 'dst {self.board_ip}' > /proc/net/pktgen/eth0@0",
            f"echo 'dst_mac {self.client_mac}' > /proc/net/pktgen/eth0@0",
            "echo 'skb_priority 1' > /proc/net/pktgen/eth0@0",
            "echo 'queue_map_min 0' > /proc/net/pktgen/eth0@0",
            "echo 'queue_map_max 0' > /proc/net/pktgen/eth0@0",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(5)
        commands = [
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_1",
            "echo 'add_device eth0@1' > /proc/net/pktgen/kpktgend_1",
            "echo 'count 20' > /proc/net/pktgen/eth0@1",
            "echo 'burst 20' > /proc/net/pktgen/eth0@1",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0@1",
            "echo 'pkt_size 1400' > /proc/net/pktgen/eth0@1",
            "echo 'delay 0' > /proc/net/pktgen/eth0@1",
            "echo 'frags 0' > /proc/net/pktgen/eth0@1",
            f"echo 'dst {self.board_ip}' > /proc/net/pktgen/eth0@1",
            f"echo 'dst_mac {self.client_mac}' > /proc/net/pktgen/eth0@1",
            "echo 'skb_priority 1' > /proc/net/pktgen/eth0@1",
            "echo 'queue_map_min 1' > /proc/net/pktgen/eth0@1",
            "echo 'queue_map_max 1' > /proc/net/pktgen/eth0@1",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(5)
        commands = [
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_2",
            "echo 'add_device eth0@2' > /proc/net/pktgen/kpktgend_2",
            "echo 'count 500' > /proc/net/pktgen/eth0@2",
            "echo 'burst 50' > /proc/net/pktgen/eth0@2",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0@2",
            "echo 'pkt_size 1200' > /proc/net/pktgen/eth0@2",
            "echo 'delay 0' > /proc/net/pktgen/eth0@2",
            "echo 'frags 0' > /proc/net/pktgen/eth0@2",
            f"echo 'dst {self.board_ip}' > /proc/net/pktgen/eth0@2",
            f"echo 'dst_mac {self.client_mac}' > /proc/net/pktgen/eth0@2",
            "echo 'skb_priority 1' > /proc/net/pktgen/eth0@2",
            "echo 'queue_map_min 0' > /proc/net/pktgen/eth0@2",
            "echo 'queue_map_max 0' > /proc/net/pktgen/eth0@2",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(5)
        commands = [
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_3",
            "echo 'add_device eth0@3' > /proc/net/pktgen/kpktgend_3",
            "echo 'count 20' > /proc/net/pktgen/eth0@3",
            "echo 'burst 20' > /proc/net/pktgen/eth0@3",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0@3",
            "echo 'pkt_size 1100' > /proc/net/pktgen/eth0@3",
            "echo 'delay 0' > /proc/net/pktgen/eth0@3",
            "echo 'frags 0' > /proc/net/pktgen/eth0@3",
            f"echo 'dst {self.board_ip}' > /proc/net/pktgen/eth0@3",
            f"echo 'dst_mac {self.client_mac}' > /proc/net/pktgen/eth0@3",
            "echo 'skb_priority 1' > /proc/net/pktgen/eth0@3",
            "echo 'queue_map_min 1' > /proc/net/pktgen/eth0@3",
            "echo 'queue_map_max 1' > /proc/net/pktgen/eth0@3",
            "echo 'start' > /proc/net/pktgen/pgctrl &",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(5)
        self.client_console.runcmd(cmd="killall -s INT tcpdump &", timeout=20)
        self.client_console.runcmd(cmd="cat ~/priority.txt &", timeout=20)
Example #3
0
class Ethernet:

    attributes = [
        "hostIp",
        "targetIp",
        "ping_intervel",
        "ping_size",
        "ping_count",
        "file_size",
        "pktgen_size",
        "pktgen_count",
        "pktgen_burst",
        "pktgen_delay",
        "pktgen_frags",
        "pktgen_vlan_id",
        "host_interface",
        "ifupdwn_count",
        "mtu",
        "eth_interface",
        "user",
        "password",
        "iperf_binary",
        "extra_iperf_args",
    ]

    targetIp = "10.10.70.101"
    hostIp = "10.10.70.21"
    ping_intervel = "1"
    ping_size = "45"
    ping_count = "10"
    file_size = "4096"
    pktgen_size = "200"
    pktgen_count = "1"
    pktgen_burst = "1"
    pktgen_delay = "0"
    pktgen_frags = "4"
    pktgen_vlan_id = "0"
    eth_interface = "eth0"
    host_interface = "enp9s0"
    updown_count = "3"
    mtu = "1500"
    udp_mtu = "1500"
    iperf_binary = "iperf"
    extra_iperf_args = ""
    timeout = "60"
    user = ""
    password = ""

    def __init__(self, config, terminal, eth_interface):
        self.config = config
        self.terminal = terminal
        self.log = log
        self.eth_interface = eth_interface
        self.terminal.prompt = "~# "
        self.terminal._setup_init()
        if config["user"]:
            self.user = config["user"]
        if config["password"]:
            self.password = config["password"]

    def _setip_config(self, config):
        self.config = config

    def eth_default_runner(func):
        @functools.wraps(func)
        def override_defaults(self, **kwargs):
            ts = time.time()
            self.log.info(f"Start ethernet test {func.__name__} ...")
            for attr, value in kwargs.items():
                if attr not in self.attributes:
                    raise ValueError(
                        "Attribute [{}] not supported.".format(attr))
                else:
                    setattr(self, attr, value)
                    self.log.info(f"key: {attr}, value: {value}")
            func(self, **kwargs)
            te = time.time()
            self.log.info(
                f"Ethernet test {func.__name__} end .. Total time taken:{round((te -ts),1)}, sec"
            )
            self.__init__(self.config, self.terminal, self.eth_interface)
            return True

        return override_defaults

    @eth_default_runner
    def ping_test(self, **kwargs):

        cmd = f"ping {self.targetIp} -s {self.ping_size} -c {self.ping_count}"
        self.terminal.runcmd(cmd=str(cmd),
                             timeout=20,
                             expected=" 0% packet loss")

    @eth_default_runner
    def eth_speed(self, **kwargs):
        import random

        for speed in [1000, 10, 100]:
            cmd = f"ethtool -s {self.eth_interface} speed {speed} duplex full"
            self.terminal.runcmd(cmd=cmd, timeout=30, expected="link")
            self.terminal.sendline("\r\n")
            self.terminal.runcmd(cmd=f"ethtool {self.eth_interface}")
            self.ping_test()
        cmd = f"ethtool -s {self.eth_interface} autoneg on"
        self.terminal.runcmd(cmd=cmd, timeout=30, expected="link")
        self.terminal.sendline("\r\n")
        self.terminal.runcmd(cmd=f"ethtool {self.eth_interface}")
        self.ping_test()

    @eth_default_runner
    def ifupdown(self, **kwargs):
        for count in self.updown_count:
            self.terminal.runcmd(cmd=f"ifconfig {self.eth_interface} down",
                                 timeout=15,
                                 expected="root")
            self.terminal.runcmd(
                cmd=f"ifconfig {self.eth_interface} up;sleep 3",
                timeout=15,
                expected="root",
                expected_failures="link is not ready",
            )
            self.ping_test()

    @eth_default_runner
    def ifplugd(self, **kwargs):
        cmd = f'pgrep -f ifplugd >/dev/null || echo "ifplugd demon not running"'
        self.terminal.runcmd(cmd=cmd,
                             timeout=30,
                             expected_failures=["ifplugd demon not running"])
        self.ifupdown()
        cmd = f"ifconfig {self.eth_interface} {self.hostIp} netmask 255.255.255.0"
        self.terminal.runcmd(cmd=cmd, timeout=self.timeout)

    @eth_default_runner
    def eth_tftp(self, **kwargs):
        failures = [
            "server error:",
            "(2) Access violation",
            "No such file or directory",
            "ERROR",
        ]
        cmd_list = [
            "tftp_file=$(mktemp tftp.XXXXXX)",
            f"dd if=/dev/zero of=$tftp_file bs=1 count=0 seek={self.file_size}",
        ]
        self.terminal.runcmd_list(cmd_list=cmd_list,
                                  timeout=30,
                                  expected_failures=failures)
        self.run_on_host(cmd="chmod 777 -R /tftpboot/")

        cmd_list = [
            f"tftp -p -r $tftp_file {self.targetIp}",
            "file1=$(md5sum $tftp_file | awk '{print $1}')",
            "rm $tftp_file",
        ]
        self.terminal.runcmd_list(cmd_list=cmd_list,
                                  timeout=300,
                                  expected_failures=failures)
        self.run_on_host(cmd="chmod 777 -R /tftpboot/")
        cmd_list = [
            f"tftp -g -r $tftp_file {self.targetIp}",
            "file2=$(md5sum $tftp_file | awk '{print $1}')",
            "[ $file1 == $file2 ] || return 1",
        ]
        self.terminal.runcmd_list(cmd_list=cmd_list,
                                  timeout=300,
                                  expected_failures=failures)
        self.run_on_host(cmd="rm -rf /tftpboot/tftp*")

    @eth_default_runner
    def eth_nfs(self, **kwargs):
        self.log.info("Output test files and clean up..")
        cmd_list = [
            "out_dir=/tmp/nfs_temp_output",
            "mkdir -p ${out_dir} > /dev/null 2>&1",
            "out_prefix=${out_dir}/nfs_test",
            "out_mount=${out_prefix}.mount",
            "out_mount_prefix=${out_mount}/nfs_test",
            "unmount ${out_mount} && rm -rf ${out_prefix}*",
        ]

        self.terminal.runcmd_list(cmd_list=cmd_list, timeout=60)

        self.log.info("Mounting NFS...")
        cmd_list = [
            "mkdir -p ${out_mount}",
            f'rpcinfo "{self.targetIp}" | grep "nfs"',
            f"mount -o port=2049,nolock,proto=tcp,vers=2 {self.targetIp}:/exports/root $out_mount",
        ]
        self.terminal.runcmd_list(cmd_list=cmd_list, timeout=200)

        self.log.info("Creating large pattern data files..")
        cmd_list = [
            " [ -c /dev/urandom ] || mknod -m 777 /dev/urandom c 1 9 > /dev/null 2>&1;",
            "dd if=/dev/urandom of=${out_prefix}.r2m-pattern.bin bs=1024 count=4096;",
            "dd if=/dev/urandom of=${out_mount_prefix}.m2r-pattern.bin bs=1024 count=4096;",
            "cp ${out_mount_prefix}.m2r-pattern.bin ${out_prefix}.m2r-pattern.bin;",
            "cp ${out_prefix}.r2m-pattern.bin ${out_mount_prefix}.r2m-pattern.bin;",
        ]

        self.terminal.runcmd_list(cmd_list=cmd_list, timeout=200)
        self.log.info("Re-mounting the NFS.. Verifying the read back data...")
        cmd_list = [
            "umount ${out_mount};",
            f"mount -o port=2049,nolock,proto=tcp,vers=2 {self.targetIp}:/exports/root $out_mount;"
            "diff -q ${out_prefix}.m2r-pattern.bin ${out_mount_prefix}.m2r-pattern.bin",
            "diff -q ${out_mount_prefix}.r2m-pattern.bin ${out_prefix}.r2m-pattern.bin",
        ]
        self.terminal.runcmd_list(cmd_list=cmd_list, timeout=200)

    @eth_default_runner
    def eth_scp(self, **kwargs):
        cmd_list = [
            "scp_file=$(mktemp scp.XXXXXXXXX)",
            f"dd if=/dev/zero of=$scp_file bs=1 count=0 seek={self.file_size}",
            f'expect -c "spawn scp -r $scp_file {self.user}@{self.targetIp}:/home/{self.user}/;expect "password"; send "{self.password}"; interact"',
            "file1=$(md5sum $scp_file | awk '{print $1}') && rm $scp_file",
            f'expect -c "spawn scp {self.user}@{self.targetIp}:/home/{self.user}/$scp_file ./;expect "password:"******"{self.password}"; interact"',
            "file2=$(md5sum $scp_file | awk '{print $1})'",
            "[ $file1 == $file2 ] || echo 'scp test failed'",
        ]
        self.terminal.runcmd_list(cmd_list=cmd_list,
                                  timeout=120,
                                  expected_failure=["scp test failed"])

    @eth_default_runner
    def eth_telnet(self, **kwargs):
        self.terminal.runcmd(cmd="telnetd", timeout=20)
        self.test_host_console = Xexpect(
            hostname=self.config["eth_host_name"],
            non_interactive=False,
            log=log,
        )
        self.test_host_console.runcmd(
            cmd=f"telnet {self.hostIp}",
            timeout=20,
            expected="Peta",
            wait_for_prompt=False,
        )
        self.test_host_console.sendline("root")
        self.test_host_console.sendline("root")
        time.sleep(1)
        self.test_host_console.sendline("root")
        self.test_host_console.runcmd(cmd=f"ls",
                                      timeout=20,
                                      expected=":~# ",
                                      wait_for_prompt=False)

    @eth_default_runner
    def eth_dhcp(self, **kwargs):
        cmd = f"udhcp -i {self.eth_interface}"
        self.terminal.runcmd(cmd=cmd,
                             timeout=30,
                             expected_failures=["not found"])
        self.ping_test()

    @eth_default_runner
    def iperf_test(self, **kwargs):
        self.log.info("Starting an iperf server on the host...")
        cmd = f"{self.iperf_binary} -s &"
        self.run_on_host(cmd=cmd, timeout=50)
        time.sleep(3)
        self.terminal.runcmd(
            cmd=f"tftp -g -r {self.iperf_binary} {self.targetIp}", timeout=60)
        self.terminal.runcmd(
            cmd=
            f"chmod 777 {self.iperf_binary}; mv {self.iperf_binary} /usr/sbin/",
            timeout=60,
        )
        time.sleep(3)
        self.log.info(f"Measuring {self.iperf_binary} TCP throughput...")
        cmd = f"{self.iperf_binary} -c {self.targetIp} -f m {self.extra_iperf_args}"
        self.terminal.runcmd(cmd=cmd, timeout=60)
        time.sleep(3)
        self.log.info(f"Measuring {self.iperf_binary} UDP throughput...")
        cmd = f"{self.iperf_binary} -c {self.targetIp} -f m -u {self.extra_iperf_args}"
        self.terminal.runcmd(cmd=cmd, timeout=60)
        self.log.info(
            f"Running {self.iperf_binary} with option -d | --dualtest ....")
        cmd = f"{self.iperf_binary} -c {self.targetIp} -f m -d {self.extra_iperf_args}"
        self.terminal.runcmd(cmd=cmd, timeout=60)
        time.sleep(3)
        self.run_on_host(cmd=f"pkill {self.iperf_binary}", timeout=50)
        self.log.info(
            f"Starting an {self.iperf_binary} server on the target...")
        # self.terminal.runcmd(cmd="tftp -g -r {self.iperf_binary} {self.targetIp}",timeout=60)
        self.terminal.runcmd(cmd=f"{self.iperf_binary} -s &", timeout=60)
        time.sleep(3)
        self.log.info(f"Starting an iperf client on the host...")
        self.run_on_host(
            cmd=
            f"{self.iperf_binary} -c {self.hostIp} -f m {self.extra_iperf_args}",
            timeout=50,
        )
        time.sleep(3)

    def run_on_host(self,
                    cmd,
                    expected="root",
                    timeout=60,
                    expected_failures=None,
                    **kwargs):
        self.test_host_console = Xexpect(
            hostname=self.config["eth_host_name"],
            non_interactive=False,
            log=log,
        )
        if cmd == "gettest_hostmac":
            self.test_host_console.runcmd(
                cmd="ifconfig enp9s0 | awk '/HWaddr {print substr($5,1)}'",
                timeout=30)
            self.targetMac = self.test_host_console.output()
        self.test_host_console.runcmd(cmd="sudo su -",
                                      timeout=timeout,
                                      expected="root")
        if type(cmd) is list:
            self.test_host_console.runcmd_list(
                cmd_list=f"{cmd}",
                expected_failures=expected_failures,
                timeout=timeout,
                expected=expected,
            )
        else:
            self.test_host_console.runcmd(
                cmd=f"{cmd}",
                expected=expected,
                timeout=timeout,
                expected_failures=expected_failures,
            )

    @eth_default_runner
    def netperf(self, **kwargs):
        failures = ["No space left on device", "recv_response:"]
        cmd = f"ps -ef | grep netserver || netserver -D -4 &"
        self.terminal.runcmd(cmd=cmd, timeout=20)
        if self.mtu != "1500":
            time.sleep(2)
            self.log.info(
                f"Updating MTU size on host and device... : {self.mtu}")
            self.terminal.runcmd(
                cmd=
                f"ifconfig {self.eth_interface} down; ifconfig {self.eth_interface} mtu {self.mtu} up; ifconfig"
            )
            time.sleep(3)
            self.run_on_host(
                cmd=
                f"ifconfig {self.host_interface} down; ifconfig {self.host_interface} mtu {self.mtu} up; ifconfig"
            )
            self.udp_mtu = f"{self.mtu} - 28"
            time.sleep(3)
        self.log.info(
            f"Device Netperf Output for TCP(Tx Mode) with MTU size {self.mtu}")
        time.sleep(1)
        cmd = f"netperf -c -C -H {self.targetIp} -t TCP_STREAM"
        self.terminal.runcmd(cmd=cmd, expected_failures=failures, timeout=50)
        time.sleep(3)
        self.log.info(
            f"Device Netperf Output for UDP(Tx Mode) with MTU Size: {self.mtu}"
        )
        time.sleep(1)
        cmd = f"netperf -c -C -H {self.targetIp} -t UDP_STREAM"
        self.terminal.runcmd(cmd=cmd, timeout=50)
        time.sleep(3)
        cmd = f"ps -ef | grep netserver"
        self.run_on_host(cmd=cmd, timeout=50)
        time.sleep(1)
        self.log.info(
            f"Host Netperf Output for TCP(Rx Mode) with MTU size: {self.mtu}")
        cmd = f"netperf -c -C -H {self.hostIp} -t TCP_STREAM -- -m {self.mtu} -M {self.mtu}"
        self.run_on_host(cmd=cmd, expected_failures=failures, timeout=50)
        time.sleep(3)
        self.log.info(
            f"Host Netperf Output for UDP(Rx Mode) with MTU Size: {self.udp_mtu}"
        )
        cmd = f"netperf -c -C -H {self.hostIp} -t UDP_STREAM -- -m {self.mtu} -M {self.udp_mtu}"
        self.run_on_host(cmd=cmd, timeout=50)
        time.sleep(2)

    @eth_default_runner
    def vlan_test(self, **kwargs):
        cmd = "board_mac=$(ifconfig eth0 | awk '/HWaddr {print substr($5,1)}')"
        self.terminal.runcmd(cmd=cmd, timeout=60)
        self.BoardMac = self.terminal.output()
        time.sleep(2)
        self.log.info(f"Board HWaddr : {self.BoardMac}... ")
        cmd = 'tcpdump -i {self.eth_interface} "vlan and icmp" and ip host 10.10.70.2 and ether host "$board_mac" -n -ev &'
        self.terminal.runcmd(cmd=cmd, timeout=60)
        time.sleep(2)
        cmd_list = [
            "ip link set dev eth2.5 down &",
            "ip link del eth2.5 &",
            "modprobe 8021q &",
            "ip link add link eth2 name eth2.5 type vlan id 5 &",
            "ip addr add 10.10.70.2 brd 10.10.70.255 dev eth2.5 &",
            "ip link set dev eth2.5 up &",
            f"arp -s {self.hostIp} $board_mac dev eth2.5 &",
            f"{self.hostIp} -I eth2.5 -c 3 &",
        ]
        self.run_on_host(cmd=cmd_list, timeout=120)
        time.sleep(10)
        self.log.info("=================== rx output ===================")
        self.terminal.runcmd(cmd="killall -s INT tcpdump &", timeout=60)
        time.sleep(2)
        cmd_list = [
            "ip link set dev eth2.5 down &",
            "ip link del eth2.5 &",
            f"route del {self.hostIp} &",
            f"route add {self.hostIp} dev eth2 &",
            f"tcpdump -n -i eth2 dst port 9 and ip host {self.hostIp} -e -v > ~/tx_tcpdump_vlan.txt &",
        ]
        self.run_on_host(cmd=cmd_list, timeout=120)
        time.sleep(10)
        self.run_on_host(cmd="gettest_hostmac", timeout=20)
        time.sleep(1)
        commands = [
            "echo 'stop' > /proc/net/pktgen/pgctrl",
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_0",
            "echo 'add_device eth0' > /proc/net/pktgen/kpktgend_0",
            "echo 'count 1' > /proc/net/pktgen/eth0",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0",
            "echo 'pkt_size 200' > /proc/net/pktgen/eth0",
            "echo 'delay 0' > /proc/net/pktgen/eth0",
            "echo 'frags 4' > /proc/net/pktgen/eth0",
            "echo 'vlan_id 0' > /proc/net/pktgen/eth0",
            "echo 'vlan_p 0' > /proc/net/pktgen/eth0",
            "echo 'vlan_cfi 0' > /proc/net/pktgen/eth0",
            f"echo 'dst {self.targetIp}' > /proc/net/pktgen/eth0",
            f"echo 'dst_mac {self.targetMac}' > /proc/net/pktgen/eth0",
            "echo 'start' > /proc/net/pktgen/pgctrl",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(4)
        self.log.info("=================== tx output ===================")
        cmd_list = [
            "killall -s INT tcpdump &",
            "cat ~/tx_tcpdump_vlan.txt",
            "rm ~/tx_tcpdump_vlan.txt",
        ]
        self.run_on_host(cmd=cmd_list, timeout=120)
        time.sleep(10)

    @eth_default_runner
    def ping_flood(self, **kwargs):
        self.terminal.runcmd(
            cmd=f"tftp -g -r ping 10.10.70.101; chmod 777 ping")
        self.terminal.runcmd(
            cmd=f"./ping -f {self.hostIp} -i 5 -c 5",
            timeout=60,
            expected=" 0% packet loss",
        )
        self.terminal.runcmd(cmd=f"ping {self.targetIp} -c 5",
                             timeout=30,
                             expected=" 0% packet loss")

    @eth_default_runner
    def ping_jumbo_frame(self, **kwargs):
        for mtu in [2048, 4096, 8192]:
            self.log.info(f"Updating MTU size on device... : {mtu}")
            self.terminal.runcmd(
                cmd=
                f"ifconfig {self.eth_interface} down; ifconfig {self.eth_interface} mtu {mtu} up; ifconfig"
            )
            time.sleep(2)
            self.log.info(f"Updating MTU size on test host... : {mtu}")
            self.run_on_host(
                cmd=
                f"ifconfig {self.host_interface} down; ifconfig {self.host_interface} mtu {mtu} up; ifconfig"
            )
            time.sleep(2)
            self.run_on_host(
                cmd=f"ping {self.hostIp} -l {mtu-28} -c 5",
                timeout=30,
                expected=" 0% packet loss",
            )
            time.sleep(2)
        self.terminal.runcmd(
            cmd=
            f"ifconfig {self.eth_interface} down; ifconfig {self.eth_interface} mtu 1500 up; ifconfig"
        )
        time.sleep(3)
        self.run_on_host(
            cmd=
            f"ifconfig {self.host_interface} down; ifconfig {self.host_interface} mtu {mtu} up; ifconfig"
        )

    @eth_default_runner
    def eth_pktgen(self, **kwargs):
        self.run_on_host(cmd="gettest_hostmac", timeout=20)
        commands = [
            "echo 'stop' > /proc/net/pktgen/pgctrl",
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_0",
            f"echo 'add_device {self.eth_interface}' > /proc/net/pktgen/kpktgend_0",
            f"echo 'count {self.pktgen_count}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'clone_skb 100' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'pkt_size {self.pktgen_size}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'burst {self.pktgen_burst} > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'delay {self.pktgen_delay}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'vlan_id {self.pktgen_vlan_id}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'vlan_p 0' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'vlan_cfi 0' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'frags {self.pktgen_frags}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'dst {self.targetIp}' > /proc/net/pktgen/{self.eth_interface}",
            f"echo 'dst_mac {self.targetMac}' > /proc/net/pktgen/{self.eth_interface}",
            "echo 'start' > /proc/net/pktgen/pgctrl",
            f"cat /proc/net/pktgen/{self.eth_interface}",
            "paramsCount=$(grep -E 'Params: count' /proc/net/pktgen/eth0 | awk '{print substr($3,1)}')",
            "pktSofar=$(grep -E 'pkts-sofar' /proc/net/pktgen/eth0 | awk '{print substr($2,1)}')",
            '[ "$paramsCount" -eq "$pktSofar" ] || echo "fail"',
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)

    @eth_default_runner
    def eth_pqueue(self, **kwargs):
        self.run_on_host(cmd="gettest_hostmac", timeout=20)
        self.run_on_host(cmd="killall -s INT tcpdump &", timeout=20)
        self.run_on_host(cmd="rm ~/priority.txt &", timeout=20)
        self.run_on_host(
            cmd=
            f"tcpdump -n -i {self.host_interface} ip host {self.targetIp} -ev > ~/priority.txt &",
            timeout=20,
        )
        time.sleep(5)
        self.log.info(f"targetMac = {self.targetMac}")
        commands = [
            "echo 'stop' > /proc/net/pktgen/pgctrl",
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_0",
            "echo 'add_device eth0@0' > /proc/net/pktgen/kpktgend_0",
            "echo 'count 500' > /proc/net/pktgen/eth0@0",
            "echo 'burst 50' > /proc/net/pktgen/eth0@0",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0@0",
            "echo 'pkt_size 1500' > /proc/net/pktgen/eth0@0",
            "echo 'delay 0' > /proc/net/pktgen/eth0@0",
            "echo 'frags 0' > /proc/net/pktgen/eth0@0",
            f"echo 'dst {self.targetIp}' > /proc/net/pktgen/eth0@0",
            f"echo 'dst_mac {self.targetMac}' > /proc/net/pktgen/eth0@0",
            "echo 'skb_priority 1' > /proc/net/pktgen/eth0@0",
            "echo 'queue_map_min 0' > /proc/net/pktgen/eth0@0",
            "echo 'queue_map_max 0' > /proc/net/pktgen/eth0@0",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(5)
        commands = [
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_1",
            "echo 'add_device eth0@1' > /proc/net/pktgen/kpktgend_1",
            "echo 'count 20' > /proc/net/pktgen/eth0@1",
            "echo 'burst 20' > /proc/net/pktgen/eth0@1",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0@1",
            "echo 'pkt_size 1400' > /proc/net/pktgen/eth0@1",
            "echo 'delay 0' > /proc/net/pktgen/eth0@1",
            "echo 'frags 0' > /proc/net/pktgen/eth0@1",
            f"echo 'dst {self.targetIp}' > /proc/net/pktgen/eth0@1",
            f"echo 'dst_mac {self.targetMac}' > /proc/net/pktgen/eth0@1",
            "echo 'skb_priority 1' > /proc/net/pktgen/eth0@1",
            "echo 'queue_map_min 1' > /proc/net/pktgen/eth0@1",
            "echo 'queue_map_max 1' > /proc/net/pktgen/eth0@1",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(5)
        commands = [
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_2",
            "echo 'add_device eth0@2' > /proc/net/pktgen/kpktgend_2",
            "echo 'count 500' > /proc/net/pktgen/eth0@2",
            "echo 'burst 50' > /proc/net/pktgen/eth0@2",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0@2",
            "echo 'pkt_size 1200' > /proc/net/pktgen/eth0@2",
            "echo 'delay 0' > /proc/net/pktgen/eth0@2",
            "echo 'frags 0' > /proc/net/pktgen/eth0@2",
            f"echo 'dst {self.targetIp}' > /proc/net/pktgen/eth0@2",
            f"echo 'dst_mac {self.targetMac}' > /proc/net/pktgen/eth0@2",
            "echo 'skb_priority 1' > /proc/net/pktgen/eth0@2",
            "echo 'queue_map_min 0' > /proc/net/pktgen/eth0@2",
            "echo 'queue_map_max 0' > /proc/net/pktgen/eth0@2",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(5)
        commands = [
            "echo 'rem_device_all' > /proc/net/pktgen/kpktgend_3",
            "echo 'add_device eth0@3' > /proc/net/pktgen/kpktgend_3",
            "echo 'count 20' > /proc/net/pktgen/eth0@3",
            "echo 'burst 20' > /proc/net/pktgen/eth0@3",
            "echo 'clone_skb 0' > /proc/net/pktgen/eth0@3",
            "echo 'pkt_size 1100' > /proc/net/pktgen/eth0@3",
            "echo 'delay 0' > /proc/net/pktgen/eth0@3",
            "echo 'frags 0' > /proc/net/pktgen/eth0@3",
            f"echo 'dst {self.targetIp}' > /proc/net/pktgen/eth0@3",
            f"echo 'dst_mac {self.targetMac}' > /proc/net/pktgen/eth0@3",
            "echo 'skb_priority 1' > /proc/net/pktgen/eth0@3",
            "echo 'queue_map_min 1' > /proc/net/pktgen/eth0@3",
            "echo 'queue_map_max 1' > /proc/net/pktgen/eth0@3",
            "echo 'start' > /proc/net/pktgen/pgctrl &",
        ]
        self.terminal.runcmd_list(cmd_list=commands, timeout=60)
        time.sleep(5)
        self.run_on_host(cmd="killall -s INT tcpdump &", timeout=20)
        self.run_on_host(cmd="cat ~/priority.txt &", timeout=20)