{"id":19454579,"url":"https://github.com/p4lang/p4-constraints","last_synced_at":"2026-03-11T22:10:42.969Z","repository":{"id":43286479,"uuid":"237127631","full_name":"p4lang/p4-constraints","owner":"p4lang","description":"Constraints on P4 objects enforced at runtime","archived":false,"fork":false,"pushed_at":"2025-04-15T23:58:33.000Z","size":969,"stargazers_count":16,"open_issues_count":9,"forks_count":15,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-04-25T02:11:57.059Z","etag":null,"topics":["p4","p4runtime"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/p4lang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-01-30T02:54:49.000Z","updated_at":"2025-04-15T23:58:36.000Z","dependencies_parsed_at":"2023-10-04T22:20:28.631Z","dependency_job_id":"40339cb6-cc21-4307-800b-6be2383a85ba","html_url":"https://github.com/p4lang/p4-constraints","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p4lang%2Fp4-constraints","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p4lang%2Fp4-constraints/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p4lang%2Fp4-constraints/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p4lang%2Fp4-constraints/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/p4lang","download_url":"https://codeload.github.com/p4lang/p4-constraints/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250760550,"owners_count":21482826,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["p4","p4runtime"],"created_at":"2024-11-10T17:10:16.974Z","updated_at":"2026-03-11T22:10:42.963Z","avatar_url":"https://github.com/p4lang.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"![native build \u0026 test](https://github.com/p4lang/p4-constraints/workflows/native%20build%20\u0026%20test/badge.svg)\n\n# p4-constraints\n\np4-constraints extends the [P4 language](https://p4.org/) with support for\nconstraint\n[annotations](https://p4.org/p4-spec/docs/P4-16-v1.2.0.html#sec-annotations).\nThese constraints can be enforced at runtime using the p4-constraints library.\n\nThe project currently provides two main artifacts:\n\n1. A [C++ library](p4_constraints/) for parsing and checking constraints.\n2. A [command line interface (CLI)](p4_constraints/cli) that takes as input a P4\n   program with constraints and a set of table entries, and reports if the table\n   entries satisfy the constraints placed on their respective tables or not.\n   (Note that the CLI is intended for testing and experimentation, not for\n   production use.)\n   \n**_Check out [these slides](docs/2020-08-17_LDWG.pdf) for a tour of p4-constraints (up to date as of May 2020)._**\n\n## Example - Entry Restrictions\n\nAn *entry restriction* is a constraint specifying what entries are allowed to be\nplaced in a P4 table. Here is an example:\n```p4\n@entry_restriction(\"\n  // Only match on IPv4 addresses of IPv4 packets.\n  hdr.ipv4.dst_addr::mask != 0 -\u003e\n    hdr.ethernet.ether_type == IPv4_ETHER_TYPE;\n\n  // Only match on IPv6 addresses of IPv6 packets.\n  hdr.ipv6.dst_addr::mask != 0 -\u003e\n    hdr.ethernet.ether_type == IPv6_ETHER_TYPE;\n\n  // Either wildcard or exact match (i.e., \"optional\" match).\n  hdr.ipv4.dst_addr::mask == 0 || hdr.ipv4.dst_addr::mask == -1;\n\")\ntable acl_table {\n  key = {\n    hdr.ethernet.ether_type : ternary;\n    hdr.ethernet.src_addr : ternary;\n    hdr.ipv4.dst_addr : ternary;\n    standard_metadata.ingress_port: ternary;\n    hdr.ipv6.dst_addr : ternary;\n    hdr.ipv4.src_addr : ternary;\n    local_metadata.dscp : ternary;\n    local_metadata.is_ip_packet : ternary;\n  }\n  actions = { ... }\n}\n```\nThe `@entry_restriction` says that a valid ACL table entry must meet\nthree requirements:\n\n1. It can only match on the IPv4 destination address of IPv4 packets.\n2. It can only match on the IPv6 destination address of IPv6 packets.\n3. It can only perform a wildcard or an exact match on the IPv4 address.\n\nThe first two requirements are to rule out undefined behavior. The third\nrequirement captures the intent of the P4 programmer that the ACL table\nshould not require general ternary matches on the destination address; the\nconstraint documents this intent and let's us catch accidental ternary matches\ninstalled by the control plane at runtime.\n\n## Example - Action Restrictions\n\nAn *action restriction* is similar to an entry restriction, but is placed on a\nP4 action:\n```p4\n// Disallow multicast group ID 0, since it indicates \"no multicast\" in \n// `v1model.p4`.\n@action_restriction(\"multicast_group_id != 0\")\naction multicast(bit\u003c16\u003e multicast_group_id) {\n  standard_metadata.mcast_grp = multicast_group_id;\n}\n```\n\n## API\n\nAt a high level, p4-constraint's API consists of only two functions:\none function for parsing constraints and one function for checking them.\n```C++\n/* p4_constraints/backend/constraint_info.h */\n\n// Translates `P4Info` to `ConstraintInfo`.\n//\n// Parses all tables and actions and their p4-constraints annotations into an\n// in-memory representation suitable for constraint checking. Returns parsed\n// representation, or an error status if parsing fails.\nabsl::StatusOr\u003cConstraintInfo\u003e P4ToConstraintInfo(\n    const p4::config::v1::P4Info \u0026p4info);\n```\n```C++\n/* p4_constraints/backend/interpreter.h */\n\n// Checks if a given table entry satisfies the constraints attached to its\n// associated table/action.\n//\n// Returns the empty string if this is the case, or a human-readable nonempty\n// string explaining why it is not the case otherwise. Returns an\n// `InvalidArgument` if the entry's table or action is not defined in\n// `ConstraintInfo`, or if `entry` is inconsistent with these definitions.\nabsl::StatusOr\u003cstd::string\u003e ReasonEntryViolatesConstraint(\n    const p4::v1::TableEntry\u0026 entry, const ConstraintInfo\u0026 constraint_info);\n```\nFor those who seek more fine-grained control, the API also offers more\nlow-level functions that are documented in the various header files.\n\n## Use cases\n\np4-constraints can be used as follows:\n\n- As a specification language to further clarify the control plane API.\n- In P4Runtime server implementations to reject ill-formed table entries.\n- In the controller as a defense-in-depth check.\n- During testing to check for valid vs invalid table entries.\n  - To guide a fuzzer to valid table entries.\n\n## Building\n\nBuilding p4-constraints requires [Bazel](https://bazel.build/) 7.6 or newer\nwith Bzlmod enabled and a C++20 compiler.\n\nWe inherit a few additional dependencies\n([Bison](https://en.wikipedia.org/wiki/GNU_Bison) and\n[Flex](https://en.wikipedia.org/wiki/Flex_\\(lexical_analyser_generator\\)))\nfrom [p4c](https://github.com/p4lang/p4c); these are required for\n[golden testing](#golden-tests) only and can be installed on Ubuntu as follows:\n```sh\napt-get install bison flex libfl-dev\n```\n\nTo build, run\n```sh\nbazel build //p4_constraints/...\n```\n\nTo run all tests except [golden tests](#golden-tests), run\n```sh\nbazel test //p4_constraints/...\n```\n\nTo run all tests including [golden tests](#golden-tests), run\n```sh\nbazel test //...\n```\nThis may take a while when executed for the first time,\nas it will build p4c from source.\n\nTo see the output of a failed test, invoke it using `bazel run` like so:\n```sh\nbazel run //p4_constraints/frontend:lexer_test\n```\n\n### MacOS\n\nWhile building under MacOS is not officially supported, it currently works with\nApple Command Line Tools installed. The checked-in `.bazelrc` already selects\nthe system Clang toolchain and sets the macOS deployment target needed by\n`std::filesystem`.\n\n### Docker\n\nYou can also build p4-constraint in a Docker container, for example:\n```sh\ndocker build --tag p4-constraints .                 # Time to get coffee...\ndocker run --tty --interactive p4-constraints bash  # Open shell in container.\nbazel test //...                                    # Run tests in container.\n```\n\n## Golden tests\n\nThe easiest way to experiment with p4-constraints is to write a\n[golden test](https://ro-che.info/articles/2017-12-04-golden-tests).\nWe provide [Bazel rules](e2e_tests/p4check.bzl) `run_p4check` and `diff_test` to\nmake this convenient.\nSee the [e2e_tests/](e2e_tests/) folder -- in particular\n[e2e_tests/BUILD.bazel](e2e_tests/BUILD.bazel) -- for examples of how to use them.\n\nTo run all golden tests, execute\n```sh\nbazel test //e2e_tests/...\n```\n[Recall](#building) that this will build p4c and requires\n[Bison](https://en.wikipedia.org/wiki/GNU_Bison) and\n[Flex](https://en.wikipedia.org/wiki/Flex_\\(lexical_analyser_generator\\))\nto be installed.\n\nTo see the output of a failed test, invoke it using `bazel run` like so:\n```sh\nbazel run //e2e_test:invalid_constraints_test\n```\n\n## p4check\n\nThe `p4check` CLI allows invoking the p4-constraints library from the command\nline. The most convenient way to run `p4check` is using the\n[`run_p4check`-rule](e2e_tests/p4check.bzl), as is done for\n[golden testing](#golden-tests).\n\nTo learn how to invoke [p4check](p4_constraints/cli/p4check.cc) manually,\nconsult [the source file](p4_constraints/cli/p4check.cc) or run\n```sh\nbazel run p4_constraints/cli:p4check -- --help\n```\n\n## Constraint language\n\nSee [docs/language-specification.md](docs/language-specification.md) for a\ndocumentation of the constraint languages, or look at some example constraints\nin the .p4-files in the [e2e_tests folder](e2e_tests/).\n\n## Contributing\n\nFeedback, suggestions, and contributions in the form of GitHub issues and\n[pull requests](CONTRIBUTING.md) are welcome and encouraged.\n\n### Source Code Headers\n\nPlease note that every file containing source code must include the following\ncopyright header:\n\n    Copyright 2020 The P4-Constraints Authors\n    \n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n    \n        https://www.apache.org/licenses/LICENSE-2.0\n    \n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n    SPDX-License-Identifier: Apache-2.0\n\nThis can be done automatically using\n[addlicense](https://github.com/google/addlicense) as follows:\n```sh\naddlicense -c \"The P4-Constraints Authors\" -s -l apache ./p4_constraints\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp4lang%2Fp4-constraints","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fp4lang%2Fp4-constraints","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp4lang%2Fp4-constraints/lists"}