├── py ├── p4 │ ├── __init__.py │ ├── v1 │ │ ├── __init__.py │ │ ├── p4data_pb2_grpc.py │ │ └── p4runtime_pb2_grpc.py │ └── config │ │ ├── __init__.py │ │ └── v1 │ │ ├── __init__.py │ │ ├── p4info_pb2_grpc.py │ │ └── p4types_pb2_grpc.py ├── LICENSE ├── README.md ├── setup.py ├── pyproject.toml └── setup.cfg ├── rust ├── LICENSE ├── Cargo.toml ├── p4runtime-tonic │ ├── src │ │ └── lib.rs │ ├── Cargo.toml │ └── build.rs ├── p4runtime-prost │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ └── lib.rs └── README.md ├── docs ├── v1 │ ├── resources │ │ ├── figs │ │ │ ├── .gitignore │ │ │ ├── error-report.odg │ │ │ ├── reference-architecture.odg │ │ │ ├── psa-metadata-translation.odg │ │ │ ├── single-embedded-controller.odg │ │ │ ├── single-remote-controller.odg │ │ │ ├── embedded-plus-two-remote-controllers.odg │ │ │ ├── embedded-plus-single-remote-controller.odg │ │ │ └── embedded-plus-two-remote-ha-controllers.odg │ │ ├── theme │ │ │ ├── logo.png │ │ │ ├── references.bib │ │ │ └── p4-theme.yml │ │ └── fonts │ │ │ ├── LuxiMono │ │ │ ├── luximb.ttf │ │ │ ├── luximr.ttf │ │ │ ├── luximbi.ttf │ │ │ ├── luximri.ttf │ │ │ └── LICENSE.txt │ │ │ ├── Utopia │ │ │ ├── utopia-bold.ttf │ │ │ ├── utopia-italic.ttf │ │ │ ├── utopia-regular.ttf │ │ │ ├── utopia-bolditalic.ttf │ │ │ └── LICENSE-utopia.txt │ │ │ ├── OpenSans │ │ │ ├── OpenSans-Bold.ttf │ │ │ ├── OpenSans-Italic.ttf │ │ │ ├── OpenSans-Regular.ttf │ │ │ └── OpenSans-BoldItalic.ttf │ │ │ └── verify-font │ ├── libre-office.png │ ├── Makefile │ ├── README.md │ └── guidance-for-generating-p4info.md ├── libre-office.png ├── tools │ ├── fonts │ │ ├── luximr.ttf │ │ ├── UtopiaStd-Regular.otf │ │ └── fix_helvetica.conf │ ├── Makefile │ ├── README.md │ └── Dockerfile.asciidoc └── README.md ├── bazel └── example │ ├── using-workspace │ ├── .bazelversion │ ├── BUILD.bazel │ ├── .bazelrc │ ├── hello_p4runtime.cc │ └── WORKSPACE.bazel │ └── using-bzlmod │ ├── BUILD.bazel │ ├── .bazelrc │ ├── MODULE.bazel │ └── hello_p4runtime.cc ├── .gitignore ├── proto ├── .bazelrc ├── WORKSPACE.bzlmod ├── update_google_rpc_status.sh ├── MODULE.bazel ├── WORKSPACE.bazel ├── google │ └── rpc │ │ └── status.proto ├── p4 │ ├── v1 │ │ └── p4data.proto │ └── config │ │ └── v1 │ │ ├── p4types.proto │ │ └── p4info.proto ├── p4runtime_deps.bzl ├── BUILD.bazel └── LICENSE ├── .github ├── workflows │ ├── rust-build.yml │ ├── codegen.yml │ ├── spec.yml │ ├── google-rpc-status-synced.yml │ ├── any-branch-uploads.yml │ ├── main-branch-uploads.yml │ ├── tag-uploads.yml │ └── bazel-build.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── go.mod ├── CONTRIBUTING.md ├── CI └── check_codegen.sh ├── codegen ├── update.sh ├── Dockerfile └── compile_protos.sh ├── tools ├── asciidocint.conf.json └── asciidoclint.py ├── go.sum ├── README.md ├── LICENSE └── go └── p4 └── v1 └── p4runtime_grpc.pb.go /py/p4/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /py/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /py/p4/v1/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /rust/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /py/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /py/p4/config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /py/p4/config/v1/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/v1/resources/figs/.gitignore: -------------------------------------------------------------------------------- 1 | stem* 2 | -------------------------------------------------------------------------------- /bazel/example/using-workspace/.bazelversion: -------------------------------------------------------------------------------- 1 | 7.4.1 2 | -------------------------------------------------------------------------------- /docs/libre-office.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/libre-office.png -------------------------------------------------------------------------------- /py/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | if __name__ == "__main__": 4 | setuptools.setup() 5 | -------------------------------------------------------------------------------- /docs/v1/libre-office.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/libre-office.png -------------------------------------------------------------------------------- /docs/tools/fonts/luximr.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/tools/fonts/luximr.ttf -------------------------------------------------------------------------------- /docs/v1/resources/theme/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/theme/logo.png -------------------------------------------------------------------------------- /docs/tools/fonts/UtopiaStd-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/tools/fonts/UtopiaStd-Regular.otf -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "p4runtime-prost", 4 | "p4runtime-tonic", 5 | ] 6 | resolver = "2" 7 | -------------------------------------------------------------------------------- /docs/v1/resources/figs/error-report.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/figs/error-report.odg -------------------------------------------------------------------------------- /docs/v1/resources/fonts/LuxiMono/luximb.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/LuxiMono/luximb.ttf -------------------------------------------------------------------------------- /docs/v1/resources/fonts/LuxiMono/luximr.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/LuxiMono/luximr.ttf -------------------------------------------------------------------------------- /docs/tools/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | docker build -t p4rt-asciidoc -f Dockerfile.asciidoc . 3 | docker tag p4rt-asciidoc p4lang/p4rt-asciidoc:latest -------------------------------------------------------------------------------- /docs/v1/resources/fonts/LuxiMono/luximbi.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/LuxiMono/luximbi.ttf -------------------------------------------------------------------------------- /docs/v1/resources/fonts/LuxiMono/luximri.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/LuxiMono/luximri.ttf -------------------------------------------------------------------------------- /docs/v1/resources/fonts/Utopia/utopia-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/Utopia/utopia-bold.ttf -------------------------------------------------------------------------------- /docs/v1/resources/fonts/Utopia/utopia-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/Utopia/utopia-italic.ttf -------------------------------------------------------------------------------- /docs/v1/resources/figs/reference-architecture.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/figs/reference-architecture.odg -------------------------------------------------------------------------------- /docs/v1/resources/fonts/OpenSans/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/OpenSans/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /docs/v1/resources/fonts/Utopia/utopia-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/Utopia/utopia-regular.ttf -------------------------------------------------------------------------------- /docs/v1/resources/figs/psa-metadata-translation.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/figs/psa-metadata-translation.odg -------------------------------------------------------------------------------- /docs/v1/resources/figs/single-embedded-controller.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/figs/single-embedded-controller.odg -------------------------------------------------------------------------------- /docs/v1/resources/figs/single-remote-controller.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/figs/single-remote-controller.odg -------------------------------------------------------------------------------- /docs/v1/resources/fonts/OpenSans/OpenSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/OpenSans/OpenSans-Italic.ttf -------------------------------------------------------------------------------- /docs/v1/resources/fonts/OpenSans/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/OpenSans/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /docs/v1/resources/fonts/Utopia/utopia-bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/Utopia/utopia-bolditalic.ttf -------------------------------------------------------------------------------- /docs/v1/resources/fonts/OpenSans/OpenSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/fonts/OpenSans/OpenSans-BoldItalic.ttf -------------------------------------------------------------------------------- /docs/v1/resources/figs/embedded-plus-two-remote-controllers.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/figs/embedded-plus-two-remote-controllers.odg -------------------------------------------------------------------------------- /docs/v1/resources/figs/embedded-plus-single-remote-controller.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/figs/embedded-plus-single-remote-controller.odg -------------------------------------------------------------------------------- /docs/v1/resources/figs/embedded-plus-two-remote-ha-controllers.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/p4runtime/HEAD/docs/v1/resources/figs/embedded-plus-two-remote-ha-controllers.odg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Emacs 2 | *~ 3 | docs/v1/build/ 4 | .DS_Store 5 | build 6 | dist 7 | *.egg-info 8 | .eggs 9 | 10 | # Rust 11 | target/ 12 | 13 | # Bazel 14 | bazel-* 15 | *.lock 16 | -------------------------------------------------------------------------------- /py/p4/v1/p4data_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | -------------------------------------------------------------------------------- /py/p4/config/v1/p4info_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | -------------------------------------------------------------------------------- /py/p4/config/v1/p4types_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | -------------------------------------------------------------------------------- /rust/p4runtime-tonic/src/lib.rs: -------------------------------------------------------------------------------- 1 | /// The official Tonic API for all P4Runtime gRPC services, including clients and server code. 2 | pub mod p4 { 3 | pub mod v1 { 4 | tonic::include_proto!("p4.v1"); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /bazel/example/using-bzlmod/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_binary( 2 | name = "hello_p4runtime", 3 | srcs = ["hello_p4runtime.cc"], 4 | deps = [ 5 | "@com_github_p4lang_p4runtime//:p4info_cc_proto", 6 | "@com_google_protobuf//:protobuf", 7 | ] 8 | ) 9 | -------------------------------------------------------------------------------- /bazel/example/using-workspace/BUILD.bazel: -------------------------------------------------------------------------------- 1 | cc_binary( 2 | name = "hello_p4runtime", 3 | srcs = ["hello_p4runtime.cc"], 4 | deps = [ 5 | "@com_github_p4lang_p4runtime//:p4info_cc_proto", 6 | "@com_google_protobuf//:protobuf", 7 | ] 8 | ) 9 | -------------------------------------------------------------------------------- /proto/.bazelrc: -------------------------------------------------------------------------------- 1 | # Use Bzlmod (`MODULE.bazel`) instead of `WORKSPACE.bazel`. 2 | common --enable_bzlmod 3 | common --noenable_workspace 4 | 5 | # Use C++17 (required for recent gRPC versions). 6 | build --cxxopt=-std=c++17 7 | build --host_cxxopt=-std=c++17 8 | -------------------------------------------------------------------------------- /docs/v1/resources/fonts/verify-font: -------------------------------------------------------------------------------- 1 | require 'ttfunk' 2 | require 'ttfunk/subset_collection' 3 | 4 | ttf_subsets = TTFunk::SubsetCollection.new TTFunk::File.open ARGV[0] 5 | (0...(ttf_subsets.instance_variable_get :@subsets).size).each {|idx| ttf_subsets[idx].encode } -------------------------------------------------------------------------------- /bazel/example/using-bzlmod/.bazelrc: -------------------------------------------------------------------------------- 1 | # Use Bzlmod (`MODULE.bazel`) instead of `WORKSPACE.bazel`. 2 | common --enable_bzlmod 3 | common --noenable_workspace 4 | 5 | # Use C++17 (required for recent gRPC versions). 6 | build --cxxopt=-std=c++17 7 | build --host_cxxopt=-std=c++17 8 | -------------------------------------------------------------------------------- /bazel/example/using-workspace/.bazelrc: -------------------------------------------------------------------------------- 1 | # Use `WORKSPACE.bazel` instead of bzlmod (`MODULE.bazel`). 2 | common --enable_workspace 3 | common --noenable_bzlmod 4 | 5 | # Use C++17 (required for recent gRPC versions). 6 | build --cxxopt=-std=c++17 7 | build --host_cxxopt=-std=c++17 8 | -------------------------------------------------------------------------------- /proto/WORKSPACE.bzlmod: -------------------------------------------------------------------------------- 1 | # https://bazel.build/external/migration#workspace.bzlmod 2 | # 3 | # This file is intentionally empty. When bzlmod is enabled and this 4 | # file exists, the contents of WORKSPACE.bazel is ignored. This prevents 5 | # bzlmod builds from unintentionally depending on the WORKSPACE.bazel file. 6 | -------------------------------------------------------------------------------- /.github/workflows/rust-build.yml: -------------------------------------------------------------------------------- 1 | name: "Rust build" 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | 8 | jobs: 9 | build: 10 | runs-on: [ubuntu-latest] 11 | steps: 12 | - uses: actions/checkout@v5 13 | - run: cd rust && cargo build 14 | - run: cd rust && cargo test 15 | -------------------------------------------------------------------------------- /py/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools", 4 | "setuptools_scm[toml]", 5 | "setuptools_scm_git_archive", 6 | "wheel", 7 | ] 8 | build-backend = 'setuptools.build_meta' 9 | 10 | [tool.setuptools_scm] 11 | root = "../" 12 | # use current tag and not next one 13 | version_scheme = "post-release" 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **This is to suggest improvements to the `P4Runtime` specification. For issues regarding a specific implementation, please open an issue with the appropriate repository (e.g. https://github.com/p4lang/behavioral-model or https://github.com/p4lang/PI for bmv2).** 8 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/p4lang/p4runtime 2 | 3 | go 1.20 4 | 5 | require ( 6 | google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 7 | google.golang.org/grpc v1.56.3 8 | google.golang.org/protobuf v1.33.0 9 | ) 10 | 11 | require ( 12 | github.com/golang/protobuf v1.5.3 // indirect 13 | golang.org/x/net v0.38.0 // indirect 14 | golang.org/x/sys v0.31.0 // indirect 15 | golang.org/x/text v0.23.0 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report an issue with the code / documents hosted in this repository 4 | 5 | --- 6 | 7 | **This is for reporting issues with the specification only. If you are running into a bug with a specific `P4Runtime` implementation, please open an issue with the appropriate repository (e.g. https://github.com/p4lang/behavioral-model or https://github.com/p4lang/PI for bmv2).** 8 | -------------------------------------------------------------------------------- /docs/tools/fonts/fix_helvetica.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | Helvetica 12 | 13 | 14 | sans-serif 15 | 16 | 17 | ~/.fonts 18 | 19 | 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | You can fork the repo and submit a pull request in Github. 2 | 3 | ### Apache CLA 4 | 5 | All developers must have signed the [P4.org](http://p4.org) CLA. 6 | 7 | ### AsciiDoc style checker 8 | 9 | The P4Runtime specification is written using [AsciiDoc](https://docs.asciidoctor.org/). 10 | We provide a lint tool to catch basic formatting issues and try to keep the spec uniform. 11 | The lint tool will be run as part of CI and patches cannot be merged until it returns success. You can 12 | run the lint tool locally with `./tools/asciidoclint.py`. 13 | -------------------------------------------------------------------------------- /proto/update_google_rpc_status.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Updates proto/google/rpc/status.proto with the latest version from the 4 | # official upstream repository. 5 | # 6 | # The file is very stable and hasn't changed in many years, but we enforce 7 | # freshness of this copy using a GitHub Actions workflow just in case. 8 | 9 | set -e 10 | 11 | STATUS_PROTO_URL="https://raw.githubusercontent.com/googleapis/googleapis/refs/heads/master/google/rpc/status.proto" 12 | THIS_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" 13 | 14 | wget "$STATUS_PROTO_URL" -O "$THIS_DIR/google/rpc/status.proto" 15 | -------------------------------------------------------------------------------- /.github/workflows/codegen.yml: -------------------------------------------------------------------------------- 1 | name: Check generated code 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - "*-dev" 8 | pull_request: 9 | branches: 10 | - main 11 | - "*-dev" 12 | 13 | jobs: 14 | check-codegen: 15 | runs-on: [ubuntu-latest] 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Compile protobufs 19 | run: | 20 | docker build -t p4runtime-ci -f codegen/Dockerfile . 21 | docker run -t p4runtime-ci /p4runtime/codegen/compile_protos.sh /tmp 22 | - name: Check codegen 23 | run: | 24 | ./CI/check_codegen.sh 25 | -------------------------------------------------------------------------------- /rust/p4runtime-prost/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "p4runtime-prost" 3 | version = "1.4.0" 4 | edition = "2021" 5 | authors = ["P4 API Working Group "] 6 | description = "P4Runtime Specification - Protobuf message API (Prost)" 7 | categories = ["network-programming"] 8 | keywords = ["p4runtime", "protobuf"] 9 | license = "Apache-2.0" 10 | repository = "https://github.com/p4lang/p4runtime" 11 | 12 | [dependencies] 13 | prost = "0.14" 14 | prost-types = "0.14" 15 | 16 | [build-dependencies] 17 | protoc-prebuilt = "0.3" # To obtain `protoc` binary (the Protobuf compiler). 18 | prost-build = "0.14" # To generate API for Protobuf messages. 19 | walkdir = "2" # To find proto files. 20 | -------------------------------------------------------------------------------- /bazel/example/using-bzlmod/MODULE.bazel: -------------------------------------------------------------------------------- 1 | bazel_dep( 2 | name = "p4runtime", 3 | repo_name = "com_github_p4lang_p4runtime", 4 | ) 5 | 6 | # In your own project, you will likely want to use `http_archive` instead 7 | # of `local_repository` to load p4runtime. 8 | local_path_override( 9 | module_name = "p4runtime", 10 | path = "../../../proto", 11 | ) 12 | 13 | # git_override( 14 | # module_name = "p4runtime", 15 | # strip_prefix = "p4runtime-1.4.1/proto", 16 | # urls = ["https://github.com/p4lang/p4runtime/archive/v1.4.1.tar.gz"], 17 | # # sha256 = "", 18 | # ) 19 | 20 | bazel_dep( 21 | name = "protobuf", 22 | version = "29.1", 23 | repo_name = "com_google_protobuf", 24 | ) 25 | -------------------------------------------------------------------------------- /.github/workflows/spec.yml: -------------------------------------------------------------------------------- 1 | name: Build spec 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - '*-dev' 8 | pull_request: 9 | branches: 10 | - main 11 | - '*-dev' 12 | 13 | jobs: 14 | asciidoc-lint: 15 | runs-on: [ubuntu-latest] 16 | steps: 17 | - uses: actions/checkout@v3 18 | - name: Run linter 19 | run: | 20 | ./tools/asciidoclint.py docs/v1/P4Runtime-Spec.adoc 21 | 22 | build-spec: 23 | runs-on: [ubuntu-latest] 24 | steps: 25 | - uses: actions/checkout@v3 26 | - name: Build spec 27 | run: | 28 | make -C docs/tools/ 29 | docker run -v `pwd`/docs/v1:/usr/src/p4-spec p4lang/p4rt-asciidoc make build_spec_with_images 30 | ls docs/v1/build 31 | -------------------------------------------------------------------------------- /.github/workflows/google-rpc-status-synced.yml: -------------------------------------------------------------------------------- 1 | name: Ensure google/rpc/status.proto is synced with upstream. 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | check-google-rpc-status-synced: 8 | runs-on: [ubuntu-latest] 9 | steps: 10 | - uses: actions/checkout@v5 11 | - run: ./proto/update_google_rpc_status.sh 12 | - run: | 13 | DIFF=$(git diff proto/google/rpc/status.proto) 14 | if [ -n "$DIFF" ]; then 15 | echo "$DIFF" 16 | echo "" 17 | echo "ERROR: proto/google/rpc/status.proto is not synced with upstream." 18 | echo "Please run ./proto/update_google_rpc_status.sh to fix it." 19 | exit 1 20 | fi 21 | echo "SUCCESS: proto/google/rpc/status.proto is synced with upstream." 22 | -------------------------------------------------------------------------------- /CI/check_codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | THIS_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" 6 | 7 | pushd "$THIS_DIR/.." >/dev/null 8 | 9 | rm -rf go/* 10 | rm -rf py/p4 11 | ./codegen/update.sh 12 | 13 | diff="$(git status --porcelain go go.mod go.sum)" 14 | 15 | if [ ! -z "$diff" ]; then 16 | echo "The generated Go files are not up-to-date" 17 | echo "You can regenerate them with './codegen/update.sh' and commit the changes" 18 | exit 1 19 | fi 20 | 21 | diff="$(git status --porcelain py)" 22 | 23 | if [ ! -z "$diff" ]; then 24 | echo "The generated Python files are not up-to-date" 25 | echo "You can regenerate them with './codegen/update.sh' and commit the changes" 26 | exit 1 27 | fi 28 | 29 | popd >/dev/null 30 | -------------------------------------------------------------------------------- /py/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = p4runtime 3 | description = Python bindings for P4Runtime protocol 4 | long_description = file: README.md 5 | long_description_content_type = text/markdown; charset=UTF-8 6 | url = https://github.com/p4lang/p4runtime 7 | author = P4 API Working Group 8 | author_email = p4-api@lists.p4.org 9 | license = Apache-2.0 10 | license_file = LICENSE 11 | classifiers = 12 | License :: OSI Approved :: Apache Software License 13 | Programming Language :: Python 14 | Programming Language :: Python :: 3 15 | 16 | [options] 17 | packages = find: 18 | platforms = any 19 | python_requires = >=3.6 20 | setup_requires = 21 | setuptools_scm 22 | install_requires = 23 | protobuf >= 3.6.1 24 | grpcio >= 1.17.2 25 | googleapis-common-protos >= 1.52 26 | -------------------------------------------------------------------------------- /bazel/example/using-bzlmod/hello_p4runtime.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "google/protobuf/text_format.h" 4 | #include "p4/config/v1/p4info.pb.h" 5 | 6 | using ::google::protobuf::TextFormat; 7 | using ::p4::config::v1::P4Info; 8 | 9 | int main() { 10 | P4Info p4info; 11 | TextFormat::ParseFromString(R"PROTO( 12 | tables { 13 | preamble { 14 | id: 10 15 | name: "Hello, P4Runtime!" 16 | } 17 | } 18 | )PROTO", &p4info); 19 | p4info.mutable_tables()->at(0).mutable_preamble()->set_id(42); 20 | std::cout << p4info.DebugString(); 21 | } 22 | -------------------------------------------------------------------------------- /bazel/example/using-workspace/hello_p4runtime.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "google/protobuf/text_format.h" 4 | #include "p4/config/v1/p4info.pb.h" 5 | 6 | using ::google::protobuf::TextFormat; 7 | using ::p4::config::v1::P4Info; 8 | 9 | int main() { 10 | P4Info p4info; 11 | TextFormat::ParseFromString(R"PROTO( 12 | tables { 13 | preamble { 14 | id: 10 15 | name: "Hello, P4Runtime!" 16 | } 17 | } 18 | )PROTO", &p4info); 19 | p4info.mutable_tables()->at(0).mutable_preamble()->set_id(42); 20 | std::cout << p4info.DebugString(); 21 | } 22 | -------------------------------------------------------------------------------- /rust/p4runtime-tonic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "p4runtime-tonic" 3 | version = "1.4.0" 4 | edition = "2021" 5 | authors = ["P4 API Working Group "] 6 | description = "P4Runtime Specification - gRPC service definitions" 7 | categories = ["network-programming"] 8 | keywords = ["p4runtime", "grpc", "tonic"] 9 | license = "Apache-2.0" 10 | repository = "https://github.com/p4lang/p4runtime" 11 | 12 | [dependencies] 13 | p4runtime-prost = { path = "../p4runtime-prost" } 14 | prost = "0.14" 15 | prost-types = "0.14" 16 | tonic = "0.14" 17 | tonic-prost = "0.14" 18 | 19 | [build-dependencies] 20 | # To obtain `protoc` binary (the Protobuf compiler). 21 | protoc-prebuilt = "0.3" 22 | # To generate client/server code for grpc services. 23 | tonic-prost-build = "0.14" 24 | # To find proto files. 25 | walkdir = "2" 26 | -------------------------------------------------------------------------------- /docs/v1/Makefile: -------------------------------------------------------------------------------- 1 | SPEC=P4Runtime-Spec 2 | 3 | ROUGE_STYLE=github 4 | ROUGE_CSS=style 5 | 6 | all: ${SPEC}.pdf ${SPEC}.html 7 | 8 | folder: 9 | mkdir -p build 10 | 11 | build: 12 | 13 | ${SPEC}.pdf: ${SPEC}.adoc images folder 14 | time asciidoctor-pdf -v \ 15 | -a pdf-fontsdir=resources/fonts \ 16 | -r asciidoctor-mathematical \ 17 | -r asciidoctor-bibtex \ 18 | -r asciidoctor-lists \ 19 | -a rouge-style=$(ROUGE_STYLE) \ 20 | -D build $< 21 | 22 | ${SPEC}.html: ${SPEC}.adoc images folder 23 | time asciidoctor -v \ 24 | -r asciidoctor-mathematical \ 25 | -r asciidoctor-bibtex \ 26 | -r asciidoctor-lists \ 27 | -a rouge-css=$(ROUGE_CSS) \ 28 | -D build $< 29 | 30 | images: 31 | soffice --convert-to svg --outdir resources/figs resources/figs/*.odg > /dev/null 2>&1 32 | soffice --convert-to png --outdir resources/figs resources/figs/*.odg > /dev/null 2>&1 33 | 34 | build_spec_with_images: images all 35 | 36 | clean: 37 | /bin/rm -rf build resources/figs/*.png resources/figs/*.svg -------------------------------------------------------------------------------- /docs/tools/README.md: -------------------------------------------------------------------------------- 1 | Dockerfile.asciidoc is used to build a Docker image which we use to render the 2 | P4Runtime specification (HTML & PDF) in CI. The image can also be used locally 3 | to build the specification without having to worry about installing all the 4 | dependencies yourself. 5 | 6 | Only maintainers of this repository need to build the Docker image when a new 7 | image needs to be pushed to dockerhub. Contributors to the specification can 8 | simply pull the image from dockerhub and don't have to worry about building the 9 | image themselves. If you are a maintainer and you need to upload a new version 10 | of the Docker image to to dockerhub, you will need the following commands: 11 | ```bash 12 | docker build -t p4rt-asciidoc -f Dockerfile.asciidoc . 13 | docker tag p4rt-asciidoc p4lang/p4rt-asciidoc:latest 14 | docker push p4lang/p4rt-asciidoc:latest 15 | ``` 16 | 17 | Note that you need to have write permissions to the p4lang dockerhub repository 18 | to push the image (and you need to be logged in). 19 | -------------------------------------------------------------------------------- /codegen/update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" 6 | 7 | pushd "$THIS_DIR/.." >/dev/null 8 | 9 | docker build -t p4runtime-ci -f codegen/Dockerfile . 10 | 11 | tmpdir="$(mktemp -d /tmp/p4rt.XXXXXX)" 12 | 13 | docker run --rm \ 14 | -v "$tmpdir:/tmp/gen" \ 15 | p4runtime-ci /p4runtime/codegen/compile_protos.sh /tmp/gen 16 | 17 | # Go 18 | cp -r "$tmpdir"/go_out/github.com/p4lang/p4runtime/go/* go/ 19 | 20 | # Python 21 | cp -r "$tmpdir"/py_out/p4 py/ 22 | find py/p4 -type d -exec touch {}/__init__.py \; 23 | 24 | # Cleanup files owned by root user 25 | docker run --rm \ 26 | -v "$tmpdir:/tmp/gen" \ 27 | p4runtime-ci bash -c "rm -r /tmp/gen/*" 28 | 29 | docker run --rm -u "$(id -u):$(id -g)" \ 30 | -e "GOCACHE=/tmp/gocache" \ 31 | -e "GOPATH=/tmp/gopath" \ 32 | -v "$(pwd):/p4runtime" \ 33 | -w /p4runtime \ 34 | golang:1.20 bash -c "go mod tidy" 35 | 36 | rm -rf "$tmpdir" 37 | 38 | popd >/dev/null 39 | -------------------------------------------------------------------------------- /.github/workflows/any-branch-uploads.yml: -------------------------------------------------------------------------------- 1 | name: Any branch uploads 2 | 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | 8 | jobs: 9 | any-branch-uploads: 10 | if: ${{ github.repository == 'p4lang/p4runtime' }} 11 | runs-on: [ubuntu-latest] 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: Build spec 15 | run: | 16 | make -C docs/tools/ 17 | docker run -v `pwd`/docs/v1:/usr/src/p4-spec p4lang/p4rt-asciidoc make 18 | ls docs/v1/build 19 | - name: Upload spec to S3 if needed 20 | if: ${{ github.actor != 'dependabot[bot]' }} 21 | uses: jakejarvis/s3-sync-action@v0.5.1 22 | with: 23 | args: --acl public-read --follow-symlinks --delete 24 | env: 25 | AWS_S3_BUCKET: 'p4runtime' 26 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 27 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 28 | AWS_REGION: 'us-west-2' 29 | SOURCE_DIR: 'docs/v1/build' 30 | DEST_DIR: ci/${{ github.ref_name }} # only runs for push events 31 | -------------------------------------------------------------------------------- /codegen/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM p4lang/third-party:latest 2 | LABEL maintainer="P4 API Working Group " 3 | LABEL description="Dockerfile used for CI testing of p4lang/p4runtime" 4 | 5 | # No questions asked during package installation. 6 | ARG DEBIAN_FRONTEND=noninteractive 7 | 8 | RUN apt-get update && \ 9 | apt-get install -y --no-install-recommends software-properties-common git curl 10 | 11 | ARG GO_VERSION=1.20.5 12 | 13 | RUN set -eux; \ 14 | dpkgArch="$(dpkg --print-architecture)"; \ 15 | case "${dpkgArch##*-}" in \ 16 | amd64) arch='amd64' ;; \ 17 | arm64) arch='arm64' ;; \ 18 | *) arch=''; echo >&2; echo >&2 "unsupported architecture '$dpkgArch'"; echo >&2 ; exit 1 ;; \ 19 | esac; \ 20 | curl -L -o go.tar.gz https://dl.google.com/go/go${GO_VERSION}.linux-${arch}.tar.gz; \ 21 | tar -C /usr/local -xzf go.tar.gz; \ 22 | rm -f go.tar.gz 23 | 24 | ENV PATH="${PATH}:/usr/local/go/bin:/root/go/bin" 25 | 26 | RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.31 27 | RUN go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3 28 | 29 | COPY . /p4runtime/ 30 | WORKDIR /p4runtime/ 31 | -------------------------------------------------------------------------------- /proto/MODULE.bazel: -------------------------------------------------------------------------------- 1 | module( 2 | name = "p4runtime", 3 | bazel_compatibility = [">=7.4.1"], 4 | repo_name = "com_github_p4lang_p4runtime", 5 | ) 6 | 7 | bazel_dep(name = "bazel_skylib", version = "1.7.1") 8 | bazel_dep( 9 | name = "googleapis", 10 | version = "0.0.0-20240819-fe8ba054a", 11 | repo_name = "com_google_googleapis", 12 | ) 13 | bazel_dep( 14 | name = "grpc", 15 | version = "1.68.0", 16 | repo_name = "com_github_grpc_grpc", 17 | ) 18 | bazel_dep( 19 | name = "protobuf", 20 | version = "29.1", 21 | repo_name = "com_google_protobuf", 22 | ) 23 | bazel_dep(name = "rules_license", version = "1.0.0") 24 | bazel_dep(name = "rules_proto", version = "7.0.2") 25 | bazel_dep( 26 | name = "rules_go", 27 | version = "0.59.0", 28 | repo_name = "io_bazel_rules_go", 29 | ) 30 | bazel_dep(name = "gazelle", version = "0.45.0") 31 | 32 | switched_rules = use_extension("@com_google_googleapis//:extensions.bzl", "switched_rules") 33 | switched_rules.use_languages( 34 | cc = True, 35 | go = True, 36 | grpc = True, 37 | python = True, 38 | ) 39 | use_repo(switched_rules, "com_google_googleapis_imports") 40 | -------------------------------------------------------------------------------- /docs/tools/Dockerfile.asciidoc: -------------------------------------------------------------------------------- 1 | FROM ruby:3.3.5 2 | LABEL maintainer="P4 API Working Group " 3 | LABEL description="Dockerfile used for building the asciidoc specification" 4 | 5 | RUN apt-get update && \ 6 | apt-get install -y cmake flex bison libglib2.0-dev libcairo2-dev libpango1.0-dev libxml2-dev libwebp-dev libzstd-dev libgdk-pixbuf-2.0-dev time 7 | 8 | RUN apt-get install -y libreoffice && \ 9 | gem install asciidoctor && \ 10 | echo 'gem: --no-document' > /etc/gemrc && \ 11 | gem install nokogiri && \ 12 | gem install rghost && \ 13 | gem install asciidoctor-diagram && \ 14 | gem install asciidoctor-plantuml && \ 15 | gem install asciidoctor-pdf --version 2.3.19 && \ 16 | gem install asciidoctor-pdf-cjk && \ 17 | gem install asciidoctor-lists --version 1.1.2 && \ 18 | gem install coderay pygments.rb thread_safe && \ 19 | gem install slim && \ 20 | gem install concurrent-ruby && \ 21 | gem install haml tilt && \ 22 | gem install asciidoctor-mathematical && \ 23 | gem install asciidoctor-bibtex &&\ 24 | git clone https://github.com/rouge-ruby/rouge &&\ 25 | cd rouge && \ 26 | git log -n 1 | cat && \ 27 | gem build rouge.gemspec && \ 28 | gem install rouge 29 | 30 | VOLUME ["/usr/src/p4-spec"] 31 | WORKDIR /usr/src/p4-spec -------------------------------------------------------------------------------- /tools/asciidocint.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "keywords": [ 3 | { 4 | "category": "P4Runtime message", 5 | "keywords": [ 6 | "WriteRequest", 7 | "WriteResponse", 8 | "ReadRequest", 9 | "ReadResponse", 10 | "SetForwardingPipelineConfigRequest", 11 | "SetForwardingPipelineConfigResponse", 12 | "GetForwardingPipelineConfigRequest", 13 | "GetForwardingPipelineConfigResponse", 14 | "StreamMessageRequest", 15 | "StreamMessageResponse" 16 | ] 17 | }, 18 | { 19 | "category": "gRPC error code", 20 | "keywords": [ 21 | "CANCELLED", 22 | "UNKNOWN", 23 | "INVALID_ARGUMENT", 24 | "DEADLINE_EXCEEDED", 25 | "NOT_FOUND", 26 | "ALREADY_EXISTS", 27 | "PERMISSION_DENIED", 28 | "UNAUTHENTICATED", 29 | "RESOURCE_EXHAUSTED", 30 | "FAILED_PRECONDITION", 31 | "ABORTED", 32 | "OUT_OF_RANGE", 33 | "UNIMPLEMENTED", 34 | "INTERNAL", 35 | "UNAVAILABLE", 36 | "DATA_LOSS" 37 | ] 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /rust/p4runtime-tonic/build.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | fn main() -> Result<(), Box> { 4 | // Define constants. 5 | let protoc_version = "33.0"; // Version of the Protobuf compiler to use. 6 | let proto_root = "../../proto"; 7 | 8 | // Set `protoc` binary (the Protobuf compiler). 9 | let (protoc_bin, protoc_include) = protoc_prebuilt::init(protoc_version).unwrap(); 10 | std::env::set_var("PROTOC", protoc_bin); 11 | std::env::set_var("PROTOC_INCLUDE", protoc_include); 12 | 13 | // Find all .proto files. 14 | let mut proto_files: Vec = Vec::new(); 15 | for entry in walkdir::WalkDir::new(proto_root) 16 | .into_iter() 17 | .filter_map(|e| e.ok()) 18 | { 19 | let path = entry.path(); 20 | if path.is_file() && path.extension().map_or(false, |ext| ext == "proto") { 21 | println!("cargo:rerun-if-changed={}", path.display()); 22 | proto_files.push(path.to_path_buf()); 23 | } 24 | } 25 | println!("cargo:rerun-if-changed={}", proto_root); 26 | 27 | // Compile the `.proto` files into Rust code. 28 | tonic_prost_build::configure() 29 | // Tell tonic to use the prost-generated types for the Protobuf messages. 30 | .extern_path(".p4", "::p4runtime_prost::p4") 31 | // Build server and client code for the gRPC service. 32 | .build_server(true) 33 | .build_client(true) 34 | .compile_protos(&proto_files, &[PathBuf::from(proto_root)])?; 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /rust/p4runtime-prost/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::path::PathBuf; 3 | 4 | fn main() -> Result<(), Box> { 5 | // Define constants. 6 | let protoc_version = "33.0"; // Version of the Protobuf compiler to use. 7 | let proto_root = "../../proto"; 8 | let out_dir = PathBuf::from(env::var("OUT_DIR").expect("environment variable OUT_DIR not set")); 9 | let descriptor_path = PathBuf::from(out_dir).join("file_descriptor_set.bin"); 10 | 11 | // Set `protoc` binary (the Protobuf compiler). 12 | let (protoc_bin, protoc_include) = protoc_prebuilt::init(protoc_version).unwrap(); 13 | std::env::set_var("PROTOC", protoc_bin); 14 | std::env::set_var("PROTOC_INCLUDE", protoc_include); 15 | 16 | // Find all .proto files. 17 | let mut proto_files: Vec = Vec::new(); 18 | for entry in walkdir::WalkDir::new(proto_root) 19 | .into_iter() 20 | .filter_map(|e| e.ok()) 21 | { 22 | let path = entry.path(); 23 | if path.is_file() && path.extension().map_or(false, |ext| ext == "proto") { 24 | println!("cargo:rerun-if-changed={}", path.display()); 25 | proto_files.push(path.to_path_buf()); 26 | } 27 | } 28 | println!("cargo:rerun-if-changed={}", proto_root); 29 | 30 | // Compile the `.proto` files into Rust code. 31 | prost_build::Config::new() 32 | // Tell prost to generate a file descriptor set (for gRPC reflection). 33 | .file_descriptor_set_path(&descriptor_path) 34 | .compile_protos(&proto_files, &[proto_root])?; 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /rust/p4runtime-prost/src/lib.rs: -------------------------------------------------------------------------------- 1 | use prost::Message; 2 | use prost_types::FileDescriptorSet; 3 | 4 | /// The official Prost API for all 5 | /// [P4Runtime Protobuf messages](https://github.com/p4lang/p4runtime/blob/main/proto). 6 | pub mod p4 { 7 | pub mod v1 { 8 | include!(concat!(env!("OUT_DIR"), "/p4.v1.rs")); 9 | } 10 | pub mod config { 11 | pub mod v1 { 12 | include!(concat!(env!("OUT_DIR"), "/p4.config.v1.rs")); 13 | } 14 | } 15 | } 16 | 17 | /// Unofficial Prost API for [`google/rpc/status.proto`](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto). 18 | /// 19 | /// Included as a workaround here since there is currently no official crate providing this API. 20 | pub mod google { 21 | pub mod rpc { 22 | include!(concat!(env!("OUT_DIR"), "/google.rpc.rs")); 23 | } 24 | } 25 | 26 | /// Returns a `FileDescriptorSet` defining all Protobuf messages used by P4Runtime. 27 | /// 28 | /// Enables [gRPC reflection](https://grpc.io/docs/guides/reflection/). 29 | pub fn file_descriptor_set() -> FileDescriptorSet { 30 | let raw_proto: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/file_descriptor_set.bin")); 31 | return FileDescriptorSet::decode(raw_proto).unwrap(); 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | 38 | #[test] 39 | fn file_descriptor_set_is_not_empty() { 40 | let descriptor_set = file_descriptor_set(); 41 | assert!( 42 | !descriptor_set.file.is_empty(), 43 | "FileDescriptorSet is empty" 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.github/workflows/main-branch-uploads.yml: -------------------------------------------------------------------------------- 1 | name: Main branch uploads 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | main-branch-uploads: 10 | if: ${{ github.repository == 'p4lang/p4runtime' }} 11 | runs-on: [ubuntu-latest] 12 | steps: 13 | - uses: actions/checkout@v3 14 | with: 15 | # fetch all history for all branches and tags 16 | fetch-depth: 0 17 | - name: Build spec 18 | run: | 19 | make -C docs/tools/ 20 | docker run -v `pwd`/docs/v1:/usr/src/p4-spec p4lang/p4rt-asciidoc make 21 | ls docs/v1/build 22 | - name: Upload spec to S3 23 | uses: jakejarvis/s3-sync-action@v0.5.1 24 | with: 25 | args: --acl public-read --follow-symlinks --delete 26 | env: 27 | AWS_S3_BUCKET: 'p4runtime' 28 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 29 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 30 | AWS_REGION: 'us-west-2' 31 | SOURCE_DIR: 'docs/v1/build' 32 | DEST_DIR: docs/main 33 | - name: Prepare spec for upload to gh-pages 34 | run: | 35 | git checkout gh-pages 36 | mkdir -p spec 37 | rm -rf spec/main 38 | cp -r docs/v1/build spec/main 39 | - name: Upload spec to gh-pages 40 | uses: EndBug/add-and-commit@v9 41 | with: 42 | add: 'spec' 43 | author_name: 'P4Runtime CI' 44 | author_email: 'p4-api@lists.p4.org' 45 | default_author: github_actions 46 | message: 'Publish spec from Github Actions' 47 | commit: '--amend' 48 | push: 'origin gh-pages --force' 49 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 2 | github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= 3 | github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 4 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 5 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 6 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 7 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 8 | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 9 | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 10 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 11 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 12 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 13 | google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= 14 | google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= 15 | google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= 16 | google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= 17 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 18 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 19 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 20 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 21 | -------------------------------------------------------------------------------- /proto/WORKSPACE.bazel: -------------------------------------------------------------------------------- 1 | workspace(name = "com_github_p4lang_p4runtime") 2 | 3 | load("//:p4runtime_deps.bzl", "p4runtime_deps") 4 | 5 | p4runtime_deps() 6 | 7 | # -- Transitive dependencies. -------------------------------------------------- 8 | 9 | load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") 10 | 11 | protobuf_deps() 12 | 13 | load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies") 14 | 15 | rules_proto_dependencies() 16 | 17 | load("@rules_proto//proto:setup.bzl", "rules_proto_setup") 18 | 19 | rules_proto_setup() 20 | 21 | load("@rules_proto//proto:toolchains.bzl", "rules_proto_toolchains") 22 | 23 | rules_proto_toolchains() 24 | 25 | load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") 26 | 27 | go_rules_dependencies() 28 | 29 | load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") 30 | 31 | switched_rules_by_language( 32 | name = "com_google_googleapis_imports", 33 | cc = True, 34 | go = True, 35 | grpc = True, 36 | python = True, 37 | ) 38 | 39 | load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") 40 | 41 | grpc_deps() 42 | 43 | load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") 44 | 45 | grpc_extra_deps() 46 | 47 | load("@com_github_grpc_grpc//bazel:grpc_python_deps.bzl", "grpc_python_deps") 48 | 49 | grpc_python_deps() 50 | 51 | load("@rules_python//python:pip.bzl", "pip_parse") 52 | 53 | pip_parse( 54 | name = "grpc_python_dependencies", 55 | requirements_lock = "@com_github_grpc_grpc//:requirements.bazel.txt", 56 | ) 57 | 58 | load("@grpc_python_dependencies//:requirements.bzl", "install_deps") 59 | 60 | install_deps() 61 | 62 | load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") 63 | 64 | bazel_skylib_workspace() 65 | -------------------------------------------------------------------------------- /codegen/compile_protos.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This ensures that the P4Runtime Protobuf files are correct and compile with 4 | # the protoc compiler (CPP, gRPC, Python and Go). 5 | 6 | if [ "$#" -ne 1 ]; then 7 | echo "Usage: compile_protos.sh " 8 | exit 1 9 | fi 10 | 11 | BUILD_DIR="$1" 12 | PROTOC="$(which protoc)" 13 | if [ "$?" -ne 0 ]; then 14 | echo "Could not find protoc" 15 | exit 2 16 | fi 17 | 18 | echo "Using $PROTOC" 19 | 20 | GRPC_CPP_PLUGIN="$(which grpc_cpp_plugin)" 21 | if [ "$?" -ne 0 ]; then 22 | echo "Could not find CPP protoc plugin" 23 | exit 2 24 | fi 25 | GRPC_PY_PLUGIN="$(which grpc_python_plugin)" 26 | if [ "$?" -ne 0 ]; then 27 | echo "Could not find Python protoc plugin" 28 | exit 2 29 | fi 30 | 31 | set -e 32 | 33 | THIS_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" 34 | PROTO_DIR="$THIS_DIR/../proto" 35 | 36 | PROTOS="\ 37 | $PROTO_DIR/p4/v1/p4data.proto \ 38 | $PROTO_DIR/p4/v1/p4runtime.proto \ 39 | $PROTO_DIR/p4/config/v1/p4info.proto \ 40 | $PROTO_DIR/p4/config/v1/p4types.proto" 41 | 42 | PROTOFLAGS="-I$PROTO_DIR" 43 | 44 | mkdir -p "$BUILD_DIR/cpp_out" 45 | mkdir -p "$BUILD_DIR/grpc_out" 46 | mkdir -p "$BUILD_DIR/py_out" 47 | mkdir -p "$BUILD_DIR/go_out" 48 | 49 | set -o xtrace 50 | $PROTOC $PROTOS --cpp_out "$BUILD_DIR/cpp_out" $PROTOFLAGS 51 | $PROTOC $PROTOS --grpc_out "$BUILD_DIR/grpc_out" --plugin=protoc-gen-grpc="$GRPC_CPP_PLUGIN" $PROTOFLAGS 52 | # With the Python plugin, it seems that I need to use a single command for proto 53 | # + grpc and that the output directory needs to be the same (because the grpc 54 | # plugin inserts code into the proto-generated files). But maybe I am just using 55 | # an old version of the Python plugin. 56 | $PROTOC $PROTOS --python_out "$BUILD_DIR/py_out" $PROTOFLAGS --grpc_out "$BUILD_DIR/py_out" --plugin=protoc-gen-grpc="$GRPC_PY_PLUGIN" 57 | 58 | $PROTOC $PROTOS --go_out="$BUILD_DIR/go_out" --go-grpc_out="$BUILD_DIR/go_out" $PROTOFLAGS 59 | 60 | echo "SUCCESS" 61 | -------------------------------------------------------------------------------- /proto/google/rpc/status.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.rpc; 18 | 19 | import "google/protobuf/any.proto"; 20 | 21 | option cc_enable_arenas = true; 22 | option go_package = "google.golang.org/genproto/googleapis/rpc/status;status"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "StatusProto"; 25 | option java_package = "com.google.rpc"; 26 | option objc_class_prefix = "RPC"; 27 | 28 | // The `Status` type defines a logical error model that is suitable for 29 | // different programming environments, including REST APIs and RPC APIs. It is 30 | // used by [gRPC](https://github.com/grpc). Each `Status` message contains 31 | // three pieces of data: error code, error message, and error details. 32 | // 33 | // You can find out more about this error model and how to work with it in the 34 | // [API Design Guide](https://cloud.google.com/apis/design/errors). 35 | message Status { 36 | // The status code, which should be an enum value of 37 | // [google.rpc.Code][google.rpc.Code]. 38 | int32 code = 1; 39 | 40 | // A developer-facing error message, which should be in English. Any 41 | // user-facing error message should be localized and sent in the 42 | // [google.rpc.Status.details][google.rpc.Status.details] field, or localized 43 | // by the client. 44 | string message = 2; 45 | 46 | // A list of messages that carry the error details. There is a common set of 47 | // message types for APIs to use. 48 | repeated google.protobuf.Any details = 3; 49 | } 50 | -------------------------------------------------------------------------------- /docs/v1/resources/fonts/LuxiMono/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Bigelow & Holmes Inc and URW++ GmbH Luxi font license 2 | 3 | Luxi fonts copyright (c) 2001 by Bigelow & Holmes Inc. Luxi font instruction 4 | code copyright (c) 2001 by URW++ GmbH. All Rights Reserved. Luxi is a regis- 5 | tered trademark of Bigelow & Holmes Inc. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of these Fonts and associated documentation files (the "Font Software"), to 9 | deal in the Font Software, including without limitation the rights to use, 10 | copy, merge, publish, distribute, sublicense, and/or sell copies of the Font 11 | Software, and to permit persons to whom the Font Software is furnished to do 12 | so, subject to the following conditions: 13 | 14 | The above copyright and trademark notices and this permission notice shall be 15 | included in all copies of one or more of the Font Software. 16 | 17 | The Font Software may not be modified, altered, or added to, and in particu- 18 | lar the designs of glyphs or characters in the Fonts may not be modified nor 19 | may additional glyphs or characters be added to the Fonts. This License 20 | becomes null and void when the Fonts or Font Software have been modified. 21 | 22 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 23 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, 25 | TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BIGELOW & HOLMES INC. OR URW++ 26 | GMBH. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GEN- 27 | ERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN 28 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR 29 | INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFT- 30 | WARE. 31 | 32 | Except as contained in this notice, the names of Bigelow & Holmes Inc. and 33 | URW++ GmbH. shall not be used in advertising or otherwise to promote the 34 | sale, use or other dealings in this Font Software without prior written 35 | authorization from Bigelow & Holmes Inc. and URW++ GmbH. 36 | 37 | For further information, contact: 38 | 39 | info@urwpp.de or design@bigelowandholmes.com 40 | 41 | 42 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # P4Runtime specification documents 2 | 3 | ## Inline code with backticks 4 | 5 | Use backticks for: 6 | 7 | * names of Protobuf messages / fields / RPCs / enum symbols 8 | * P4 code 9 | * name of variables when describing examples (pseudo-code or P4) 10 | 11 | Do not use backticks for: 12 | 13 | * PSA extern names 14 | * "P4Runtime" & "P4Info" 15 | 16 | ## What to capitalize? 17 | 18 | * "Protobuf" 19 | * Each significant word in a heading / section name 20 | * PSA extern names 21 | 22 | ## Hexadecimal numbers 23 | 24 | We use lowercase for the letter digits when writing hexadecimal numbers. This is 25 | a very arbitrary decision, purely for the sake of uniformity. Maybe lowercase 26 | letters are easier to type for most people? 27 | 28 | ## Hyphen, en dash and em dash 29 | 30 | Use `-` for the hyphen, `--` for en dash and `—` for em dash. 31 | 32 | ## Document Figures 33 | 34 | Each image in the specification has a corresponding `.odg` file in 35 | `resources/figs/`. These are LibreOffice drawing files. The files are rendered into 36 | `.svg` and `.png` images (for HTML and PDF output, resepectively) at build time, 37 | using the `soffice` command-line tool. The page size for each image should be 38 | adjusted manually by the author ("artist") to just fit the image on the 39 | apparent "page," to minimize padding around the image in the rendered 40 | document. Use the menu item `Format | Page/Size Properties.` See the example 41 | screen shot below. (Do not check the "Fit object to paper format" box - it will 42 | change the object's aspect ratio.) 43 | ![LibreOffice](libre-office.png) 44 | 45 | ## CI upload of built documents 46 | 47 | Github Actions take care of uploading the built HTML version of the spec to 48 | Github. The latest working draft (main branch) can be found 49 | [here](https://p4.org/p4runtime/spec/main/P4Runtime-Spec.html). 50 | 51 | Additionally, you can access the HTML & PDF versions of the spec for any given 52 | branch of this repository by using the following URLs: 53 | * `https://s3-us-west-2.amazonaws.com/p4runtime/ci//P4Runtime-Spec.html` 54 | for the **HTML** version 55 | * `https://s3-us-west-2.amazonaws.com/p4runtime/ci//P4Runtime-Spec.pdf` 56 | for the **PDF** version 57 | 58 | Unfortunately, for security reasons, this does not work for branches in forked 59 | repositories, even for opened pull requests. 60 | -------------------------------------------------------------------------------- /bazel/example/using-workspace/WORKSPACE.bazel: -------------------------------------------------------------------------------- 1 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") 2 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 3 | 4 | # In your own project, you will likely want to use `http_archive` instead 5 | # of `local_repository` to load p4runtime. 6 | local_repository( 7 | name = "com_github_p4lang_p4runtime", 8 | path = "../../../proto", 9 | ) 10 | # http_archive( 11 | # name = "com_github_p4lang_p4runtime", 12 | # urls = ["https://github.com/p4lang/p4runtime/archive/v1.4.1.tar.gz"], 13 | # strip_prefix = "p4runtime-1.4.1/proto", 14 | # # sha256 = "", 15 | # ) 16 | 17 | load("@com_github_p4lang_p4runtime//:p4runtime_deps.bzl", "p4runtime_deps") 18 | 19 | p4runtime_deps() 20 | 21 | # -- Transitive dependencies of P4Runtime dependencies ------------------------- 22 | 23 | load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") 24 | 25 | protobuf_deps() 26 | 27 | load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies") 28 | 29 | rules_proto_dependencies() 30 | 31 | load("@rules_proto//proto:setup.bzl", "rules_proto_setup") 32 | 33 | rules_proto_setup() 34 | 35 | load("@rules_proto//proto:toolchains.bzl", "rules_proto_toolchains") 36 | 37 | rules_proto_toolchains() 38 | 39 | load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies") 40 | 41 | go_rules_dependencies() 42 | 43 | load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language") 44 | 45 | switched_rules_by_language( 46 | name = "com_google_googleapis_imports", 47 | cc = True, 48 | go = True, 49 | grpc = True, 50 | python = True, 51 | ) 52 | 53 | load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") 54 | 55 | grpc_deps() 56 | 57 | load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") 58 | 59 | grpc_extra_deps() 60 | 61 | load("@com_github_grpc_grpc//bazel:grpc_python_deps.bzl", "grpc_python_deps") 62 | 63 | grpc_python_deps() 64 | 65 | load("@rules_python//python:pip.bzl", "pip_parse") 66 | 67 | pip_parse( 68 | name = "grpc_python_dependencies", 69 | requirements_lock = "@com_github_grpc_grpc//:requirements.bazel.txt", 70 | ) 71 | 72 | load("@grpc_python_dependencies//:requirements.bzl", "install_deps") 73 | 74 | install_deps() 75 | 76 | load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") 77 | 78 | bazel_skylib_workspace() 79 | -------------------------------------------------------------------------------- /proto/p4/v1/p4data.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013-present Barefoot Networks, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package p4.v1; 18 | 19 | option go_package = "github.com/p4lang/p4runtime/go/p4/v1"; 20 | 21 | message P4Data { 22 | oneof data { 23 | bytes bitstring = 1; // for bit, int 24 | P4Varbit varbit = 2; // for varbit 25 | bool bool = 3; 26 | P4StructLike tuple = 4; 27 | P4StructLike struct = 5; 28 | P4Header header = 6; 29 | P4HeaderUnion header_union = 7; 30 | P4HeaderStack header_stack = 8; 31 | P4HeaderUnionStack header_union_stack = 9; 32 | string enum = 10; // safe (non-serializable) enums only 33 | string error = 11; 34 | bytes enum_value = 12; // serializable enums only 35 | } 36 | } 37 | 38 | message P4Varbit { 39 | bytes bitstring = 1; 40 | int32 bitwidth = 2; // dynamic bitwidth of the field 41 | } 42 | 43 | message P4StructLike { 44 | repeated P4Data members = 1; 45 | } 46 | 47 | message P4Header { 48 | // If the header is invalid (is_valid is "false"), then the bitstrings 49 | // repeated field must be empty. 50 | bool is_valid = 1; 51 | repeated bytes bitstrings = 2; 52 | } 53 | 54 | message P4HeaderUnion { 55 | // An empty string indicates that none of the union members are valid and 56 | // valid_header must therefore be unset. 57 | string valid_header_name = 1; 58 | P4Header valid_header = 2; 59 | } 60 | 61 | message P4HeaderStack { 62 | // The length of this repeated field must always be equal to the compile-time 63 | // size of the header stack, which is specified in P4Info. 64 | repeated P4Header entries = 1; 65 | } 66 | 67 | message P4HeaderUnionStack { 68 | // The length of this repeated field must always be equal to the compile-time 69 | // size of the header union stack, which is specified in P4Info. 70 | repeated P4HeaderUnion entries = 1; 71 | } 72 | -------------------------------------------------------------------------------- /.github/workflows/tag-uploads.yml: -------------------------------------------------------------------------------- 1 | name: Tag uploads 2 | 3 | on: 4 | push: 5 | tags: 6 | - v* 7 | 8 | jobs: 9 | tag-uploads: 10 | if: ${{ github.repository == 'p4lang/p4runtime' }} 11 | runs-on: [ubuntu-latest] 12 | env: 13 | TAG: ${{ github.ref_name }} 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | # fetch all history for all branches and tags 18 | fetch-depth: 0 19 | - name: Build spec 20 | run: | 21 | make -C docs/tools/ 22 | docker run -v `pwd`/docs/v1:/usr/src/p4-spec p4lang/p4rt-asciidoc make 23 | ls docs/v1/build 24 | - name: Upload spec to S3 25 | uses: jakejarvis/s3-sync-action@v0.5.1 26 | with: 27 | args: --acl public-read --follow-symlinks --delete 28 | env: 29 | AWS_S3_BUCKET: 'p4runtime' 30 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 31 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 32 | AWS_REGION: 'us-west-2' 33 | SOURCE_DIR: 'docs/v1/' 34 | DEST_DIR: docs/${{ github.ref_name }} 35 | - name: Prepare spec for upload to gh-pages 36 | run: | 37 | git checkout gh-pages 38 | mkdir -p spec 39 | rm -rf spec/$TAG 40 | cp -r docs/v1/build spec/$TAG 41 | - name: Upload spec to gh-pages 42 | uses: EndBug/add-and-commit@v9 43 | with: 44 | add: 'spec' 45 | author_name: 'P4Runtime CI' 46 | author_email: 'p4-api@lists.p4.org' 47 | default_author: github_actions 48 | message: 'Publish spec from Github Actions' 49 | commit: '--amend' 50 | push: 'origin gh-pages --force' 51 | 52 | publish-to-pypi: 53 | name: Publish a Python distribution to PyPI 54 | if: ${{ github.repository == 'p4lang/p4runtime' }} 55 | runs-on: [ubuntu-latest] 56 | steps: 57 | - uses: actions/checkout@v3 58 | - name: Set up Python 59 | uses: actions/setup-python@v3 60 | with: 61 | python-version: '3.x' 62 | - name: Install pypa/build 63 | run: >- 64 | python -m 65 | pip install 66 | build 67 | --user 68 | - name: Build a binary wheel and a source tarball 69 | working-directory: py 70 | run: >- 71 | python -m 72 | build 73 | --sdist 74 | --wheel 75 | --outdir dist/ 76 | . 77 | - name: Publish distribution to PyPI 78 | uses: pypa/gh-action-pypi-publish@release/v1 79 | with: 80 | user: __token__ 81 | password: ${{ secrets.PYPI_API_TOKEN }} 82 | packages_dir: py/dist/ 83 | skip_existing: true 84 | -------------------------------------------------------------------------------- /rust/README.md: -------------------------------------------------------------------------------- 1 | # P4Runtime Rust Crates 2 | 3 | This directory contains Rust crates for the P4Runtime API specification. 4 | 5 | ## Usage in Your Project 6 | 7 | Add the following to your `Cargo.toml`: 8 | 9 | **For message types only:** 10 | ```toml 11 | [dependencies] 12 | p4runtime-prost = { git = "https://github.com/p4lang/p4runtime.git" } 13 | ``` 14 | 15 | **For gRPC services:** 16 | ```toml 17 | [dependencies] 18 | p4runtime-prost = { git = "https://github.com/p4lang/p4runtime.git" } 19 | p4runtime-tonic = { git = "https://github.com/p4lang/p4runtime.git" } 20 | ``` 21 | 22 | ## Crates 23 | 24 | ### `p4runtime-prost` 25 | 26 | Provides Protocol Buffer message types using [prost](https://docs.rs/prost/). 27 | This crate contains only the message definitions and no gRPC service 28 | implementations. 29 | 30 | **Use this crate when:** 31 | - You need to construct/serialize/deserialize P4Runtime messages 32 | - You don't need gRPC client/server functionality 33 | - You want to minimize dependencies (only depends on `prost`) 34 | 35 | **Example:** 36 | ```rust 37 | use p4runtime_prost::p4::v1::WriteRequest; 38 | 39 | let request = WriteRequest { 40 | device_id: 1, 41 | // ... other fields 42 | }; 43 | ``` 44 | 45 | ### `p4runtime-tonic` 46 | 47 | Provides gRPC service definitions using [tonic](https://docs.rs/tonic/). 48 | This crate depends on `p4runtime-prost` for message types and adds gRPC client 49 | and server implementations. 50 | 51 | **Use this crate when:** 52 | - You need to implement a P4Runtime server 53 | - You need to create a P4Runtime client 54 | 55 | **Example:** 56 | ```rust 57 | use p4runtime_tonic::p4::v1::p4_runtime_client::P4RuntimeClient; 58 | 59 | let mut client = P4RuntimeClient::connect("http://[::1]:50051").await?; 60 | ``` 61 | 62 | ## Design 63 | 64 | 1. **Automatic Code Generation**: Code is generated during `cargo build` via 65 | `build.rs` scripts, eliminating the need to run `codegen/` scripts manually. 66 | 67 | 2. **Separate Crates**: Message types and gRPC services are in separate crates, 68 | so users who only need the proto messages don't need to depend on `tonic`. 69 | 70 | 3. **gRPC Reflection**: File descriptors are exported as part of 71 | `p4runtime-prost`, enabling gRPC reflection support. 72 | 73 | ## How can I see the generated code? 74 | 75 | ### Via the documentation 76 | 77 | Simply run 78 | ``` 79 | cargo doc --open 80 | ``` 81 | to build documentation for the crates and bring it up in your default web 82 | browser. Then, navgiate to the desired object and click "Source". 83 | 84 | ### Using cargo outdir 85 | 86 | First install `cargo-outdir`: 87 | ``` 88 | cargo install cargo-outdir 89 | ``` 90 | Then navigate to the crate you're interested in, e.g. `cd p4runtime-prost`, 91 | and run 92 | ``` 93 | cd $(cargo outdir --no-names) 94 | ``` 95 | to navigate to the build directory containing all generated files. 96 | -------------------------------------------------------------------------------- /proto/p4runtime_deps.bzl: -------------------------------------------------------------------------------- 1 | """Load dependencies needed to compile p4runtime as a 3rd-party consumer.""" 2 | 3 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") 4 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 5 | 6 | def p4runtime_deps(): 7 | """Loads dependencies needed to compile p4runtime.""" 8 | if not native.existing_rule("com_google_protobuf"): 9 | http_archive( 10 | name = "com_google_protobuf", 11 | url = "https://github.com/protocolbuffers/protobuf/archive/refs/tags/v28.2.tar.gz", 12 | strip_prefix = "protobuf-28.2", 13 | sha256 = "b2340aa47faf7ef10a0328190319d3f3bee1b24f426d4ce8f4253b6f27ce16db", 14 | ) 15 | if not native.existing_rule("rules_proto"): 16 | http_archive( 17 | name = "rules_proto", 18 | sha256 = "6fb6767d1bef535310547e03247f7518b03487740c11b6c6adb7952033fe1295", 19 | strip_prefix = "rules_proto-6.0.2", 20 | url = "https://github.com/bazelbuild/rules_proto/releases/download/6.0.2/rules_proto-6.0.2.tar.gz", 21 | ) 22 | if not native.existing_rule("io_bazel_rules_go"): 23 | http_archive( 24 | name = "io_bazel_rules_go", 25 | sha256 = "f4a9314518ca6acfa16cc4ab43b0b8ce1e4ea64b81c38d8a3772883f153346b8", 26 | urls = [ 27 | "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.50.1/rules_go-v0.50.1.zip", 28 | "https://github.com/bazelbuild/rules_go/releases/download/v0.50.1/rules_go-v0.50.1.zip", 29 | ], 30 | ) 31 | if not native.existing_rule("com_google_googleapis"): 32 | git_repository( 33 | name = "com_google_googleapis", 34 | remote = "https://github.com/googleapis/googleapis", 35 | commit = "de509e38d37a2a9d8b95e1ce78831189f4f3c0f4", 36 | ) 37 | if not native.existing_rule("com_github_grpc_grpc"): 38 | http_archive( 39 | name = "com_github_grpc_grpc", 40 | url = "https://github.com/grpc/grpc/archive/refs/tags/v1.67.0.tar.gz", 41 | strip_prefix = "grpc-1.67.0", 42 | sha256 = "af0638f73e4452e22e295f8b3f452518234254104713a08497f3d3aaa76733ad", 43 | ) 44 | if not native.existing_rule("bazel_skylib"): 45 | http_archive( 46 | name = "bazel_skylib", 47 | sha256 = "bc283cdfcd526a52c3201279cda4bc298652efa898b10b4db0837dc51652756f", 48 | urls = [ 49 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz", 50 | "https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz", 51 | ], 52 | ) 53 | if not native.existing_rule("rules_license"): 54 | http_archive( 55 | name = "rules_license", 56 | urls = [ 57 | "https://mirror.bazel.build/github.com/bazelbuild/rules_license/releases/download/1.0.0/rules_license-1.0.0.tar.gz", 58 | "https://github.com/bazelbuild/rules_license/releases/download/1.0.0/rules_license-1.0.0.tar.gz", 59 | ], 60 | sha256 = "26d4021f6898e23b82ef953078389dd49ac2b5618ac564ade4ef87cced147b38", 61 | ) 62 | -------------------------------------------------------------------------------- /docs/v1/README.md: -------------------------------------------------------------------------------- 1 | # P4Runtime Specification Version 1 2 | 3 | This directory contains the sources for generating the official P4Runtime 4 | specification document. 5 | 6 | # Markup version 7 | 8 | The markup version uses [AsciiDoc](https://docs.asciidoctor.org/) to produce 9 | HTML and PDF versions of the documentation. Pre-built versions of the 10 | documentation are available on the [P4.org specifications 11 | page](https://p4.org/specs). 12 | 13 | 14 | Files: 15 | - `P4Runtime-Spec.adoc` is the main file. 16 | - resources: 17 | - figs 18 | - `*.odg` - OfficeLibre source drawing file used to export images. These are 19 | bulk-rendered at build time into .svg and .png images via `soffice` 20 | command-line (required in build environment) 21 | - fonts 22 | - `*.ttf` - Type font source file used to export fonts. 23 | - theme: 24 | - `*.yaml` - Describes how PDF P4Runtime specification will be displayed. 25 | - `*.css` - Describes how HTML P4Runtime specification will displayed. 26 | - `*.bib` - Bibliography file that contains a list of bibliographical item, such as articles, books, and theses. 27 | - `Makefile` builds documentation in the build subdirectory 28 | 29 | ## Document Figures 30 | 31 | The P4Runtime specification can be generated on your local machine or via the Docker container. Due to this, the document figure can be rendered using two different approaches 32 | 33 | ### Local machine 34 | 35 | You need to install [LibreOffice](https://nl.libreoffice.org/) on your local machine. 36 | 37 | Each image in the specification has a corresponding `.odg` file under 38 | `resources/figs/`. These are LibreOffice drawing files. The files are rendered into 39 | `.svg` and `.png` images (for HTML and PDF output, resepectively) at build time, 40 | using the `soffice` command-line tool. The page size for each image should be 41 | adjusted manually by the author ("artist") to just fit the image on the 42 | apparrent "page," to minimize padding around the image in the rendered 43 | document. Use the menu item `Format | Page/Size Properties.` See the example 44 | screen shot below. (Do not check the "Fit object to paper format" box - it will 45 | change the object's aspect ratio.) 46 | ![LibreOffice](libre-office.png) 47 | 48 | Commands to convert a image from `.odg` to `.svg` and/or `.png`: 49 | ``` 50 | soffice --convert-to svg figure_name.odg 51 | soffice --convert-to png figure_name.odg 52 | ``` 53 | 54 | Commands to convert a image `.odg` to `.svg` and/or `.png` and move to `resources/figs/`: 55 | 56 | ``` 57 | soffice --convert-to svg --outdir resources/figs/ figure_name.odg 58 | soffice --convert-to png --outdir resources/figs/ figure_name.odg 59 | ``` 60 | ### Docker container 61 | 62 | The Docker container, generated from the `p4lang/p4rt-asciidoc:latest` image, does not require 63 | LibreOffice to be installed. 64 | 65 | 66 | ## Building 67 | 68 | The easiest way to render the AsciiDoc specification documentation is to use the 69 | `p4lang/p4rt-asciidoc:latest` Docker` image: 70 | 71 | docker run -v `pwd`/docs/v1:/usr/src/p4-spec p4lang/p4rt-asciidoc:latest make build_spec_with_images 72 | 73 | ### Linux 74 | 75 | You can use the [local installation](https://github.com/p4lang/p4-spec/blob/main/p4-16/spec/install-asciidoctor-linux.sh) method, and you also need to install LibreOffice to render the 76 | images into .svg and .png formats. 77 | 78 | ### MacOS 79 | 80 | We do not yet have instructions for generating PDF and HTML from AsciiDoc source on macOS. You are welcome to contribute documentation for how to do so if you find instructions that work. 81 | 82 | ### Windows 83 | 84 | We do not yet have instructions for generating PDF and HTML from AsciiDoc source on Windows. You are welcome to contribute documentation for how to do so if you find instructions that work. 85 | -------------------------------------------------------------------------------- /.github/workflows/bazel-build.yml: -------------------------------------------------------------------------------- 1 | name: "Bazel build of protobufs" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - '*-dev' 8 | pull_request: 9 | branches: 10 | - main 11 | - '*-dev' 12 | schedule: 13 | - cron: "0 0 * * *" 14 | 15 | jobs: 16 | build: 17 | 18 | strategy: 19 | matrix: 20 | # We only test on the oldest version we want to support and latest. 21 | # We trust that things also work for versions in the middle. 22 | os: [ubuntu-22.04, ubuntu-latest] 23 | # See Bazelisk README for legal values. 24 | bazel_version: [7.x, latest] 25 | # Don't abort other runs when one of them fails, to ease debugging. 26 | fail-fast: false 27 | 28 | # The default name would be "build (ubuntu-, )". 29 | # We use a custom name to make it clearer that the second version refers to Bazel. 30 | name: ${{ matrix.os }}, bazel-${{ matrix.bazel_version }} 31 | 32 | runs-on: ${{ matrix.os }} 33 | 34 | env: 35 | # This tells Bazelisk (installed as `bazel`) to use specified version. 36 | # https://github.com/bazelbuild/bazelisk?tab=readme-ov-file#how-does-bazelisk-know-which-bazel-version-to-run 37 | USE_BAZEL_VERSION: ${{ matrix.bazel_version }} 38 | CACHE_KEY: ${{ matrix.os }}_bazel-${{ matrix.bazel_version }} 39 | 40 | steps: 41 | - uses: actions/checkout@v4 42 | with: 43 | submodules: recursive 44 | 45 | - name: Mount bazel cache 46 | uses: actions/cache/restore@v4 47 | with: 48 | # See https://docs.bazel.build/versions/master/output_directories.html 49 | path: "~/.cache/bazel" 50 | # Create a new cache entry whenever Bazel files change. 51 | # See https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows 52 | key: ${{ env.CACHE_KEY }}-${{ hashFiles('**/*.bazel*', '**/*.bzl') }} 53 | restore-keys: | 54 | ${{ env.CACHE_KEY }} 55 | 56 | - name: Save start time 57 | uses: josStorer/get-current-time@v2 58 | id: start-time 59 | with: 60 | # Unix timestamp -- seconds since 1970. 61 | format: X 62 | 63 | - name: Build proto/ 64 | run: cd proto && bazel build //... && bazel test //... 65 | 66 | - name: Build bazel/example/using-bzlmod/ 67 | run: cd bazel/example/using-bzlmod && bazel build //... 68 | 69 | - name: Build bazel/example/using-workspace/ 70 | run: cd bazel/example/using-workspace && bazel build //... 71 | # This is a legacy example that doesn't work beyond Bazel 7.x. 72 | if: ${{ env.USE_BAZEL_VERSION == '7.x' }} 73 | 74 | - name: Save end time 75 | # Always save the end time so we can calculate the build duration. 76 | if: always() 77 | uses: josStorer/get-current-time@v2 78 | id: end-time 79 | with: 80 | # Unix timestamp -- seconds since 1970. 81 | format: X 82 | 83 | - name: Calculate build duration 84 | # Always calculate the build duration so we can update the cache if needed. 85 | if: always() 86 | run: | 87 | START=${{ steps.start-time.outputs.formattedTime }} 88 | END=${{ steps.end-time.outputs.formattedTime }} 89 | DURATION=$(( $END - $START )) 90 | echo "duration=$DURATION" | tee "$GITHUB_ENV" 91 | 92 | - name: Compress cache 93 | # Always compress the cache so we can update the cache if needed. 94 | if: always() 95 | run: rm -rf $(bazel info repository_cache) 96 | 97 | - name: Save bazel cache 98 | uses: actions/cache/save@v4 99 | # Only create a new cache entry if we're on the main branch or the build takes >3mins. 100 | # 101 | # NOTE: Even though `always()` evaluates to true, and `true && x == x`, 102 | # the `always() &&` prefix is not redundant! The call to `always()` has a 103 | # side effect, which is to override the default behavior of automagically 104 | # canceling this step if a previous step failed. 105 | # (Don't blame me, blame GitHub Actions!) 106 | if: always() && (github.ref_name == 'main' || env.duration > 180) 107 | with: 108 | path: "~/.cache/bazel" 109 | key: ${{ env.CACHE_KEY }}-${{ hashFiles('**/*.bazel*', '**/*.bzl') }}-${{ github.run_id }} 110 | -------------------------------------------------------------------------------- /proto/BUILD.bazel: -------------------------------------------------------------------------------- 1 | 2 | load("@bazel_skylib//rules:build_test.bzl", "build_test") 3 | load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library") 4 | load("@com_github_grpc_grpc//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library") 5 | load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") 6 | load("@rules_license//rules:license.bzl", "license") 7 | load("@rules_proto//proto:defs.bzl", "proto_library") 8 | 9 | package( 10 | default_visibility = ["//visibility:public"], 11 | default_applicable_licenses = [":license"], 12 | ) 13 | 14 | license( 15 | name = "license", 16 | license_kinds = ["@rules_license//licenses/spdx:Apache-2.0"], 17 | license_text = "LICENSE", 18 | ) 19 | 20 | exports_files(["LICENSE"]) 21 | 22 | proto_library( 23 | name = "p4types_proto", 24 | srcs = ["p4/config/v1/p4types.proto"], 25 | # TODO(github.com/grpc/grpc/issues/20675): strip_import_prefix breaks 26 | # cc_grpc_library. Make proto folder the Bazel root folder as a workaround. 27 | # strip_import_prefix = "proto", 28 | ) 29 | 30 | proto_library( 31 | name = "p4data_proto", 32 | srcs = ["p4/v1/p4data.proto"], 33 | # TODO(github.com/grpc/grpc/issues/20675): strip_import_prefix breaks 34 | # cc_grpc_library. Make proto folder the Bazel root folder as a workaround. 35 | # strip_import_prefix = "proto", 36 | ) 37 | 38 | proto_library( 39 | name = "p4info_proto", 40 | srcs = ["p4/config/v1/p4info.proto"], 41 | deps = [ 42 | ":p4types_proto", 43 | "@com_google_protobuf//:any_proto", 44 | "@com_google_protobuf//:descriptor_proto", 45 | ], 46 | # TODO(github.com/grpc/grpc/issues/20675): strip_import_prefix breaks 47 | # cc_grpc_library. Make proto folder the Bazel root folder as a workaround. 48 | # strip_import_prefix = "proto", 49 | ) 50 | 51 | proto_library( 52 | name = "p4runtime_proto", 53 | srcs = ["p4/v1/p4runtime.proto"], 54 | deps = [ 55 | ":p4data_proto", 56 | ":p4info_proto", 57 | "@com_google_googleapis//google/rpc:status_proto", 58 | "@com_google_protobuf//:any_proto", 59 | ], 60 | # TODO(github.com/grpc/grpc/issues/20675): strip_import_prefix brakes 61 | # cc_grpc_library. Make proto folder the Bazel root folder as a workaround. 62 | # strip_import_prefix = "proto", 63 | ) 64 | 65 | cc_proto_library( 66 | name = "p4types_cc_proto", 67 | deps = [":p4types_proto"], 68 | ) 69 | 70 | cc_proto_library( 71 | name = "p4info_cc_proto", 72 | deps = [":p4info_proto"], 73 | ) 74 | 75 | cc_proto_library( 76 | name = "p4data_cc_proto", 77 | deps = [":p4data_proto"], 78 | ) 79 | 80 | cc_proto_library( 81 | name = "p4runtime_cc_proto", 82 | deps = [":p4runtime_proto"], 83 | ) 84 | 85 | py_proto_library( 86 | name = "p4types_py_proto", 87 | deps = [":p4types_proto"], 88 | ) 89 | 90 | py_proto_library( 91 | name = "p4info_py_proto", 92 | deps = [":p4info_proto"], 93 | ) 94 | 95 | py_proto_library( 96 | name = "p4data_py_proto", 97 | deps = [":p4data_proto"], 98 | ) 99 | 100 | py_proto_library( 101 | name = "p4runtime_py_proto", 102 | deps = [":p4runtime_proto"], 103 | ) 104 | 105 | go_proto_library( 106 | name = "p4info_go_proto", 107 | importpath = "github.com/p4lang/p4runtime/go/p4/config/v1", 108 | protos = [ 109 | ":p4info_proto", 110 | ":p4types_proto", 111 | ], 112 | ) 113 | 114 | go_proto_library( 115 | name = "p4runtime_go_proto", 116 | importpath = "github.com/p4lang/p4runtime/go/p4/v1", 117 | protos = [ 118 | ":p4data_proto", 119 | ":p4runtime_proto", 120 | ], 121 | deps = [ 122 | ":p4info_go_proto", 123 | "@com_google_googleapis//google/rpc:status_go_proto", 124 | ], 125 | ) 126 | 127 | cc_grpc_library( 128 | name = "p4runtime_cc_grpc", 129 | srcs = [":p4runtime_proto"], 130 | generate_mocks = True, 131 | grpc_only = True, 132 | deps = [":p4runtime_cc_proto"], 133 | ) 134 | 135 | py_grpc_library( 136 | name = "p4runtime_py_grpc", 137 | srcs = [":p4runtime_proto"], 138 | deps = [":p4runtime_py_proto"], 139 | ) 140 | 141 | build_test( 142 | name = "proto_build_test", 143 | targets = [ 144 | ":p4data_proto", 145 | ":p4info_proto", 146 | ":p4runtime_cc_grpc", 147 | ":p4runtime_proto", 148 | ":p4runtime_py_grpc", 149 | ":p4types_proto", 150 | ], 151 | ) 152 | -------------------------------------------------------------------------------- /docs/v1/resources/fonts/Utopia/LICENSE-utopia.txt: -------------------------------------------------------------------------------- 1 | The agreement below gives the TeX Users Group (TUG) the right to 2 | sublicense, and grant such sublicensees the right to further sublicense, 3 | any or all of the rights enumerated below. TUG hereby does so 4 | sublicense all such rights, irrevocably and in perpetuity, to any and 5 | all interested parties. 6 | 7 | --Karl Berry, TUG President, 8 | on behalf of the TeX Users Group board and members 9 | 17 November 2006 10 | http://tug.org/fonts/utopia 11 | 12 | ------------------------------------------------------------ 13 | October 11, 2006 14 | 15 | RE: License to TeX Users Group for the Utopia Typeface 16 | 17 | Adobe Systems Incorporated ("Adobe") hereby grants to the TeX Users 18 | Group and its members a nonexclusive, royalty-free, perpetual license to 19 | the typeface software for the Utopia Regular, Utopia Italic, Utopia Bold 20 | and Utopia bold Italic typefaces, including Adobe Type 1 font programs 21 | for each style (collectively, the "Software") as set forth below. 22 | 23 | Adobe grants the TeX Users Group a license under its copyrights, to use, 24 | reproduce, display and distribute the Software for any purpose and 25 | without fee provided that the following copyright notice appears in all 26 | whole and partial copies of the Software and provided that the following 27 | trademark symbol and attribution appear in all unmodified copies of the 28 | Software: 29 | 30 | Copyright 1989, 1991 Adobe Systems Incorporated. All rights reserved. 31 | (alternatively, @1989, 1991 Adobe Systems Incorporated. All rights reserved.) 32 | Utopia(R) 33 | Utopia is either a registered trademark or trademark of Adobe Systems 34 | Incorporated in the United States and/or other countries. Used under 35 | license. 36 | 37 | Adobe also grants to the TeX Users Group a license to modify the 38 | Software for any purpose and redistribute such modifications, for any 39 | purpose and royalty-free, provided that the modified Software shall not 40 | use the font name(s) or trademark(s), in whole or in part, unless 41 | explicit written permission is granted by Adobe. This restriction 42 | applies to all references stored in the Software for identification 43 | purposes, such as the font menu name and other font description 44 | fields. The TeX Users Group is also permitted to sublicense, and grant 45 | such sublicensees the right to further sublicense, any or all the 46 | foregoing rights through multiple tiers of distribution. The licenses 47 | granted herein are granted in perpetuity and may not be terminated by 48 | either party unless such termination is based on a breach of the terms 49 | and conditions herein stated. 50 | 51 | Adobe retains ownership of the copyright in the Software. The TeX Users 52 | Group agrees that Adobe and its suppliers are the sole and exclusive 53 | owners of all rights, title and interest, including all copyrights, 54 | patents, trademarks, trade names, trade secrets and other intellectual 55 | property rights in the Software. No title or ownership of the Software, 56 | any copies of the Software, or the patent, copyright, trade secret, 57 | trademark, trade name or other proprietary rights contained in the 58 | Software is transferred to the TeX Users Group. 59 | 60 | The Adobe trademarks shall not be used in advertising pertaining to the 61 | distribution of the Software without express prior permission from 62 | Adobe. Any such use shall be in accordance with the Adobe trademark 63 | guidelines, available on the Adobe website at 64 | http://www.adobe.com/misc/pdfs/TM GuideforThirdPartiesFinal.pdf. 65 | If any portion of the Software is changed, it cannot be marketed under 66 | Adobe's trademarks unless Adobe, in its sole discretion, approves by a 67 | prior writing the quality of the resulting implementation. 68 | 69 | The TeX Users Group shall have the right to evaluate the Software 70 | provided by Adobe. 71 | 72 | ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR 73 | ANY PURPOSE. IT IS PROVIDED "AS-IS" WITHOUT EXPRESS OR IMPLIED 74 | WARRANTY. ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THE SOFTWARE, 75 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 76 | PARTICULAR PURPOSE, AND NON-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO 77 | EVENT SHALL ADOBE BE LIABLE TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, 78 | INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN 79 | AN ACTION OF CONTRACT NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION 80 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 81 | SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE 82 | SOFTWARE. 83 | 84 | Adobe Document Id: 4400078611 85 | -------------------------------------------------------------------------------- /docs/v1/resources/theme/references.bib: -------------------------------------------------------------------------------- 1 | @ONLINE { P4RuntimeRepo, 2 | title = "p4lang/p4Runtime repository", 3 | subtitle = "P4Runtime Protobuf definition files and specification", 4 | url = "https://github.com/p4lang/p4runtime" 5 | } 6 | 7 | @ONLINE { gRPC, 8 | title = "gRPC main site", 9 | url = "https://grpc.io" 10 | } 11 | 12 | @ONLINE { Proto, 13 | title = "Protocol buffers main site", 14 | url = "https://developers.google.com/protocol-buffers" 15 | } 16 | 17 | @ONLINE { P4.org, 18 | title = "P4.org main site", 19 | url = "https://p4.org/" 20 | } 21 | 22 | @ONLINE { OpenConfig, 23 | title = "the OpenConfig project", 24 | url = "http://openconfig.net" 25 | } 26 | 27 | @ONLINE { Stratum, 28 | title = "the Stratum project", 29 | url = "https://stratumproject.org/" 30 | } 31 | 32 | @ONLINE { P4ComplexTypes, 33 | title = "Complex types in $P4_{16}$", 34 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-p4-type" 35 | } 36 | 37 | @ONLINE { ProtoDefaults, 38 | title = "Default values for Protobuf 3 ($proto3$) fields", 39 | url = "https://developers.google.com/protocol-buffers/docs/proto3#default" 40 | } 41 | 42 | @ONLINE { PIRepo, 43 | title = "p4lang/PI repository", 44 | subtitle = "Legacy repository for P4Runtime, includes reference implementation", 45 | url = "https://github.com/p4lang/PI" 46 | } 47 | 48 | @ONLINE { P4TableProperties, 49 | title = "Table properties in $P4_{16}$", 50 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-table-props" 51 | } 52 | 53 | @ONLINE { P4ValueSets, 54 | title = "Value Sets in $P4_{16}$", 55 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-value-set" 56 | } 57 | 58 | @ONLINE { P4SelectExpr, 59 | title = "Select expressions in $P4_{16}$", 60 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-select" 61 | } 62 | 63 | @ONLINE { P4Revisions110, 64 | title = "Summary of changes made in $P4_{16}$ version 1.1.0", 65 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-summary-of-changes-made-in-version-110" 66 | } 67 | 68 | @ONLINE { P4Revisions122, 69 | title = "Summary of changes made in $P4_{16}$ version 1.2.2", 70 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.4.html#sec-summary-of-changes-made-in-version-122-released-may-17-2021" 71 | } 72 | 73 | @ONLINE { P4Revisions124, 74 | title = "Summary of changes made in $P4_{16}$ version 1.2.4", 75 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.4.html#sec-summary-of-changes-made-in-version-124" 76 | } 77 | 78 | @ONLINE { P4Spec, 79 | title = "$P4_{16}$ 1.2.1 specification", 80 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html" 81 | } 82 | 83 | @ONLINE { PSA, 84 | title = "Portable Switch Architecture specification (v1.1.0)", 85 | url = "https://p4.org/p4-spec/docs/PSA-v1.1.0.html" 86 | } 87 | 88 | @ONLINE { PNA, 89 | title = "Portable NIC Architecture specification (v0.7)", 90 | url = "https://p4.org/p4-spec/docs/PNA-v0.7.html" 91 | } 92 | 93 | @ONLINE { P4Enums, 94 | title = "Enums in $P4_{16}$", 95 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-enum-types" 96 | } 97 | 98 | @ONLINE { ProtoAny, 99 | title = "the Any Protobuf message", 100 | url = "https://developers.google.com/protocol-buffers/docs/proto3#any" 101 | } 102 | 103 | @ONLINE { ProtoExtension, 104 | title = "Protobuf extension feature", 105 | url = "https://protobuf.dev/programming-guides/editions/#extensions" 106 | } 107 | 108 | @ONLINE { gRPCStatus, 109 | title = "the gRPC $Status$ class", 110 | url = "https://github.com/grpc/grpc/blob/master/include/grpcpp/impl/codegen/status.h" 111 | } 112 | 113 | @ONLINE { gRPCStatusCodes, 114 | title = "the gRPC canonical status codes", 115 | url = "https://developers.google.com/maps-booking/reference/grpc-api/status_codes" 116 | } 117 | 118 | @ONLINE { ProtoStatus, 119 | title = "status.proto", 120 | subtitle = "the Protobuf Status message", 121 | url = "https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto" 122 | } 123 | 124 | @ONLINE { gRPCErrorDetails, 125 | title = "the gRPC C++ error details library", 126 | url = "https://github.com/grpc/grpc/blob/master/include/grpcpp/support/error_details.h" 127 | } 128 | 129 | @ONLINE { P4APIWGCharter, 130 | title = "P4.org API Working Group Charter", 131 | url = "https://p4.org/p4-spec/docs/P4_API_WG_charter.html" 132 | } 133 | 134 | @ONLINE { P4NewTypes, 135 | title = "Introducing new types in $P4_{16}$", 136 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-newtype" 137 | } 138 | 139 | @ONLINE { APIVersioning, 140 | title = "Google Cloud APIs versioning", 141 | url = "https://cloud.google.com/apis/design/versioning" 142 | } 143 | 144 | @ONLINE { APIVersioningBackwardsCompatibility, 145 | title = "Google Cloud APIs versioning - Backwards-compatibility", 146 | url = "https://cloud.google.com/apis/design/versioning#backwards_compatibility" 147 | } 148 | 149 | @ONLINE { SemVer, 150 | title = "Semantic versioning", 151 | url = "https://semver.org/" 152 | } 153 | 154 | @ONLINE { RFC2698, 155 | title = "A Two Rate Three Color Marker", 156 | url = "https://tools.ietf.org/html/rfc2698" 157 | } 158 | 159 | @ONLINE { RFC2697, 160 | title = "A Single Rate Three Color Marker", 161 | url = "https://tools.ietf.org/html/rfc2697" 162 | } 163 | 164 | @ONLINE { P4MatchTypes, 165 | title = "Match types in P4", 166 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-match-kind-type" 167 | } 168 | 169 | @ONLINE { gRPCStreamC, 170 | title = "gRPC Streaming RPCs in C++", 171 | url = "https://grpc.io/docs/tutorials/basic/c.html#streaming-rpcs" 172 | } 173 | 174 | @ONLINE { gRPCAuth, 175 | title = "gRPC Authentication", 176 | url = "https://grpc.io/docs/guides/auth.html" 177 | } 178 | 179 | @ONLINE { P4ActionAnnotations, 180 | title = "P4 standard annotations on table actions", 181 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-table-action-anno" 182 | } 183 | 184 | @ONLINE { PSAActionSelector, 185 | title = "PSA Action Selector", 186 | url = "https://p4.org/p4-spec/docs/PSA-v1.1.0.html#sec-action-selector" 187 | } 188 | 189 | @ONLINE { PSAEmptyGroupActionAppendix, 190 | title = "PSA Empty Group Action Appendix", 191 | url = "https://p4.org/p4-spec/docs/PSA-v1.1.0.html#appendix-empty-action-selector-groups" 192 | } 193 | 194 | @ONLINE { PSAAtomicityOfControlPlaneOps, 195 | title = "PSA Atomicity of Control Plane Operations", 196 | url = "https://p4.org/p4-spec/docs/PSA-v1.1.0.html#sec-atomicity-of-control-plane-api-operations" 197 | } 198 | 199 | @ONLINE { P4Concurrency, 200 | title = "P4 Concurrency Model", 201 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-concurrency" 202 | } 203 | 204 | @ONLINE { PSATranslation, 205 | title = "PSA Data Plane vs Control Plane Types", 206 | url = "https://p4.org/p4-spec/docs/PSA-v1.1.0.html#sec-data-plane-vs-control-plane-values" 207 | } 208 | 209 | @ONLINE { ProtoMessageDifferencer, 210 | title = "The Protobuf MessageDifferencer in the C++ API", 211 | url = "https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.util.message_differencer" 212 | } 213 | 214 | @ONLINE { ProtoOneOfBackwardsCompatibility, 215 | title = "Protobuf OneOf backwards-compatibility issues", 216 | url = "https://developers.google.com/protocol-buffers/docs/proto3#backwards-compatibility-issues" 217 | } 218 | 219 | @ONLINE { P4Annotations, 220 | title = "P4 Annotations", 221 | url = "https://p4.org/p4-spec/docs/P4-16-v1.2.1.html#sec-annotations" 222 | } 223 | 224 | @ONLINE { v1model, 225 | title = "v1model Architecture Definition", 226 | url = "https://github.com/p4lang/p4c/blob/master/p4include/v1model.p4" 227 | } 228 | 229 | @ONLINE { ArenaAllocation, 230 | title = "C++ Arena Allocation Guide", 231 | url = "https://developers.google.com/protocol-buffers/docs/reference/arenas" 232 | } 233 | 234 | @ONLINE { p4c, 235 | title = "P4_16 reference compiler", 236 | url = "https://github.com/p4lang/p4c" 237 | } 238 | 239 | @ONLINE { p4cTestProgramForConstEntries, 240 | title = "P4_16 reference compiler test program table-entries-ternary-bmv2.p4", 241 | url = "https://github.com/p4lang/p4c/blob/main/testdata/p4_16_samples/table-entries-ternary-bmv2.p4" 242 | } 243 | -------------------------------------------------------------------------------- /docs/v1/resources/theme/p4-theme.yml: -------------------------------------------------------------------------------- 1 | extends: ~ 2 | font: 3 | catalog: 4 | UtopiaStd-Regular: 5 | normal: Utopia/utopia-regular.ttf 6 | bold: Utopia/utopia-bold.ttf 7 | italic: Utopia/utopia-italic.ttf 8 | bold_italic: Utopia/utopia-bolditalic.ttf 9 | LuxiMono: 10 | normal: LuxiMono/luximr.ttf 11 | bold: LuxiMono/luximb.ttf 12 | italic: LuxiMono/luximri.ttf 13 | bold_italic: LuxiMono/luximbi.ttf 14 | OpenSans: 15 | normal: OpenSans/OpenSans-Regular.ttf 16 | bold: OpenSans/OpenSans-Bold.ttf 17 | italic: OpenSans/OpenSans-Italic.ttf 18 | bold_italic: OpenSans/OpenSans-BoldItalic.ttf 19 | page: 20 | layout: portrait 21 | initial_zoom: FitH 22 | margin: [0.5in, 0.67in, 0.67in, 0.67in] 23 | # margin_inner and margin_outer keys are used for recto/verso print margins when media=prepress 24 | margin_inner: 0.75in 25 | margin_outer: 0.59in 26 | size: A4 27 | numbering: 28 | start-at: toc 29 | base: 30 | text_align: justify 31 | font_color: 333333 32 | font_family: UtopiaStd-Regular 33 | font_size: 10.5 34 | # line_height_length is really just a vertical spacing variable; it's not actually the height of a line 35 | line_height_length: 12 36 | # The Noto font family has a built-in line height of 1.36 37 | # With this line_height, a line of text will occupy a height of 15.78pt 38 | line_height: $base_line_height_length / 10.5 39 | font_size_large: round($base_font_size * 1.25) 40 | font_size_small: round($base_font_size * 0.85) 41 | font_size_min: $base_font_size * 0.75 42 | font_style: normal 43 | border_color: EEEEEE 44 | border_radius: 4 45 | border_width: 0.5 46 | role: 47 | lead: 48 | font_size: $base_font_size_large 49 | line-through: 50 | text_decoration: line-through 51 | underline: 52 | text_decoration: underline 53 | big: 54 | font_size: 1.2em 55 | small: 56 | font_size: 0.8em 57 | subtitle: 58 | font_color: 999999 59 | font_size: 0.8em 60 | font_style: normal_italic 61 | vertical_rhythm: $base_line_height_length 62 | horizontal_rhythm: $base_line_height_length 63 | link: 64 | font_color: 428BCA 65 | # codespan is currently used for monospaced phrases and table cells 66 | codespan: 67 | font_color: #B12146 68 | font_family: OpenSans 69 | kbd: 70 | background_color: F5F5F5 71 | border_color: CCCCCC 72 | border_offset: 2 73 | border_radius: 2 74 | border_width: 0.5 75 | font_family: $codespan_font_family 76 | separator_content: "\u202f+\u202f\u200b" 77 | mark: 78 | background_color: FFFF00 79 | border_offset: 1 80 | menu: 81 | caret_content: "\u00a0\u203a " 82 | font_style: bold 83 | heading: 84 | font-family: OpenSans 85 | font-color: #262626 86 | font-size: 17 87 | font-style: bold 88 | # h1 is used for part titles (book doctype) or the doctitle (article doctype) 89 | h1_font_size: floor($base_font_size * 2.6) 90 | # h2 is used for chapter titles (book doctype only) 91 | h2_font_size: floor($base_font_size * 2.15) 92 | h3_font_size: round($base_font_size * 1.7) 93 | h4_font_size: $base_font_size_large 94 | h5_font_size: $base_font_size 95 | h6_font_size: $base_font_size_small 96 | # rely on built-in line height in Noto 97 | line_height: 1 98 | margin_top: $vertical_rhythm * 0.4 99 | margin_bottom: $vertical_rhythm * 0.9 100 | min_height_after: auto 101 | chapter: 102 | break-before: auto 103 | title_page: 104 | font-family: OpenSans 105 | font-color: #080808 106 | font-size: 25 107 | font-style: bold 108 | text-align: center 109 | logo: 110 | image: image:logo.png[pdfwidth=3.0in,align=center] 111 | subtitle: 112 | font-family: OpenSans 113 | font-color: #080808 114 | font-size: 15 115 | text-align: center 116 | line_height: 1 117 | revision: 118 | font-family: OpenSans 119 | font-color: #080808 120 | font-size: 10 121 | text-align: center 122 | margin_top: $base_font_size * 1.25 123 | block: 124 | margin_bottom: $vertical_rhythm 125 | caption: 126 | align: left 127 | font_size: $base_font_size * 0.95 128 | font_style: italic 129 | # FIXME perhaps set line_height instead of / in addition to margins? 130 | margin_inside: $vertical_rhythm / 3 131 | margin_outside: 0 132 | abstract: 133 | title: 134 | font-family: UtopiaStd-Regular 135 | font-color: #080808 136 | font-size: 15 137 | font-style: italic 138 | text-align: center 139 | admonition: 140 | column_rule_color: $base_border_color 141 | column_rule_width: $base_border_width 142 | padding: [$vertical_rhythm / 3.0, $horizontal_rhythm, $vertical_rhythm / 3.0, $horizontal_rhythm] 143 | label: 144 | text_transform: uppercase 145 | font_style: bold 146 | quote: 147 | font_size: $base_font_size_large 148 | border_color: $base_border_color 149 | border_width: 0 150 | border_left_width: $horizontal_rhythm / 3 151 | padding: [$vertical_rhythm / 4, $horizontal_rhythm, $vertical_rhythm / 4, $horizontal_rhythm + $quote_border_left_width / 2] 152 | cite: 153 | font_size: $base_font_size_small 154 | font_color: $role_subtitle_font_color 155 | verse: 156 | font_size: $quote_font_size 157 | border_color: $quote_border_color 158 | border_width: $quote_border_width 159 | border_left_width: $quote_border_left_width 160 | padding: $quote_padding 161 | cite: 162 | font_size: $quote_cite_font_size 163 | font_color: $quote_cite_font_color 164 | # code is used for literal, listing, and source blocks and literal table cells 165 | code: 166 | font_color: #fcf3d9 167 | font_family: LuxiMono 168 | font_size: 9 169 | padding: $code_font_size 170 | line_height: 1.25 171 | # line_gap is an experimental property to control how a background color is applied to an inline block element 172 | line_gap: 3.8 173 | background_color: F5F5F5 174 | border_color: CCCCCC 175 | border_radius: $base_border_radius 176 | border_width: 0.75 177 | conum: 178 | font_family: $codespan_font_family 179 | font_color: $codespan_font_color 180 | font_size: $base_font_size 181 | line_height: 4 / 3 182 | glyphs: circled 183 | example: 184 | border_color: $base_border_color 185 | border_radius: $base_border_radius 186 | border_width: 0.75 187 | padding: [$vertical_rhythm, $horizontal_rhythm, $vertical_rhythm, $horizontal_rhythm] 188 | image: 189 | caption: 190 | font-family: UtopiaStd-Regular 191 | font-color: #080808 192 | font-size: 10 193 | font-style: italic 194 | text-align: center 195 | prose: 196 | margin_bottom: $block_margin_bottom 197 | sidebar: 198 | background_color: EEEEEE 199 | border_color: E1E1E1 200 | border_radius: $base_border_radius 201 | border_width: $base_border_width 202 | padding: [$vertical_rhythm, $vertical_rhythm * 1.25, $vertical_rhythm, $vertical_rhythm * 1.25] 203 | title: 204 | text_align: center 205 | font_color: $heading_font_color 206 | font_size: $heading_h4_font_size 207 | font_style: $heading_font_style 208 | thematic_break: 209 | border_color: $base_border_color 210 | border_style: solid 211 | border_width: $base_border_width 212 | padding: [$vertical_rhythm * 0.5, 0] 213 | list: 214 | indent: $horizontal_rhythm * 1.5 215 | #marker_font_color: 404040 216 | # NOTE list_item_spacing only applies to list items that do not have complex content 217 | item_spacing: $vertical_rhythm / 2 218 | # Force all indent levels of an unordered list to use the same font 219 | # glyph for all symbols, because the fonts we are using do not have 220 | # definitions for any of the ones that asciidoctor-pdf normally uses. 221 | # If we change our fonts to have definitions for the default code points 222 | # used by asciidoctor-pdf, the 'ulist:' section can be deleted. 223 | ulist: 224 | marker: 225 | square: 226 | content: "\u2022" 227 | circle: 228 | content: "\u2022" 229 | checked: 230 | content: "\u2022" 231 | unchecked: 232 | content: "\u2022" 233 | description_list: 234 | term_font_style: bold 235 | term_spacing: $vertical_rhythm / 4 236 | description_indent: $horizontal_rhythm * 1.25 237 | callout_list: 238 | margin_top_after_code: -$block_margin_bottom / 2 239 | table: 240 | border_color: DDDDDD 241 | border_width: $base_border_width 242 | grid_width: $base_border_width 243 | cell_padding: 3 244 | head: 245 | font_style: bold 246 | border_bottom_width: $base_border_width * 2.5 247 | body: 248 | stripe_background_color: F9F9F9 249 | foot: 250 | background_color: F0F0F0 251 | caption: 252 | text-align: center 253 | end: bottom 254 | toc: 255 | indent: $horizontal_rhythm 256 | font-family: OpenSans 257 | font-color: #01226e 258 | font-size: 10 259 | indent: 20 260 | title: 261 | font-family: OpenSans 262 | font-color: #080808 263 | font-size: 15 264 | font-style: bold 265 | dot-leader: 266 | content: ". " 267 | levels: 2 3 4 5 268 | footnotes: 269 | font_size: round($base_font_size * 0.75) 270 | item_spacing: $list_item_spacing / 2 271 | index: 272 | column_gap: $vertical_rhythm 273 | header: 274 | font_size: $base_font_size_small 275 | line_height: 1 276 | vertical_align: middle 277 | footer: 278 | font_size: 10 279 | font-family: UtopiaStd-Regular 280 | height: 1in 281 | columns: =100% 282 | recto: 283 | center: 284 | content: '{page-number}' 285 | verso: 286 | center: 287 | content: '{page-number}' 288 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # P4Runtime Specification 2 | 3 | This directory contains protobuf files, specifications and related artifacts for 4 | all versions of the P4Runtime API. Documentation and protobuf definitions are 5 | placed into two distinct top-level directories. In each of these directories, 6 | files are organized based on the P4Runtime major version number (e.g. v1) as 7 | follows: 8 | ``` 9 | . 10 | ├── docs 11 | │ └── v1 # documentation for P4Runtime v1 12 | ├── proto 13 | │ └── p4 14 | │ ├── config 15 | │ │ └── v1 # p4.config.v1 protobuf package (P4Info message definition) 16 | │ └── v1 # p4.v1 protobuf package (P4Runtime service definition) 17 | ``` 18 | 19 | Git tags are used to mark minor and patch release versions. 20 | 21 | ## Reading the latest version of the documentation 22 | 23 | The latest version of the P4Runtime v1 specification is available: 24 | * [here](https://p4.org/p4-spec/docs/p4runtime-spec-working-draft-html-version.html) 25 | in **HTML** format 26 | * [here](https://p4.org/p4-spec/docs/p4runtime-spec-working-draft-pdf-version.html) 27 | in **PDF** format 28 | 29 | It is updated every time a new commit is pushed to the main branch. 30 | 31 | ## Overview 32 | 33 | P4 is a language for programming the data plane of network devices. The 34 | P4Runtime API is a control plane specification for controlling the data plane 35 | elements of a device or program defined by a P4 program. This repository 36 | provides a precise definition of the P4Runtime API via protobuf (.proto) files 37 | and accompanying documentation. The target audience for this includes system 38 | architects and developers who want to write controller applications for P4 39 | devices or switches. 40 | 41 | # Community 42 | 43 | * **Meetings**: the P4.org API Working Group meets every other Friday at 44 | 9:30AM (Pacific Time). Please see the [P4 Working Groups Calendar](https://calendar.google.com/calendar/u/0/embed?src=j4to42rsjqtfks0qb7iah8gous@group.calendar.google.com&ctz=America/Los_Angeles) 45 | for meeting details. 46 | * **Email**: join our [mailing 47 | list](https://lists.p4.org/mailman/listinfo/p4-dev_lists.p4.org) to receive 48 | announcements and stay up-to-date with Working Group activities. 49 | * **Slack**: ask to join the [P4 Slack Workspace] to get (or provide!) 50 | interactive help. 51 | 52 | # Compiling P4Runtime Protobuf files 53 | 54 | ## Build Using Docker 55 | 56 | You can use Docker to run the protoc compiler on the P4Runtime Protobuf files 57 | and generate the Protobuf & gRPC bindings for C++, Python and Go: 58 | 59 | ``` 60 | docker build -t p4runtime -f codegen/Dockerfile . 61 | docker run -v :/out/ -t p4runtime /p4runtime/codegen/compile_protos.sh /out/ 62 | ``` 63 | 64 | This will generate the bindings in the local `` directory. **You need to 65 | provide the absolute path for ``.** The default Docker user is root, so you 66 | may need to change the permissions manually for the generated files after the 67 | `docker run` command exits. 68 | 69 | These commands are the ones used by our CI system to ensure that the Protobuf 70 | files stay semantically valid. 71 | 72 | ## Build Using Bazel ![build protobufs](https://github.com/p4lang/p4runtime/workflows/build%20protobufs/badge.svg) 73 | 74 | The protobufs can also be built using [Bazel](https://bazel.build/). 75 | The Bazel WORKSPACE and BUILD files are located in the [proto folder](proto/). 76 | 77 | To build, run 78 | ```sh 79 | cd proto && bazel build //... 80 | ``` 81 | 82 | We run [continuous integration](.github/workflows/ci-build-proto.yml) to ensure 83 | this works with the latest version of Bazel. 84 | 85 | For an example of how to include P4Runtime in your own Bazel project, see 86 | [bazel/example](bazel/example). 87 | 88 | # Modification Policy 89 | 90 | We use the following processes when making changes to the P4Runtime 91 | specification and associated documents. These processes are designed to be 92 | lightweight, to encourage active participation by members of the P4.org 93 | community, while also ensuring that all proposed changes are properly vetted 94 | before they are incorporated into the repository and released to the community. 95 | 96 | ## Core Processes 97 | 98 | * Only members of the P4.org community may propose changes to the P4Runtime 99 | specification, and all contributed changes will be governed by the 100 | Apache-style license specified in the P4.org membership agreement. 101 | 102 | * We will use [semantic versioning](http://semver.org/) to track changes to the 103 | P4Runtime specification: major version numbers track API-incompatible changes; 104 | minor version numbers track backward-compatible changes; and patch versions 105 | make backward-compatible bug fixes. Generally speaking, the P4Runtime working 106 | group co-chairs will typically batch together multiple changes into a single 107 | release, as appropriate. 108 | 109 | ## Detailed Processes 110 | 111 | We now identify detailed processes for three classes of changes. The text below 112 | refers to [key 113 | committers](https://github.com/orgs/p4lang/teams/p4lang-key-committers), a 114 | GitHub team that is authorized to modify the specification according to these 115 | processes. 116 | 117 | 1. **Non-Technical Changes:** Changes that do not affect the definition of the 118 | API can be incorporated via a simple, lightweight review process: the author 119 | creates a pull request against the specification that a key committer must 120 | review and approve. The P4Runtime Working Group does not need to be 121 | explicitly notified. Such changes include improvements to the wording of the 122 | specification document, the addition of examples or figures, typo fixes, and 123 | so on. 124 | 125 | 2. **Technical Bug Fixes:** Any changes that repair an ambiguity or flaw in the 126 | current API specification can also be incorporated via the same lightweight 127 | review process: the author creates a GitHub issue as well as a pull request 128 | against the specification that a key committer must review and approve. The 129 | key committer should use their judgment in deciding if the fix should be 130 | incorporated without broader discussion or if it should be escalated to the 131 | P4Runtime Working Group. In any event, the Working Group should be notified 132 | by email. 133 | 134 | 3. **API Changes** Any change that substantially modifies the definition of the 135 | API, or extends it with new features, must be reviewed by the P4Runtime 136 | Working Group, either in an email discussion or a meeting. We imagine that 137 | such proposals would go through three stages: (i) a preliminary proposal with 138 | text that gives the motivation for the change and examples; (ii) a more 139 | detailed proposal with a discussion of relevant issues including the impact 140 | on existing programs; (iii) a final proposal accompanied by a design 141 | document, a pull request against the specification, and prototype 142 | implementation on a branch of `p4runtime`, and example(s) that illustrate the 143 | change. After approval, the author would create a GitHub issue as well as a 144 | pull request against the specification that a key committer must review and 145 | approve. 146 | 147 | >**Generated protobuf files**: When updating the Protobuf files in a pull request, you will also need to update 148 | the generated Go and Python files, which are hosted in this repository under 149 | [go/](go/) and [py/](py/). This can be done easily **by running `./codegen/update.sh`**, 150 | provided docker is installed and your user is part of the "docker" group 151 | (which means that the `docker` command can be executed without `sudo`). 152 | 153 | ## Use generated P4Runtime library 154 | 155 | ### Go 156 | 157 | To include the P4Runtime Go library to your project, you can add this repository url 158 | to your `go.mod` file, for example: 159 | 160 | ``` 161 | module your_module_name 162 | 163 | go 1.13 164 | 165 | require ( 166 | github.com/p4lang/p4runtime v1.3.0 167 | ) 168 | ``` 169 | 170 | ### Python 171 | 172 | To install P4Runtime Python library, use the `pip3` command: 173 | 174 | ```bash 175 | pip3 install p4runtime 176 | # Or specify the version 177 | pip3 install p4runtime==1.3.0 178 | ``` 179 | 180 | ### Rust 181 | 182 | See the [rust/README.md](rust/README.md). 183 | 184 | ## Guidelines for using Protocol Buffers (protobuf) in backwards-compatible ways 185 | 186 | P4Runtime generally follows "Live at Head" development principles - new 187 | development happens on the `main` branch and there are no support branches. 188 | New releases are periodically created from the head of `main`. 189 | 190 | P4Runtime follows [semantic versioning](https://semver.org/) for release 191 | numbering, which means changes to the P4Runtime protobuf definitions have 192 | implications on the next release number. The team has tried its best so 193 | far to avoid a major version number bump, but recognizes that one may be 194 | necessary in the future. 195 | 196 | Whenever possible, it is best to introduce new functionality in backward 197 | compatible ways. For example when role config was introduced, an unset 198 | (empty) role configuration implies full pipeline access, which was the 199 | default behavior before the feature was introduced. 200 | 201 | There are no strict rules here for updating P4Runtime protobuf message 202 | definitions, only advice written by those with experience in using 203 | protobuf for applications while they have been extended over 204 | time. They are here for learning and reference: 205 | 206 | * [Updating Proto Definitions Without Updating Code](https://developers.google.com/protocol-buffers/docs/overview#updating-defs) 207 | * [Updating A Message Type](https://developers.google.com/protocol-buffers/docs/proto3#updating) 208 | * [Backwards-compatibility issues in `oneof` fields](https://developers.google.com/protocol-buffers/docs/proto3#backwards-compatibility_issues) 209 | * [API design guide](https://cloud.google.com/apis/design) 210 | 211 | Some brief points, but not the full story: 212 | 213 | * Do not change or reuse field numbers. 214 | * Be careful when changing types. 215 | * You can deprecate fields, but do not remove them (and make sure that 216 | you continue to support them) until you are sure that all clients 217 | and servers are updated. 218 | 219 | 220 | [P4 Slack Workspace]: https://p4-lang.slack.com/join/shared_invite/enQtODA0NzY4Mjc5MTExLTRlMWVmN2I5ZTY4MTAzMDI3MGQ1OTZjM2ZmM2Q1MWE2YzZjYTQ2ZWMyMGUyYjQ2ZmIxMjFjZDE4ZThiN2ZkZWI 221 | -------------------------------------------------------------------------------- /proto/p4/config/v1/p4types.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013-present Barefoot Networks, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package p4.config.v1; 18 | 19 | option go_package = "github.com/p4lang/p4runtime/go/p4/config/v1"; 20 | 21 | // P4 type specs --------------------------------------------------------------- 22 | 23 | // From the P4_16 spec: 24 | /* |--------------------|--------------------------------------------| 25 | * | | Container type | 26 | * | Element type |-----------|--------------|-----------------| 27 | * | | header | header_union | struct or tuple | 28 | * |--------------------|-----------|--------------|-----------------| 29 | * | bit | allowed | error | allowed | 30 | * | int | allowed | error | allowed | 31 | * | varbit | allowed | error | allowed | 32 | * | int | error | error | error | 33 | * | void | error | error | error | 34 | * | error | error | error | allowed | 35 | * | match_kind | error | error | error | 36 | * | bool | error | error | allowed | 37 | * | enum | allowed* | error | allowed | 38 | * | header | error | allowed | allowed | 39 | * | header stack | error | error | allowed | 40 | * | header_union | error | error | allowed | 41 | * | struct | error | error | allowed | 42 | * | tuple | error | error | allowed | 43 | * |--------------------|-----------|--------------|-----------------| 44 | * 45 | * *if serializable 46 | */ 47 | 48 | // These P4 types (struct, header_type, header_union and enum) are guaranteed to 49 | // have a fully-qualified name (e.g. you cannot use an anonymous struct to 50 | // declare a variable like in C). Instead of duplicating the type spec for these 51 | // every time the type is used, we include the type spec once in this P4TypeInfo 52 | // message and refer to the types by name in the P4DataTypeSpec message. We also 53 | // support annotations for these type specs which can be useful, e.g. to 54 | // identify well-known headers (such as ipv4). 55 | message P4TypeInfo { 56 | map structs = 1; 57 | map headers = 2; 58 | map header_unions = 3; 59 | map enums = 4; 60 | P4ErrorTypeSpec error = 5; 61 | map serializable_enums = 6; 62 | map new_types = 7; 63 | } 64 | 65 | // Describes a P4_16 type. 66 | message P4DataTypeSpec { 67 | oneof type_spec { 68 | P4BitstringLikeTypeSpec bitstring = 1; 69 | P4BoolType bool = 2; 70 | P4TupleTypeSpec tuple = 3; 71 | P4NamedType struct = 4; 72 | P4NamedType header = 5; 73 | P4NamedType header_union = 6; 74 | P4HeaderStackTypeSpec header_stack = 7; 75 | P4HeaderUnionStackTypeSpec header_union_stack = 8; 76 | P4NamedType enum = 9; 77 | P4ErrorType error = 10; 78 | P4NamedType serializable_enum = 11; 79 | P4NamedType new_type = 12; 80 | } 81 | } 82 | 83 | message P4NamedType { 84 | string name = 1; 85 | } 86 | 87 | // Empty message as no type information needed, just used as a placeholder in 88 | // the oneof to identify boolean types. 89 | message P4BoolType { } 90 | 91 | message P4ErrorType { } 92 | 93 | message P4BitstringLikeTypeSpec { 94 | oneof type_spec { 95 | P4BitTypeSpec bit = 1; // bit 96 | P4IntTypeSpec int = 2; // int 97 | P4VarbitTypeSpec varbit = 3; // varbit 98 | } 99 | // Useful to identify well-known types, such as IP address or Ethernet MAC 100 | // address. 101 | repeated string annotations = 4; 102 | // Optional. If present, the location of `annotations[i]` is given by 103 | // `annotation_locations[i]`. 104 | repeated SourceLocation annotation_locations = 5; 105 | repeated StructuredAnnotation structured_annotations = 6; 106 | } 107 | 108 | message P4BitTypeSpec { 109 | int32 bitwidth = 1; 110 | } 111 | 112 | message P4IntTypeSpec { 113 | int32 bitwidth = 1; 114 | } 115 | 116 | message P4VarbitTypeSpec { 117 | int32 max_bitwidth = 1; 118 | } 119 | 120 | // From the P4_16 spec: "A tuple is similar to a struct, in that it holds 121 | // multiple values. Unlike a struct type, tuples have no named fields." 122 | message P4TupleTypeSpec { 123 | repeated P4DataTypeSpec members = 1; 124 | } 125 | 126 | message P4StructTypeSpec { 127 | message Member { 128 | string name = 1; 129 | P4DataTypeSpec type_spec = 2; 130 | } 131 | repeated Member members = 1; 132 | repeated string annotations = 2; 133 | // Optional. If present, the location of `annotations[i]` is given by 134 | // `annotation_locations[i]`. 135 | repeated SourceLocation annotation_locations = 3; 136 | repeated StructuredAnnotation structured_annotations = 4; 137 | } 138 | 139 | message P4HeaderTypeSpec { 140 | message Member { 141 | string name = 1; 142 | P4BitstringLikeTypeSpec type_spec = 2; 143 | } 144 | repeated Member members = 1; 145 | repeated string annotations = 2; 146 | // Optional. If present, the location of `annotations[i]` is given by 147 | // `annotation_locations[i]`. 148 | repeated SourceLocation annotation_locations = 3; 149 | repeated StructuredAnnotation structured_annotations = 4; 150 | } 151 | 152 | message P4HeaderUnionTypeSpec { 153 | message Member { 154 | string name = 1; 155 | P4NamedType header = 2; 156 | } 157 | repeated Member members = 1; 158 | repeated string annotations = 2; 159 | // Optional. If present, the location of `annotations[i]` is given by 160 | // `annotation_locations[i]`. 161 | repeated SourceLocation annotation_locations = 3; 162 | repeated StructuredAnnotation structured_annotations = 4; 163 | } 164 | 165 | message P4HeaderStackTypeSpec { 166 | P4NamedType header = 1; 167 | int32 size = 2; 168 | } 169 | 170 | message P4HeaderUnionStackTypeSpec { 171 | P4NamedType header_union = 1; 172 | int32 size = 2; 173 | } 174 | 175 | message KeyValuePair { 176 | string key = 1; 177 | Expression value = 2; 178 | } 179 | 180 | message KeyValuePairList { 181 | repeated KeyValuePair kv_pairs = 1; 182 | } 183 | 184 | message Expression { 185 | oneof value { 186 | string string_value = 1; 187 | int64 int64_value = 2; 188 | bool bool_value = 3; 189 | } 190 | } 191 | 192 | message ExpressionList { 193 | repeated Expression expressions = 1; 194 | } 195 | 196 | message StructuredAnnotation { 197 | string name = 1; 198 | oneof body { 199 | ExpressionList expression_list = 2; 200 | KeyValuePairList kv_pair_list = 3; 201 | } 202 | // Optional. Location of the '@' symbol of this annotation in the source code. 203 | SourceLocation source_location = 4; 204 | } 205 | 206 | // Location of code relative to a given source file. 207 | message SourceLocation { 208 | // Path to the source file (absolute or relative to the working directory). 209 | string file = 1; 210 | // Line and column numbers within the source file, 1-based. 211 | int32 line = 2; 212 | int32 column = 3; 213 | } 214 | 215 | // For "safe" enums with no underlying representation and no member integer 216 | // values. 217 | message P4EnumTypeSpec { 218 | message Member { 219 | string name = 1; 220 | repeated string annotations = 2; 221 | // Optional. If present, the location of `annotations[i]` is given by 222 | // `annotation_locations[i]`. 223 | repeated SourceLocation annotation_locations = 4; 224 | repeated StructuredAnnotation structured_annotations = 3; 225 | } 226 | repeated Member members = 1; 227 | repeated string annotations = 2; 228 | // Optional. If present, the location of `annotations[i]` is given by 229 | // `annotation_locations[i]`. 230 | repeated SourceLocation annotation_locations = 4; 231 | repeated StructuredAnnotation structured_annotations = 3; 232 | } 233 | 234 | // For serializable (or "unsafe") enums, which have an underlying type. Note 235 | // that as per the P4_16 specification, the underlying representation can only 236 | // be a bit type. 237 | message P4SerializableEnumTypeSpec { 238 | message Member { 239 | string name = 1; 240 | bytes value = 2; 241 | repeated string annotations = 3; 242 | // Optional. If present, the location of `annotations[i]` is given by 243 | // `annotation_locations[i]`. 244 | repeated SourceLocation annotation_locations = 5; 245 | repeated StructuredAnnotation structured_annotations = 4; 246 | } 247 | P4BitTypeSpec underlying_type = 1; 248 | repeated Member members = 2; 249 | repeated string annotations = 3; 250 | // Optional. If present, the location of `annotations[i]` is given by 251 | // `annotation_locations[i]`. 252 | repeated SourceLocation annotation_locations = 5; 253 | repeated StructuredAnnotation structured_annotations = 4; 254 | } 255 | 256 | // Similar to an enum, but there is always one and only one instance per P4 257 | // program. 258 | message P4ErrorTypeSpec { 259 | repeated string members = 1; 260 | } 261 | 262 | message P4NewTypeTranslation { 263 | message SdnString {} 264 | 265 | // the URI uniquely identifies the translation in order to enable the 266 | // P4Runtime agent to perform value-mapping appropriately when required. It is 267 | // recommended that the URI includes at least the P4 architecture name and the 268 | // type name. 269 | string uri = 1; 270 | 271 | // The object is either represented as an unsigned integer with a bitwidth of 272 | // `sdn_bitwidth`, or as a string. 273 | oneof sdn_type { 274 | int32 sdn_bitwidth = 2; 275 | SdnString sdn_string = 3; 276 | } 277 | } 278 | 279 | // New types introduced with the "type" keyword 280 | message P4NewTypeSpec { 281 | oneof representation { 282 | // if no @p4runtime_translation annotation present 283 | P4DataTypeSpec original_type = 1; 284 | // if @p4runtime_translation annotation present 285 | P4NewTypeTranslation translated_type = 2; 286 | } 287 | // for other annotations (not @p4runtime_translation) 288 | repeated string annotations = 3; 289 | // Optional. If present, the location of `annotations[i]` is given by 290 | // `annotation_locations[i]`. 291 | repeated SourceLocation annotation_locations = 5; 292 | repeated StructuredAnnotation structured_annotations = 4; 293 | } 294 | 295 | // End of P4 type specs -------------------------------------------------------- 296 | -------------------------------------------------------------------------------- /tools/asciidoclint.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2024 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | 19 | # DISCLAIMER: This is a work in progress. This linter was written specifically 20 | # for the P4Runtime specification document and may not be useful for other 21 | # AsciiDoc documents, as it may be making some assumptions as to how the document 22 | # was written. 23 | 24 | 25 | 26 | 27 | import argparse 28 | from collections import namedtuple 29 | import json 30 | import os.path 31 | import re 32 | import sys 33 | import traceback 34 | 35 | 36 | DEFAULT_CONF = 'asciidocint.conf.json' 37 | LINE_WRAP_LENGTH = 80 38 | 39 | 40 | parser = argparse.ArgumentParser(description='Lint tool for Asciidoc code') 41 | parser.add_argument('files', metavar='FILE', type=str, nargs='+', 42 | help='Input files') 43 | parser.add_argument('--conf', type=str, 44 | help='Configuration file for lint tool') 45 | 46 | 47 | class AsciidocFmtError(Exception): 48 | def __init__(self, filename, lineno, description): 49 | self.filename = filename 50 | self.lineno = lineno 51 | self.description = description 52 | 53 | def __str__(self): 54 | return "Unexpected Asciidoc code in file {} at line {}: {}".format( 55 | self.filename, self.lineno, self.description) 56 | 57 | 58 | class LintState: 59 | def __init__(self): 60 | self.errors_cnt = 0 61 | 62 | def error(self, filename, lineno, line, description): 63 | # TODO: print line later? 64 | print("Error in file {} at line {}: {}.".format(filename, lineno, description)) 65 | self.errors_cnt += 1 66 | 67 | 68 | lint_state = LintState() 69 | 70 | 71 | class LintConf: 72 | class BadConfException(Exception): 73 | def __init__(self, what): 74 | self.what = what 75 | 76 | def __str__(self): 77 | return self.what 78 | 79 | 80 | def __init__(self): 81 | self.keywords = {} 82 | 83 | def build_from(self, conf_fp): 84 | try: 85 | conf_d = json.load(conf_fp) 86 | for entry in conf_d['keywords']: 87 | category = entry['category'] 88 | for keyword in entry['keywords']: 89 | if keyword in self.keywords: 90 | raise LintConf.BadConfException( 91 | "Keyword '{}' is present multiple times in configuration".format( 92 | keyword)) 93 | self.keywords[keyword] = category 94 | except json.JSONDecodeError: 95 | print("Provided configuration file is not a valid JSON file") 96 | sys.exit(1) 97 | except KeyError: 98 | print("Provided JSON configuration file has missing attributes") 99 | traceback.print_exc() 100 | sys.exit(1) 101 | except LintConf.BadConfException as e: 102 | print(str(e)) 103 | sys.exit(1) 104 | 105 | 106 | lint_conf = LintConf() 107 | 108 | 109 | class Context: 110 | """A context is an object that is used to determine whether a specific "checker" (check_* 111 | method) should visit a given line.""" 112 | 113 | def enter(self, line, filename, lineno): 114 | """Called before visiting a line. 115 | Returns True iff the checker should visit the given line. 116 | """ 117 | return True 118 | 119 | def exit(self, line, filename, lineno): 120 | """Called after visiting a line.""" 121 | pass 122 | 123 | 124 | class ContextSkipBlocks(Context): 125 | """A context used to only visit Asciidoc code outside of blocks.""" 126 | 127 | Block = namedtuple('Block', ['num_tildes', 'name']) 128 | 129 | def __init__(self): 130 | self.p_block = re.compile('^ *(?P~+) *(?:(?PBegin|End)(?: +))?(?P\w+)?') 131 | self.blocks_stack = [] 132 | 133 | def enter(self, line, filename, lineno): 134 | m = self.p_block.match(line) 135 | if m: 136 | num_tildes = len(m.group("tildes")) 137 | has_begin = m.group("cmd") == "Begin" 138 | has_end = m.group("cmd") == "End" 139 | blockname = m.group("name") 140 | 141 | if has_begin: 142 | self.blocks_stack.append(self.Block(num_tildes, blockname)) 143 | return False 144 | if has_end: 145 | if not self.blocks_stack: 146 | raise AsciidocFmtError(filename, lineno, "Block end line but no block was begun") 147 | expected = self.blocks_stack.pop() 148 | if num_tildes != expected.num_tildes or blockname != expected.name: 149 | raise AsciidocFmtError( 150 | filename, lineno, 151 | "Block end line does not match last visited block begin line") 152 | return False 153 | if blockname is None: 154 | if not self.blocks_stack: 155 | raise AsciidocFmtError(filename, lineno, "Block end line but no block was begun") 156 | expected = self.blocks_stack.pop() 157 | if num_tildes != expected.num_tildes: 158 | raise AsciidocFmtError( 159 | filename, lineno, 160 | "Block end line does not match last visited block begin line") 161 | return False 162 | self.blocks_stack.append(self.Block(num_tildes, blockname)) 163 | return False 164 | if self.blocks_stack: 165 | return False 166 | return True 167 | 168 | 169 | # TODO: would "skip metadata" be more generic? 170 | class ContextAfterTitle(Context): 171 | """A context used to visit only Asciidoc code after the [TITLE] block element. 172 | """ 173 | 174 | def __init__(self, *args): 175 | self.title_found = False 176 | self.p_title = re.compile('^ *\[TITLE\] *$') 177 | 178 | def enter(self, line, filename, lineno): 179 | if self.title_found: 180 | return True 181 | self.title_found = self.p_title.match(line) is not None 182 | return False 183 | 184 | 185 | class ContextSkipHeadings(Context): 186 | """A context used to skip headings (lines starting with #).""" 187 | 188 | def __init__(self, *args): 189 | self.p_headings = re.compile('^ *#') 190 | 191 | def enter(self, line, filename, lineno): 192 | return self.p_headings.match(line) is None 193 | 194 | 195 | class ContextCompose(Context): 196 | """A special context used to combine an arbitrary number of contexts.""" 197 | 198 | def __init__(self, *args): 199 | self.contexts = list(args) 200 | 201 | def enter(self, line, filename, lineno): 202 | res = True 203 | for c in self.contexts: 204 | # we use a short-circuit on purpose, if a context returns False we do not even enter 205 | # subsequent contexts. This has some implications on how contexts are used. 206 | res = res and c.enter(line, filename, lineno) 207 | return res 208 | 209 | def exit(self, line, filename, lineno): 210 | for c in self.contexts: 211 | c.exit(line, filename, lineno) 212 | 213 | 214 | def foreach_line(path, context, fn): 215 | """Iterate over every line in the file. For each line, call fn iff the enter method of the 216 | provided context returns True.""" 217 | lineno = 1 218 | with open(path, 'r') as f: 219 | for line in f: 220 | if context.enter(line, path, lineno): 221 | fn(line, lineno) 222 | lineno += 1 223 | context.exit(line, path, lineno) 224 | 225 | 226 | def check_line_wraps(path): 227 | def check(line, lineno): 228 | if "http" in line: # TODO: we can probably do better than this 229 | return 230 | if len(line) > LINE_WRAP_LENGTH + 1: # +1 for the newline characted 231 | lint_state.error(path, lineno, line, 232 | "is more than {} characters long".format(LINE_WRAP_LENGTH)) 233 | 234 | foreach_line(path, 235 | ContextCompose(ContextAfterTitle(), ContextSkipBlocks(), ContextSkipHeadings()), 236 | check) 237 | 238 | 239 | def check_trailing_whitespace(path): 240 | def check(line, lineno): 241 | if len(line) >= 2 and line[-2].isspace(): 242 | lint_state.error(path, lineno, line, "trailing whitespace") 243 | 244 | foreach_line(path, Context(), check) 245 | 246 | 247 | def check_keywords(path): 248 | def check(line, lineno): 249 | for word in line.split(): 250 | if word not in lint_conf.keywords: 251 | continue 252 | category = lint_conf.keywords[word] 253 | lint_state.error( 254 | path, lineno, line, 255 | "'{}' is a known keyword ({}), highlight it with backticks".format(word, category)) 256 | 257 | foreach_line(path, ContextCompose(ContextAfterTitle(), ContextSkipBlocks()), check) 258 | 259 | 260 | def process_one(path): 261 | check_line_wraps(path) 262 | check_trailing_whitespace(path) 263 | check_keywords(path) 264 | 265 | 266 | def main(): 267 | args = parser.parse_args() 268 | 269 | for f in args.files: 270 | if not os.path.isfile(f): 271 | print("'{}' is not a valid file path".format(f)) 272 | sys.exit(1) 273 | _, ext = os.path.splitext(f) 274 | if ext != ".adoc": 275 | print("'{}' does not have an .mdk extension") 276 | sys.exit(1) 277 | 278 | conf_path = None 279 | if args.conf is not None: 280 | if not os.path.isfile(args.conf): 281 | print("'{}' is not a valid file path".format(args.conf)) 282 | sys.exit(1) 283 | conf_path = args.conf 284 | elif os.path.isfile(DEFAULT_CONF): # search working directory 285 | conf_path = DEFAULT_CONF 286 | else: # search directory of Python script 287 | this_dir = os.path.dirname(os.path.abspath(__file__)) 288 | path = os.path.join(this_dir, DEFAULT_CONF) 289 | if os.path.isfile(path): 290 | conf_path = path 291 | 292 | if conf_path is not None: 293 | with open(conf_path, 'r') as conf_fp: 294 | lint_conf.build_from(conf_fp) 295 | 296 | for f in args.files: 297 | try: 298 | process_one(f) 299 | except AsciidocFmtError as e: 300 | print(e) 301 | 302 | errors_cnt = lint_state.errors_cnt 303 | print("**********") 304 | print("Errors found: {}".format(errors_cnt)) 305 | rc = 0 if errors_cnt == 0 else 2 306 | sys.exit(rc) 307 | 308 | 309 | if __name__ == '__main__': 310 | main() 311 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /proto/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /py/p4/v1/p4runtime_pb2_grpc.py: -------------------------------------------------------------------------------- 1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! 2 | """Client and server classes corresponding to protobuf-defined services.""" 3 | import grpc 4 | 5 | from p4.v1 import p4runtime_pb2 as p4_dot_v1_dot_p4runtime__pb2 6 | 7 | 8 | class P4RuntimeStub(object): 9 | """Missing associated documentation comment in .proto file.""" 10 | 11 | def __init__(self, channel): 12 | """Constructor. 13 | 14 | Args: 15 | channel: A grpc.Channel. 16 | """ 17 | self.Write = channel.unary_unary( 18 | '/p4.v1.P4Runtime/Write', 19 | request_serializer=p4_dot_v1_dot_p4runtime__pb2.WriteRequest.SerializeToString, 20 | response_deserializer=p4_dot_v1_dot_p4runtime__pb2.WriteResponse.FromString, 21 | ) 22 | self.Read = channel.unary_stream( 23 | '/p4.v1.P4Runtime/Read', 24 | request_serializer=p4_dot_v1_dot_p4runtime__pb2.ReadRequest.SerializeToString, 25 | response_deserializer=p4_dot_v1_dot_p4runtime__pb2.ReadResponse.FromString, 26 | ) 27 | self.SetForwardingPipelineConfig = channel.unary_unary( 28 | '/p4.v1.P4Runtime/SetForwardingPipelineConfig', 29 | request_serializer=p4_dot_v1_dot_p4runtime__pb2.SetForwardingPipelineConfigRequest.SerializeToString, 30 | response_deserializer=p4_dot_v1_dot_p4runtime__pb2.SetForwardingPipelineConfigResponse.FromString, 31 | ) 32 | self.GetForwardingPipelineConfig = channel.unary_unary( 33 | '/p4.v1.P4Runtime/GetForwardingPipelineConfig', 34 | request_serializer=p4_dot_v1_dot_p4runtime__pb2.GetForwardingPipelineConfigRequest.SerializeToString, 35 | response_deserializer=p4_dot_v1_dot_p4runtime__pb2.GetForwardingPipelineConfigResponse.FromString, 36 | ) 37 | self.StreamChannel = channel.stream_stream( 38 | '/p4.v1.P4Runtime/StreamChannel', 39 | request_serializer=p4_dot_v1_dot_p4runtime__pb2.StreamMessageRequest.SerializeToString, 40 | response_deserializer=p4_dot_v1_dot_p4runtime__pb2.StreamMessageResponse.FromString, 41 | ) 42 | self.Capabilities = channel.unary_unary( 43 | '/p4.v1.P4Runtime/Capabilities', 44 | request_serializer=p4_dot_v1_dot_p4runtime__pb2.CapabilitiesRequest.SerializeToString, 45 | response_deserializer=p4_dot_v1_dot_p4runtime__pb2.CapabilitiesResponse.FromString, 46 | ) 47 | 48 | 49 | class P4RuntimeServicer(object): 50 | """Missing associated documentation comment in .proto file.""" 51 | 52 | def Write(self, request, context): 53 | """Update one or more P4 entities on the target. 54 | """ 55 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 56 | context.set_details('Method not implemented!') 57 | raise NotImplementedError('Method not implemented!') 58 | 59 | def Read(self, request, context): 60 | """Read one or more P4 entities from the target. 61 | """ 62 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 63 | context.set_details('Method not implemented!') 64 | raise NotImplementedError('Method not implemented!') 65 | 66 | def SetForwardingPipelineConfig(self, request, context): 67 | """Sets the P4 forwarding-pipeline config. 68 | """ 69 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 70 | context.set_details('Method not implemented!') 71 | raise NotImplementedError('Method not implemented!') 72 | 73 | def GetForwardingPipelineConfig(self, request, context): 74 | """Gets the current P4 forwarding-pipeline config. 75 | """ 76 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 77 | context.set_details('Method not implemented!') 78 | raise NotImplementedError('Method not implemented!') 79 | 80 | def StreamChannel(self, request_iterator, context): 81 | """Represents the bidirectional stream between the controller and the 82 | switch (initiated by the controller), and is managed for the following 83 | purposes: 84 | - connection initiation through client arbitration 85 | - indicating switch session liveness: the session is live when switch 86 | sends a positive client arbitration update to the controller, and is 87 | considered dead when either the stream breaks or the switch sends a 88 | negative update for client arbitration 89 | - the controller sending/receiving packets to/from the switch 90 | - streaming of notifications from the switch 91 | """ 92 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 93 | context.set_details('Method not implemented!') 94 | raise NotImplementedError('Method not implemented!') 95 | 96 | def Capabilities(self, request, context): 97 | """Missing associated documentation comment in .proto file.""" 98 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) 99 | context.set_details('Method not implemented!') 100 | raise NotImplementedError('Method not implemented!') 101 | 102 | 103 | def add_P4RuntimeServicer_to_server(servicer, server): 104 | rpc_method_handlers = { 105 | 'Write': grpc.unary_unary_rpc_method_handler( 106 | servicer.Write, 107 | request_deserializer=p4_dot_v1_dot_p4runtime__pb2.WriteRequest.FromString, 108 | response_serializer=p4_dot_v1_dot_p4runtime__pb2.WriteResponse.SerializeToString, 109 | ), 110 | 'Read': grpc.unary_stream_rpc_method_handler( 111 | servicer.Read, 112 | request_deserializer=p4_dot_v1_dot_p4runtime__pb2.ReadRequest.FromString, 113 | response_serializer=p4_dot_v1_dot_p4runtime__pb2.ReadResponse.SerializeToString, 114 | ), 115 | 'SetForwardingPipelineConfig': grpc.unary_unary_rpc_method_handler( 116 | servicer.SetForwardingPipelineConfig, 117 | request_deserializer=p4_dot_v1_dot_p4runtime__pb2.SetForwardingPipelineConfigRequest.FromString, 118 | response_serializer=p4_dot_v1_dot_p4runtime__pb2.SetForwardingPipelineConfigResponse.SerializeToString, 119 | ), 120 | 'GetForwardingPipelineConfig': grpc.unary_unary_rpc_method_handler( 121 | servicer.GetForwardingPipelineConfig, 122 | request_deserializer=p4_dot_v1_dot_p4runtime__pb2.GetForwardingPipelineConfigRequest.FromString, 123 | response_serializer=p4_dot_v1_dot_p4runtime__pb2.GetForwardingPipelineConfigResponse.SerializeToString, 124 | ), 125 | 'StreamChannel': grpc.stream_stream_rpc_method_handler( 126 | servicer.StreamChannel, 127 | request_deserializer=p4_dot_v1_dot_p4runtime__pb2.StreamMessageRequest.FromString, 128 | response_serializer=p4_dot_v1_dot_p4runtime__pb2.StreamMessageResponse.SerializeToString, 129 | ), 130 | 'Capabilities': grpc.unary_unary_rpc_method_handler( 131 | servicer.Capabilities, 132 | request_deserializer=p4_dot_v1_dot_p4runtime__pb2.CapabilitiesRequest.FromString, 133 | response_serializer=p4_dot_v1_dot_p4runtime__pb2.CapabilitiesResponse.SerializeToString, 134 | ), 135 | } 136 | generic_handler = grpc.method_handlers_generic_handler( 137 | 'p4.v1.P4Runtime', rpc_method_handlers) 138 | server.add_generic_rpc_handlers((generic_handler,)) 139 | 140 | 141 | # This class is part of an EXPERIMENTAL API. 142 | class P4Runtime(object): 143 | """Missing associated documentation comment in .proto file.""" 144 | 145 | @staticmethod 146 | def Write(request, 147 | target, 148 | options=(), 149 | channel_credentials=None, 150 | call_credentials=None, 151 | insecure=False, 152 | compression=None, 153 | wait_for_ready=None, 154 | timeout=None, 155 | metadata=None): 156 | return grpc.experimental.unary_unary(request, target, '/p4.v1.P4Runtime/Write', 157 | p4_dot_v1_dot_p4runtime__pb2.WriteRequest.SerializeToString, 158 | p4_dot_v1_dot_p4runtime__pb2.WriteResponse.FromString, 159 | options, channel_credentials, 160 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 161 | 162 | @staticmethod 163 | def Read(request, 164 | target, 165 | options=(), 166 | channel_credentials=None, 167 | call_credentials=None, 168 | insecure=False, 169 | compression=None, 170 | wait_for_ready=None, 171 | timeout=None, 172 | metadata=None): 173 | return grpc.experimental.unary_stream(request, target, '/p4.v1.P4Runtime/Read', 174 | p4_dot_v1_dot_p4runtime__pb2.ReadRequest.SerializeToString, 175 | p4_dot_v1_dot_p4runtime__pb2.ReadResponse.FromString, 176 | options, channel_credentials, 177 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 178 | 179 | @staticmethod 180 | def SetForwardingPipelineConfig(request, 181 | target, 182 | options=(), 183 | channel_credentials=None, 184 | call_credentials=None, 185 | insecure=False, 186 | compression=None, 187 | wait_for_ready=None, 188 | timeout=None, 189 | metadata=None): 190 | return grpc.experimental.unary_unary(request, target, '/p4.v1.P4Runtime/SetForwardingPipelineConfig', 191 | p4_dot_v1_dot_p4runtime__pb2.SetForwardingPipelineConfigRequest.SerializeToString, 192 | p4_dot_v1_dot_p4runtime__pb2.SetForwardingPipelineConfigResponse.FromString, 193 | options, channel_credentials, 194 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 195 | 196 | @staticmethod 197 | def GetForwardingPipelineConfig(request, 198 | target, 199 | options=(), 200 | channel_credentials=None, 201 | call_credentials=None, 202 | insecure=False, 203 | compression=None, 204 | wait_for_ready=None, 205 | timeout=None, 206 | metadata=None): 207 | return grpc.experimental.unary_unary(request, target, '/p4.v1.P4Runtime/GetForwardingPipelineConfig', 208 | p4_dot_v1_dot_p4runtime__pb2.GetForwardingPipelineConfigRequest.SerializeToString, 209 | p4_dot_v1_dot_p4runtime__pb2.GetForwardingPipelineConfigResponse.FromString, 210 | options, channel_credentials, 211 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 212 | 213 | @staticmethod 214 | def StreamChannel(request_iterator, 215 | target, 216 | options=(), 217 | channel_credentials=None, 218 | call_credentials=None, 219 | insecure=False, 220 | compression=None, 221 | wait_for_ready=None, 222 | timeout=None, 223 | metadata=None): 224 | return grpc.experimental.stream_stream(request_iterator, target, '/p4.v1.P4Runtime/StreamChannel', 225 | p4_dot_v1_dot_p4runtime__pb2.StreamMessageRequest.SerializeToString, 226 | p4_dot_v1_dot_p4runtime__pb2.StreamMessageResponse.FromString, 227 | options, channel_credentials, 228 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 229 | 230 | @staticmethod 231 | def Capabilities(request, 232 | target, 233 | options=(), 234 | channel_credentials=None, 235 | call_credentials=None, 236 | insecure=False, 237 | compression=None, 238 | wait_for_ready=None, 239 | timeout=None, 240 | metadata=None): 241 | return grpc.experimental.unary_unary(request, target, '/p4.v1.P4Runtime/Capabilities', 242 | p4_dot_v1_dot_p4runtime__pb2.CapabilitiesRequest.SerializeToString, 243 | p4_dot_v1_dot_p4runtime__pb2.CapabilitiesResponse.FromString, 244 | options, channel_credentials, 245 | insecure, call_credentials, compression, wait_for_ready, timeout, metadata) 246 | -------------------------------------------------------------------------------- /go/p4/v1/p4runtime_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016, Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 16 | // versions: 17 | // - protoc-gen-go-grpc v1.3.0 18 | // - protoc v3.18.1 19 | // source: p4/v1/p4runtime.proto 20 | 21 | // This package and its contents are a work-in-progress. 22 | 23 | package v1 24 | 25 | import ( 26 | context "context" 27 | grpc "google.golang.org/grpc" 28 | codes "google.golang.org/grpc/codes" 29 | status "google.golang.org/grpc/status" 30 | ) 31 | 32 | // This is a compile-time assertion to ensure that this generated file 33 | // is compatible with the grpc package it is being compiled against. 34 | // Requires gRPC-Go v1.32.0 or later. 35 | const _ = grpc.SupportPackageIsVersion7 36 | 37 | const ( 38 | P4Runtime_Write_FullMethodName = "/p4.v1.P4Runtime/Write" 39 | P4Runtime_Read_FullMethodName = "/p4.v1.P4Runtime/Read" 40 | P4Runtime_SetForwardingPipelineConfig_FullMethodName = "/p4.v1.P4Runtime/SetForwardingPipelineConfig" 41 | P4Runtime_GetForwardingPipelineConfig_FullMethodName = "/p4.v1.P4Runtime/GetForwardingPipelineConfig" 42 | P4Runtime_StreamChannel_FullMethodName = "/p4.v1.P4Runtime/StreamChannel" 43 | P4Runtime_Capabilities_FullMethodName = "/p4.v1.P4Runtime/Capabilities" 44 | ) 45 | 46 | // P4RuntimeClient is the client API for P4Runtime service. 47 | // 48 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 49 | type P4RuntimeClient interface { 50 | // Update one or more P4 entities on the target. 51 | Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) 52 | // Read one or more P4 entities from the target. 53 | Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (P4Runtime_ReadClient, error) 54 | // Sets the P4 forwarding-pipeline config. 55 | SetForwardingPipelineConfig(ctx context.Context, in *SetForwardingPipelineConfigRequest, opts ...grpc.CallOption) (*SetForwardingPipelineConfigResponse, error) 56 | // Gets the current P4 forwarding-pipeline config. 57 | GetForwardingPipelineConfig(ctx context.Context, in *GetForwardingPipelineConfigRequest, opts ...grpc.CallOption) (*GetForwardingPipelineConfigResponse, error) 58 | // Represents the bidirectional stream between the controller and the 59 | // switch (initiated by the controller), and is managed for the following 60 | // purposes: 61 | // - connection initiation through client arbitration 62 | // - indicating switch session liveness: the session is live when switch 63 | // sends a positive client arbitration update to the controller, and is 64 | // considered dead when either the stream breaks or the switch sends a 65 | // negative update for client arbitration 66 | // - the controller sending/receiving packets to/from the switch 67 | // - streaming of notifications from the switch 68 | StreamChannel(ctx context.Context, opts ...grpc.CallOption) (P4Runtime_StreamChannelClient, error) 69 | Capabilities(ctx context.Context, in *CapabilitiesRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error) 70 | } 71 | 72 | type p4RuntimeClient struct { 73 | cc grpc.ClientConnInterface 74 | } 75 | 76 | func NewP4RuntimeClient(cc grpc.ClientConnInterface) P4RuntimeClient { 77 | return &p4RuntimeClient{cc} 78 | } 79 | 80 | func (c *p4RuntimeClient) Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) { 81 | out := new(WriteResponse) 82 | err := c.cc.Invoke(ctx, P4Runtime_Write_FullMethodName, in, out, opts...) 83 | if err != nil { 84 | return nil, err 85 | } 86 | return out, nil 87 | } 88 | 89 | func (c *p4RuntimeClient) Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (P4Runtime_ReadClient, error) { 90 | stream, err := c.cc.NewStream(ctx, &P4Runtime_ServiceDesc.Streams[0], P4Runtime_Read_FullMethodName, opts...) 91 | if err != nil { 92 | return nil, err 93 | } 94 | x := &p4RuntimeReadClient{stream} 95 | if err := x.ClientStream.SendMsg(in); err != nil { 96 | return nil, err 97 | } 98 | if err := x.ClientStream.CloseSend(); err != nil { 99 | return nil, err 100 | } 101 | return x, nil 102 | } 103 | 104 | type P4Runtime_ReadClient interface { 105 | Recv() (*ReadResponse, error) 106 | grpc.ClientStream 107 | } 108 | 109 | type p4RuntimeReadClient struct { 110 | grpc.ClientStream 111 | } 112 | 113 | func (x *p4RuntimeReadClient) Recv() (*ReadResponse, error) { 114 | m := new(ReadResponse) 115 | if err := x.ClientStream.RecvMsg(m); err != nil { 116 | return nil, err 117 | } 118 | return m, nil 119 | } 120 | 121 | func (c *p4RuntimeClient) SetForwardingPipelineConfig(ctx context.Context, in *SetForwardingPipelineConfigRequest, opts ...grpc.CallOption) (*SetForwardingPipelineConfigResponse, error) { 122 | out := new(SetForwardingPipelineConfigResponse) 123 | err := c.cc.Invoke(ctx, P4Runtime_SetForwardingPipelineConfig_FullMethodName, in, out, opts...) 124 | if err != nil { 125 | return nil, err 126 | } 127 | return out, nil 128 | } 129 | 130 | func (c *p4RuntimeClient) GetForwardingPipelineConfig(ctx context.Context, in *GetForwardingPipelineConfigRequest, opts ...grpc.CallOption) (*GetForwardingPipelineConfigResponse, error) { 131 | out := new(GetForwardingPipelineConfigResponse) 132 | err := c.cc.Invoke(ctx, P4Runtime_GetForwardingPipelineConfig_FullMethodName, in, out, opts...) 133 | if err != nil { 134 | return nil, err 135 | } 136 | return out, nil 137 | } 138 | 139 | func (c *p4RuntimeClient) StreamChannel(ctx context.Context, opts ...grpc.CallOption) (P4Runtime_StreamChannelClient, error) { 140 | stream, err := c.cc.NewStream(ctx, &P4Runtime_ServiceDesc.Streams[1], P4Runtime_StreamChannel_FullMethodName, opts...) 141 | if err != nil { 142 | return nil, err 143 | } 144 | x := &p4RuntimeStreamChannelClient{stream} 145 | return x, nil 146 | } 147 | 148 | type P4Runtime_StreamChannelClient interface { 149 | Send(*StreamMessageRequest) error 150 | Recv() (*StreamMessageResponse, error) 151 | grpc.ClientStream 152 | } 153 | 154 | type p4RuntimeStreamChannelClient struct { 155 | grpc.ClientStream 156 | } 157 | 158 | func (x *p4RuntimeStreamChannelClient) Send(m *StreamMessageRequest) error { 159 | return x.ClientStream.SendMsg(m) 160 | } 161 | 162 | func (x *p4RuntimeStreamChannelClient) Recv() (*StreamMessageResponse, error) { 163 | m := new(StreamMessageResponse) 164 | if err := x.ClientStream.RecvMsg(m); err != nil { 165 | return nil, err 166 | } 167 | return m, nil 168 | } 169 | 170 | func (c *p4RuntimeClient) Capabilities(ctx context.Context, in *CapabilitiesRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error) { 171 | out := new(CapabilitiesResponse) 172 | err := c.cc.Invoke(ctx, P4Runtime_Capabilities_FullMethodName, in, out, opts...) 173 | if err != nil { 174 | return nil, err 175 | } 176 | return out, nil 177 | } 178 | 179 | // P4RuntimeServer is the server API for P4Runtime service. 180 | // All implementations must embed UnimplementedP4RuntimeServer 181 | // for forward compatibility 182 | type P4RuntimeServer interface { 183 | // Update one or more P4 entities on the target. 184 | Write(context.Context, *WriteRequest) (*WriteResponse, error) 185 | // Read one or more P4 entities from the target. 186 | Read(*ReadRequest, P4Runtime_ReadServer) error 187 | // Sets the P4 forwarding-pipeline config. 188 | SetForwardingPipelineConfig(context.Context, *SetForwardingPipelineConfigRequest) (*SetForwardingPipelineConfigResponse, error) 189 | // Gets the current P4 forwarding-pipeline config. 190 | GetForwardingPipelineConfig(context.Context, *GetForwardingPipelineConfigRequest) (*GetForwardingPipelineConfigResponse, error) 191 | // Represents the bidirectional stream between the controller and the 192 | // switch (initiated by the controller), and is managed for the following 193 | // purposes: 194 | // - connection initiation through client arbitration 195 | // - indicating switch session liveness: the session is live when switch 196 | // sends a positive client arbitration update to the controller, and is 197 | // considered dead when either the stream breaks or the switch sends a 198 | // negative update for client arbitration 199 | // - the controller sending/receiving packets to/from the switch 200 | // - streaming of notifications from the switch 201 | StreamChannel(P4Runtime_StreamChannelServer) error 202 | Capabilities(context.Context, *CapabilitiesRequest) (*CapabilitiesResponse, error) 203 | mustEmbedUnimplementedP4RuntimeServer() 204 | } 205 | 206 | // UnimplementedP4RuntimeServer must be embedded to have forward compatible implementations. 207 | type UnimplementedP4RuntimeServer struct { 208 | } 209 | 210 | func (UnimplementedP4RuntimeServer) Write(context.Context, *WriteRequest) (*WriteResponse, error) { 211 | return nil, status.Errorf(codes.Unimplemented, "method Write not implemented") 212 | } 213 | func (UnimplementedP4RuntimeServer) Read(*ReadRequest, P4Runtime_ReadServer) error { 214 | return status.Errorf(codes.Unimplemented, "method Read not implemented") 215 | } 216 | func (UnimplementedP4RuntimeServer) SetForwardingPipelineConfig(context.Context, *SetForwardingPipelineConfigRequest) (*SetForwardingPipelineConfigResponse, error) { 217 | return nil, status.Errorf(codes.Unimplemented, "method SetForwardingPipelineConfig not implemented") 218 | } 219 | func (UnimplementedP4RuntimeServer) GetForwardingPipelineConfig(context.Context, *GetForwardingPipelineConfigRequest) (*GetForwardingPipelineConfigResponse, error) { 220 | return nil, status.Errorf(codes.Unimplemented, "method GetForwardingPipelineConfig not implemented") 221 | } 222 | func (UnimplementedP4RuntimeServer) StreamChannel(P4Runtime_StreamChannelServer) error { 223 | return status.Errorf(codes.Unimplemented, "method StreamChannel not implemented") 224 | } 225 | func (UnimplementedP4RuntimeServer) Capabilities(context.Context, *CapabilitiesRequest) (*CapabilitiesResponse, error) { 226 | return nil, status.Errorf(codes.Unimplemented, "method Capabilities not implemented") 227 | } 228 | func (UnimplementedP4RuntimeServer) mustEmbedUnimplementedP4RuntimeServer() {} 229 | 230 | // UnsafeP4RuntimeServer may be embedded to opt out of forward compatibility for this service. 231 | // Use of this interface is not recommended, as added methods to P4RuntimeServer will 232 | // result in compilation errors. 233 | type UnsafeP4RuntimeServer interface { 234 | mustEmbedUnimplementedP4RuntimeServer() 235 | } 236 | 237 | func RegisterP4RuntimeServer(s grpc.ServiceRegistrar, srv P4RuntimeServer) { 238 | s.RegisterService(&P4Runtime_ServiceDesc, srv) 239 | } 240 | 241 | func _P4Runtime_Write_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 242 | in := new(WriteRequest) 243 | if err := dec(in); err != nil { 244 | return nil, err 245 | } 246 | if interceptor == nil { 247 | return srv.(P4RuntimeServer).Write(ctx, in) 248 | } 249 | info := &grpc.UnaryServerInfo{ 250 | Server: srv, 251 | FullMethod: P4Runtime_Write_FullMethodName, 252 | } 253 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 254 | return srv.(P4RuntimeServer).Write(ctx, req.(*WriteRequest)) 255 | } 256 | return interceptor(ctx, in, info, handler) 257 | } 258 | 259 | func _P4Runtime_Read_Handler(srv interface{}, stream grpc.ServerStream) error { 260 | m := new(ReadRequest) 261 | if err := stream.RecvMsg(m); err != nil { 262 | return err 263 | } 264 | return srv.(P4RuntimeServer).Read(m, &p4RuntimeReadServer{stream}) 265 | } 266 | 267 | type P4Runtime_ReadServer interface { 268 | Send(*ReadResponse) error 269 | grpc.ServerStream 270 | } 271 | 272 | type p4RuntimeReadServer struct { 273 | grpc.ServerStream 274 | } 275 | 276 | func (x *p4RuntimeReadServer) Send(m *ReadResponse) error { 277 | return x.ServerStream.SendMsg(m) 278 | } 279 | 280 | func _P4Runtime_SetForwardingPipelineConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 281 | in := new(SetForwardingPipelineConfigRequest) 282 | if err := dec(in); err != nil { 283 | return nil, err 284 | } 285 | if interceptor == nil { 286 | return srv.(P4RuntimeServer).SetForwardingPipelineConfig(ctx, in) 287 | } 288 | info := &grpc.UnaryServerInfo{ 289 | Server: srv, 290 | FullMethod: P4Runtime_SetForwardingPipelineConfig_FullMethodName, 291 | } 292 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 293 | return srv.(P4RuntimeServer).SetForwardingPipelineConfig(ctx, req.(*SetForwardingPipelineConfigRequest)) 294 | } 295 | return interceptor(ctx, in, info, handler) 296 | } 297 | 298 | func _P4Runtime_GetForwardingPipelineConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 299 | in := new(GetForwardingPipelineConfigRequest) 300 | if err := dec(in); err != nil { 301 | return nil, err 302 | } 303 | if interceptor == nil { 304 | return srv.(P4RuntimeServer).GetForwardingPipelineConfig(ctx, in) 305 | } 306 | info := &grpc.UnaryServerInfo{ 307 | Server: srv, 308 | FullMethod: P4Runtime_GetForwardingPipelineConfig_FullMethodName, 309 | } 310 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 311 | return srv.(P4RuntimeServer).GetForwardingPipelineConfig(ctx, req.(*GetForwardingPipelineConfigRequest)) 312 | } 313 | return interceptor(ctx, in, info, handler) 314 | } 315 | 316 | func _P4Runtime_StreamChannel_Handler(srv interface{}, stream grpc.ServerStream) error { 317 | return srv.(P4RuntimeServer).StreamChannel(&p4RuntimeStreamChannelServer{stream}) 318 | } 319 | 320 | type P4Runtime_StreamChannelServer interface { 321 | Send(*StreamMessageResponse) error 322 | Recv() (*StreamMessageRequest, error) 323 | grpc.ServerStream 324 | } 325 | 326 | type p4RuntimeStreamChannelServer struct { 327 | grpc.ServerStream 328 | } 329 | 330 | func (x *p4RuntimeStreamChannelServer) Send(m *StreamMessageResponse) error { 331 | return x.ServerStream.SendMsg(m) 332 | } 333 | 334 | func (x *p4RuntimeStreamChannelServer) Recv() (*StreamMessageRequest, error) { 335 | m := new(StreamMessageRequest) 336 | if err := x.ServerStream.RecvMsg(m); err != nil { 337 | return nil, err 338 | } 339 | return m, nil 340 | } 341 | 342 | func _P4Runtime_Capabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 343 | in := new(CapabilitiesRequest) 344 | if err := dec(in); err != nil { 345 | return nil, err 346 | } 347 | if interceptor == nil { 348 | return srv.(P4RuntimeServer).Capabilities(ctx, in) 349 | } 350 | info := &grpc.UnaryServerInfo{ 351 | Server: srv, 352 | FullMethod: P4Runtime_Capabilities_FullMethodName, 353 | } 354 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 355 | return srv.(P4RuntimeServer).Capabilities(ctx, req.(*CapabilitiesRequest)) 356 | } 357 | return interceptor(ctx, in, info, handler) 358 | } 359 | 360 | // P4Runtime_ServiceDesc is the grpc.ServiceDesc for P4Runtime service. 361 | // It's only intended for direct use with grpc.RegisterService, 362 | // and not to be introspected or modified (even as a copy) 363 | var P4Runtime_ServiceDesc = grpc.ServiceDesc{ 364 | ServiceName: "p4.v1.P4Runtime", 365 | HandlerType: (*P4RuntimeServer)(nil), 366 | Methods: []grpc.MethodDesc{ 367 | { 368 | MethodName: "Write", 369 | Handler: _P4Runtime_Write_Handler, 370 | }, 371 | { 372 | MethodName: "SetForwardingPipelineConfig", 373 | Handler: _P4Runtime_SetForwardingPipelineConfig_Handler, 374 | }, 375 | { 376 | MethodName: "GetForwardingPipelineConfig", 377 | Handler: _P4Runtime_GetForwardingPipelineConfig_Handler, 378 | }, 379 | { 380 | MethodName: "Capabilities", 381 | Handler: _P4Runtime_Capabilities_Handler, 382 | }, 383 | }, 384 | Streams: []grpc.StreamDesc{ 385 | { 386 | StreamName: "Read", 387 | Handler: _P4Runtime_Read_Handler, 388 | ServerStreams: true, 389 | }, 390 | { 391 | StreamName: "StreamChannel", 392 | Handler: _P4Runtime_StreamChannel_Handler, 393 | ServerStreams: true, 394 | ClientStreams: true, 395 | }, 396 | }, 397 | Metadata: "p4/v1/p4runtime.proto", 398 | } 399 | -------------------------------------------------------------------------------- /docs/v1/guidance-for-generating-p4info.md: -------------------------------------------------------------------------------- 1 | # Guidance for generating P4Info messages 2 | 3 | 4 | ## Recommendations for URIs in `p4runtime_translation` annotations 5 | 6 | For the use of P4Runtime major version 1 with the PSA architecture, 7 | all URIs for `p4runtime_translation` annotations defined in the psa.p4 8 | include file will be of this form: 9 | 10 | p4.org/psa/v1/ 11 | 12 | No other organization should use URIs beginning with `p4.org`. They 13 | are reserved for use by the `p4.org` organization. 14 | 15 | It is recommended that another organization that wishes to use the 16 | `p4runtime_translation` annotation for types defined in an 17 | architecture they create, other than PSA, will be of this form: 18 | 19 | // 20 | 21 | For example, `mycompany.com/our_arch/PortId`. The organization should 22 | document its rules for such URIs. 23 | 24 | For P4_16 `type` definitions for which P4Runtime translation is 25 | desired, where the `type` is not defined within an architecture, but 26 | in the user's P4 code, we recommend using a URI of this form: 27 | 28 | /// 29 | 30 | Where here the `domain_name` is that of the organization or individual 31 | who developed or owns the P4 program, and the `` element is 32 | optional. Again, the organization or individual should form and 33 | document a policy for how they form such URIs. For example, they may 34 | create libraries of P4 code containing widely used types and 35 | translations for them, and wish to include an element in the URI 36 | representing the name of the library, its major version, etc. 37 | 38 | 39 | ## Handling P4_16 `type` and the `p4runtime_translation` annotation 40 | 41 | The P4Runtime v1.4 specification restricts the types that it supports 42 | for the following kinds of things: 43 | 44 | + table search key fields, defined in the P4Info message in a 45 | `MatchField` message 46 | + fields of a `ValueSet`, also defined in the P4Info message in a 47 | `MatchField` message 48 | + parameters specified by the control plane for a table action, 49 | defined in the P4Info message in a `Param` message 50 | + metadata fields in a header sent from data plane to controller, or 51 | from controller to the data plane, defined in the P4Info message in 52 | a `Metadata` message (the `type_name` field was added to `Metadata` 53 | messages in P4Runtime version 1.1.0). 54 | 55 | Later in this section, we will use the term "constrained value" for 56 | brevity, instead of repeating all of the kinds of objects listed 57 | above. For such values, the P4Runtime specification v1.4 supports all 58 | of the following types, but currently no others: 59 | 60 | + `bit` 61 | + an `enum` with an underlying type of `bit`, also called a 62 | serializable `enum` (TBD whether all of the pieces needed to make 63 | this work are actually supported for P4Runtime 1.4) 64 | + a `typedef` or `type` name that, when "followed back" to the lowest 65 | base type, is one of the above. (As of the P4_16 language 66 | specification version 1.2.1, it is not required to support a `type` 67 | definition with a serializable `enum` as its base type. See 68 | [p4runtime issue 69 | #192](https://github.com/p4lang/p4runtime/issues/192).) 70 | 71 | P4Info `MatchField`, `Param`, and `Metadata` messages may optionally 72 | contain the following two fields: 73 | 74 | + `int32 bitwidth` 75 | + `P4NamedType type_name` 76 | 77 | Below we will describe what values these fields should have. 78 | 79 | Consider a single constrained value `x`. Create a list of types 80 | `type_list(x)` using the pseudocode shown below. 81 | 82 | ``` 83 | type_list(x) { 84 | tlist = []; // tlist initialized to empty list 85 | T = declared type of object x in the P4 program; 86 | while (true) { 87 | if (T is declared as "type B T") { 88 | tlist = tlist + [T]; // append T to end of tlist 89 | T = B; 90 | } else if (T is declared as "typedef B T") { 91 | T = B; 92 | } else { 93 | tlist = tlist + [T]; // append T to end of tlist 94 | return tlist; 95 | } 96 | } 97 | } 98 | ``` 99 | 100 | Note that `type_list(x)` always starts with zero or more `type` names, 101 | and always ends with one type that is neither a `type` nor `typedef` 102 | name, e.g. `bit`, a header type, struct type, etc. It never 103 | contains the name of a type declared using `typedef`. P4Runtime v1.4 104 | only supports `p4runtime_translation` annotations on `type` 105 | definitions. If any such annotations occur on a `typedef` definition, 106 | they should be ignored. 107 | 108 | The `p4c` compiler signals an error if you attempt to create a cycle 109 | of type names. In order to create such a cycle, the first `type` or 110 | `typedef` that appears in the program would have to refer to a later 111 | type name, and this is not allowed. 112 | 113 | If the last type is not `bit` or `enum bit`, that is an error 114 | for P4Runtime v1.4. The "base" type must always be one of those for 115 | every constrained value. 116 | 117 | 118 | ### `type_name` field 119 | 120 | Let `first_type` be the first element of the list `type_list(x)`. 121 | 122 | If `first_type` is a `type` name (i.e. not `bit` or `enum bit`), 123 | then the value of the P4Info `type_name` field should be `{name = 124 | "first_type_name"}`, where `first_type_name` is the name of 125 | `first_type`. 126 | 127 | Otherwise, the `type_name` field should be unset in the P4info 128 | message. 129 | 130 | 131 | ### `bitwidth` field 132 | 133 | If `first_type` is a `type` name, _and_ if the `type` definition for 134 | this type has a `p4runtime_translation(uri_string, )` annotation in 135 | the source code, then the P4Info `bitwidth` field should follow these 136 | rules: 137 | 138 | * if `` is `n`, where `n` is a positive integer, then the `bitwidth` 139 | field should be assigned the value `n` 140 | * if `` is `bit`, where `W` is a postive integer, then the 141 | `bitwidth` field should be assigned value `W` 142 | * if `` is `string`, then the `bitwidth` field should be unset 143 | (which in Protobuf version 3 is the same as setting it explicitly to 144 | 0) 145 | * all other cases for `` are illegal 146 | 147 | Otherwise, `bitwidth` should be equal to `W` where `bit` or `enum 148 | bit` is the last element of `type_list(x)`. 149 | 150 | Note that all type names that are present as the value of a 151 | `type_name` field anywhere in a P4Info message must contain an entry 152 | describing it in the `type_info` field of the P4Info message. Thus 153 | this `bitwidth` value could be considered redundant information, since 154 | it can be derived from the description of the type contained within 155 | the `type_info` field. However, it is considered worth keeping this 156 | small amount of redundancy for simplicity of interpreting the messages 157 | that contain these `bitwidth` fields, without having to find the value 158 | elsewhere in the P4Info message. 159 | 160 | 161 | ## Example 1: field with simple `bit` type 162 | 163 | ``` 164 | bit<10> f1; 165 | 166 | type_list(f1) -> [bit<10>] 167 | 168 | type_name: left unset in P4Info message 169 | bitwidth: 10 170 | ``` 171 | 172 | Based on the P4 code snippet above, there is no need to describe any 173 | type inside of the `type_info` field of the P4Info message, because 174 | there are no named types in this code. 175 | 176 | 177 | ## Example 2: field with a type defined via `type`, simplest possible case 178 | 179 | ``` 180 | type bit<7> MyCustomType_t; 181 | MyCustomType_t f2; 182 | 183 | type_list(f2) -> [MyCustomType_t, bit<7>] 184 | 185 | type_name: "MyCustomType_t" 186 | 187 | Reason: T2_t is the first type name in type_list(f2) 188 | 189 | bitwidth: 7 190 | 191 | Reason: Type MyCustomType_t is the first type name in 192 | type_list(f2), but it has no p4runtime_translation on it. Use the 193 | width 7 from bit<7>, the last element of type_list(f2). 194 | ``` 195 | 196 | Based on the P4 code snippet above (copied below for easy reference), 197 | the value below starting with `type_info {` should be in the P4Info 198 | message describing the program, because of the `type` definitions. 199 | 200 | ``` 201 | type bit<7> MyCustomType_t; 202 | MyCustomType_t f2; 203 | ``` 204 | 205 | ``` 206 | type_info { 207 | new_types { 208 | key: "MyCustomType_t" 209 | value { 210 | original_type { 211 | bitstring { 212 | bit { 213 | bitwidth: 7 214 | } 215 | } 216 | } 217 | } 218 | } 219 | } 220 | ``` 221 | 222 | Type `MyCustomType_t` is described via an `original_type` message, 223 | because the definition of `MyCustomType_t` in the program does not 224 | have a `p4runtime_translation` annotation. 225 | 226 | 227 | ## Example 3: field with a type defined via `type`, with no annotation 228 | 229 | It is not clear whether there are strong use cases for declaring a 230 | `type` based upon another `type` in a P4_16 program. However, 231 | currently the P4_16 language and `p4c` compiler allow it, so it seems 232 | to be a good idea to have predictable rules to follow for what the 233 | P4Info message contents should be, and how the resulting system should 234 | behave. 235 | 236 | The basic design described here tries to keep things fairly 237 | straightforward to explain and understand, if a P4_16 program does so. 238 | 239 | If a constrained value `f` has a `type` name as the first element of 240 | the list `type_list(f)`, then that type name is used for `f`, 241 | regardless of whether it has a `p4runtime_translation` annotation. 242 | 243 | In the absence of such an annotation on that `type`, no P4runtime 244 | translation is done for that type, _even if a later type in 245 | `type_list(x)` does have such an annotation_. 246 | 247 | Below is an example of a P4 code snippet that demonstrates one 248 | example, but I do _not_ claim that it is useful for any actual 249 | production P4 program to be written this way (until and unless some 250 | demonstrates a reason why it would be useful). 251 | 252 | ``` 253 | typedef bit<10> T1uint_t; 254 | @p4runtime_translation("mycompany.com/myco_p4lib/v1/T1_t", 32) 255 | type T1uint_t T1_t; 256 | type T1_t T2_t; 257 | T2_t f3; 258 | ``` 259 | 260 | Note that starting with P4Runtime v1.2.0, the following syntax for the 261 | `p4runtime_translation` is equivalent (and preferred): 262 | ``` 263 | @p4runtime_translation("mycompany.com/myco_p4lib/v1/T1_t", bit<32>) 264 | type T1uint_t T1_t; 265 | ``` 266 | 267 | ``` 268 | Execution trace for call to type_list(f3): 269 | tlist = [] 270 | T = declared type of object f3 in the P4 program = T2_t 271 | Evaluate condition (T2_t is declared as "type B T") -> true, 272 | because T2_t is declared as "type T1_t T2_t" 273 | tlist = tlist + [T] -> tlist=[T2_t] 274 | T = B = T1_t 275 | Evaluate condition (T1_t is declared as "type B T") -> true, 276 | because T1_t is declared as "type T1uint_t T1_t" 277 | tlist = tlist + [T] -> tlist=[T2_t, T1_t] 278 | T = B = T1uint_t 279 | Evaluate condition (T1uint_t is declared as "type B T") -> false 280 | Evaluate condition (T1uint_t is declared as "typedef B T") -> true, 281 | because T1uint_t is declared as "typedef bit<10> T1uint_t" 282 | T = B = bit<10> 283 | Evaluate condition (bit<10> is declared as "type B T") -> false 284 | Evaluate condition (bit<10> is declared as "typedef B T") -> false 285 | tlist = tlist + [T] -> tlist=[T2_t, T1_t, bit<10>] 286 | return tlist 287 | 288 | type_list(f3) -> [T2_t, T1_t, bit<10>] 289 | 290 | type_name: "T2_t" 291 | 292 | Reason: T2_t is the first type name in type_list(f3) 293 | 294 | bitwidth: 10 295 | 296 | Reason: Type T2_t is the first type name in type_list(f3), but it 297 | has no p4runtime_translation on it, so even though T1_t does, that 298 | is ignored. Use the width 10 from bit<10>, the last element of 299 | type_list(f3). 300 | ``` 301 | 302 | Based on the P4 code snippet above (copied below for easy reference), 303 | the value below starting with `type_info {` should be in the P4Info 304 | message describing the program, because of the `type` definitions. 305 | There is never anything put into a P4Info message because of `typedef` 306 | definitions in a P4 program. 307 | 308 | Note that the bit width of 10 appears in the P4Info message for any 309 | `type`s "built on top of" a `bit<10>`, _unless that type has its own 310 | `p4runtime_translation` annotation_. 311 | 312 | ``` 313 | typedef bit<10> T1uint_t; 314 | @p4runtime_translation("mycompany.com/myco_p4lib/v1/T1_t", 32) 315 | type T1uint_t T1_t; 316 | type T1_t T2_t; 317 | T2_t f3; 318 | ``` 319 | 320 | ``` 321 | type_info { 322 | new_types { 323 | key: "T2_t" 324 | value { 325 | original_type { 326 | bitstring { 327 | bit { 328 | bitwidth: 10 329 | } 330 | } 331 | } 332 | } 333 | } 334 | } 335 | ``` 336 | 337 | Type `T2_t` is described via an `original_type` message, because the 338 | definition of `T2_t` in the program, `type T1_t T2_t`, does not have a 339 | `p4runtime_translation` annotation. 340 | 341 | Based on the P4 code snippet above, there is no reason to include a 342 | description for the type `T1_t` in the P4Info message. If there were 343 | some other variable other than `f3` in the program declared with type 344 | `T1_t`, and that variable caused the type name `T1_t` to be included 345 | in the P4Info message, then the following description for type `T1_t` 346 | must be included in the `type_info` field. 347 | 348 | ``` 349 | type_info { 350 | new_types { 351 | key: "T1_t" 352 | value { 353 | translated_type { 354 | uri: "mycompany.com/myco_p4lib/v1/T1_t" 355 | sdn_bitwidth: 32 356 | } 357 | } 358 | } 359 | } 360 | ``` 361 | 362 | Type `T1_t` is described via a `translated_type` message, because the 363 | definition of `T1_t` in the program, `type T1uint T1_t`, has a 364 | `p4runtime_translation` annotation. 365 | 366 | 367 | ## Example 4: field with a type defined via `type`, with `p4runtime_translation` annotation 368 | 369 | This example is very similar to Example 3, except that all three `type` 370 | definitions have a `p4runtime_translation` annotation. 371 | 372 | ``` 373 | @p4runtime_translation("mycompany.com/myco_p4lib/v1/T1_t", 32) 374 | type bit<10> T1_t; 375 | @p4runtime_translation("mycompany.com/myco_p4lib/v1/T2_t", 18) 376 | type T1_t T2_t; 377 | T2_t f4; 378 | 379 | type_list(f4) -> [T2_t, T1_t, bit<10>] 380 | 381 | type_name: "T2_t" 382 | 383 | Reason: T2_t is the first type name in type_list(f4) 384 | 385 | bitwidth: 18 386 | 387 | Reason: Type T2_t is the first type name in type_list(f4), and it 388 | has a p4runtime_translation annotation on it. Use the width 18 389 | that is the second parameter of that annotation. 390 | ``` 391 | 392 | The contents of the `type_info` field of the P4Info message should be 393 | as follows. For the code snippet above, there is no reason to include 394 | a description of the type `T1_t`. The description of type `T1_t` is 395 | shown below for the sake of an example, but it only needs to be 396 | included in the P4Info message if there is a reference to type `T1_t` 397 | somewhere in the P4Info message. 398 | 399 | ``` 400 | type_info { 401 | new_types { 402 | key: "T1_t" 403 | value { 404 | translated_type { 405 | uri: "mycompany.com/myco_p4lib/v1/T1_t" 406 | sdn_bitwidth: 32 407 | } 408 | } 409 | } 410 | new_types { 411 | key: "T2_t" 412 | value { 413 | translated_type { 414 | uri: "mycompany.com/myco_p4lib/v1/T2_t" 415 | sdn_bitwidth: 18 416 | } 417 | } 418 | } 419 | } 420 | ``` 421 | 422 | Note that both types `T1_t` and `T2_t` are described via 423 | `translated_type` messages, because they both have a 424 | `p4runtime_translation` annotation. 425 | 426 | 427 | ## Example 5: field with serializable `enum` type 428 | 429 | See [p4runtime issue 430 | #192](https://github.com/p4lang/p4runtime/issues/192). 431 | 432 | ``` 433 | enum bit<10> enum1_t { 434 | A = 1, 435 | B = 2 436 | } 437 | 438 | enum1_t f5; 439 | 440 | type_list(f1) -> [enum1_t] 441 | 442 | type_name: see discussion below 443 | bitwidth: 10 444 | ``` 445 | 446 | It seems pretty clear that `bitwidth` should be 10 bits for field 447 | `f5`. 448 | 449 | However, what about `type_name`? 450 | 451 | Should `type_name` be unset? If so, there is the disadvantage that 452 | the control plane software has no indication that field `f5` is of 453 | type `enum1_t`. As far as it could tell from the P4Info message, it 454 | is declared as type `bit<10>`. This is not necessarily a fatal flaw, 455 | but it is a loss of potentially useful information in the P4Info 456 | message. 457 | 458 | Should `type_name` be `"enum1_t"`, and then `"enum1_t"` should be 459 | described within the `type_info` field of the message? 460 | 461 | As of early June 2020, `p4c` does not support users defining their 462 | own `type` definitions with a serializable `enum` like `enum1_t` as 463 | the base type. The disadvantage with this situation is that there is 464 | no way to define a serializable `enum` type for a constrained value, 465 | and also have `p4runtime_translation` annotated on a `type` with the 466 | serializable `enum` as its underlying type. 467 | 468 | If `p4c` ever does support defining a `type` with a serializable 469 | `enum` as its underlying type, with an optional 470 | `p4runtime_translation` annotation, then we should think about how 471 | that should be represented in a P4Info message, and add an example of 472 | it here. 473 | -------------------------------------------------------------------------------- /proto/p4/config/v1/p4info.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2013-present Barefoot Networks, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | import "google/protobuf/any.proto"; 18 | import "p4/config/v1/p4types.proto"; 19 | 20 | // This package and its contents are a work-in-progress. 21 | 22 | package p4.config.v1; 23 | 24 | option go_package = "github.com/p4lang/p4runtime/go/p4/config/v1"; 25 | 26 | message P4Info { 27 | PkgInfo pkg_info = 1; 28 | repeated Table tables = 2; 29 | repeated Action actions = 3; 30 | repeated ActionProfile action_profiles = 4; 31 | repeated Counter counters = 5; 32 | repeated DirectCounter direct_counters = 6; 33 | repeated Meter meters = 7; 34 | repeated DirectMeter direct_meters = 8; 35 | repeated ControllerPacketMetadata controller_packet_metadata = 9; 36 | repeated ValueSet value_sets = 10; 37 | repeated Register registers = 11; 38 | repeated Digest digests = 12; 39 | repeated Extern externs = 100; 40 | P4TypeInfo type_info = 200; 41 | } 42 | 43 | message Documentation { 44 | // A brief description of something, e.g. one sentence 45 | string brief = 1; 46 | // A more verbose description of something. Multiline is accepted. Markup 47 | // format (if any) is TBD. 48 | string description = 2; 49 | } 50 | 51 | // Used to describe the required properties of the underlying platform. 52 | // Added in v1.4.0 53 | message PlatformProperties { 54 | // The minimum number of multicast entries (i.e. multicast groups) that the 55 | // platform is required to support. If 0, there are no requirements. 56 | int32 multicast_group_table_size = 1; 57 | // The minimum number of replicas that the platform is required to support 58 | // across all groups. If 0, there are no requirements. 59 | int32 multicast_group_table_total_replicas = 2; 60 | // The number of replicas that the platform is required to support per 61 | // group/entry. If 0, `multicast_group_table_total_replicas` should be used. 62 | // Must be no larger than `multicast_group_table_total_replicas`. 63 | int32 multicast_group_table_max_replicas_per_entry = 3; 64 | } 65 | 66 | // Top-level package documentation describing the forwarding pipeline config 67 | // Can be used to manage multiple P4 packages. 68 | message PkgInfo { 69 | // a definitive name for this configuration, e.g. switch.p4_v1.0 70 | string name = 1; 71 | // configuration version, free-format string 72 | string version = 2; 73 | // brief and detailed descriptions 74 | Documentation doc = 3; 75 | // Miscellaneous metadata, free-form; a way to extend PkgInfo 76 | repeated string annotations = 4; 77 | // Optional. If present, the location of `annotations[i]` is given by 78 | // `annotation_locations[i]`. 79 | repeated SourceLocation annotation_locations = 10; 80 | // the target architecture, e.g. "psa" 81 | string arch = 5; 82 | // organization which produced the configuration, e.g. "p4.org" 83 | string organization = 6; 84 | // contact info for support,e.g. "tech-support@acme.org" 85 | string contact = 7; 86 | // url for more information, e.g. 87 | // "http://support.p4.org/ref/p4/switch.p4_v1.0" 88 | string url = 8; 89 | // Miscellaneous metadata, structured; a way to extend PkgInfo 90 | repeated StructuredAnnotation structured_annotations = 9; 91 | // If set, specifies the properties that the underlying platform should have. 92 | // If the platform does not conform to these properties, the server should 93 | // reject the P4Info when used with a SetForwardingPipelineConfigRequest. 94 | // Added in 1.4.0 95 | PlatformProperties platform_properties = 11; 96 | } 97 | 98 | // wrapping the enum in a message to avoid name collisions in C++, where "enum 99 | // values are siblings of their type, not children of it" 100 | message P4Ids { 101 | // ids are allocated in such a way that it is possible based on an id to 102 | // deduce the resource type (e.g. table, action, counter, ...). The 103 | // most-significant byte of the 32-bit id encodes the resource type. The 104 | // purpose of this enum is to define which value is used as the 105 | // most-significant byte for each resource type. The P4 compiler must use 106 | // these values when allocating ids for P4 objects. Other users of P4Info can 107 | // refer to this enum to identify a resource type based on its id. 108 | enum Prefix { 109 | UNSPECIFIED = 0; 110 | 111 | // P4 language built-ins 112 | ACTION = 0x01; 113 | TABLE = 0x02; 114 | VALUE_SET = 0x03; 115 | CONTROLLER_HEADER = 0x04; 116 | 117 | // PSA externs 118 | PSA_EXTERNS_START = 0x10; 119 | ACTION_PROFILE = 0x11; 120 | COUNTER = 0x12; 121 | DIRECT_COUNTER = 0x13; 122 | METER = 0x14; 123 | DIRECT_METER = 0x15; 124 | REGISTER = 0x16; 125 | DIGEST = 0x17; 126 | 127 | // externs for other architectures (vendor extensions) 128 | OTHER_EXTERNS_START = 0x80; 129 | 130 | // max value for an unsigned 8-bit byte 131 | MAX = 0xff; 132 | // requires protoc >= 3.5.0 133 | // reserved 0x100 to max; 134 | } 135 | } 136 | 137 | message Preamble { 138 | // ids share the same number-space; e.g. table ids cannot overlap with counter 139 | // ids. Even though this is irrelevant to this proto definition, the ids are 140 | // allocated in such a way that it is possible based on an id to deduce the 141 | // resource type (e.g. table, action, counter, ...). This means that code 142 | // using these ids can detect if the wrong resource type is used 143 | // somewhere. This also means that ids of different types can be mixed 144 | // (e.g. direct resource list for a table) without ambiguity. Note that id 0 145 | // is reserved and means "invalid id". 146 | uint32 id = 1; 147 | // fully qualified name of the P4 object, e.g. c1.c2.ipv4_lpm 148 | string name = 2; 149 | // an alias (alternative name) for the P4 object, probably shorter than its 150 | // fully qualified name. The only constraint is for it to be unique with 151 | // respect to other P4 objects of the same type. By default, the compiler uses 152 | // the shortest suffix of the name that uniquely identifies the object. For 153 | // example if the P4 program contains two tables with names s.c1.t and s.c2.t, 154 | // the default aliases will respectively be c1.t and c2.t. In the future, the 155 | // P4 programmer may also be able to override the default alias for any P4 156 | // object (TBD). 157 | string alias = 3; 158 | repeated string annotations = 4; 159 | // Optional. If present, the location of `annotations[i]` is given by 160 | // `annotation_locations[i]`. 161 | repeated SourceLocation annotation_locations = 7; 162 | // Documentation of the entity 163 | Documentation doc = 5; 164 | repeated StructuredAnnotation structured_annotations = 6; 165 | } 166 | 167 | // used to group all extern instances of the same type in one message 168 | message Extern { 169 | // the extern_type_id is unique for a given architecture and must be in the 170 | // range [0x81, 0xfe]. 171 | uint32 extern_type_id = 1; 172 | string extern_type_name = 2; 173 | repeated ExternInstance instances = 3; 174 | } 175 | 176 | message ExternInstance { 177 | Preamble preamble = 1; 178 | // specific to the extern type, declared in a separate vendor-specific proto 179 | // file 180 | google.protobuf.Any info = 2; 181 | } 182 | 183 | message MatchField { 184 | uint32 id = 1; 185 | string name = 2; 186 | repeated string annotations = 3; 187 | // Optional. If present, the location of `annotations[i]` is given by 188 | // `annotation_locations[i]`. 189 | repeated SourceLocation annotation_locations = 10; 190 | int32 bitwidth = 4; 191 | enum MatchType { 192 | UNSPECIFIED = 0; 193 | EXACT = 2; 194 | LPM = 3; 195 | TERNARY = 4; 196 | RANGE = 5; 197 | OPTIONAL = 6; 198 | } 199 | oneof match { 200 | MatchType match_type = 5; 201 | // used for architecture-specific match types which are not part of the core 202 | // P4 language or of the PSA architecture. 203 | string other_match_type = 7; 204 | } 205 | // Documentation of the match field 206 | Documentation doc = 6; 207 | // unset if not user-defined type 208 | P4NamedType type_name = 8; 209 | repeated StructuredAnnotation structured_annotations = 9; 210 | } 211 | 212 | // A TableActionCall references a particular action id and executes the 213 | // action with the supplied list of arguments. 214 | // Arguments are matched to the id of the respective action parameter. 215 | // TableActionCalls may be used as the default action call of a table implementation. 216 | // Added in 1.4.0. 217 | message TableActionCall { 218 | uint32 action_id = 1; 219 | message Argument { 220 | uint32 param_id = 2; 221 | bytes value = 3; 222 | } 223 | repeated Argument arguments = 4; 224 | } 225 | 226 | message Table { 227 | Preamble preamble = 1; 228 | repeated MatchField match_fields = 2; 229 | // even when the table is indirect (see implementation_id) below, this field 230 | // includes all possible actions for the table; by using ActionRef instead of 231 | // a repeated field of action ids, each action reference in a P4 table is able 232 | // to have its own annotations 233 | repeated ActionRef action_refs = 3; 234 | // 0 (default value) means that the table does not have a const default action 235 | uint32 const_default_action_id = 4; 236 | // The initial default action of the table. This can be overridden at runtime. 237 | // Added in 1.4.0. 238 | TableActionCall initial_default_action = 5; 239 | // P4 id of the "implementation" for this table (e.g. action profile id); 0 240 | // (default value) means that the table is a regular (direct) match table. As 241 | // of today, only action profiles are supported but other table 242 | // implementations may be added in the future 243 | uint32 implementation_id = 6; 244 | // ids of the direct resources (if any) attached to this table; for now this 245 | // includes only direct counters and direct meters, but other resources may be 246 | // added in the future 247 | repeated uint32 direct_resource_ids = 7; 248 | int64 size = 8; // max number of entries in table 249 | // this enum can be extended in the future with other behaviors, such as 250 | // "HARD_EVICTION" 251 | enum IdleTimeoutBehavior { 252 | NO_TIMEOUT = 0; 253 | NOTIFY_CONTROL = 1; 254 | } 255 | // is idle timeout supported for this table? 256 | IdleTimeoutBehavior idle_timeout_behavior = 9; 257 | // True if and only if the table's entries are immutable, 258 | // i.e. defined using the 'const entries' table property in the P4 259 | // source code, and thus entries cannot be deleted, modified, or 260 | // inserted at run time. 261 | bool is_const_table = 10; 262 | // True if and only if the table has initial entries defined using 263 | // the 'entries' table property in the P4 source code, either with 264 | // or without the 'const' qualifier on 'entries', and there is at 265 | // least one entry in that list. This field is false if the list of 266 | // entries is empty in the P4 source code. 267 | // Added in 1.4.0. 268 | bool has_initial_entries = 11; 269 | // architecture-specific table properties which are not part of the core P4 270 | // language or of the PSA architecture. 271 | google.protobuf.Any other_properties = 100; 272 | } 273 | 274 | // used to list all possible actions in a Table 275 | message ActionRef { 276 | uint32 id = 1; 277 | enum Scope { 278 | TABLE_AND_DEFAULT = 0; 279 | TABLE_ONLY = 1; 280 | DEFAULT_ONLY = 2; 281 | } 282 | Scope scope = 3; 283 | repeated string annotations = 2; 284 | // Optional. If present, the location of `annotations[i]` is given by 285 | // `annotation_locations[i]`. 286 | repeated SourceLocation annotation_locations = 5; 287 | repeated StructuredAnnotation structured_annotations = 4; 288 | } 289 | 290 | message Action { 291 | Preamble preamble = 1; 292 | message Param { 293 | uint32 id = 1; 294 | string name = 2; 295 | repeated string annotations = 3; 296 | // Optional. If present, the location of `annotations[i]` is given by 297 | // `annotation_locations[i]`. 298 | repeated SourceLocation annotation_locations = 8; 299 | int32 bitwidth = 4; 300 | // Documentation of the Param. 301 | Documentation doc = 5; 302 | // unset if not user-defined type. 303 | P4NamedType type_name = 6; 304 | repeated StructuredAnnotation structured_annotations = 7; 305 | } 306 | repeated Param params = 2; 307 | } 308 | 309 | message ActionProfile { 310 | Preamble preamble = 1; 311 | // the ids of the tables sharing this action profile 312 | repeated uint32 table_ids = 2; 313 | // true iff the action profile used dynamic selection 314 | bool with_selector = 3; 315 | // max number of member entries across all groups if the action profile does 316 | // not have a selector. Otherwise, semantics as specified by 317 | // `selector_size_semantics` below. 318 | int64 size = 4; 319 | // 0 if the action profile does not have a selector. Otherwise, semantics as 320 | // specified by `selector_size_semantics` below. 321 | int32 max_group_size = 5; 322 | 323 | // indicates that `size` and `max_group_size` represent the maximum sum of 324 | // weights that can be present across all selector groups and within a 325 | // single selector group respectively. 326 | // Added in v1.4.0. 327 | message SumOfWeights {} 328 | 329 | // indicates that `size` and `max_group_size` represent the maximum number 330 | // of members that can be present across all selector groups and within a 331 | // single selector group respectively. 332 | // Added in v1.4.0. 333 | message SumOfMembers { 334 | // the maximum weight of each individual member in a group. 335 | int32 max_member_weight = 1; 336 | } 337 | 338 | // specifies the semantics of `size` and `max_group_size` above. 339 | oneof selector_size_semantics { 340 | // group size is the sum of the group's weights. 341 | // Added in v1.4.0. 342 | SumOfWeights sum_of_weights = 6; 343 | // group size is the sum of the group's members. 344 | // Added in v1.4.0. 345 | SumOfMembers sum_of_members = 7; 346 | } 347 | 348 | // Dictates whether the controller can specify weights for groups programmed 349 | // in this ActionProfile. If `weights_disallowed` is true, then all weights 350 | // must be absent. Unset (false) in action profiles without selectors. 351 | // Added in v1.5.0. 352 | bool weights_disallowed = 8; 353 | } 354 | 355 | message CounterSpec { 356 | // Corresponds to 'type' constructor parameter for Counter / DirectCounter in 357 | // PSA 358 | enum Unit { 359 | UNSPECIFIED = 0; 360 | BYTES = 1; 361 | PACKETS = 2; 362 | BOTH = 3; 363 | } 364 | Unit unit = 1; 365 | } 366 | 367 | message Counter { 368 | Preamble preamble = 1; 369 | CounterSpec spec = 2; 370 | // number of entries in the counter array 371 | int64 size = 3; 372 | // unset if index is not user-defined type 373 | P4NamedType index_type_name = 4; 374 | } 375 | 376 | message DirectCounter { 377 | Preamble preamble = 1; 378 | CounterSpec spec = 2; 379 | // the id of the table to which the counter is attached 380 | uint32 direct_table_id = 3; 381 | } 382 | 383 | message MeterSpec { 384 | // Corresponds to 'type' constructor parameter for Meter / DirectMeter in PSA 385 | enum Unit { 386 | UNSPECIFIED = 0; 387 | BYTES = 1; 388 | PACKETS = 2; 389 | } 390 | // Used to restrict the MeterConfigs that can be used to instantiate the 391 | // meter. 392 | // Added in 1.4.0. 393 | enum Type { 394 | // As described in RFC 2698, allows meters to use two rates to split packets 395 | // into three potential colors. 396 | // MeterConfigs on table entries using this meter type MUST have `eburst == 397 | // 0` (i.e. unset). 398 | TWO_RATE_THREE_COLOR = 0; 399 | // As described in RFC 2697, allows meters to use one rate with an Excess 400 | // Burst Size (EBS) to split packets into three potential colors. 401 | // MeterConfigs on table entries using this meter type MUST have 402 | // `cir == pir && cburst == pburst`. 403 | SINGLE_RATE_THREE_COLOR = 1; 404 | // A simplified version of RFC 2697, restricting meters to using a single 405 | // rate to split packets into only RED or GREEN, by not providing an Excess 406 | // Burst Size (EBS). 407 | // MeterConfigs on table entries using this meter type MUST have 408 | // `cir == pir && cburst == pburst && eburst == 0` (i.e. unset). 409 | SINGLE_RATE_TWO_COLOR = 2; 410 | } 411 | Unit unit = 1; 412 | // Added in 1.4.0. 413 | Type type = 2; 414 | } 415 | 416 | message Meter { 417 | Preamble preamble = 1; 418 | MeterSpec spec = 2; 419 | // number of entries in the meter array 420 | int64 size = 3; 421 | // unset if index is not user-defined type 422 | P4NamedType index_type_name = 4; 423 | } 424 | 425 | message DirectMeter { 426 | Preamble preamble = 1; 427 | MeterSpec spec = 2; 428 | // the id of the table to which the meter is attached 429 | uint32 direct_table_id = 3; 430 | } 431 | 432 | // Any metadata associated with controller Packet-IO (Packet-In or Packet-Out) 433 | // is modeled as P4 headers carrying special annotations 434 | // @controller_header("packet_out") and @controller_header("packet_in") 435 | // respectively. There can be at most one header each with these annotations. 436 | // This message captures the info contained within these special headers, 437 | // and used in p4runtime.proto to supply the metadata. 438 | message ControllerPacketMetadata { 439 | // preamble.name and preamble.id will specify header type ("packet_out" or 440 | // "packet_in" for now). 441 | Preamble preamble = 1; 442 | message Metadata { 443 | uint32 id = 1; 444 | // This is the name of the header field (not fully-qualified), similar 445 | // to e.g. Action.Param.name. 446 | string name = 2; 447 | repeated string annotations = 3; 448 | // Optional. If present, the location of `annotations[i]` is given by 449 | // `annotation_locations[i]`. 450 | repeated SourceLocation annotation_locations = 7; 451 | int32 bitwidth = 4; 452 | // unset if not user-defined type 453 | P4NamedType type_name = 5; 454 | repeated StructuredAnnotation structured_annotations = 6; 455 | } 456 | // Ordered based on header layout. 457 | // This is a constraint on the generator of this P4Info. 458 | repeated Metadata metadata = 2; 459 | } 460 | 461 | message ValueSet { 462 | Preamble preamble = 1; 463 | repeated MatchField match = 2; 464 | // number of entries in the value_set, as per the P4 constructor call. 465 | int32 size = 3; 466 | } 467 | 468 | message Register { 469 | Preamble preamble = 1; 470 | P4DataTypeSpec type_spec = 2; 471 | int32 size = 3; 472 | // unset if index is not user-defined type 473 | P4NamedType index_type_name = 4; 474 | } 475 | 476 | message Digest { 477 | Preamble preamble = 1; 478 | P4DataTypeSpec type_spec = 2; 479 | } 480 | --------------------------------------------------------------------------------