Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
dfccabe
tablesapply
sudhanshu112233shukla Apr 11, 2025
9c63103
ControlNodefix
sudhanshu112233shukla Apr 12, 2025
f4d9b99
Fix multiple table applications
sudhanshu112233shukla Apr 12, 2025
baf04d9
checks for tables
sudhanshu112233shukla Apr 14, 2025
b78b84f
table applications
sudhanshu112233shukla Apr 18, 2025
f606dca
pipeline fix
sudhanshu112233shukla Apr 20, 2025
479c7aa
fix: improve workflow logging and test diagnostics
sudhanshu112233shukla Jun 11, 2025
7d2828f
fix: update actions/upload-artifact to v4
sudhanshu112233shukla Jun 11, 2025
16842da
fix: update test cases and workflow for better error handling
sudhanshu112233shukla Jun 11, 2025
e7227ce
chore: restore Dockerfile with PI support
sudhanshu112233shukla Jun 13, 2025
a6421d9
Remove debugging steps from test workflow
sudhanshu112233shukla Jun 18, 2025
57c2bab
Fix CI: add PI library install and remove deleted test
sudhanshu112233shukla Jun 18, 2025
3741b77
Fix uthash dependency: add submodule init
sudhanshu112233shukla Jun 18, 2025
c371a0a
Fix PI headers validation and make check command
sudhanshu112233shukla Jun 18, 2025
0758659
Improve PI install: use stable branch, parallel build, fix Docker
sudhanshu112233shukla Jun 18, 2025
98ff1ba
Revert "Improve PI install: use stable branch, parallel build, fix Do…
sudhanshu112233shukla Jun 18, 2025
2fc0d63
Fix PI headers: add dependencies, disable other jobs
sudhanshu112233shukla Jun 18, 2025
a957d62
Add PI install retry and Makefile check
sudhanshu112233shukla Jun 18, 2025
ccaccca
Fix PI install deps and Makefile generation
sudhanshu112233shukla Jun 18, 2025
cceb471
Add Thrift dependencies to fix missing headers
sudhanshu112233shukla Jun 18, 2025
28a8aca
Add nanomsg and debug PI install in workflow
sudhanshu112233shukla Jun 19, 2025
d3d31bf
Resolve merge conflicts in workflow and Dockerfile
sudhanshu112233shukla Jun 20, 2025
d04a3c0
Resolve merge conflicts in test.yml and Dockerfile, merging CI and bu…
sudhanshu112233shukla Jul 14, 2025
05348a8
Resolve merge conflicts in test.yml and Dockerfile
sudhanshu112233shukla Jul 17, 2025
7dd43ea
Resolve merge conflicts in test.yml and Dockerfile with main branch l…
sudhanshu112233shukla Jul 17, 2025
d58d7e2
Resolve final Dockerfile merge conflict: keep pkg-config and all depe…
sudhanshu112233shukla Jul 17, 2025
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
76 changes: 68 additions & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,47 +38,107 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Install build dependencies for PI
run: |
sudo apt-get update
sudo apt-get install -y build-essential autoconf libtool pkg-config libthrift-dev thrift-compiler libnanomsg-dev libpcap-dev
- name: Install PI library
run: |
git clone https://github.com/p4lang/PI.git /tmp/PI
cd /tmp/PI && git submodule update --init --recursive
sudo apt-get install -y autoconf automake libtool pkg-config
./autogen.sh && ./configure && make -j$(nproc) && sudo make install
ls -al /usr/local/include/PI # Debugging step to verify installation
if [ ! -f /usr/local/include/PI/pi.h ]; then
echo "PI headers not found after installation. Retrying..."
./autogen.sh && ./configure && make -j$(nproc) && sudo make install
ls -al /usr/local/include/PI # Debugging step to verify installation
if [ ! -f /usr/local/include/PI/pi.h ]; then
echo "PI headers still missing. Please review installation steps."
exit 1
fi
fi
- name: Check Makefile existence
run: |
if [ ! -f Makefile ]; then
echo "Makefile not found. Attempting to regenerate..."
./autogen.sh && ./configure
if [ ! -f Makefile ]; then
echo "Makefile still missing. Please ensure the repository is set up correctly."
exit 1
fi
fi
- name: Build test Docker image
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
run: |
docker build -t bm --build-arg IMAGE_TYPE=test --build-arg CC=$CC --build-arg CXX=$CXX --build-arg GCOV=$GCOV .
docker build -t bm --build-arg IMAGE_TYPE=test --build-arg CC=$CC --build-arg CXX=$CXX --build-arg GCOV=$GCOV --build-arg BUILDER=autoconf .
- name: Run tests
run: |
ci_env=`bash <(curl -s https://codecov.io/env)`
docker run --rm $ci_env --env GCOV -w /behavioral-model bm /bin/bash -c "make check -j$(nproc) && ./ci/codecov.sh"
docker run --rm $ci_env --env GCOV -w /behavioral-model bm /bin/bash -c \
"make check -j$(nproc) VERBOSE=1 && ./ci/codecov.sh"
# FIXME: replace the command above with the following when switching to cmake
# "cd build && make -j$(nproc) && ctest -j$(nproc) --output-on-failure && cd .. && ./ci/codecov.sh"
- name: Check style
run: |
./tools/check_style.sh

test-no-pi:
if: false
needs: check-changes
if: ${{ needs.check-changes.outputs.has_changes == 'yes' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Install PI library
run: |
git clone https://github.com/p4lang/PI.git /tmp/PI
cd /tmp/PI && git submodule update --init --recursive
cd /tmp/PI && ./autogen.sh && ./configure && make && sudo make install
if [ ! -f /usr/local/include/PI/pi.h ]; then
echo "PI headers not found after installation."
exit 1
fi
- name: Build Dockerfile.noPI image
run: docker build -t bm-no-pi --build-arg IMAGE_TYPE=test -f Dockerfile.noPI .
- name: Run tests
run: docker run --rm -w /behavioral-model bm-no-pi /bin/bash -c "make check -j$(nproc)"
run: docker run --rm -w /behavioral-model bm-no-pi /bin/bash -c "make check -j$(nproc) VERBOSE=1"
# FIXME: replace the command above with the following when switching to cmake
# "cd build && make -j$(nproc) && ctest -j$(nproc) --output-on-failure"

test-ubuntu22:
if: false
needs: check-changes
if: ${{ needs.check-changes.outputs.has_changes == 'yes' }}
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Install dependencies
run: sudo ./install_deps_ubuntu_22.04.sh
- name: Install PI library
run: |
git clone https://github.com/p4lang/PI.git /tmp/PI
cd /tmp/PI && git submodule update --init --recursive
cd /tmp/PI && ./autogen.sh && ./configure && make && sudo make install
if [ ! -f /usr/local/include/PI/pi.h ]; then
echo "PI headers not found after installation."
exit 1
fi
- name: Build BMv2
run: |
./autogen.sh
./configure --with-pdfixed --with-pi --with-stress-tests --enable-debugger --enable-Werror
mkdir -p build
cd build
cmake -DWITH_PDFIXED=ON -DWITH_PI=ON -DWITH_STRESS_TESTS=ON -DENABLE_DEBUGGER=ON -DENABLE_WERROR=ON ..
make -j$(nproc)
- name: Run tests
run: make check -j$(nproc)
run: cd build && make -j$(nproc) && ctest -j$(nproc) --output-on-failure
65 changes: 40 additions & 25 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ARG PARENT_VERSION=latest
FROM p4lang/pi:${PARENT_VERSION}
FROM p4lang/third-party:latest
LABEL maintainer="P4 Developers <[email protected]>"
LABEL description="This Docker image includes PI and P4 Runtime support for bmv2 simple_switch."

# Select the type of image we're building. Use `build` for a normal build, which
# is optimized for image size. Use `test` if this image will be used for
Expand All @@ -11,24 +11,25 @@ ARG IMAGE_TYPE=build
ARG CC=gcc
ARG CXX=g++
ARG GCOV=
ARG USE_CMAKE=
ARG sswitch_grpc=yes

ENV BM_DEPS automake \
build-essential \
clang-8 \
clang-10 \
curl \
git \
lcov \
libgmp-dev \
libpcap-dev \
libboost-dev \
libboost-program-options-dev \
libboost-system-dev \
libboost-filesystem-dev \
libboost-thread-dev \
libtool \
pkg-config
build-essential \
clang-8 \
clang-10 \
cmake \
pkg-config \
curl \
git \
libgmp-dev \
libpcap-dev \
libboost-dev \
libboost-program-options-dev \
libboost-system-dev \
libboost-filesystem-dev \
libboost-thread-dev \
libtool
ENV BM_RUNTIME_DEPS libboost-program-options1.71.0 \
libboost-system1.71.0 \
libboost-filesystem1.71.0 \
Expand All @@ -42,16 +43,30 @@ COPY . /behavioral-model/
WORKDIR /behavioral-model/
RUN apt-get update -qq && \
apt-get install -qq --no-install-recommends $BM_DEPS $BM_RUNTIME_DEPS && \
./autogen.sh && \
if [ "$GCOV" != "" ]; then ./configure --with-pdfixed --with-pi --with-stress-tests --enable-debugger --enable-coverage --enable-Werror; fi && \
if [ "$GCOV" = "" ]; then ./configure --with-pdfixed --with-pi --with-stress-tests --enable-debugger --enable-Werror; fi && \
if [ "$USE_CMAKE" -gt 0 ] ; then \
mkdir -p build && cd build && \
if [ "$GCOV" != "" ]; then cmake -DWITH_PDFIXED=ON -DWITH_PI=ON -DWITH_STRESS_TESTS=ON -DENABLE_DEBUGGER=ON -DENABLE_COVERAGE=ON -DENABLE_WERROR=ON ..; fi && \
if [ "$GCOV" = "" ]; then cmake -DWITH_PDFIXED=ON -DWITH_PI=ON -DWITH_STRESS_TESTS=ON -DENABLE_DEBUGGER=ON -DENABLE_WERROR=ON ..; fi ; \
else \
./autogen.sh && \
if [ "$GCOV" != "" ]; then ./configure --with-pdfixed --with-pi --with-stress-tests --enable-debugger --enable-coverage --enable-Werror; fi && \
if [ "$GCOV" = "" ]; then ./configure --with-pdfixed --with-pi --with-stress-tests --enable-debugger --enable-Werror; fi ; \
fi && \
make -j$(nproc) && \
make install-strip && \
if [ "$USE_CMAKE" -gt 0 ] ; then \
make install && cd .. ; \
else \
make install-strip ; \
fi && \
ldconfig && \
(test "$IMAGE_TYPE" = "build" && \
apt-get purge -qq $BM_DEPS && \
apt-get autoremove --purge -qq && \
rm -rf /behavioral-model /var/cache/apt/* /var/lib/apt/lists/* && \
echo 'Build image ready') || \
apt-get purge -qq $BM_DEPS && \
apt-get autoremove --purge -qq && \
rm -rf /behavioral-model /var/cache/apt/* /var/lib/apt/lists/* && \
echo 'Build image ready') || \
(test "$IMAGE_TYPE" = "test" && \
echo 'Test image ready')

# Trigger rebuild: confirming Dockerfile is up to date for CI troubleshooting

# CI debug: force rebuild at 2024-06-19
27 changes: 26 additions & 1 deletion docs/JSON_format.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on each attribute.

## Current bmv2 JSON format version

The version described in this document is *2.24*.
The version described in this document is *3.0*.

The major version number will be increased by the compiler only when
backward-compatibility of the JSON format is broken. After a major version
Expand All @@ -23,6 +23,17 @@ itself, under the key `__meta__` -> `version`.
Note that the bmv2 code will perform a version check against the provided input
JSON.

### Version 3.0 Changes

Version 3.0 introduces support for multiple applications of the same table in a single pipeline. This is achieved by:

1. Adding a new `table_applies` array to each pipeline
2. Removing the `next_tables` field from table objects
3. Adding a `table` field to each table_apply object that references the actual table to apply
4. Adding a `next_tables` field to each table_apply object

BMv2 will continue to support the 2.x format for backward compatibility.

## General information

Tentative support for signed fields (with a 2 complement representation) has
Expand Down Expand Up @@ -648,6 +659,16 @@ attributes for these objects are:
added. This doesn't impact the default entry though (see the `default_entry`
attribute). `entries` is a JSON array where each element follows the
[match-action entry format](#match-action-entry-format) described below.
- `table_applies`: a JSON array of JSON objects (only in version 3.0+). Each of these objects stores the
information for a specific application of a table in the pipeline. This allows the same table to be applied
multiple times in the same pipeline with different next nodes. The attributes for these objects are:
- `name`: a unique name for this table application
- `id`: a unique integer (unique with respect to other table applications)
- `table`: the name of the table being applied
- `next_tables`: maps each action to a next node name. Alternatively, maps
special string `__HIT__` and `__MISS__` to a next node name. This is the same format as the `next_tables`
attribute in the table object in version 2.x.

- `conditionals`: a JSON array of JSON objects. Each of these objects stores the
information for a given P4 condition, which is used by the current pipeline. The
attributes for these objects are:
Expand Down Expand Up @@ -712,6 +733,10 @@ of these ways:
not use that construct, then the next node to be executed will be
the same for all actions.

In version 3.0+, the `next_tables` attribute is moved from the table object to the
`table_applies` object. This allows the same table to be applied multiple times in the
same pipeline with different next nodes for each application.

The `match_type` for the table needs to follow the following rules:
- If one match field is `range`, the table `match_type` has to be `range`
- If one match field is `ternary`, the table `match_type` has to be `ternary`
Expand Down
15 changes: 15 additions & 0 deletions include/bm/bm_sim/P4Objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "enums.h"
#include "control_action.h"
#include "device_id.h"
#include "table_apply.h"

// forward declaration of Json::Value
namespace Json {
Expand Down Expand Up @@ -192,6 +193,15 @@ class P4Objects {
return match_action_tables_map.at(name).get();
}

TableApply *get_table_apply(const std::string &name) const {
return table_applies_map.at(name).get();
}

TableApply *get_table_apply_rt(const std::string &name) const {
auto it = table_applies_map.find(name);
return (it != table_applies_map.end()) ? it->second.get() : nullptr;
}

Conditional *get_conditional(const std::string &name) const {
return conditionals_map.at(name).get();
}
Expand Down Expand Up @@ -384,6 +394,7 @@ class P4Objects {
bool *next_is_hit_miss);
void init_pipelines(const Json::Value &root, LookupStructureFactory *,
InitState *);
void init_table_applies(const Json::Value &root, int json_version);
void init_checksums(const Json::Value &root);
void init_learn_lists(const Json::Value &root);
void init_field_lists(const Json::Value &root);
Expand Down Expand Up @@ -418,6 +429,10 @@ class P4Objects {
std::unordered_map<std::string, std::unique_ptr<MatchActionTable> >
match_action_tables_map{};

// table applies (for multiple applications of the same table)
std::unordered_map<std::string, std::unique_ptr<TableApply> >
table_applies_map{};

std::unordered_map<std::string, std::unique_ptr<ActionProfile> >
action_profiles_map{};

Expand Down
1 change: 1 addition & 0 deletions include/bm/bm_sim/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class DebuggerIface;
#define DBG_CTR_CONDITION (5 << 24)
#define DBG_CTR_ACTION (6 << 24)
#define DBG_CTR_DEPARSER (7 << 24)
#define DBG_CTR_TABLE_APPLY (8 << 24)

#define DBG_CTR_EXIT(x) (x | (0x80 << 24))

Expand Down
8 changes: 8 additions & 0 deletions include/bm/bm_sim/match_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ class MatchTableAbstract : public NamedP4Object {
handle_iterator handles_begin() const;
handle_iterator handles_end() const;

// Get the next_nodes map
// Added for issue #1286 to allow get_action_ids() to access it
const std::unordered_map<p4object_id_t, const ControlFlowNode *> &get_next_nodes() const {
return next_nodes;
}

// meant to be called by P4Objects when loading the JSON
// set_default_entry sets a default entry obtained from the JSON. You can make
// sure that it cannot be changed by the control plane by using the is_const
Expand All @@ -211,6 +217,8 @@ class MatchTableAbstract : public NamedP4Object {
const ControlFlowNode *get_next_node(p4object_id_t action_id) const;
const ControlFlowNode *get_next_node_default(p4object_id_t action_id) const;



// assumes that entry->handle has been set
void set_entry_common_info(EntryCommon *entry) const;

Expand Down
5 changes: 5 additions & 0 deletions include/bm/bm_sim/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ class Pipeline : public NamedP4Object {
//! Default move assignment operator
Pipeline &operator=(Pipeline &&other) /*noexcept*/ = default;

//! Get the first node of the pipeline
const ControlFlowNode *get_first_node() const {
return first_node;
}

private:
ControlFlowNode *first_node;
};
Expand Down
Loading