diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 000000000..75385a214 --- /dev/null +++ b/.bazelrc @@ -0,0 +1,18 @@ +# C++17 enforce for BMv2 +build --cxxopt=-std=c++17 +build --host_cxxopt=-std=c++17 + +# Shared libraries and PIC +build --copt=-fPIC + +# Build configurations and features (analogous to CMake defaults) +build --copt=-DLOG_DEBUG_ON +build --copt=-DLOG_TRACE_ON +build --copt=-DWP4_16_STACKS + +# Strict warnings for our code but not for third-party +build --copt=-Wall +build --copt=-Wextra +build --per_file_copt=external/.*@-Wno-error + + diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 000000000..6d2890793 --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +8.5.0 diff --git a/.github/workflows/bazel_ci.yml b/.github/workflows/bazel_ci.yml new file mode 100644 index 000000000..585f70bb6 --- /dev/null +++ b/.github/workflows/bazel_ci.yml @@ -0,0 +1,35 @@ +name: Bazel Integration + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + bazel-build: + runs-on: ubuntu-22.04 + steps: + - name: Git Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup System Requirements + run: sudo ./install_deps_ubuntu_22.04.sh + + - name: Initialize Bazel Cache + uses: actions/cache@v3 + with: + path: ~/.cache/bazel + key: ${{ runner.os }}-bazel-${{ hashFiles('MODULE.bazel', '.bazelversion', '.bazelrc') }} + restore-keys: | + ${{ runner.os }}-bazel- + + - name: Compile simple_switch_grpc + run: bazel build //targets/simple_switch_grpc:simple_switch_grpc + + - name: Execute simple_switch_grpc tests + run: bazel test //targets/simple_switch_grpc/tests/... diff --git a/.gitignore b/.gitignore index fa3f77839..e7f97b6ad 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,7 @@ VERSION-build core vgcore* + +# Bazel +bazel-* +MODULE.bazel.lock \ No newline at end of file diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 000000000..a896987de --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,2 @@ +# Expose VERSION file for the code generation +exports_files(["VERSION"]) diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 000000000..1768ac3a5 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,9 @@ +module( + name = "behavioral_model", + version = "1.13.0", +) + +bazel_dep(name = "rules_cc", version = "0.1.1") +bazel_dep(name = "googletest", version = "1.17.0") +bazel_dep(name = "rules_proto", version = "7.1.0") +# gRPC and Protobuf are provided by the Ubuntu system to maintain ABI compatibility with PI. diff --git a/PI/BUILD.bazel b/PI/BUILD.bazel new file mode 100644 index 000000000..d738bfd17 --- /dev/null +++ b/PI/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +cc_library( + name = "bmpi_frontend", + srcs = glob(["src/*.cpp"]), + hdrs = glob([ + "src/*.h", + "bm/PI/*.h", + ]), + includes = [ + ".", + "../targets/simple_switch", + ], + defines = ["WITH_SIMPLE_SWITCH"], + deps = [ + "//include:bmv2_headers", + "//src/bm_sim:bmv2_core_engine", + "//targets/simple_switch:headers", + ], + alwayslink = True, + visibility = ["//visibility:public"], +) diff --git a/include/BUILD.bazel b/include/BUILD.bazel new file mode 100644 index 000000000..7bcace469 --- /dev/null +++ b/include/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +genrule( + name = "cmake_config_header_gen", + srcs = ["bm/config.h.in"], + outs = ["bm/config.h"], + cmd = "sed -e 's/#cmakedefine/#undef/g' $(location bm/config.h.in) > $@", + message = "Generating bm/config.h from CMake template...", +) + +cc_library( + name = "bmv2_headers", + hdrs = glob(["bm/**/*.h"]) + [":cmake_config_header_gen"], + includes = ["."], + visibility = ["//visibility:public"], +) diff --git a/install_deps_ubuntu_22.04.sh b/install_deps_ubuntu_22.04.sh index 9ac35b871..d44be1df8 100755 --- a/install_deps_ubuntu_22.04.sh +++ b/install_deps_ubuntu_22.04.sh @@ -3,8 +3,8 @@ set -e apt-get update apt-get install -y curl gnupg -echo 'deb http://download.opensuse.org/repositories/home:/p4lang/xUbuntu_22.04/ /' | tee /etc/apt/sources.list.d/home:p4lang.list -curl -fsSL https://download.opensuse.org/repositories/home:p4lang/xUbuntu_22.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/home_p4lang.gpg > /dev/null +# Add repository as trusted to bypass expired GPG keys from openSUSE build service +echo 'deb [trusted=yes] http://download.opensuse.org/repositories/home:/p4lang/xUbuntu_22.04/ /' | tee /etc/apt/sources.list.d/home:p4lang.list apt-get update diff --git a/services/BUILD.bazel b/services/BUILD.bazel new file mode 100644 index 000000000..61cd89d48 --- /dev/null +++ b/services/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +genrule( + name = "dataplane_interface_codegen", + srcs = ["p4/bm/dataplane_interface.proto"], + outs = [ + "p4/bm/dataplane_interface.pb.h", + "p4/bm/dataplane_interface.pb.cc", + "p4/bm/dataplane_interface.grpc.pb.h", + "p4/bm/dataplane_interface.grpc.pb.cc", + ], + cmd = "protoc -Iservices --cpp_out=$(RULEDIR) --grpc_out=$(RULEDIR) --plugin=protoc-gen-grpc=/usr/bin/grpc_cpp_plugin $(location p4/bm/dataplane_interface.proto)", +) + +cc_library( + name = "dataplane_grpc_interface", + srcs = [ + "p4/bm/dataplane_interface.pb.cc", + "p4/bm/dataplane_interface.grpc.pb.cc", + ], + hdrs = [ + "p4/bm/dataplane_interface.pb.h", + "p4/bm/dataplane_interface.grpc.pb.h", + ], + includes = ["."], + visibility = ["//visibility:public"], +) diff --git a/src/BMI/BUILD.bazel b/src/BMI/BUILD.bazel new file mode 100644 index 000000000..e03e84dd1 --- /dev/null +++ b/src/BMI/BUILD.bazel @@ -0,0 +1,10 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +cc_library( + name = "bmi_lib", + srcs = ["bmi_interface.c", "bmi_port.c"], + hdrs = glob(["*.h", "BMI/*.h"]), + includes = ["."], + linkopts = ["-lpcap"], + visibility = ["//visibility:public"], +) diff --git a/src/bm_sim/BUILD.bazel b/src/bm_sim/BUILD.bazel new file mode 100644 index 000000000..9356e1edf --- /dev/null +++ b/src/bm_sim/BUILD.bazel @@ -0,0 +1,38 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +genrule( + name = "generate_version_file", + srcs = ["version.cpp.in", "//:VERSION"], + outs = ["version.cpp"], + cmd = "sed 's/@BM_VERSION@/1.13.0/g' $(location version.cpp.in) > $@", + message = "Injecting BMv2 Version Information...", +) + +cc_library( + name = "bmv2_core_engine", + srcs = glob([ + "*.cpp", + "*.c", + "core/*.cpp", + ]) + [":generate_version_file"], + hdrs = glob(["*.h"]), + includes = ["."], + linkopts = [ + "-lgmp", + "-lpcap", + "-lnanomsg", + "-lpthread", + "-ldl", + "-lboost_program_options", + "-lboost_system", + "-lboost_filesystem", + "-lboost_thread", + ], + deps = [ + "//include:bmv2_headers", + "//src/BMI:bmi_lib", + "//third_party:jsoncpp_external", + "//third_party:spdlog_external", + ], + visibility = ["//visibility:public"], +) diff --git a/targets/simple_switch/BUILD.bazel b/targets/simple_switch/BUILD.bazel new file mode 100644 index 000000000..1d5e513a1 --- /dev/null +++ b/targets/simple_switch/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +cc_library( + name = "simple_switch_base", + srcs = glob(["*.cpp"], exclude = ["main.cpp"]), + hdrs = glob([ + "*.h", + "bm/**/*.h" + ]), + includes = ["."], + deps = [ + "//include:bmv2_headers", + "//src/bm_sim:bmv2_core_engine", + "//src/BMI:bmi_lib", + ], + visibility = ["//visibility:public"], +) + +alias( + name = "headers", + actual = ":simple_switch_base", + visibility = ["//visibility:public"], +) diff --git a/targets/simple_switch_grpc/BUILD.bazel b/targets/simple_switch_grpc/BUILD.bazel new file mode 100644 index 000000000..7904cdca1 --- /dev/null +++ b/targets/simple_switch_grpc/BUILD.bazel @@ -0,0 +1,40 @@ +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") + +PI_AND_GRPC_LINKOPTS = [ + "-L/usr/local/lib", + "-Wl,-rpath=/usr/local/lib", + "-lpigrpcserver", "-lpifeproto", "-lpiprotogrpc", "-lpiprotobuf", + "-lpifecpp", "-lpiconvertproto", "-lpi", "-lpip4info", "-lpifegeneric", + "-lgrpc++_reflection", "-lgrpc++", "-lgrpc", "-lprotobuf", "-lgpr", +] + +cc_library( + name = "simple_switch_grpc_runner", + srcs = ["switch_runner.cpp"], + hdrs = ["switch_runner.h"], + includes = ["."], + deps = [ + "//targets/simple_switch:simple_switch_base", + "//PI:bmpi_frontend", + "//services:dataplane_grpc_interface", + ], + linkopts = PI_AND_GRPC_LINKOPTS, + visibility = ["//visibility:public"], +) + +cc_binary( + name = "simple_switch_grpc_app", + srcs = ["main.cpp"], + deps = [ + ":simple_switch_grpc_runner", + "//targets/simple_switch:simple_switch_base", + ], + linkopts = PI_AND_GRPC_LINKOPTS, + visibility = ["//visibility:public"], +) + +alias( + name = "simple_switch_grpc", + actual = ":simple_switch_grpc_app", + visibility = ["//visibility:public"], +) diff --git a/targets/simple_switch_grpc/tests/BUILD.bazel b/targets/simple_switch_grpc/tests/BUILD.bazel new file mode 100644 index 000000000..99600ab69 --- /dev/null +++ b/targets/simple_switch_grpc/tests/BUILD.bazel @@ -0,0 +1,55 @@ +load("@rules_cc//cc:defs.bzl", "cc_test", "cc_library") + +PI_AND_GRPC_LINKOPTS = [ + "-L/usr/local/lib", + "-Wl,-rpath=/usr/local/lib", + "-lpigrpcserver", "-lpifeproto", "-lpiprotogrpc", "-lpiprotobuf", + "-lpifecpp", "-lpiconvertproto", "-lpi", "-lpip4info", "-lpifegeneric", + "-lgrpc++_reflection", "-lgrpc++", "-lgrpc", "-lprotobuf", "-lgpr", +] + +cc_library( + name = "bmv2_test_utilities", + srcs = [ + "base_test.cpp", + "utils.cpp", + ], + hdrs = [ + "base_test.h", + "utils.h", + ], + deps = [ + "//targets/simple_switch_grpc:simple_switch_grpc_runner", + "//targets/simple_switch:simple_switch_base", + "//services:dataplane_grpc_interface", + "@googletest//:gtest", + ], + linkopts = PI_AND_GRPC_LINKOPTS, + defines = ["TESTDATADIR=\\\"targets/simple_switch_grpc/tests/testdata\\\""], + copts = [ + "-Wno-error=unused-result", + "-Wno-error=deprecated-declarations" + ], +) + +TEST_MODULES = [ + "test_basic", "test_grpc_dp", "test_packet_io", "test_counter", + "test_meter", "test_ternary", "test_pre", "test_digest", + "test_idle_timeout", "test_action_profile", "test_optional" +] + +[cc_test( + name = t, + srcs = [t + ".cpp", "main.cpp"], + deps = [":bmv2_test_utilities", "@googletest//:gtest"], + data = glob(["testdata/**"]), + linkopts = PI_AND_GRPC_LINKOPTS, + linkstatic = True, + tags = ["exclusive"], +) for t in TEST_MODULES] + +# Provide a single alias to run all tests +test_suite( + name = "all_tests", + tests = [":{}".format(t) for t in TEST_MODULES], +) diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel new file mode 100644 index 000000000..57b8e73dd --- /dev/null +++ b/third_party/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") + +cc_library( + name = "jsoncpp_external", + srcs = ["jsoncpp/src/jsoncpp.cpp"], + hdrs = ["jsoncpp/include/jsoncpp/json.h"], + includes = ["jsoncpp/include"], + visibility = ["//visibility:public"], +) + +cc_library( + name = "spdlog_external", + hdrs = glob([ + "spdlog/bm/spdlog/**/*.h", + "spdlog/bm/spdlog/**/*.cc", + ]), + includes = ["spdlog"], + visibility = ["//visibility:public"], +) diff --git a/tools/bazel/BUILD.bazel b/tools/bazel/BUILD.bazel new file mode 100644 index 000000000..6072e3b5f --- /dev/null +++ b/tools/bazel/BUILD.bazel @@ -0,0 +1,2 @@ +# Define this directory as a Bazel package so bzl files can be loaded using //tools/bazel:bmv2_macros.bzl +exports_files(["bmv2_macros.bzl"])