diff --git a/sai_p4/BUILD.bazel b/sai_p4/BUILD.bazel index 38889a709..5be625c54 100644 --- a/sai_p4/BUILD.bazel +++ b/sai_p4/BUILD.bazel @@ -14,3 +14,29 @@ cc_proto_library( name = "capabilities_cc_proto", deps = [":capabilities_proto"], ) + +cc_library( + name = "capabilities", + srcs = ["capabilities.cc"], + hdrs = ["capabilities.h"], + deps = [ + ":capabilities_cc_proto", + "//gutil/gutil:status", + "@com_github_p4lang_p4runtime//:p4runtime_cc_proto", + "@com_google_absl//absl/status", + "@com_google_protobuf//:protobuf", + ], +) + +cc_test( + name = "capabilities_test", + srcs = ["capabilities_test.cc"], + deps = [ + ":capabilities", + ":capabilities_cc_proto", + "//gutil/gutil:proto_matchers", + "//gutil/gutil:status_matchers", + "@com_google_googletest//:gtest_main", + ], +) + diff --git a/sai_p4/capabilities.cc b/sai_p4/capabilities.cc new file mode 100644 index 000000000..e2f910bec --- /dev/null +++ b/sai_p4/capabilities.cc @@ -0,0 +1,39 @@ +#include "sai_p4/capabilities.h" + +#include + +#include "absl/status/status.h" +#include "google/protobuf/any.pb.h" +#include "p4/v1/p4runtime.pb.h" +#include "sai_p4/capabilities.pb.h" + +namespace sai { + +using ::p4::v1::CapabilitiesResponse; + +absl::Status AddExperimentalResourceCapabilities( + ExperimentalResourceCapabilities capabilities, + CapabilitiesResponse& response) { + if (!response.mutable_experimental()->PackFrom(std::move(capabilities))) { + return absl::InvalidArgumentError( + "Failed to pack ExperimentalResourceCapabilities into " + "CapabilitiesResponse."); + } + return absl::OkStatus(); +} + +ExperimentalResourceCapabilities GetExperimentalResourceCapabilities( + const CapabilitiesResponse& response) { + ExperimentalResourceCapabilities capabilities; + response.experimental().UnpackTo(&capabilities); + return capabilities; +}; + +WcmpGroupLimitations GetWcmpGroupLimitations( + const CapabilitiesResponse& response) { + ExperimentalResourceCapabilities capabilities = + GetExperimentalResourceCapabilities(response); + return capabilities.wcmp_group_limitations(); +} + +} // namespace sai diff --git a/sai_p4/capabilities.h b/sai_p4/capabilities.h new file mode 100644 index 000000000..97867d04d --- /dev/null +++ b/sai_p4/capabilities.h @@ -0,0 +1,28 @@ +#ifndef PINS_SAI_P4_CAPABILITIES_H_ +#define PINS_SAI_P4_CAPABILITIES_H_ + +#include "absl/status/status.h" +#include "p4/v1/p4runtime.pb.h" +#include "sai_p4/capabilities.pb.h" + +namespace sai { + +// Adds `experimental_resource_capabilities` to `response`. Returns an error if +// `experimental_resource_capabilities` cannot be added into `response`. +absl::Status AddExperimentalResourceCapabilities( + ExperimentalResourceCapabilities capabilities, + p4::v1::CapabilitiesResponse& response); + +// If `response` contains a `ExperimentalResourceCapabilities`, returns it. +// Otherwise, returns an empty `ExperimentalResourceCapabilities`. +ExperimentalResourceCapabilities GetExperimentalResourceCapabilities( + const p4::v1::CapabilitiesResponse& response); + +// If `response` contains a `WcmpGroupLimitations`, returns it. +// Otherwise, returns an empty `WcmpGroupLimitations`. +WcmpGroupLimitations GetWcmpGroupLimitations( + const p4::v1::CapabilitiesResponse& response); + +} // namespace sai + +#endif // PINS_SAI_P4_CAPABILITIES_H_ diff --git a/sai_p4/capabilities.proto b/sai_p4/capabilities.proto index 4ea097d26..3d99bf1f3 100644 --- a/sai_p4/capabilities.proto +++ b/sai_p4/capabilities.proto @@ -14,7 +14,7 @@ syntax = "proto3"; -package p4.v1; +package sai; // A switch can provide limitations of the WCMP groups that can be installed // on the switch. A switch may report a ResourceExhausted error, if: diff --git a/sai_p4/capabilities_test.cc b/sai_p4/capabilities_test.cc new file mode 100644 index 000000000..dfd5db9df --- /dev/null +++ b/sai_p4/capabilities_test.cc @@ -0,0 +1,100 @@ +#include "sai_p4/capabilities.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "gutil/gutil/proto_matchers.h" +#include "gutil/gutil/status_matchers.h" // IWYU pragma: keep +#include "sai_p4/capabilities.pb.h" + +namespace sai { +namespace { + +using ::gutil::EqualsProto; +using ::p4::v1::CapabilitiesResponse; + +TEST(CapabilitiesTest, AddExperimentalResourceCapabilitiesWorks) { + CapabilitiesResponse response; + ExperimentalResourceCapabilities experimental_resource_capabilities; + experimental_resource_capabilities.mutable_wcmp_group_limitations() + ->set_max_distinct_weights_per_group(8); + experimental_resource_capabilities.mutable_wcmp_group_limitations() + ->set_max_total_weight_per_group(2000); + + EXPECT_OK(AddExperimentalResourceCapabilities( + experimental_resource_capabilities, response)); + + ExperimentalResourceCapabilities unpacked_experimental_resource_capabilities; + response.mutable_experimental()->UnpackTo( + &unpacked_experimental_resource_capabilities); + EXPECT_THAT(unpacked_experimental_resource_capabilities, + EqualsProto(experimental_resource_capabilities)); +} + +TEST(CapabilitiesTest, GetExperimentalResourceCapabilitiesWorks) { + CapabilitiesResponse response; + ExperimentalResourceCapabilities experimental_resource_capabilities; + experimental_resource_capabilities.mutable_wcmp_group_limitations() + ->set_max_distinct_weights_per_group(8); + experimental_resource_capabilities.mutable_wcmp_group_limitations() + ->set_max_total_weight_per_group(2000); + + ASSERT_OK(AddExperimentalResourceCapabilities( + experimental_resource_capabilities, response)); + EXPECT_THAT(GetExperimentalResourceCapabilities(response), + EqualsProto(experimental_resource_capabilities)); +} + +TEST(CapabilitiesTest, + GetExperimentalResourceCapabilitiesReturnsEmptyWhenMissing) { + EXPECT_THAT(GetExperimentalResourceCapabilities(CapabilitiesResponse()), + EqualsProto(ExperimentalResourceCapabilities())); +} + +TEST(CapabilitiesTest, + GetExperimentalResourceCapabilitiesReturnsEmptyWhenWrongType) { + CapabilitiesResponse response; + p4::v1::TableEntry entry; + ASSERT_TRUE(response.mutable_experimental()->PackFrom(entry)); + EXPECT_THAT(GetExperimentalResourceCapabilities(response), + EqualsProto(ExperimentalResourceCapabilities())); +} + +TEST(CapabilitiesTest, GetWcmpGroupLimitationsWorks) { + CapabilitiesResponse response; + ExperimentalResourceCapabilities experimental_resource_capabilities; + experimental_resource_capabilities.mutable_wcmp_group_limitations() + ->set_max_distinct_weights_per_group(8); + experimental_resource_capabilities.mutable_wcmp_group_limitations() + ->set_max_total_weight_per_group(2000); + + ASSERT_OK(AddExperimentalResourceCapabilities( + experimental_resource_capabilities, response)); + EXPECT_THAT( + GetWcmpGroupLimitations(response), + EqualsProto(experimental_resource_capabilities.wcmp_group_limitations())); +} + +TEST(CapabilitiesTest, GetWcmpGroupLimitationsWorksWhenMissing) { + CapabilitiesResponse response; + ASSERT_OK(AddExperimentalResourceCapabilities( + ExperimentalResourceCapabilities(), response)); + EXPECT_THAT(GetWcmpGroupLimitations(response), + EqualsProto(WcmpGroupLimitations())); +} + +TEST(CapabilitiesTest, + GetWcmpGroupLimitationsReturnsEmptyWhenParentWhenMissing) { + EXPECT_THAT(GetWcmpGroupLimitations(CapabilitiesResponse()), + EqualsProto(WcmpGroupLimitations())); +} + +TEST(CapabilitiesTest, GetWcmpGroupLimitationsReturnsEmptyWhenWrongType) { + CapabilitiesResponse response; + p4::v1::TableEntry entry; + ASSERT_TRUE(response.mutable_experimental()->PackFrom(entry)); + EXPECT_THAT(GetWcmpGroupLimitations(response), + EqualsProto(WcmpGroupLimitations())); +} + +} // namespace +} // namespace sai diff --git a/sai_p4/fixed/l3_admit.p4 b/sai_p4/fixed/l3_admit.p4 index b0f1113b9..ea02b74a8 100644 --- a/sai_p4/fixed/l3_admit.p4 +++ b/sai_p4/fixed/l3_admit.p4 @@ -22,7 +22,9 @@ control l3_admit(in headers_t headers, key = { headers.ethernet.dst_addr : ternary @name("dst_mac") @id(1) @format(MAC_ADDRESS); +#if defined(L3_ADMIT_SUPPORTS_IN_PORT) local_metadata.ingress_port : optional @name("in_port") @id(2); +#endif } actions = { @proto_id(1) admit_to_l3; diff --git a/sai_p4/fixed/routing.p4 b/sai_p4/fixed/routing.p4 index ca5fb1f18..4b2aa7935 100644 --- a/sai_p4/fixed/routing.p4 +++ b/sai_p4/fixed/routing.p4 @@ -414,9 +414,11 @@ control routing_resolution(in headers_t headers, router_interface_id_value : exact @id(1) @name("router_interface_id"); } - // TODO: Remove once no longer in use on our switches. actions = { +#if defined(RIF_PROGRAMMING_MY_MAC_SUPPORTED) + // TODO: Remove once no longer in use on our switches. @proto_id(1) set_port_and_src_mac; +#endif @proto_id(2) unicast_set_port_and_src_mac_and_vlan_id; @proto_id(3) unicast_set_port_and_src_mac; @defaultonly NoAction; diff --git a/sai_p4/instantiations/google/acl_ingress.p4 b/sai_p4/instantiations/google/acl_ingress.p4 index e1bbb8b85..d38bd8371 100644 --- a/sai_p4/instantiations/google/acl_ingress.p4 +++ b/sai_p4/instantiations/google/acl_ingress.p4 @@ -276,6 +276,9 @@ control acl_ingress(in headers_t headers, @sai_acl(INGRESS) @sai_acl_priority(5) @nonessential_for_upgrade +#if defined(SAI_INSTANTIATION_TOR) + @reinstall_during_upgrade +#endif @entry_restriction(" // Forbid using ether_type for IP packets (by convention, use is_ip* instead). ether_type != 0x0800 && ether_type != 0x86dd; @@ -422,6 +425,9 @@ control acl_ingress(in headers_t headers, @sai_acl_priority(10) @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @nonessential_for_upgrade +#if defined(SAI_INSTANTIATION_TOR) + @reinstall_during_upgrade +#endif @entry_restriction(" // Forbid using ether_type for IP packets (by convention, use is_ip* instead). ether_type != 0x0800 && ether_type != 0x86dd; @@ -652,6 +658,10 @@ control acl_ingress(in headers_t headers, @id(ACL_INGRESS_MIRROR_AND_REDIRECT_TABLE_ID) @sai_acl(INGRESS) @sai_acl_priority(15) + @nonessential_for_upgrade +#if defined(SAI_INSTANTIATION_TOR) + @reinstall_during_upgrade +#endif @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @entry_restriction(" // Only allow IP field matches for IP packets. diff --git a/sai_p4/instantiations/google/fabric_border_router.p4 b/sai_p4/instantiations/google/fabric_border_router.p4 index f5910e679..98af9e18b 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4 +++ b/sai_p4/instantiations/google/fabric_border_router.p4 @@ -3,9 +3,11 @@ #define ACL_REDIRECT_TO_NEXTHOP_CAPABLE #define ACL_REDIRECT_TO_PORT_CAPABLE #define DSCP_REWRITE_CAPABLE -#define NEXTHOP_DISABLE_REWRITES_CAPABLE #define IP_MULTICAST_CAPABLE +#define L3_ADMIT_SUPPORTS_IN_PORT +#define NEXTHOP_DISABLE_REWRITES_CAPABLE #define MIRROR_CAPABLE +#define RIF_PROGRAMMING_MY_MAC_SUPPORTED #define TIMESTAMP_CAPABLE #define TUNNEL_ENCAP_CAPABLE diff --git a/sai_p4/instantiations/google/middleblock.p4 b/sai_p4/instantiations/google/middleblock.p4 index 5784742a6..4876e99a6 100644 --- a/sai_p4/instantiations/google/middleblock.p4 +++ b/sai_p4/instantiations/google/middleblock.p4 @@ -3,9 +3,11 @@ #define ACL_REDIRECT_TO_NEXTHOP_CAPABLE #define ACL_REDIRECT_TO_PORT_CAPABLE #define DSCP_REWRITE_CAPABLE -#define NEXTHOP_DISABLE_REWRITES_CAPABLE #define IP_MULTICAST_CAPABLE +#define L3_ADMIT_SUPPORTS_IN_PORT +#define NEXTHOP_DISABLE_REWRITES_CAPABLE #define MIRROR_CAPABLE +#define RIF_PROGRAMMING_MY_MAC_SUPPORTED #define TIMESTAMP_CAPABLE #define TUNNEL_ENCAP_CAPABLE diff --git a/sai_p4/instantiations/google/middleblock.p4info.pb.txt b/sai_p4/instantiations/google/middleblock.p4info.pb.txt index ead090546..dec28764b 100755 --- a/sai_p4/instantiations/google/middleblock.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock.p4info.pb.txt @@ -597,6 +597,7 @@ tables { alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" annotations: "@sai_acl_priority(15)" + annotations: "@nonessential_for_upgrade" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } diff --git a/sai_p4/instantiations/google/sai_pd.proto b/sai_p4/instantiations/google/sai_pd.proto index 211b7f495..762220c2d 100755 --- a/sai_p4/instantiations/google/sai_pd.proto +++ b/sai_p4/instantiations/google/sai_pd.proto @@ -836,7 +836,18 @@ message AclIngressSecurityTableEntry { // is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0); // ## Forbid unsupported combinations of IP_TYPE fields. // is_ipv4::mask != 0 -> (is_ipv4 == 1); -// is_ipv6::mask != 0 -> (is_ipv6 == 1); +// is_ipv6::mask != 0 -> (is_ipv6 == 1);" "route_hit::mask != 0 -> ( +// ## Multicast IPv4. +// ## I.e. 224.X.X.X - 239.X.X.X +// (dst_ip::mask >= 0xf0000000 +// && dst_ip::value >= 0xe0000000 +// && dst_ip::value < 0xf0000000) +// || +// ## Multicast IPv6. +// ## I.e. FFXX:XXXX:... +// (dst_ipv6::mask >= 0xff00000000000000 +// && dst_ipv6::value >= 0xff00000000000000) +// ); message AclIngressMirrorAndRedirectTableEntry { message Match { Optional in_port = 1; // optional match / Format::STRING diff --git a/sai_p4/instantiations/google/tor.p4 b/sai_p4/instantiations/google/tor.p4 index b9765bb94..be2b629e9 100644 --- a/sai_p4/instantiations/google/tor.p4 +++ b/sai_p4/instantiations/google/tor.p4 @@ -16,9 +16,11 @@ #define ACL_REDIRECT_TO_NEXTHOP_CAPABLE #define ACL_REDIRECT_TO_PORT_CAPABLE #define DSCP_REWRITE_CAPABLE -#define NEXTHOP_DISABLE_REWRITES_CAPABLE #define IP_MULTICAST_CAPABLE +#define L3_ADMIT_SUPPORTS_IN_PORT +#define NEXTHOP_DISABLE_REWRITES_CAPABLE #define MIRROR_CAPABLE +#define RIF_PROGRAMMING_MY_MAC_SUPPORTED #define TIMESTAMP_CAPABLE #define TUNNEL_ENCAP_CAPABLE diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index 71b43c80d..09da3a529 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -544,6 +544,7 @@ tables { annotations: "@sai_acl(INGRESS)" annotations: "@sai_acl_priority(5)" annotations: "@nonessential_for_upgrade" + annotations: "@reinstall_during_upgrade" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Forbid match on ethertype if is_ip* is set.\n (is_ip::mask != 0 || is_ipv4::mask != 0 || is_ipv6::mask != 0) -> ether_type::mask == 0;\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n\n\n\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n src_ipv6::mask != 0 -> is_ipv6 == 1;\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n\n\n\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets.\n l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n\n\n // Only allow icmp_type matches for ICMP packets\n icmp_type::mask != 0 -> ip_protocol == 1;\n\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } match_fields { @@ -744,6 +745,7 @@ tables { annotations: "@sai_acl_priority(10)" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@nonessential_for_upgrade" + annotations: "@reinstall_during_upgrade" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Forbid match on ethertype if is_ip* is set.\n (is_ip::mask != 0 || is_ipv4::mask != 0 || is_ipv6::mask != 0) -> ether_type::mask == 0;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n\n\n\n\n\n\n\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n\n \")" } match_fields { @@ -897,6 +899,8 @@ tables { alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" annotations: "@sai_acl_priority(15)" + annotations: "@nonessential_for_upgrade" + annotations: "@reinstall_during_upgrade" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index 62e814de6..1de570dda 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -538,6 +538,7 @@ tables { annotations: "@nonessential_for_upgrade" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Forbid match on ethertype if is_ip* is set.\n (is_ip::mask != 0 || is_ipv4::mask != 0 || is_ipv6::mask != 0) -> ether_type::mask == 0;\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n\n src_ip::mask != 0 -> is_ipv4 == 1;\n\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n src_ipv6::mask != 0 -> is_ipv6 == 1;\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n dscp::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ecn::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets.\n l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n\n\n\n\n\n // Only allow icmp_type matches for ICMP packets\n icmp_type::mask != 0 -> ip_protocol == 1;\n\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Forbid match on ethertype if is_ip* is set.\n (is_ip::mask != 0 || is_ipv4::mask != 0 || is_ipv6::mask != 0) -> ether_type::mask == 0;\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n\n src_ip::mask != 0 -> is_ipv4 == 1;\n\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n src_ipv6::mask != 0 -> is_ipv6 == 1;\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n dscp::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ecn::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets.\n l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n\n\n\n\n\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" + annotations: "@reinstall_during_upgrade" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Forbid match on ethertype if is_ip* is set.\n (is_ip::mask != 0 || is_ipv4::mask != 0 || is_ipv6::mask != 0) -> ether_type::mask == 0;\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n\n\n\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n src_ipv6::mask != 0 -> is_ipv6 == 1;\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n\n\n\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets.\n l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n\n\n // Only allow icmp_type matches for ICMP packets\n icmp_type::mask != 0 -> ip_protocol == 1;\n\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" } match_fields { @@ -754,6 +755,7 @@ tables { annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@nonessential_for_upgrade" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Forbid match on ethertype if is_ip* is set.\n (is_ip::mask != 0 || is_ipv4::mask != 0 || is_ipv6::mask != 0) -> ether_type::mask == 0;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Only allow icmp_type matches for ICMP packets\n icmp_type::mask != 0 -> ip_protocol == 1;\n\n\n\n\n\n \")" + annotations: "@reinstall_during_upgrade" annotations: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n // Forbid match on ethertype if is_ip* is set.\n (is_ip::mask != 0 || is_ipv4::mask != 0 || is_ipv6::mask != 0) -> ether_type::mask == 0;\n // Only allow IP field matches for IP packets.\n ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n // Only allow icmp_type matches for ICMP packets\n icmpv6_type::mask != 0 -> ip_protocol == 58;\n\n\n\n\n\n\n\n // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n\n \")" } match_fields { @@ -1444,8 +1446,10 @@ tables { alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" annotations: "@sai_acl_priority(15)" + annotations: "@nonessential_for_upgrade" annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n // Forbid illegal combinations of IP_TYPE fields.\n is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0);\n is_ipv4::mask != 0 -> (is_ip::mask == 0 && is_ipv6::mask == 0);\n is_ipv6::mask != 0 -> (is_ip::mask == 0 && is_ipv4::mask == 0);\n // Forbid unsupported combinations of IP_TYPE fields.\n is_ipv4::mask != 0 -> (is_ipv4 == 1);\n is_ipv6::mask != 0 -> (is_ipv6 == 1);\n \")" + annotations: "@reinstall_during_upgrade" } match_fields { id: 1