Skip to content

Fuzzer for bmv2 #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions targets/bmv2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ if(ENABLE_TESTING)
include(test/P4Tests.cmake)
endif()

find_program(RTSMITH_DRIVER p4rtsmith)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already set this binary with a variable, you just need to use that variable. Do not use find_program

if (NOT RTSMITH_DRIVER)
message(FATAL_ERROR "RtSmith tool not found! Please ensure it is in your PATH.")
endif()

# Find p4c (for JSON generation)
find_program(P4C_EXECUTABLE p4c)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the wrong way to do this, this is why the current tests fail. You directly access the P4C binary in the script, you shouldn't need to use find_program.

if (NOT P4C_EXECUTABLE)
message(FATAL_ERROR "p4c not found! Please ensure it is in your PATH.")
endif()

# Source files for the main P4RtSmith.
set(RTSMITH_SOURCES
${RTSMITH_SOURCES}
Expand All @@ -16,3 +27,56 @@ set(RTSMITH_SOURCES

set(RTSMITH_LIBS ${RTSMITH_LIBS} ${P4C_LIBRARIES} ${P4C_LIB_DEPS} ${CMAKE_THREAD_LIBS_INIT} PARENT_SCOPE)

set(CONFIG_DIR "${CMAKE_BINARY_DIR}/rtsmith/configs")
set(JSON_DIR "${CMAKE_BINARY_DIR}/rtsmith/jsons")

file(MAKE_DIRECTORY ${CONFIG_DIR})
file(MAKE_DIRECTORY ${JSON_DIR})

file(GLOB P4_PROGRAMS
# "${P4C_SOURCE_DIR}/testdata/p4_16_samples/*.p4"
# "${P4C_SOURCE_DIR}/testdata/p4_16_samples/dash/*.p4"
# "${P4C_SOURCE_DIR}/testdata/p4_16_samples/fabric_*/fabric.p4"
# "${P4C_SOURCE_DIR}/testdata/p4_16_samples/omec/*.p4"
# "${P4C_SOURCE_DIR}/testdata/p4_16_samples/pins/*.p4"
# "${flay_SOURCE_DIR}/targets/bmv2/test/programs/*.p4"
"${P4C_SOURCE_DIR}/testdata/p4_16_samples/dash/dash-pipeline-pna-dpdk.p4"
)

set(ALL_DEPENDENCIES "")

foreach(P4_PROGRAM ${P4_PROGRAMS})
get_filename_component(PROGRAM_NAME ${P4_PROGRAM} NAME_WE)

# Generate random config
set(CONFIG_FILE "${CONFIG_DIR}/${PROGRAM_NAME}_init_config.txtpb")
if (NOT CONFIG_FILE IN_LIST ALL_DEPENDENCIES)
add_custom_command(
OUTPUT ${CONFIG_FILE}
COMMAND ${RTSMITH_DRIVER} ${P4_PROGRAM} --target bmv2 --arch v1model --output-dir ${CONFIG_DIR} --config-name ${PROGRAM_NAME} --random-seed
DEPENDS ${P4_PROGRAM}
COMMENT "Generating random config for ${PROGRAM_NAME}"
)
list(APPEND ALL_DEPENDENCIES ${CONFIG_FILE})
endif()

# Compile P4 program
set(JSON_FILE "${JSON_DIR}/${PROGRAM_NAME}.json")
if (NOT JSON_FILE IN_LIST ALL_DEPENDENCIES)
add_custom_command(
OUTPUT ${JSON_FILE}
COMMAND ${P4C_EXECUTABLE} --target bmv2 --arch v1model --output "${JSON_DIR}/${PROGRAM_NAME}.json" ${P4_PROGRAM}
DEPENDS ${P4_PROGRAM}
COMMENT "Compiling ${PROGRAM_NAME} to JSON"
)
list(APPEND ALL_DEPENDENCIES ${JSON_FILE})
endif()
endforeach()

# Step 3: Run BMv2 with the config
add_custom_target(
run_all
COMMAND ${CMAKE_SOURCE_DIR}/run_bmv2.sh "${JSON_DIR}" "${CONFIG_DIR}"
DEPENDS ${ALL_DEPENDENCIES}
COMMENT "Running BMv2 for all programs"
)
25 changes: 25 additions & 0 deletions targets/bmv2/run_bmv2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

# Arguments
JSON_DIR=$1
CONFIG_DIR=$1

# Loop through all JSON files in the output directory
for JSON_FILE in ${JSON_DIR}/*.json; do
# Get the program name (e.g., program1 from program1.json)
PROGRAM_NAME=$(basename ${JSON_FILE} .json)

# Start BMv2
simple_switch -i 0@veth0 -i 1@veth1 ${JSON_FILE} &

# Wait for BMv2 to start
sleep 2

# Send the config file to BMv2 using P4Runtime
CONFIG_FILE="${CONFIG_DIR}/${PROGRAM_NAME}_init_config.txtpb"
if [[ -f ${CONFIG_FILE} ]]; then
python3 ${CMAKE_SOURCE_DIR}/send_config.py ${CONFIG_FILE}
else
echo "Config file not found: ${CONFIG_FILE}"
fi
done
23 changes: 23 additions & 0 deletions targets/bmv2/send_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import sys
from p4runtime_lib import helper
from p4runtime_lib.switch import ShutdownAllSwitchConnections
from google.protobuf import text_format
from p4.v1 import p4runtime_pb2

# Load the config file
config_file = sys.argv[1]
with open(config_file, "r") as f:
config = f.read()

# Parse the config
write_request = p4runtime_pb2.WriteRequest()
text_format.Parse(config, write_request)

# Connect to BMv2
switch = helper.P4RuntimeSwitchConnection("localhost", 50051, device_id=0)

# Send the config
switch.WriteRequest(write_request)

# Clean up
ShutdownAllSwitchConnections()
4 changes: 4 additions & 0 deletions targets/bmv2/test/run_test_batch.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# This script takes a P4 program and runs it through the p4rtsmith tool to generate a config file.
# i.e. python run_test_batch.py <p4_program> <p4rtsmith_bin> -td <testdir> -s <seed>

import argparse
import logging
import os
Expand Down Expand Up @@ -73,6 +76,7 @@ def find_p4c_dir():


def run_tests(options: Options) -> int:
"""Run the tests for the given options."""
config_file_path = "initial_config.txtpb"

seed = options.seed
Expand Down
Loading