예제 #1
0
def validate(dump_dir, p4_file, log_file, config):
    try:
        result = validate_p4(p4_file, dump_dir, config["compiler_bin"],
                             log_file)
    except TimeoutError:
        log.error("Validation timed out.")
        dump_file(TIMEOUT_DIR, p4_file)
        dump_file(TIMEOUT_DIR, log_file)
        # reset the dump directory
        return util.EXIT_FAILURE
    if result != util.EXIT_SUCCESS:
        info_file = p4_file.with_suffix("").joinpath(
            f"{p4_file.stem}_info.json")
        bug_dir = None
        if result == util.EXIT_UNDEF:
            log.error("Found instance of unstable code!")
            bug_dir = UNDEF_DIR
        else:
            log.error("Failed to validate the P4 code!")
            bug_dir = VALIDATION_BUG_DIR
        log.error("Rerun the example with:")
        out_file = bug_dir.joinpath(p4_file.name)
        log.error("python3 bin/validate_p4_translation -u -i %s", out_file)
        dump_file(bug_dir, log_file)
        dump_file(bug_dir, p4_file)
        dump_file(bug_dir, info_file)
        if config["do_prune"]:
            info_file = bug_dir.joinpath(f"{p4_file.stem}_info.json")
            p4_cmd = f"{PRUNER_BIN} "
            p4_cmd += f"--config {info_file} "
            p4_cmd += f" {bug_dir.joinpath(f'{p4_file.stem}.p4')} "
            p4_cmd += f" --working-dir {bug_dir.joinpath(f'{p4_file.stem}')}"
            log.info("Pruning P4 file with command %s ", p4_cmd)
            util.start_process(p4_cmd)
    return result
예제 #2
0
def check(idx, config):
    test_id = generate_id()
    test_name = f"{test_id}_{idx}"
    dump_dir = OUTPUT_DIR.joinpath(f"dmp_{test_name}")
    util.check_dir(dump_dir)
    log_file = dump_dir.joinpath(f"{test_name}.log")
    p4_file = dump_dir.joinpath(f"{test_name}.p4")
    seed = int.from_bytes(os.getrandom(8), "big")
    log.info("Testing P4 program: %s - Seed: %s", p4_file.name, seed)
    # generate a random program
    result, p4_file = generate_p4_prog(P4RANDOM_BIN, p4_file, config, seed)
    if result.returncode != util.EXIT_SUCCESS:
        log.error("Failed generate P4 code!")
        dump_result(result, GENERATOR_BUG_DIR, p4_file)
        # reset the dump directory
        util.del_dir(dump_dir)
        return result.returncode
    # check compilation
    result = compile_p4_prog(config["compiler_bin"], p4_file, dump_dir)
    if result.returncode != util.EXIT_SUCCESS:
        if not is_known_bug(result):
            log.error("Failed to compile the P4 code!")
            log.error("Found a new bug!")
            dump_result(result, CRASH_BUG_DIR, p4_file)
            dump_file(CRASH_BUG_DIR, p4_file)
            if config["do_prune"]:
                info_file = CRASH_BUG_DIR.joinpath(f"{p4_file.stem}_info.json")
                info = validation.INFO
                # customize the main info with the new information
                info["compiler"] = str(config["compiler_bin"])
                info["exit_code"] = result.returncode
                info["p4z3_bin"] = str(P4Z3_BIN)
                info["out_dir"] = str(CRASH_BUG_DIR)
                info["input_file"] = str(p4_file)
                info["allow_undef"] = False
                info["err_string"] = result.stderr.decode("utf-8")
                log.error("Dumping configuration to %s.", info_file)
                with open(info_file, 'w') as json_file:
                    json.dump(info, json_file, indent=2, sort_keys=True)
                p4_cmd = f"{PRUNER_BIN} "
                p4_cmd += f"--config {info_file} "
                p4_cmd += f" {CRASH_BUG_DIR.joinpath(f'{p4_file.stem}.p4')} "
                log.error("Pruning P4 file with command %s ", p4_cmd)
                util.start_process(p4_cmd)
        # reset the dump directory
        util.del_dir(dump_dir)
        return result
    # check validation
    if config["do_validate"]:
        result = validate(dump_dir, p4_file, log_file, config)
    elif config["use_blackbox"]:
        result = run_p4_test(dump_dir, p4_file, log_file, config)

    # reset the dump directory
    util.del_dir(dump_dir)
    return result
예제 #3
0
def run_bmv2_test(out_dir, p4_input):
    cmd = "python3 "
    cmd += f"{P4C_DIR}/backends/bmv2/run-bmv2-test.py "
    cmd += f"{P4C_DIR} -v "
    cmd += f"-bd {P4C_DIR}/build "
    cmd += f"{out_dir}/{p4_input.name} "
    test_proc = util.start_process(cmd, cwd=out_dir)

    def signal_handler(sig, frame):
        log.warning("run_tofino_test: Caught Interrupt, exiting...")
        os.kill(test_proc.pid, signal.SIGINT)
        sys.exit(1)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    stdout, stderr = test_proc.communicate()

    return test_proc, stdout, stderr
예제 #4
0
def run_tofino_test(out_dir, p4_input, stf_file_name):
    # we need to change the working directory
    # tofino scripts make some assumptions where to dump files
    prog_name = p4_input.stem
    # we need to create a specific test dir in which we can run tests
    test_dir = out_dir.joinpath("test_dir")
    util.check_dir(test_dir)
    util.copy_file(stf_file_name, test_dir)
    template_name = test_dir.joinpath(f"{prog_name}.py")
    # use a test template that runs stf tests
    util.copy_file(f"{FILE_DIR}/tofino_test_template.py", template_name)

    # initialize the target install
    log.info("Building the tofino target...")
    config_cmd = f"{TOFINO_DIR}/pkgsrc/p4-build/configure "
    config_cmd += f"--with-tofino --with-p4c=bf-p4c "
    config_cmd += f"--prefix={TOFINO_DIR}/install "
    config_cmd += f"--bindir={TOFINO_DIR}/install/bin "
    config_cmd += f"P4_NAME={prog_name} "
    config_cmd += f"P4_PATH={p4_input.resolve()} "
    config_cmd += f"P4_VERSION=p4-16 "
    config_cmd += f"P4_ARCHITECTURE=tna "
    result = util.exec_process(config_cmd, cwd=out_dir)
    if result.returncode != util.EXIT_SUCCESS:
        return result, result.stdout, result.stderr
    # create the target
    make_cmd = f"make -C {out_dir} "
    result = util.exec_process(make_cmd)
    if result.returncode != util.EXIT_SUCCESS:
        return result, result.stdout, result.stderr
    # install the target in the tofino folder
    make_cmd = f"make install -C {out_dir} "
    result = util.exec_process(make_cmd)
    if result.returncode != util.EXIT_SUCCESS:
        return result, result.stdout, result.stderr
    procs = []
    test_proc = None
    # start the target in the background
    log.info("Starting the tofino model...")
    os_env = os.environ.copy()
    os_env["SDE"] = f"{TOFINO_DIR}"
    os_env["SDE_INSTALL"] = f"{TOFINO_DIR}/install"

    model_cmd = f"{TOFINO_DIR}/run_tofino_model.sh "
    model_cmd += f"-p {prog_name} "
    proc = util.start_process(model_cmd,
                              preexec_fn=os.setsid,
                              env=os_env,
                              cwd=out_dir)
    procs.append(proc)
    # start the binary for the target in the background
    log.info("Launching switchd...")
    os_env = os.environ.copy()
    os_env["SDE"] = f"{TOFINO_DIR}"
    os_env["SDE_INSTALL"] = f"{TOFINO_DIR}/install"

    switch_cmd = f"{TOFINO_DIR}/run_switchd.sh "
    switch_cmd += f"--arch tofino "
    switch_cmd += f"-p {prog_name} "
    proc = util.start_process(switch_cmd,
                              preexec_fn=os.setsid,
                              env=os_env,
                              cwd=out_dir)
    procs.append(proc)

    # wait for a bit
    time.sleep(2)
    # finally we can run the test
    log.info("Running the actual test...")
    test_cmd = f"{TOFINO_DIR}/run_p4_tests.sh "
    test_cmd += f"-t {test_dir} "
    os_env = os.environ.copy()
    os_env["SDE"] = f"{TOFINO_DIR}"
    os_env["SDE_INSTALL"] = f"{TOFINO_DIR}/install"
    os_env["PYTHONPATH"] = f"${{PYTHONPATH}}:{FILE_DIR}"
    test_proc = util.start_process(test_cmd, env=os_env, cwd=out_dir)

    def signal_handler(sig, frame):
        log.warning("run_tofino_test: Caught Interrupt, exiting...")
        cleanup(procs)
        os.kill(test_proc.pid, signal.SIGINT)
        os.kill(test_proc.pid, signal.SIGTERM)
        sys.exit(1)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    stdout, stderr = test_proc.communicate()
    cleanup(procs)
    return test_proc, stdout, stderr