diff --git a/sai_p4/fixed/routing.p4 b/sai_p4/fixed/routing.p4 index a7402b28..85fd4ee1 100644 --- a/sai_p4/fixed/routing.p4 +++ b/sai_p4/fixed/routing.p4 @@ -87,6 +87,10 @@ control routing(in headers_t headers, // TODO: Remove @unsupported when the switch supports this // action. @unsupported + @action_restriction(" + // Disallow reserved VLAN IDs with implementation-defined semantics. + vlan_id != 0 && vlan_id != 4095" + ) action set_port_and_src_mac_and_vlan_id(@id(1) port_id_t port, @id(2) @format(MAC_ADDRESS) ethernet_addr_t src_mac, @@ -435,13 +439,14 @@ control routing(in headers_t headers, // Calling this action will override unicast, and can itself be overriden by // `mark_to_drop`. // - // Using a `multicast_group_id` of 0 is not allowed. - // TODO: Enforce this requirement using p4-constraints. - // // TODO: Remove `@unsupported` annotation once the switch stack // supports multicast. @unsupported @id(ROUTING_SET_MULTICAST_GROUP_ID_ACTION_ID) + @action_restriction(" + // Disallow 0 since it encodes 'no multicast' in V1Model. + multicast_group_id != 0" + ) action set_multicast_group_id( @id(1) // TODO: Add this once supported by PDPI and its customers. diff --git a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt index 93dcdfe2..d0936f1d 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt +++ b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt @@ -978,6 +978,7 @@ actions { name: "ingress.routing.set_port_and_src_mac_and_vlan_id" alias: "set_port_and_src_mac_and_vlan_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow reserved VLAN IDs with implementation-defined semantics.\n vlan_id != 0 && vlan_id != 4095\")" } params { id: 1 @@ -1231,6 +1232,7 @@ actions { name: "ingress.routing.set_multicast_group_id" alias: "set_multicast_group_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0\")" } params { id: 1 diff --git a/sai_p4/instantiations/google/middleblock.p4info.pb.txt b/sai_p4/instantiations/google/middleblock.p4info.pb.txt index 1879afdb..d2f7921d 100755 --- a/sai_p4/instantiations/google/middleblock.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock.p4info.pb.txt @@ -908,6 +908,7 @@ actions { name: "ingress.routing.set_port_and_src_mac_and_vlan_id" alias: "set_port_and_src_mac_and_vlan_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow reserved VLAN IDs with implementation-defined semantics.\n vlan_id != 0 && vlan_id != 4095\")" } params { id: 1 @@ -1161,6 +1162,7 @@ actions { name: "ingress.routing.set_multicast_group_id" alias: "set_multicast_group_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0\")" } params { id: 1 diff --git a/sai_p4/instantiations/google/middleblock_with_s2_ecmp_profile.p4info.pb.txt b/sai_p4/instantiations/google/middleblock_with_s2_ecmp_profile.p4info.pb.txt index 1c33f449..f7081554 100644 --- a/sai_p4/instantiations/google/middleblock_with_s2_ecmp_profile.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock_with_s2_ecmp_profile.p4info.pb.txt @@ -964,6 +964,7 @@ actions { name: "ingress.routing.set_port_and_src_mac_and_vlan_id" alias: "set_port_and_src_mac_and_vlan_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow reserved VLAN IDs with implementation-defined semantics.\n vlan_id != 0 && vlan_id != 4095\")" } params { id: 1 @@ -1241,6 +1242,7 @@ actions { name: "ingress.routing.set_multicast_group_id" alias: "set_multicast_group_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0\")" } params { id: 1 diff --git a/sai_p4/instantiations/google/test_tools/BUILD.bazel b/sai_p4/instantiations/google/test_tools/BUILD.bazel index 18b75fda..fcd4effe 100644 --- a/sai_p4/instantiations/google/test_tools/BUILD.bazel +++ b/sai_p4/instantiations/google/test_tools/BUILD.bazel @@ -32,6 +32,8 @@ cc_library( "//p4_pdpi:ir_cc_proto", "//p4_pdpi:pd", "//p4_pdpi:translation_options", + "//p4_pdpi/netaddr:ipv4_address", + "//p4_pdpi/netaddr:ipv6_address", "//p4_pdpi/netaddr:mac_address", "//p4_pdpi/string_encodings:hex_string", "//sai_p4/instantiations/google:sai_pd_cc_proto", @@ -57,6 +59,8 @@ cc_test( "//gutil:testing", "//p4_pdpi:ir_cc_proto", "//p4_pdpi:pd", + "//p4_pdpi/netaddr:ipv4_address", + "//p4_pdpi/netaddr:ipv6_address", "//p4_pdpi/netaddr:mac_address", "//sai_p4/instantiations/google:instantiations", "//sai_p4/instantiations/google:sai_p4info_cc", diff --git a/sai_p4/instantiations/google/test_tools/test_entries.cc b/sai_p4/instantiations/google/test_tools/test_entries.cc index bda79b82..6d1bc66a 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.cc +++ b/sai_p4/instantiations/google/test_tools/test_entries.cc @@ -33,6 +33,8 @@ #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.h" #include "p4_pdpi/ir.pb.h" +#include "p4_pdpi/netaddr/ipv4_address.h" +#include "p4_pdpi/netaddr/ipv6_address.h" #include "p4_pdpi/netaddr/mac_address.h" #include "p4_pdpi/pd.h" #include "p4_pdpi/string_encodings/hex_string.h" @@ -401,6 +403,36 @@ EntryBuilder& EntryBuilder::AddMulticastRouterInterfaceEntry( return *this; } +EntryBuilder& EntryBuilder::AddRouteForwardingIpv4PacketsToGivenMulticastGroup( + int multicast_group_id, absl::string_view vrf, netaddr::Ipv4Address& dst_ip, + int prefix_length) { + sai::Ipv4TableEntry& entry = + *entries_.add_entries()->mutable_ipv4_table_entry(); + entry.mutable_match()->set_vrf_id(vrf); + auto* ipv4_dst = entry.mutable_match()->mutable_ipv4_dst(); + ipv4_dst->set_value(dst_ip.ToString()); + ipv4_dst->set_prefix_length(prefix_length); + entry.mutable_action() + ->mutable_set_multicast_group_id() + ->set_multicast_group_id(pdpi::BitsetToHexString<16>(multicast_group_id)); + return *this; +} + +EntryBuilder& EntryBuilder::AddRouteForwardingIpv6PacketsToGivenMulticastGroup( + int multicast_group_id, absl::string_view vrf, netaddr::Ipv6Address& dst_ip, + int prefix_length) { + sai::Ipv6TableEntry& entry = + *entries_.add_entries()->mutable_ipv6_table_entry(); + entry.mutable_match()->set_vrf_id(vrf); + auto* ipv6_dst = entry.mutable_match()->mutable_ipv6_dst(); + ipv6_dst->set_value(dst_ip.ToString()); + ipv6_dst->set_prefix_length(prefix_length); + entry.mutable_action() + ->mutable_set_multicast_group_id() + ->set_multicast_group_id(pdpi::BitsetToHexString<16>(multicast_group_id)); + return *this; +} + EntryBuilder& EntryBuilder::AddIngressAclDroppingAllPackets() { *entries_.add_entries() = gutil::ParseProtoOrDie(R"pb( acl_ingress_table_entry { diff --git a/sai_p4/instantiations/google/test_tools/test_entries.h b/sai_p4/instantiations/google/test_tools/test_entries.h index 077a7b62..ffca2b7d 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.h +++ b/sai_p4/instantiations/google/test_tools/test_entries.h @@ -32,6 +32,8 @@ #include "absl/types/span.h" #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.pb.h" +#include "p4_pdpi/netaddr/ipv4_address.h" +#include "p4_pdpi/netaddr/ipv6_address.h" #include "p4_pdpi/netaddr/mac_address.h" #include "sai_p4/instantiations/google/sai_pd.pb.h" @@ -156,6 +158,12 @@ class EntryBuilder { std::optional vlan_hexstr = std::nullopt); EntryBuilder& AddDefaultRouteForwardingAllPacketsToGivenMulticastGroup( int multicast_group_id, IpVersion ip_version, absl::string_view vrf); + EntryBuilder& AddRouteForwardingIpv4PacketsToGivenMulticastGroup( + int multicast_group_id, absl::string_view vrf, + netaddr::Ipv4Address& dst_ip, int prefix_length); + EntryBuilder& AddRouteForwardingIpv6PacketsToGivenMulticastGroup( + int multicast_group_id, absl::string_view vrf, + netaddr::Ipv6Address& dst_ip, int prefix_length); EntryBuilder& AddPreIngressAclEntryAssigningVrfForGivenIpType( absl::string_view vrf, IpVersion ip_version); EntryBuilder& AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf( diff --git a/sai_p4/instantiations/google/test_tools/test_entries_test.cc b/sai_p4/instantiations/google/test_tools/test_entries_test.cc index 3b33a120..0c97b2e0 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries_test.cc +++ b/sai_p4/instantiations/google/test_tools/test_entries_test.cc @@ -27,6 +27,9 @@ #include "p4_pdpi/netaddr/mac_address.h" #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.pb.h" +#include "p4_pdpi/netaddr/ipv4_address.h" +#include "p4_pdpi/netaddr/ipv6_address.h" +#include "p4_pdpi/netaddr/mac_address.h" #include "p4_pdpi/pd.h" #include "sai_p4/instantiations/google/instantiations.h" #include "sai_p4/instantiations/google/sai_p4info.h" @@ -351,6 +354,81 @@ TEST(EntryBuilder, AddMulticastRouterInterfaceEntryAddsEntry) { )pb")))); } +TEST(EntryBuilder, + AddRouteForwardingIpv4PacketsToGivenMulticastGroupAddsEntry) { + pdpi::IrP4Info kIrP4Info = GetIrP4Info(Instantiation::kFabricBorderRouter); + ASSERT_OK_AND_ASSIGN(auto dst_ip, + netaddr::Ipv4Address::OfString("225.10.20.32")); + ASSERT_OK_AND_ASSIGN( + pdpi::IrEntities entities, + EntryBuilder() + .AddRouteForwardingIpv4PacketsToGivenMulticastGroup( + /*multicast_group_id=*/17, /*vrf=*/"vrf-1", dst_ip, 32) + .LogPdEntries() + .GetDedupedIrEntities(kIrP4Info, /*allow_unsupported=*/true)); + EXPECT_THAT(entities.entities(), Contains(Partially(EqualsProto(R"pb( + table_entry { + table_name: "ipv4_table" + matches { + name: "vrf_id" + exact { str: "vrf-1" } + } + matches { + name: "ipv4_dst" + lpm { + value { ipv4: "225.10.20.32" } + prefix_length: 32 + } + } + action { + name: "set_multicast_group_id" + params { + name: "multicast_group_id" + value { hex_str: "0x0011" } + } + } + } + )pb")))); +} + +TEST(EntryBuilder, + AddRouteForwardingIpv6PacketsToGivenMulticastGroupAddsEntry) { + pdpi::IrP4Info kIrP4Info = GetIrP4Info(Instantiation::kFabricBorderRouter); + ASSERT_OK_AND_ASSIGN(auto dst_ip, + netaddr::Ipv6Address::OfString( + "ff00:8888:1111:2222:3333:4444:5555:6666")); + ASSERT_OK_AND_ASSIGN( + pdpi::IrEntities entities, + EntryBuilder() + .AddRouteForwardingIpv6PacketsToGivenMulticastGroup( + /*multicast_group_id=*/33, /*vrf=*/"vrf-2", dst_ip, 128) + .LogPdEntries() + .GetDedupedIrEntities(kIrP4Info, /*allow_unsupported=*/true)); + EXPECT_THAT(entities.entities(), Contains(Partially(EqualsProto(R"pb( + table_entry { + table_name: "ipv6_table" + matches { + name: "vrf_id" + exact { str: "vrf-2" } + } + matches { + name: "ipv6_dst" + lpm { + value { ipv6: "ff00:8888:1111:2222:3333:4444:5555:6666" } + prefix_length: 128 + } + } + action { + name: "set_multicast_group_id" + params { + name: "multicast_group_id" + value { hex_str: "0x0021" } + } + } + } + )pb")))); +} + TEST(EntryBuilder, AddIngressAclDroppingAllPacketsAddsEntry) { pdpi::IrP4Info kIrP4Info = GetIrP4Info(Instantiation::kFabricBorderRouter); ASSERT_OK_AND_ASSIGN(pdpi::IrEntities entities, diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index fd8de5b5..2706035b 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -1221,6 +1221,7 @@ actions { name: "ingress.routing.set_port_and_src_mac_and_vlan_id" alias: "set_port_and_src_mac_and_vlan_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow reserved VLAN IDs with implementation-defined semantics.\n vlan_id != 0 && vlan_id != 4095\")" } params { id: 1 @@ -1474,6 +1475,7 @@ actions { name: "ingress.routing.set_multicast_group_id" alias: "set_multicast_group_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0\")" } params { id: 1 diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index 2b42d410..772deb3d 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -1473,6 +1473,7 @@ actions { name: "ingress.routing.set_port_and_src_mac_and_vlan_id" alias: "set_port_and_src_mac_and_vlan_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow reserved VLAN IDs with implementation-defined semantics.\n vlan_id != 0 && vlan_id != 4095\")" } params { id: 1 @@ -1726,6 +1727,7 @@ actions { name: "ingress.routing.set_multicast_group_id" alias: "set_multicast_group_id" annotations: "@unsupported" + annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0\")" } params { id: 1