diff --git a/p4_fuzzer/BUILD.bazel b/p4_fuzzer/BUILD.bazel index 429358e3..6ae2b42b 100644 --- a/p4_fuzzer/BUILD.bazel +++ b/p4_fuzzer/BUILD.bazel @@ -120,11 +120,13 @@ cc_library( "//gutil:collections", "//gutil:status", "//lib/p4rt:p4rt_port", + "//p4_pdpi:built_ins", "//p4_pdpi:entity_keys", "//p4_pdpi:ir_cc_proto", "//p4_pdpi:references", "//p4_pdpi/internal:ordered_map", "//p4_pdpi/netaddr:ipv6_address", + "//p4_pdpi/string_encodings:byte_string", "//p4_pdpi/utils:ir", "@com_github_google_glog//:glog", "@com_github_p4lang_p4_constraints//p4_constraints/backend:constraint_info", @@ -163,6 +165,8 @@ cc_test( "//gutil:collections", "//gutil:proto_matchers", "//gutil:status_matchers", + "//gutil:testing", + "//p4_pdpi:built_ins", "//p4_pdpi:ir_cc_proto", "@com_github_google_glog//:glog", "@com_github_p4lang_p4runtime//:p4info_cc_proto", diff --git a/p4_fuzzer/fuzz_util.cc b/p4_fuzzer/fuzz_util.cc index ba933d1c..fa7d8552 100644 --- a/p4_fuzzer/fuzz_util.cc +++ b/p4_fuzzer/fuzz_util.cc @@ -35,8 +35,8 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" -#include "absl/strings/substitute.h" #include "absl/types/span.h" +#include "glog/logging.h" #include "google/protobuf/repeated_field.h" #include "google/protobuf/repeated_ptr_field.h" #include "gutil/collections.h" @@ -50,28 +50,30 @@ #include "p4_fuzzer/fuzzer_config.h" #include "p4_fuzzer/mutation.h" #include "p4_fuzzer/switch_state.h" +#include "p4_pdpi/built_ins.h" #include "p4_pdpi/entity_keys.h" #include "p4_pdpi/internal/ordered_map.h" #include "p4_pdpi/ir.pb.h" #include "p4_pdpi/netaddr/ipv6_address.h" #include "p4_pdpi/references.h" +#include "p4_pdpi/string_encodings/byte_string.h" #include "p4_pdpi/utils/ir.h" -#include "p4_pdpi/entity_keys.h" namespace p4_fuzzer { using ::absl::gntohll; using ::absl::Uniform; -using ::pdpi::TableEntryKey; using ::p4::v1::Action; using ::p4::v1::Entity; using ::p4::v1::FieldMatch; +using ::p4::v1::MulticastGroupEntry; +using ::p4::v1::Replica; using ::p4::v1::TableEntry; using ::p4::v1::Update; +using ::pdpi::EntityKey; using ::pdpi::IrTableDefinition; using ::pdpi::IrTableReference; -using ::pdpi::TableEntryKey; constexpr int kBitsInByte = 8; @@ -233,39 +235,66 @@ CreateReferenceMapping( const google::protobuf::RepeatedPtrField& references) { absl::flat_hash_map reference_map; for (const IrTableReference& reference : references) { - if (reference.destination_table().has_p4_table()) { - if (reference.destination_table().p4_table().table_name() == - "router_interface_table" && - reference.source_table().p4_table().table_name() != - "neighbor_table") { - // TODO: b/317404235 - Remove once a less "baked-in" way of masking this - // is found. - // This is a mask that is consistent with `CheckReferenceAssumptions`, - // which is used when creating the `FuzzerConfig`. - continue; - } + Entity referenced_entity; + switch (reference.destination_table().table_case()) { + case pdpi::IrTable::kP4Table: { + if (reference.destination_table().p4_table().table_name() == + "router_interface_table" && + reference.source_table().p4_table().table_name() != + "neighbor_table") { + // TODO: b/317404235 - Remove once a less "baked-in" way of masking + // this is found. This is a mask that is consistent with + // `CheckReferenceAssumptions`, which is used when creating the + // `FuzzerConfig`. + continue; + } + + if (switch_state.IsTableEmpty( + reference.destination_table().p4_table().table_id())) { + return gutil::FailedPreconditionErrorBuilder() + << "Table with id " + << reference.destination_table().p4_table().table_id() + << " is empty. Cannot currently generate references to table."; + } - if (switch_state.IsTableEmpty( - reference.destination_table().p4_table().table_id())) { - return gutil::FailedPreconditionErrorBuilder() - << "Table with id " - << reference.destination_table().p4_table().table_id() - << " is empty. Cannot currently generate references to table."; + *referenced_entity.mutable_table_entry() = UniformValueFromMap( + gen, switch_state.GetTableEntries( + reference.destination_table().p4_table().table_id())); + break; } + case pdpi::IrTable::kBuiltInTable: { + if (reference.destination_table().built_in_table() != + pdpi::BUILT_IN_TABLE_MULTICAST_GROUP_TABLE) { + return gutil::UnimplementedErrorBuilder() + << "Only built-in destination table of type " + "BUILT_IN_TABLE_MULTICAST_GROUP_TABLE is supported, got: " + << reference.DebugString(); + } - Entity referenced_entity; - *referenced_entity.mutable_table_entry() = UniformValueFromMap( - gen, switch_state.GetTableEntries( - reference.destination_table().p4_table().table_id())); - ASSIGN_OR_RETURN( - absl::flat_hash_set concrete_references, - pdpi::PossibleIncomingConcreteTableReferences(reference, - referenced_entity)); - for (const pdpi::ConcreteTableReference& concrete_reference : - concrete_references) { - for (const auto& field : concrete_reference.fields) { - reference_map[field.source_field] = field.value; + if (switch_state.GetMulticastGroupEntries().empty()) { + return gutil::FailedPreconditionErrorBuilder() + << "Multicast group table is empty. Cannot currently " + "generate references."; } + *referenced_entity.mutable_packet_replication_engine_entry() + ->mutable_multicast_group_entry() = + UniformValueFromMap(gen, switch_state.GetMulticastGroupEntries()); + break; + } + default: { + return gutil::InvalidArgumentErrorBuilder() + << "Destination table type in reference info is not known: " + << reference.DebugString(); + } + } + ASSIGN_OR_RETURN( + absl::flat_hash_set concrete_references, + pdpi::PossibleIncomingConcreteTableReferences(reference, + referenced_entity)); + for (const pdpi::ConcreteTableReference& concrete_reference : + concrete_references) { + for (const auto& field : concrete_reference.fields) { + reference_map[field.source_field] = field.value; } } } @@ -311,26 +340,34 @@ absl::StatusOr FuzzActionProfileAction( bool IsAccidentallyInvalidUpdate( const FuzzerConfig& config, const SwitchState& switch_state, const AnnotatedWriteRequest& request, - const absl::flat_hash_set& entry_keys_in_request, + const absl::flat_hash_set& entity_keys_in_request, const AnnotatedUpdate& candidate_update) { // Mutated updates are never accidentally invalid (they should always be // invalid) so return early if update contains any mutations. if (!candidate_update.mutations().empty()) return false; - // Table entries are the only entity types used. Even if this is the case, - // existence of a table entry should always be checked before accessing. - if (candidate_update.pi().entity().has_table_entry()) { - const TableEntry& candidate_entry = - candidate_update.pi().entity().table_entry(); - // Checks for duplicates in current write request. - if (entry_keys_in_request.contains(TableEntryKey(candidate_entry))) { - return true; - } - // Checks that an insert does not insert an existing entry. - if (candidate_update.pi().type() == p4::v1::Update_Type_INSERT && - switch_state.GetTableEntry(candidate_entry).has_value()) { - return true; - } + const Entity& candidate_entity = candidate_update.pi().entity(); + // Checks for duplicates in current write request. + if (auto candidate_entity_key = EntityKey::MakeEntityKey(candidate_entity); + candidate_entity_key.ok() && + entity_keys_in_request.contains(*candidate_entity_key)) { + return true; + } + // Checks that an insert does not insert an existing entry. + if (candidate_update.pi().type() == p4::v1::Update_Type_INSERT && + // This entity is a table entry that exists. + ((candidate_entity.has_table_entry() && + switch_state.GetTableEntry(candidate_entity.table_entry()) + .has_value()) || + // This entity is a multicast group entry that exists. + (candidate_entity.packet_replication_engine_entry() + .has_multicast_group_entry() && + switch_state + .GetMulticastGroupEntry( + candidate_entity.packet_replication_engine_entry() + .multicast_group_entry()) + .has_value()))) { + return true; } const std::string& table_name = @@ -456,8 +493,9 @@ bool ModifiableTableExists(const FuzzerConfig& config, // Randomly generates an update type. Update::Type FuzzUpdateType(absl::BitGen* gen, const FuzzerConfig& config, - const SwitchState& state) { - if (state.AllTablesEmpty()) { + const SwitchState& state, bool is_multicast) { + if (is_multicast ? state.GetMulticastGroupEntries().empty() + : state.AllTablesEmpty()) { // Insert if there are no entries to delete. return Update::INSERT; } else { @@ -469,7 +507,10 @@ Update::Type FuzzUpdateType(absl::BitGen* gen, const FuzzerConfig& config, return Update::INSERT; } else { // Equally split the rest between modify and delete. - if (ModifiableTableExists(config, state) && absl::Bernoulli(*gen, 0.5)) { + if ((is_multicast || ModifiableTableExists(config, state)) && + absl::Bernoulli(*gen, 0.5)) { + // Multicast entities are always modifiable, otherwise we need to ensure + // that a modifiable table is non-empty. return Update::MODIFY; } return Update::DELETE; @@ -477,6 +518,88 @@ Update::Type FuzzUpdateType(absl::BitGen* gen, const FuzzerConfig& config, } } +// Fuzzes `Replica` for a packet replication engine entry (multicast +// group/clone session). `packet_replication_engine_definition` provides +// outgoing references. +absl::StatusOr FuzzReplica(absl::BitGen* gen, + const FuzzerConfig& config, + const SwitchState& switch_state, + const pdpi::IrBuiltInTableDefinition& + packet_replication_engine_definition) { + Replica replica; + + // NOTE: The ability to fuzz references for actions and match fields + // independently is based on an assumption enforced in + // `CheckReferenceAssumptions` when constructing `FuzzerConfig`. Should that + // assumption ever be removed, this code should be updated. + absl::flat_hash_map reference_map; + ASSIGN_OR_RETURN( + reference_map, + CreateReferenceMapping( + gen, switch_state, + packet_replication_engine_definition.outgoing_references())); + + ASSIGN_OR_RETURN( + std::string port_param, + pdpi::IrBuiltInParameterToString( + pdpi::IrBuiltInParameter::BUILT_IN_PARAMETER_REPLICA_PORT)); + if (auto it = reference_map.find(port_param); it != reference_map.end()) { + replica.set_port(it->second); + } else { + replica.set_port(FuzzPort(gen, config).GetP4rtEncoding()); + } + + // Inherited from v1model, see `standard_metadata_t.egress_rid`. + // https://github.com/p4lang/p4c/blob/main/p4include/v1model.p4 + constexpr int kReplicaInstanceBitwidth = 16; + + ASSIGN_OR_RETURN( + std::string instance_param, + pdpi::IrBuiltInParameterToString( + pdpi::IrBuiltInParameter::BUILT_IN_PARAMETER_REPLICA_INSTANCE)); + if (auto it = reference_map.find(instance_param); it != reference_map.end()) { + ASSIGN_OR_RETURN( + auto instance, + pdpi::ByteStringToBitset(it->second)); + replica.set_instance(instance.to_ullong()); + } else { + replica.set_instance(FuzzUint64(gen, kReplicaInstanceBitwidth)); + } + + return replica; +} + +// Randomly changes the `multicast_group_entry` without affecting the key +// fields. +void FuzzNonKeyFields(absl::BitGen* gen, const FuzzerConfig& config, + const SwitchState& switch_state, + MulticastGroupEntry* multicast_group_entry) { + multicast_group_entry->clear_replicas(); + // Fuzz 0-64 unique replicas + // TODO: b/286413264 - Replace how iteration count is chosen with information + // from p4 info or config once multicast resource limits are finalized and + // modeled. + int replica_fuzz_iterations = FuzzUint64(gen, /*bits=*/6); + absl::flat_hash_set> unique_replicas; + // Depending on references, the number of unique replicas can be capped so + // replicas generated can be less than `replica_fuzz_iterations`. + for (int i = 0; i < replica_fuzz_iterations; ++i) { + // Generate replica. + absl::StatusOr replica = + FuzzReplica(gen, config, switch_state, + config.GetIrP4Info().built_in_tables().at( + pdpi::GetMulticastGroupTableName())); + + // Within a given multicast entry, replicas must be unique. + if (replica.ok() && + unique_replicas + .insert(std::make_pair(replica->instance(), replica->port())) + .second) { + *multicast_group_entry->add_replicas() = std::move(*replica); + } + } +} + // Randomly changes the table_entry, without affecting the key fields. void FuzzNonKeyFields(absl::BitGen* gen, const FuzzerConfig& config, const SwitchState& switch_state, @@ -521,6 +644,22 @@ void FuzzNonKeyFields(absl::BitGen* gen, const FuzzerConfig& config, // TODO: also fuzz meters } +// Randomly changes the entity, without affecting the key fields. +void FuzzNonKeyFields(absl::BitGen* gen, const FuzzerConfig& config, + const SwitchState& switch_state, Entity* entity) { + // This function only supports table entries and multicast group entries. + CHECK(entity->has_table_entry() || // Crash OK + entity->packet_replication_engine_entry().has_multicast_group_entry()); + if (entity->has_table_entry()) { + FuzzNonKeyFields(gen, config, switch_state, entity->mutable_table_entry()); + } + if (entity->packet_replication_engine_entry().has_multicast_group_entry()) { + FuzzNonKeyFields(gen, config, switch_state, + entity->mutable_packet_replication_engine_entry() + ->mutable_multicast_group_entry()); + } +} + // Generates `WeightedItems` for all valid table_ids where weight is equal to // table_size. std::vector> GenerateAllValidWeightedTableIds( @@ -562,6 +701,30 @@ std::vector> GenerateModifiableWeightedTableIds( return modifiable_weighted_table_ids; } +// Uses the Entity type (and if table entry, its `table_id`) to fuzz a new +// Entity. +// Pre-requisites: Entity must be a table entry with a table id or a multicast +// group entry. All other fields will be ignored. +absl::Status FuzzValidEntity(absl::BitGen* gen, const FuzzerConfig& config, + const SwitchState& switch_state, Entity& entity) { + CHECK((entity.has_table_entry() && // Crash OK + entity.table_entry().table_id() != 0) || + entity.packet_replication_engine_entry().has_multicast_group_entry()); + + if (entity.has_table_entry()) { + ASSIGN_OR_RETURN(*entity.mutable_table_entry(), + FuzzValidTableEntry(gen, config, switch_state, + entity.table_entry().table_id())); + } + if (entity.packet_replication_engine_entry().has_multicast_group_entry()) { + ASSIGN_OR_RETURN(*entity.mutable_packet_replication_engine_entry() + ->mutable_multicast_group_entry(), + FuzzValidMulticastGroupEntry(gen, config, switch_state)); + } + + return absl::OkStatus(); +} + // Randomly generates an INSERT, MODIFY or DELETE update. The update may be // mutated (see go/p4-fuzzer-design for mutation types). AnnotatedUpdate FuzzUpdate(absl::BitGen* gen, const FuzzerConfig& config, @@ -569,12 +732,16 @@ AnnotatedUpdate FuzzUpdate(absl::BitGen* gen, const FuzzerConfig& config, CHECK_GT(AllValidTablesForP4RtRole(config).size(), 0) // Crash OK << "Cannot generate updates for program with no tables"; + bool fuzz_multicast_update = + absl::Bernoulli(*gen, config.fuzz_multicast_group_entry_probability); + Mutation mutation; - bool do_mutate = false; + // Multicast updates do not support mutations yet. + bool do_mutate = !fuzz_multicast_update && + absl::Bernoulli(*gen, config.mutate_update_probability); std::vector mutation_table_ids; - if (absl::Bernoulli(*gen, config.mutate_update_probability)) { - do_mutate = true; + if (do_mutate) { mutation = FuzzMutation(gen, config); switch (mutation) { case Mutation::INVALID_ACTION_SELECTOR_WEIGHT: @@ -616,50 +783,56 @@ AnnotatedUpdate FuzzUpdate(absl::BitGen* gen, const FuzzerConfig& config, } } - Update::Type type = FuzzUpdateType(gen, config, switch_state); + Update::Type type = FuzzUpdateType(gen, config, switch_state, + /*is_multicast=*/fuzz_multicast_update); Update update; update.set_type(type); + Entity& entity = *update.mutable_entity(); switch (type) { case Update::INSERT: { - int table_id; - if (do_mutate) { - table_id = UniformFromSpan(gen, mutation_table_ids); + if (fuzz_multicast_update) { + entity.mutable_packet_replication_engine_entry() + ->mutable_multicast_group_entry(); } else { - table_id = FuzzTableId(gen, config); + if (do_mutate) { + entity.mutable_table_entry()->set_table_id( + UniformFromSpan(gen, mutation_table_ids)); + } else { + entity.mutable_table_entry()->set_table_id(FuzzTableId(gen, config)); + } } - // This might (with low probability) generate an entry that already - // exists leading to a duplicate insert. This is fine since `IsBadUpdate` - // will catch it and discard the update. - absl::StatusOr table_entry = - FuzzValidTableEntry(gen, config, switch_state, table_id); - if (!table_entry.ok()) { + // This might (with low probability) generate an entity that already + // exists leading to a duplicate insert. This is fine since + // `IsAccidentallyInvalidUpdate` will catch it and discard the update. + if (!FuzzValidEntity(gen, config, switch_state, entity).ok()) { // Retry. return FuzzUpdate(gen, config, switch_state); } - *update.mutable_entity()->mutable_table_entry() = *table_entry; - - break; - } - case Update::MODIFY: { - const int table_id = FuzzModifiableTableId(gen, config, switch_state); - TableEntry table_entry = - UniformValueFromMap(gen, switch_state.GetTableEntries(table_id)); - FuzzNonKeyFields(gen, config, switch_state, &table_entry); - *update.mutable_entity()->mutable_table_entry() = table_entry; break; } + case Update::MODIFY: case Update::DELETE: { - const int table_id = FuzzNonEmptyTableId(gen, config, switch_state); - // Within a single call of FuzzWriteRequest, this might delete the same - // entry multiple times. This is fine since `IsBadUpdate` will catch it - // and discard the update. - TableEntry table_entry = - UniformValueFromMap(gen, switch_state.GetTableEntries(table_id)); - FuzzNonKeyFields(gen, config, switch_state, &table_entry); - *update.mutable_entity()->mutable_table_entry() = table_entry; + if (fuzz_multicast_update) { + *entity.mutable_packet_replication_engine_entry() + ->mutable_multicast_group_entry() = + UniformValueFromMap(gen, switch_state.GetMulticastGroupEntries()); + } else { + const int table_id = + type == Update::DELETE + // Tables must be non-empty if the update is a delete. + ? FuzzNonEmptyTableId(gen, config, switch_state) + // Tables must be modifiable if the update is a modify. + : FuzzModifiableTableId(gen, config, switch_state); + // Within a single call of FuzzWriteRequest, this might delete the same + // entry multiple times. This is fine since + // `IsAccidentallyInvalidUpdate` will catch it and discard the update. + *entity.mutable_table_entry() = + UniformValueFromMap(gen, switch_state.GetTableEntries(table_id)); + } + FuzzNonKeyFields(gen, config, switch_state, &entity); break; } default: @@ -731,6 +904,7 @@ const std::vector AllValidActions( for (const auto& action : table.entry_actions()) { // Skip deprecated, unused, and disallowed actions. if (pdpi::IsElementDeprecated(action.action().preamble().annotations()) || + action.action().is_unsupported() || IsDisabledForFuzzing(config, action.action().preamble().name())) continue; actions.push_back(action); @@ -1057,7 +1231,6 @@ absl::StatusOr FuzzAction( return action; } - // Gets a set of actions with a skewed distribution of weights, which add up to // at most the max_group_size of the action profile by repeatedly sampling a // uniform weight from 1 to the maximum possible weight remaining. We could @@ -1082,8 +1255,8 @@ absl::StatusOr FuzzActionProfileActionSet( ? action_profile.max_group_size() : kActionProfileActionSetMaxCardinality; int number_of_actions = Uniform( - absl::IntervalClosedClosed, *gen, - config.no_empty_action_profile_groups ? 1 : 0, max_number_of_actions); + absl::IntervalClosedClosed, *gen, + config.no_empty_action_profile_groups ? 1 : 0, max_number_of_actions); // Get the max member weight from the P4Info if it is set. int max_member_weight = @@ -1139,10 +1312,10 @@ absl::StatusOr FuzzActionProfileActionSet( // We want to randomly select some number of actions up to our max // cardinality; however, we can't have more actions than the amount of // weight we support since every action must have weight >= 1. - int number_of_actions = Uniform( - absl::IntervalClosedClosed, *gen, - config.no_empty_action_profile_groups ? 1 : 0, - std::min(unallocated_weight, kActionProfileActionSetMaxCardinality)); + int number_of_actions = Uniform( + absl::IntervalClosedClosed, *gen, + config.no_empty_action_profile_groups ? 1 : 0, + std::min(unallocated_weight, kActionProfileActionSetMaxCardinality)); for (int i = 0; i < number_of_actions; i++) { // Since each action must have at least weight 1, we need to take the @@ -1192,6 +1365,28 @@ absl::StatusOr FuzzAction( return result; } +absl::StatusOr FuzzValidMulticastGroupEntry( + absl::BitGen* gen, const FuzzerConfig& config, + const SwitchState& switch_state) { + MulticastGroupEntry entry; + + // Inherited from v1model , see `standard_metadata_t.mcast_grp`. + // https://github.com/p4lang/p4c/blob/main/p4include/v1model.p4 + constexpr int kMulticastGroupIdWidth = 16; + + // NOTE: References from `multicast_group_id` are not implemented since there + // is no current use case, but an implementation should exist for general + // purposes. + while (entry.multicast_group_id() == 0) { + entry.set_multicast_group_id(FuzzUint64(gen, kMulticastGroupIdWidth)); + } + + // Fills in replicas randomly. + FuzzNonKeyFields(gen, config, switch_state, &entry); + + return entry; +}; + // TODO: Optional fields with @refers_to will not be properly // fuzzed if they refer to fields that currently have no existing entry. // Fuzzing fails for this, but it should simply omit the optional. Thankfully, @@ -1333,7 +1528,7 @@ AnnotatedWriteRequest FuzzWriteRequest(absl::BitGen* gen, const SwitchState& switch_state, absl::optional max_batch_size) { AnnotatedWriteRequest request; - absl::flat_hash_set entry_keys_in_request; + absl::flat_hash_set entity_keys_in_request; while (absl::Bernoulli(*gen, kAddUpdateProbability)) { if (max_batch_size.has_value() && @@ -1348,18 +1543,17 @@ AnnotatedWriteRequest FuzzWriteRequest(absl::BitGen* gen, // only if our success rate is significantly worse than this. int update_attempts = 1; while (IsAccidentallyInvalidUpdate(config, switch_state, request, - entry_keys_in_request, update) && + entity_keys_in_request, update) && update_attempts < 10000) { update = FuzzUpdate(gen, config, switch_state); update_attempts++; } - if (!IsAccidentallyInvalidUpdate(config, switch_state, request, - entry_keys_in_request, update)) { + if (auto update_entity_key = EntityKey::MakeEntityKey(update.pi().entity()); + update_entity_key.ok() && + !IsAccidentallyInvalidUpdate(config, switch_state, request, + entity_keys_in_request, update)) { *request.add_updates() = update; - if (update.pi().entity().has_table_entry()) { - entry_keys_in_request.insert( - TableEntryKey(update.pi().entity().table_entry())); - } + entity_keys_in_request.insert(*update_entity_key); } } diff --git a/p4_fuzzer/fuzz_util.h b/p4_fuzzer/fuzz_util.h index 9268ca2a..83a9af9c 100644 --- a/p4_fuzzer/fuzz_util.h +++ b/p4_fuzzer/fuzz_util.h @@ -242,6 +242,12 @@ absl::StatusOr FuzzValidTableEntry( absl::BitGen* gen, const FuzzerConfig& config, const SwitchState& switch_state, const uint32_t table_id); +// Randomly generates a multicast group entry. May fail if a reference to +// another table is required. +absl::StatusOr FuzzValidMulticastGroupEntry( + absl::BitGen* gen, const FuzzerConfig& config, + const SwitchState& switch_state); + // Randomly generates a set of valid table entries that, when installed in order // to an empty switch state, all install correctly. std::vector ValidForwardingEntries( diff --git a/p4_fuzzer/fuzz_util_test.cc b/p4_fuzzer/fuzz_util_test.cc index 187fbe63..d0f17b1d 100644 --- a/p4_fuzzer/fuzz_util_test.cc +++ b/p4_fuzzer/fuzz_util_test.cc @@ -32,11 +32,13 @@ #include "gutil/collections.h" #include "gutil/proto_matchers.h" #include "gutil/status_matchers.h" +#include "gutil/testing.h" #include "p4/config/v1/p4info.pb.h" #include "p4/v1/p4runtime.pb.h" #include "p4_fuzzer/fuzzer.pb.h" #include "p4_fuzzer/fuzzer_config.h" #include "p4_fuzzer/test_utils.h" +#include "p4_pdpi/built_ins.h" #include "p4_pdpi/ir.pb.h" namespace p4_fuzzer { @@ -204,6 +206,175 @@ TEST(FuzzUtilTest, FuzzWriteRequestAreReproducibleWithState) { } } +TEST(FuzzUtilTest, FuzzWriteRequestCanFuzzMulticastGroupEntry) { + FuzzerTestState fuzzer_state = ConstructStandardFuzzerTestState(); + absl::BitGen gen; + // Ensure a multicast entity is fuzzed. + fuzzer_state.config.fuzz_multicast_group_entry_probability = 1.0; + + AnnotatedWriteRequest write_request; + // Because there is a non-zero chance to fuzz no updates. + while (write_request.updates().empty()) { + write_request = + FuzzWriteRequest(&gen, fuzzer_state.config, fuzzer_state.switch_state, + /*max_batch_size=*/1); + } + + EXPECT_TRUE(write_request.updates(0) + .pi() + .entity() + .packet_replication_engine_entry() + .has_multicast_group_entry()); +} + +// This test uses behavior specific to the main.p4 program. In main.p4, +// `refers_to_multicast_by_action_table` is a table that uses an action whose +// parameter refers to multicast group id. +TEST(FuzzUtilTest, FuzzTableFailsWhenNoMulticastReferenceIsAvailable) { + FuzzerTestState fuzzer_state = ConstructStandardFuzzerTestState(); + + // Generate entry referring to multicast and fail due to no references. + pdpi::IrTableDefinition multicast_dependent_definition = + gutil::FindOrDie(fuzzer_state.config.GetIrP4Info().tables_by_name(), + "refers_to_multicast_by_action_table"); + absl::BitGen gen; + EXPECT_THAT( + FuzzValidTableEntry(&gen, fuzzer_state.config, fuzzer_state.switch_state, + multicast_dependent_definition), + gutil::StatusIs(absl::StatusCode::kFailedPrecondition)); +} + +// This test uses behavior specific to the main.p4 program. In main.p4, +// `refers_to_multicast_by_action_table` is a table that uses an action whose +// parameter refers to multicast group id. +TEST(FuzzUtilTest, FuzzTableRespectsMulticastReferences) { + FuzzerTestState fuzzer_state = ConstructStandardFuzzerTestState(); + + // Store multicast group entry being referenced. + ASSERT_OK(fuzzer_state.switch_state.ApplyUpdate( + gutil::ParseProtoOrDie(R"pb( + type: INSERT + entity { + packet_replication_engine_entry { + multicast_group_entry { multicast_group_id: 0x86 } + } + } + )pb"))); + + // Generate entry referring to multicast and ensure the action references + // multicast group id. + pdpi::IrTableDefinition multicast_dependent_definition = + gutil::FindOrDie(fuzzer_state.config.GetIrP4Info().tables_by_name(), + "refers_to_multicast_by_action_table"); + absl::BitGen gen; + EXPECT_THAT( + FuzzValidTableEntry(&gen, fuzzer_state.config, fuzzer_state.switch_state, + multicast_dependent_definition), + IsOkAndHolds(Partially(EqualsProto(R"pb( + action { + action { + # Action id for `refers_to_multicast_action`. + action_id: 18598416 + params { param_id: 1 value: "\x86" } + } + } + )pb")))); +} + +// This test uses behavior specific to the main.p4 program. In main.p4, +// built-in multicast group table replicas refer to fields in +// `referenced_by_multicast_replica_table`. +TEST(FuzzUtilTest, FuzzMulticastRespectsReplicaReferences) { + FuzzerTestState fuzzer_state = ConstructStandardFuzzerTestState(); + + // Store table entry being referenced. + ASSERT_OK(fuzzer_state.switch_state.ApplyUpdate( + gutil::ParseProtoOrDie(R"pb( + type: INSERT + entity { + table_entry { + table_id: 49197097 + # Port + match { + field_id: 1 + exact { value: "sample_port" } + } + # Instance + match { + field_id: 2 + exact { value: "\x86" } + } + action { action { action_id: 16777221 } } + } + } + )pb"))); + + absl::BitGen gen; + p4::v1::MulticastGroupEntry multicast_entry; + // Fuzz until multicast group entry has the one replica. + while (multicast_entry.replicas().empty()) { + ASSERT_OK_AND_ASSIGN(multicast_entry, FuzzValidMulticastGroupEntry( + &gen, fuzzer_state.config, + fuzzer_state.switch_state)); + } + + // Multicast group cannot be 0. + EXPECT_NE(multicast_entry.multicast_group_id(), 0); + + // Ensure the one replica references values in table entry. + ASSERT_EQ(multicast_entry.replicas_size(), 1); + EXPECT_THAT(multicast_entry, Partially(EqualsProto(R"pb( + replicas { instance: 0x86 port: "sample_port" } + )pb"))); +} + +// This test uses behavior specific to the main.p4 program. In main.p4, +// built-in multicast group table replicas refer to fields in +// `referenced_by_multicast_replica_table`. +TEST(FuzzUtilTest, FuzzMulticastAreReproducibleWithState) { + FuzzerTestState fuzzer_state = ConstructStandardFuzzerTestState(); + + pdpi::IrTableDefinition multicast_dependency_definition = + gutil::FindOrDie(fuzzer_state.config.GetIrP4Info().tables_by_name(), + "referenced_by_multicast_replica_table"); + + absl::BitGen init_gen; + + // Generate up to 50 random table entries that can be referenced by multicast. + for (int i = 0; i < 50; ++i) { + p4::v1::Update update; + update.set_type(p4::v1::Update::INSERT); + ASSERT_OK_AND_ASSIGN(*update.mutable_entity()->mutable_table_entry(), + FuzzValidTableEntry(&init_gen, fuzzer_state.config, + fuzzer_state.switch_state, + multicast_dependency_definition)); + ASSERT_OK(fuzzer_state.switch_state.ApplyUpdate(update)); + } + + LOG(INFO) << "State size = " + << fuzzer_state.switch_state.GetNumTableEntries(); + + // Use the same sequence seed for both generators. + absl::SeedSeq seed; + absl::BitGen gen_0(seed); + absl::BitGen gen_1(seed); + + // Create 50 instances and verify that they are identical. + for (int i = 0; i < 20; ++i) { + ASSERT_OK_AND_ASSIGN( + p4::v1::MulticastGroupEntry entry0, + FuzzValidMulticastGroupEntry(&gen_0, fuzzer_state.config, + fuzzer_state.switch_state)); + + ASSERT_OK_AND_ASSIGN( + p4::v1::MulticastGroupEntry entry1, + FuzzValidMulticastGroupEntry(&gen_1, fuzzer_state.config, + fuzzer_state.switch_state)); + + EXPECT_THAT(entry0, EqualsProto(entry1)); + } +} + // Test that FuzzActionProfileActionSet correctly generates an ActionProfile // Action Set of acceptable weights and size (derived from max_group_size and // kActionProfileActionSetMaxCardinality). @@ -399,6 +570,42 @@ TEST(FuzzUtilTest, FuzzWriteRequestRespectsDisallowList) { } } +TEST(FuzzUtilTest, FuzzValidTableEntryRespectsDisallowList) { + FuzzerTestState fuzzer_state = ConstructStandardFuzzerTestState(); + fuzzer_state.config.disabled_fully_qualified_names = { + "ingress.ternary_table.ipv6_upper_64_bits", + "ingress.ternary_table.normal", + "ingress.ternary_table.mac", + "ingress.ternary_table.unsupported_field", + }; + + ASSERT_OK_AND_ASSIGN( + const pdpi::IrTableDefinition& ternary_table, + gutil::FindOrStatus(fuzzer_state.config.GetIrP4Info().tables_by_name(), + "ternary_table")); + + absl::flat_hash_set disallowed_ids; + for (const auto& path : fuzzer_state.config.disabled_fully_qualified_names) { + std::vector parts = absl::StrSplit(path, '.'); + ASSERT_OK_AND_ASSIGN( + const pdpi::IrMatchFieldDefinition& match, + gutil::FindOrStatus(ternary_table.match_fields_by_name(), + parts[parts.size() - 1])); + disallowed_ids.insert(match.match_field().id()); + } + + for (int i = 0; i < 1000; i++) { + ASSERT_OK_AND_ASSIGN( + p4::v1::TableEntry entry, + FuzzValidTableEntry(&fuzzer_state.gen, fuzzer_state.config, + fuzzer_state.switch_state, + ternary_table.preamble().id())); + for (const auto& match : entry.match()) { + EXPECT_THAT(match.field_id(), Not(AnyOfArray(disallowed_ids))); + } + } +} + TEST(FuzzUtilTest, FuzzActionRespectsDisallowList) { FuzzerTestState fuzzer_state = ConstructStandardFuzzerTestState(); ASSERT_OK_AND_ASSIGN( diff --git a/p4_fuzzer/fuzzer_config.h b/p4_fuzzer/fuzzer_config.h index e4a72c67..7e4b1596 100644 --- a/p4_fuzzer/fuzzer_config.h +++ b/p4_fuzzer/fuzzer_config.h @@ -60,6 +60,9 @@ class FuzzerConfig { std::string role = "sdn_controller"; // The probability of performing a mutation on a given table entry. float mutate_update_probability = 0.1; + // The probability of fuzzing a multicast group entry when fuzzing an update. + // TODO: b/319260502 - Change from zero once switch supports multicast. + float fuzz_multicast_group_entry_probability = 0; // -- Optional --------------------------------------------------------------- // The set of tables where the fuzzer should treat their resource guarantees diff --git a/p4_fuzzer/switch_state.cc b/p4_fuzzer/switch_state.cc index 61236594..4f53f493 100644 --- a/p4_fuzzer/switch_state.cc +++ b/p4_fuzzer/switch_state.cc @@ -29,6 +29,7 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" +#include "absl/types/span.h" #include "glog/logging.h" #include "google/protobuf/util/message_differencer.h" #include "gutil/collections.h" @@ -51,8 +52,11 @@ namespace { using ::gutil::FindOrDie; using ::gutil::FindPtrOrStatus; using ::gutil::PrintTextProto; +using ::p4::v1::Entity; +using ::p4::v1::MulticastGroupEntry; using ::p4::v1::TableEntry; using ::p4::v1::Update; +using ::pdpi::IrEntity; using ::pdpi::IrP4Info; using ::pdpi::IrTableEntry; @@ -173,6 +177,29 @@ absl::StatusOr ReasonActionProfileCanAccommodateTableEntry( } // namespace +// Returns the canonical form of `entity` according to the P4 Runtime Spec +// https://s3-us-west-2.amazonaws.com/p4runtime/ci/main/P4Runtime-Spec.html#sec-bytestrings. +// TODO: Canonical form is achieved by performing an IR roundtrip +// translation. This ties correctness to IR functionality. Local +// canonicalization would be preferred. +absl::StatusOr CanonicalizeEntity(const IrP4Info& info, + const Entity& entity, bool key_only) { + auto pdpi_options = pdpi::TranslationOptions{ + .key_only = key_only, + }; + // IR->PI translation includes canonicalization so a PI->IR->PI translation is + // performed for canonicalization. + ASSIGN_OR_RETURN(IrEntity ir_entity, + pdpi::PiEntityToIr(info, entity, pdpi_options), + _ << "Could not canonicalize: PiToIr Error\n" + << entity.DebugString()); + ASSIGN_OR_RETURN(Entity canonical_entity, + pdpi::IrEntityToPi(info, ir_entity, pdpi_options), + _ << "Could not canonicalize: IrToPi Error\n" + << entity.DebugString()); + return canonical_entity; +} + absl::StatusOr CanonicalizeTableEntry(const IrP4Info& info, const TableEntry& entry, bool key_only) { @@ -208,6 +235,8 @@ void SwitchState::ClearTableEntries() { unordered_tables_[table_id] = UnorderedTableEntries(); current_resource_statistics_[table_id] = ResourceStatistics(); } + ordered_multicast_entries_ = {}; + unordered_multicast_entries_ = {}; current_entries_ = 0; } @@ -331,6 +360,17 @@ std::optional SwitchState::GetTableEntry( return std::nullopt; } +std::optional SwitchState::GetMulticastGroupEntry( + const MulticastGroupEntry& entry) const { + if (auto table_iter = + unordered_multicast_entries_.find(entry.multicast_group_id()); + table_iter != unordered_multicast_entries_.end()) { + auto [table_key, table_entry] = *table_iter; + return table_entry; + } + return std::nullopt; +} + absl::StatusOr SwitchState::GetPeakResourceStatistics( int table_id) const { if (!peak_resource_statistics_.contains(table_id)) { @@ -418,7 +458,116 @@ absl::Status SwitchState::UpdateResourceStatistics(const TableEntry& entry, return absl::OkStatus(); } +absl::Status SwitchState::ApplyMulticastUpdate(const Update& update) { + ASSIGN_OR_RETURN( + Entity canonical_entity, + CanonicalizeEntity(ir_p4info_, update.entity(), + /*key_only=*/update.type() == Update::DELETE)); + const p4::v1::MulticastGroupEntry& multicast_group_entry = + canonical_entity.packet_replication_engine_entry() + .multicast_group_entry(); + int multicast_group_id = multicast_group_entry.multicast_group_id(); + switch (update.type()) { + case Update::INSERT: { + auto [ordered_iter, ordered_not_present] = + ordered_multicast_entries_.insert( + /*value=*/{multicast_group_id, multicast_group_entry}); + + auto [unordered_iter, unordered_not_present] = + unordered_multicast_entries_.insert( + /*value=*/{multicast_group_id, multicast_group_entry}); + + if (ordered_not_present != unordered_not_present) { + return gutil::InternalErrorBuilder() + << "Ordered Table and Unordered Table out of sync. Entry " + << (ordered_not_present ? "not present" : "present") + << " in Ordered Table but " + << (unordered_not_present ? "not present" : "present") + << " in Unordered Table.\n" + << "Offending Entry Update\n" + << update.DebugString(); + } + + if (!ordered_not_present) { + return gutil::InvalidArgumentErrorBuilder() + << "Cannot install the same table entry multiple times. Update: " + << update.DebugString(); + } + + break; + } + case Update::DELETE: { + int ordered_entries_erased = + ordered_multicast_entries_.erase(multicast_group_id); + int unordered_entries_erased = + unordered_multicast_entries_.erase(multicast_group_id); + + if (ordered_entries_erased != unordered_entries_erased) { + return gutil::InternalErrorBuilder() + << "Ordered Table and Unordered Table out of sync. Entry " + << (ordered_entries_erased == 0 ? "not present" : "present") + << " in Ordered Table but " + << (unordered_entries_erased == 0 ? "not present" : "present") + << " in Unordered Table.\n" + << "Offending Update\n" + << update.DebugString(); + } + + if (ordered_entries_erased != 1) { + return gutil::InvalidArgumentErrorBuilder() + << "Cannot erase non-existent table entries. Update: " + << update.DebugString(); + } + + break; + } + + case Update::MODIFY: { + auto [ordered_iter, ordered_not_present] = + ordered_multicast_entries_.insert_or_assign( + /*k=*/multicast_group_id, + /*obj=*/multicast_group_entry); + + auto [unordered_iter, unordered_not_present] = + unordered_multicast_entries_ + .insert_or_assign(/*k=*/ + multicast_group_id, + /*obj=*/multicast_group_entry); + + if (ordered_not_present != unordered_not_present) { + return gutil::InternalErrorBuilder() + << "Ordered Table and Unordered Table out of sync. Entry " + << (ordered_not_present ? "not present" : "present") + << " in Ordered Table but " + << (unordered_not_present ? "not present" : "present") + << " in Unordered Table.\n" + << "Offending Update\n" + << update.DebugString(); + } + + if (ordered_not_present) { + return gutil::InvalidArgumentErrorBuilder() + << "Cannot modify a non-existing update. Update: " + << update.DebugString(); + } + + break; + } + + default: + LOG(FATAL) << "Update of unsupported type: " // Crash OK + << update.DebugString(); + } + return absl::OkStatus(); +} + absl::Status SwitchState::ApplyUpdate(const Update& update) { + if (update.entity() + .packet_replication_engine_entry() + .has_multicast_group_entry()) { + return ApplyMulticastUpdate(update); + } + const int table_id = update.entity().table_entry().table_id(); auto& ordered_table = FindOrDie(ordered_tables_, table_id); @@ -528,14 +677,14 @@ absl::Status SwitchState::ApplyUpdate(const Update& update) { return absl::OkStatus(); } -absl::Status SwitchState::SetTableEntries( - absl::Span table_entries) { +absl::Status SwitchState::SetEntities( + absl::Span entities) { ClearTableEntries(); p4::v1::Update update; update.set_type(p4::v1::Update::INSERT); - for (const p4::v1::TableEntry& entry : table_entries) { - *update.mutable_entity()->mutable_table_entry() = entry; + for (const Entity& entity : entities) { + *update.mutable_entity() = entity; RETURN_IF_ERROR(ApplyUpdate(update)); } @@ -624,6 +773,11 @@ std::string SwitchState::SwitchStateSummary() const { } } } + + absl::StrAppendFormat(&res, "\n % 12d% 16s% 18s %s", + ordered_multicast_entries_.size(), "N/A", "N/A", + "builtin::multicast_group_table"); + return absl::StrFormat( "State(\n % 12s% 16s% 18s table_name\n % 12d% 16d% 18s total " "number of table entries%s\n * marks tables where max size >= " @@ -683,6 +837,39 @@ absl::Status SwitchState::CheckConsistency() const { } } } + + if (unordered_multicast_entries_.size() != + ordered_multicast_entries_.size()) { + return absl::InternalError(absl::StrFormat( + "Number of ordered multicast group entries differs from number of " + "unordered multicast group entries. Ordered Entries: %d Unordered " + "Entries: %d", + ordered_multicast_entries_.size(), + unordered_multicast_entries_.size())); + } + + // Ensure that every `table_entry` in an ordered table has a corresponding + // `table_entry` in the unordered table. + for (const auto& [multicast_group_id, ordered_entry] : + ordered_multicast_entries_) { + std::optional unordered_entry = + GetMulticastGroupEntry(ordered_entry); + if (unordered_entry == std::nullopt) { + return absl::InternalError(absl::StrFormat( + "Ordered multicast group entry %s is missing corresponding " + "unordered multicast group entry", + ordered_entry.DebugString())); + } + + google::protobuf::util::MessageDifferencer differ; + if (!gutil::ProtoEqual(ordered_entry, *unordered_entry, differ)) { + return absl::InternalError(absl::StrFormat( + "Ordered entry differs from unordered entry\n " + "Ordered entry: %s Unordered Entry: %s", + ordered_entry.DebugString(), unordered_entry->DebugString())); + } + } + return absl::OkStatus(); } diff --git a/p4_fuzzer/switch_state.h b/p4_fuzzer/switch_state.h index b38a5986..977424b4 100644 --- a/p4_fuzzer/switch_state.h +++ b/p4_fuzzer/switch_state.h @@ -24,7 +24,6 @@ #include "absl/container/btree_map.h" #include "absl/container/flat_hash_map.h" -#include "absl/container/flat_hash_set.h" #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/types/optional.h" @@ -129,11 +128,27 @@ class SwitchState { // Returns the total number of table entries in all tables. int64_t GetNumTableEntries() const; + // Returns the number of multicast group entries. + int64_t GetNumMulticastEntries() const { + return ordered_multicast_entries_.size(); + }; + // Returns the current state of a table entry (or nullopt if it is not // present). Only the uniquely identifying fields of entry are considered. std::optional GetTableEntry( const p4::v1::TableEntry& entry) const; + // Returns the current state of a multicast group entry (or nullopt if it is + // not present). Only multicast_group_id is considered when retrieving entry. + std::optional GetMulticastGroupEntry( + const p4::v1::MulticastGroupEntry& entry) const; + + // Returns all multicast group entries. + const absl::btree_map& + GetMulticastGroupEntries() const { + return ordered_multicast_entries_; + } + // Returns the list of all non-const table IDs in the underlying P4 program. const std::vector AllTableIds() const; @@ -152,9 +167,8 @@ class SwitchState { // Returns max number of entries seen on the switch. int GetMaxEntriesSeen() const { return peak_entries_seen_; } - // Updates all tables to match the given set of table entries. - absl::Status SetTableEntries( - absl::Span table_entries); + // Updates all tables to match the given set of entities. + absl::Status SetEntities(absl::Span entities); // Clears all table entries. void ClearTableEntries(); @@ -205,6 +219,15 @@ class SwitchState { // Tracks peak resource usage of entire switch. int peak_entries_seen_ = 0; + // Internal overload used to apply multicast updates. + absl::Status ApplyMulticastUpdate(const p4::v1::Update& update); + // Multicast group entries are keyed by their multicast group id. + // Btree copy used for deterministic ordering. + absl::btree_map ordered_multicast_entries_; + // Copy of above used for fast lookups. + absl::flat_hash_map + unordered_multicast_entries_; + pdpi::IrP4Info ir_p4info_; }; diff --git a/p4_fuzzer/switch_state_assert_entry_equality_test.expected.output b/p4_fuzzer/switch_state_assert_entry_equality_test.expected.output index 3331d70e..f654c824 100644 --- a/p4_fuzzer/switch_state_assert_entry_equality_test.expected.output +++ b/p4_fuzzer/switch_state_assert_entry_equality_test.expected.output @@ -214,6 +214,7 @@ State( 0 0 1024 referenced_by_multicast_replica_table 0 0 1024 referring_by_match_field_table 0 0 1024 golden_test_friendly_table + 0 N/A N/A builtin::multicast_group_table * marks tables where max size >= guaranteed size. ) @@ -263,6 +264,7 @@ State( 0 0 1024 referenced_by_multicast_replica_table 0 0 1024 referring_by_match_field_table 0 0 1024 golden_test_friendly_table + 0 N/A N/A builtin::multicast_group_table * marks tables where max size >= guaranteed size. ) @@ -312,6 +314,7 @@ State( 0 0 1024 referenced_by_multicast_replica_table 0 0 1024 referring_by_match_field_table 0 0 1024 golden_test_friendly_table + 0 N/A N/A builtin::multicast_group_table * marks tables where max size >= guaranteed size. ) @@ -361,6 +364,7 @@ State( 0 0 1024 referenced_by_multicast_replica_table 0 0 1024 referring_by_match_field_table 0 0 1024 golden_test_friendly_table + 0 N/A N/A builtin::multicast_group_table * marks tables where max size >= guaranteed size. ) @@ -410,5 +414,6 @@ State( 0 0 1024 referenced_by_multicast_replica_table 0 0 1024 referring_by_match_field_table 0 0 1024 golden_test_friendly_table + 0 N/A N/A builtin::multicast_group_table * marks tables where max size >= guaranteed size. ) diff --git a/p4_fuzzer/switch_state_assert_entry_equality_test_runner.cc b/p4_fuzzer/switch_state_assert_entry_equality_test_runner.cc index 0dfc877e..7af79b2e 100644 --- a/p4_fuzzer/switch_state_assert_entry_equality_test_runner.cc +++ b/p4_fuzzer/switch_state_assert_entry_equality_test_runner.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "absl/status/status.h" @@ -11,6 +12,7 @@ #include "absl/types/span.h" #include "google/protobuf/util/message_differencer.h" #include "gutil/collections.h" +#include "gutil/status.h" #include "gutil/testing.h" #include "p4/config/v1/p4info.pb.h" #include "p4/v1/p4runtime.pb.h" @@ -25,6 +27,7 @@ namespace { using ::p4::config::v1::P4Info; using ::p4::config::v1::Preamble; using ::p4::config::v1::Table; +using ::p4::v1::Entity; using ::p4::v1::TableEntry; using ::pdpi::CreateIrP4Info; using ::pdpi::IrP4Info; @@ -199,14 +202,16 @@ std::vector SwitchStateSummaryTestCases() { }); } - // Exceeding max capacities for WCMP tables with SUM_OF_WEIGHTS and - // SUM_OF_MEMBERS size semantics. + // Exceeding max capacities for WCMP tables with SumOfWeights and + // SumOfMembers size semantics. { IrP4Info ir_info_sum_of_weights = pdpi::GetTestIrP4Info(); IrP4Info ir_info_sum_of_members = pdpi::GetTestIrP4Info(); for (auto& [_, action_profile] : *ir_info_sum_of_members.mutable_action_profiles_by_id()) { - action_profile.mutable_action_profile()->mutable_sum_of_members()->set_max_member_weight(4096); + action_profile.mutable_action_profile() + ->mutable_sum_of_members() + ->set_max_member_weight(4096); } // Relevant constants. @@ -314,6 +319,18 @@ absl::StatusOr> IrToPiVector( return pi_entries; } +// TODO: b/316926338 - Remove once test is refactored to use entities. +std::vector PiEntriesToEntities(std::vector pi_entries) { + std::vector pi_entities; + pi_entities.reserve(pi_entries.size()); + for (const auto& pi_entry : pi_entries) { + Entity entity; + *entity.mutable_table_entry() = pi_entry; + pi_entities.push_back(std::move(entity)); + } + return pi_entities; +} + absl::Status main() { IrP4Info ir_info = GetIrP4Info(); SwitchState state(ir_info); @@ -326,7 +343,7 @@ absl::Status main() { ASSIGN_OR_RETURN(std::vector pi_switch_entries, IrToPiVector(test.switch_entries, ir_info)); - RETURN_IF_ERROR(state.SetTableEntries(pi_fuzzer_entries)); + RETURN_IF_ERROR(state.SetEntities(PiEntriesToEntities(pi_fuzzer_entries))); RETURN_IF_ERROR(state.CheckConsistency()); std::cout << "#########################################################\n" @@ -351,7 +368,7 @@ absl::Status main() { state = SwitchState(test.ir_info); ASSIGN_OR_RETURN(std::vector pi_entries, IrToPiVector(test.entries, test.ir_info)); - RETURN_IF_ERROR(state.SetTableEntries(pi_entries)); + RETURN_IF_ERROR(state.SetEntities(PiEntriesToEntities(pi_entries))); RETURN_IF_ERROR(state.CheckConsistency()); if (test.delete_entries) { state.ClearTableEntries(); diff --git a/p4_fuzzer/switch_state_test.cc b/p4_fuzzer/switch_state_test.cc index f514f3b4..8166de2b 100644 --- a/p4_fuzzer/switch_state_test.cc +++ b/p4_fuzzer/switch_state_test.cc @@ -14,6 +14,7 @@ #include "p4_fuzzer/switch_state.h" #include +#include #include #include "absl/container/flat_hash_set.h" @@ -49,6 +50,7 @@ using ::p4::config::v1::P4Info; using ::p4::config::v1::Preamble; using ::p4::config::v1::Table; using ::p4::v1::ActionProfileAction; +using ::p4::v1::MulticastGroupEntry; using ::p4::v1::TableEntry; using ::p4::v1::Update; using ::pdpi::CreateIrP4Info; @@ -146,6 +148,40 @@ TEST(SwitchStateTest, RuleInsert) { EXPECT_TRUE(state.AllTablesEmpty()); } +TEST(SwitchStateTest, MulticastInsertWorks) { + SwitchState state(GetIrP4Info()); + + Update update = gutil::ParseProtoOrDie(R"pb( + type: INSERT + entity { + packet_replication_engine_entry { + multicast_group_entry { + multicast_group_id: 1 + replicas { port: "some-port" } + } + } + } + )pb"); + ASSERT_OK(state.ApplyUpdate(update)); + + // TODO: b/316926338 - Uncomment once multicast is treated as just another + // table in switch state. + // EXPECT_FALSE(state.AllTablesEmpty()); + + EXPECT_EQ(state.GetMulticastGroupEntries().size(), 1); + + MulticastGroupEntry& entry = *update.mutable_entity() + ->mutable_packet_replication_engine_entry() + ->mutable_multicast_group_entry(); + ASSERT_TRUE(state.GetMulticastGroupEntry(entry) != std::nullopt); + EXPECT_THAT(*state.GetMulticastGroupEntry(entry), EqualsProto(entry)); + + EXPECT_OK(state.CheckConsistency()); + + state.ClearTableEntries(); + EXPECT_TRUE(state.AllTablesEmpty()); +} + TEST(SwitchStateTest, ClearTableEntriesPreservesP4Info) { const IrP4Info p4info = pdpi::GetTestIrP4Info(); SwitchState state(p4info); @@ -409,35 +445,53 @@ TEST(SwitchStateTest, ASSERT_OK(state.CheckConsistency()); } -TEST(SwitchStateTest, SetTableEntriesSetsTableEntries) { +TEST(SwitchStateTest, SetEntitiesSetsEntities) { SwitchState state(GetIrP4Info()); EXPECT_TRUE(state.AllTablesEmpty()); // Call SetTableEntries and ensure it indeed populates the correct tables. - std::vector entries; - entries.emplace_back() = // Entry #1 in table 1. - gutil::ParseProtoOrDie( + std::vector entities; + + entities.emplace_back() = // Entry #1 in multicast table. + gutil::ParseProtoOrDie( + R"pb( + packet_replication_engine_entry { + multicast_group_entry { + multicast_group_id: 7 + replicas { instance: 1 port: "some_port" } + replicas { instance: 2 port: "some_port" } + replicas { instance: 1 port: "some_other_port" } + } + } + )pb"); + entities.emplace_back() = // Entry #1 in table 1. + gutil::ParseProtoOrDie( absl::Substitute(R"pb( - table_id: $0 - match { - field_id: 1 - exact { value: "\378\"" } + table_entry { + table_id: $0 + match { + field_id: 1 + exact { value: "\378\"" } + } } )pb", kSpamTableId)); - entries.emplace_back().set_table_id(kEggTableId); // Entry #1 in table 2. - entries.emplace_back() = // Entry #2 in table 1. - gutil::ParseProtoOrDie( + entities.emplace_back().mutable_table_entry()->set_table_id( + kEggTableId); // Entry #1 in table 2. + entities.emplace_back() = // Entry #2 in table 1. + gutil::ParseProtoOrDie( absl::Substitute(R"pb( - table_id: $0 - match { - field_id: 1 - exact { value: "\377\"" } + table_entry { + table_id: $0 + match { + field_id: 1 + exact { value: "\377\"" } + } } )pb", kSpamTableId)); - ASSERT_OK(state.SetTableEntries(entries)) + ASSERT_OK(state.SetEntities(entities)) << " with the following P4Info:\n " << state.GetIrP4Info().DebugString(); EXPECT_EQ(state.GetNumTableEntries(kSpamTableId), 2); EXPECT_EQ(state.GetNumTableEntries(kEggTableId), 1); diff --git a/p4_symbolic/symbolic/BUILD.bazel b/p4_symbolic/symbolic/BUILD.bazel index 81fa9701..c16d34e9 100644 --- a/p4_symbolic/symbolic/BUILD.bazel +++ b/p4_symbolic/symbolic/BUILD.bazel @@ -50,6 +50,7 @@ cc_library( "//p4_pdpi/netaddr:ipv4_address", "//p4_pdpi/netaddr:ipv6_address", "//p4_pdpi/netaddr:mac_address", + "//p4_pdpi/string_encodings:byte_string", "//p4_pdpi/utils:ir", "//p4_symbolic:z3_util", "//p4_symbolic/ir:ir_cc_proto", @@ -117,6 +118,7 @@ cc_test( "//gutil:status_matchers", "//gutil:testing", "//p4_pdpi:ir_cc_proto", + "//p4_symbolic:z3_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings", "@com_google_googletest//:gtest_main", diff --git a/p4_symbolic/symbolic/action.cc b/p4_symbolic/symbolic/action.cc index c49aca4d..527133db 100644 --- a/p4_symbolic/symbolic/action.cc +++ b/p4_symbolic/symbolic/action.cc @@ -168,7 +168,7 @@ absl::StatusOr EvaluateHexStr(const ir::HexstrValue &hexstr) { ASSIGN_OR_RETURN(pdpi::IrValue parsed_value, values::ParseIrValue(hexstr.value())); - return values::FormatBmv2Value(parsed_value); + return HexStringToZ3Bitvector(hexstr.value()); } absl::StatusOr EvaluateBool(const ir::BoolValue &bool_value) { @@ -335,10 +335,11 @@ absl::Status EvaluateAction(const ir::Action &action, const std::string ¶meter_name = parameter.param().name(); const std::string ¶meter_type_name = parameter.param().type_name().name(); + const int bitwidth = parameter.param().bitwidth(); ASSIGN_OR_RETURN( z3::expr parameter_value, - values::FormatP4RTValue("", parameter_type_name, args.at(i - 1).value(), - translator)); + values::FormatP4RTValue(/*field_name=*/"", parameter_type_name, + args.at(i - 1).value(), bitwidth, translator)); context.scope.insert({parameter_name, parameter_value}); } diff --git a/p4_symbolic/symbolic/expected/basic.smt2 b/p4_symbolic/symbolic/expected/basic.smt2 index f21101aa..27879e6b 100644 --- a/p4_symbolic/symbolic/expected/basic.smt2 +++ b/p4_symbolic/symbolic/expected/basic.smt2 @@ -5,8 +5,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x134 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x134)))) + (let (($x124 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x124)))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -15,41 +15,39 @@ (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let (($x73 (and $x69 (not (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x71 (and (and $x42 $x69) $x59))) - (let ((?x85 (ite $x71 ?x84 (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) + (let ((?x83 (ite $x71 (_ bv1 9) (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) (let (($x60 (and $x42 $x46))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 ?x85))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (or $x41 (or (or false (= ?x121 (_ bv0 9))) (= ?x121 (_ bv1 9))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) ?x83))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (or $x41 (or (or false (= ?x113 (_ bv0 9))) (= ?x113 (_ bv1 9)))))))))))))))))))))) (assert (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x96 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) - (let ((?x108 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x96))) + (let ((?x92 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) + (let ((?x102 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x92))) (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x128 (ite ipv4.$valid$ (ite $x60 1 ?x108) (- 1)))) - (let (($x127 (ite ipv4.$valid$ $x42 false))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let ((?x77 (ite (and $x42 (and $x69 (not $x59))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x71 (and (and $x42 $x69) $x59))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 (ite $x71 ?x84 ?x77)))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (and (and (not $x41) $x127) (= ?x128 (- 1))))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (and (and (not $x41) $x119) (= ?x120 (- 1)))))))))))))))))))))))) (check-sat) ; @@ -59,8 +57,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x134 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x134)))) + (let (($x124 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x124)))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -69,42 +67,40 @@ (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let (($x73 (and $x69 (not (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x71 (and (and $x42 $x69) $x59))) - (let ((?x85 (ite $x71 ?x84 (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) + (let ((?x83 (ite $x71 (_ bv1 9) (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) (let (($x60 (and $x42 $x46))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 ?x85))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (or $x41 (or (or false (= ?x121 (_ bv0 9))) (= ?x121 (_ bv1 9))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) ?x83))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (or $x41 (or (or false (= ?x113 (_ bv0 9))) (= ?x113 (_ bv1 9)))))))))))))))))))))) (assert (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x96 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) - (let ((?x108 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x96))) + (let ((?x92 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) + (let ((?x102 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x92))) (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x128 (ite ipv4.$valid$ (ite $x60 1 ?x108) (- 1)))) - (let (($x127 (ite ipv4.$valid$ $x42 false))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let ((?x77 (ite (and $x42 (and $x69 (not $x59))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x71 (and (and $x42 $x69) $x59))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 (ite $x71 ?x84 ?x77)))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (let (($x252 (and (not $x41) $x127))) - (and $x252 (= ?x128 0))))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (let (($x244 (and (not $x41) $x119))) + (and $x244 (= ?x120 0)))))))))))))))))))))))) (check-sat) ; @@ -114,8 +110,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x134 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x134)))) + (let (($x124 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x124)))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -124,41 +120,39 @@ (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let (($x73 (and $x69 (not (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x71 (and (and $x42 $x69) $x59))) - (let ((?x85 (ite $x71 ?x84 (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) + (let ((?x83 (ite $x71 (_ bv1 9) (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) (let (($x60 (and $x42 $x46))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 ?x85))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (or $x41 (or (or false (= ?x121 (_ bv0 9))) (= ?x121 (_ bv1 9))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) ?x83))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (or $x41 (or (or false (= ?x113 (_ bv0 9))) (= ?x113 (_ bv1 9)))))))))))))))))))))) (assert (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x96 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) - (let ((?x108 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x96))) + (let ((?x92 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) + (let ((?x102 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x92))) (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x128 (ite ipv4.$valid$ (ite $x60 1 ?x108) (- 1)))) - (let (($x127 (ite ipv4.$valid$ $x42 false))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let ((?x77 (ite (and $x42 (and $x69 (not $x59))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x71 (and (and $x42 $x69) $x59))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 (ite $x71 ?x84 ?x77)))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (and (and (not $x41) $x127) (= ?x128 1)))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (and (and (not $x41) $x119) (= ?x120 1))))))))))))))))))))))) (check-sat) ; @@ -168,8 +162,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x134 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x134)))) + (let (($x124 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x124)))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -178,41 +172,39 @@ (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let (($x73 (and $x69 (not (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x71 (and (and $x42 $x69) $x59))) - (let ((?x85 (ite $x71 ?x84 (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) + (let ((?x83 (ite $x71 (_ bv1 9) (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) (let (($x60 (and $x42 $x46))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 ?x85))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (or $x41 (or (or false (= ?x121 (_ bv0 9))) (= ?x121 (_ bv1 9))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) ?x83))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (or $x41 (or (or false (= ?x113 (_ bv0 9))) (= ?x113 (_ bv1 9)))))))))))))))))))))) (assert (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x96 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) - (let ((?x108 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x96))) + (let ((?x92 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) + (let ((?x102 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x92))) (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x128 (ite ipv4.$valid$ (ite $x60 1 ?x108) (- 1)))) - (let (($x127 (ite ipv4.$valid$ $x42 false))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let ((?x77 (ite (and $x42 (and $x69 (not $x59))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x71 (and (and $x42 $x69) $x59))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 (ite $x71 ?x84 ?x77)))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (and (and (not $x41) $x127) (= ?x128 2)))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (and (and (not $x41) $x119) (= ?x120 2))))))))))))))))))))))) (check-sat) ; @@ -222,8 +214,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun ipv4.$valid$ () Bool) (assert - (let (($x134 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x134)))) + (let (($x124 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x124)))) (assert (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) @@ -232,40 +224,38 @@ (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let (($x73 (and $x69 (not (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x71 (and (and $x42 $x69) $x59))) - (let ((?x85 (ite $x71 ?x84 (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) + (let ((?x83 (ite $x71 (_ bv1 9) (ite (and $x42 $x73) (_ bv511 9) standard_metadata.egress_spec)))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) (let (($x60 (and $x42 $x46))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 ?x85))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (or $x41 (or (or false (= ?x121 (_ bv0 9))) (= ?x121 (_ bv1 9))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) ?x83))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (or $x41 (or (or false (= ?x113 (_ bv0 9))) (= ?x113 (_ bv1 9)))))))))))))))))))))) (assert (let (($x59 (and true (= ((_ extract 31 24) ipv4.dstAddr) ((_ extract 31 24) (_ bv167772160 32)))))) (let (($x42 (and true ipv4.$valid$))) - (let ((?x96 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) - (let ((?x108 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x96))) + (let ((?x92 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32))))) 3 (ite (and $x42 $x59) 2 (- 1))))) + (let ((?x102 (ite (and $x42 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32))))) 0 ?x92))) (let (($x45 (= ipv4.dstAddr (_ bv168427520 32)))) (let (($x46 (and true $x45))) (let (($x60 (and $x42 $x46))) - (let ((?x128 (ite ipv4.$valid$ (ite $x60 1 ?x108) (- 1)))) - (let (($x127 (ite ipv4.$valid$ $x42 false))) + (let ((?x120 (ite ipv4.$valid$ (ite $x60 1 ?x102) (- 1)))) + (let (($x119 (ite ipv4.$valid$ $x42 false))) (let (($x61 (not $x46))) (let (($x65 (and $x61 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))))) (let (($x69 (and $x65 (not (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))))) (let ((?x77 (ite (and $x42 (and $x69 (not $x59))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x84 (concat (_ bv0 8) (_ bv1 1)))) (let (($x71 (and (and $x42 $x69) $x59))) (let (($x54 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))))) (let (($x67 (and (and $x42 $x65) $x54))) (let (($x50 (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))))) (let (($x63 (and (and $x42 $x61) $x50))) - (let ((?x121 (ite $x60 ?x84 (ite $x63 (concat (_ bv0 8) (_ bv0 1)) (ite $x67 ?x84 (ite $x71 ?x84 ?x77)))))) - (let (($x41 (= ?x121 (_ bv511 9)))) - (and (and (not $x41) $x127) (= ?x128 3)))))))))))))))))))))))) + (let ((?x113 (ite $x60 (_ bv1 9) (ite $x63 (_ bv0 9) (ite $x67 (_ bv1 9) (ite $x71 (_ bv1 9) ?x77)))))) + (let (($x41 (= ?x113 (_ bv511 9)))) + (and (and (not $x41) $x119) (= ?x120 3))))))))))))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/string_optional.smt2 b/p4_symbolic/symbolic/expected/string_optional.smt2 index af847f33..8a8fa204 100644 --- a/p4_symbolic/symbolic/expected/string_optional.smt2 +++ b/p4_symbolic/symbolic/expected/string_optional.smt2 @@ -4,46 +4,51 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun scalars.userMetadata.string_field () (_ BitVec 9)) (assert - (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x86))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x83 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x35) $x38))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x83))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (or $x51 (or (or (or false (= ?x77 (_ bv0 9))) (= ?x77 (_ bv1 9))) (= ?x77 (_ bv2 9))))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (or $x49 (or (or (or false (= ?x80 (_ bv0 9))) (= ?x80 (_ bv1 9))) (= ?x80 (_ bv2 9))))))))))))))))))))))) (assert - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x36 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let ((?x56 (ite (and (and true (and $x43 (not $x36))) $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let (($x66 (and true $x65))) - (let ((?x76 (ite $x66 0 (ite (and true true) 1 (- 1))))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (and (and (not $x51) true) (= ?x76 (- 1)))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let (($x69 (and true $x68))) + (let ((?x79 (ite $x69 0 (ite (and true true) 1 (- 1))))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (and (and (not $x49) true) (= ?x79 (- 1))))))))))))))))))))))) (check-sat) ; @@ -52,47 +57,52 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun scalars.userMetadata.string_field () (_ BitVec 9)) (assert - (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x86))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x83 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x35) $x38))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x83))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (or $x51 (or (or (or false (= ?x77 (_ bv0 9))) (= ?x77 (_ bv1 9))) (= ?x77 (_ bv2 9))))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (or $x49 (or (or (or false (= ?x80 (_ bv0 9))) (= ?x80 (_ bv1 9))) (= ?x80 (_ bv2 9))))))))))))))))))))))) (assert - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x36 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let ((?x56 (ite (and (and true (and $x43 (not $x36))) $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let (($x66 (and true $x65))) - (let ((?x76 (ite $x66 0 (ite (and true true) 1 (- 1))))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (let (($x144 (and (not $x51) true))) - (and $x144 (= ?x76 0)))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let (($x69 (and true $x68))) + (let ((?x79 (ite $x69 0 (ite (and true true) 1 (- 1))))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (let (($x141 (and (not $x49) true))) + (and $x141 (= ?x79 0))))))))))))))))))))))) (check-sat) ; @@ -101,46 +111,51 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun scalars.userMetadata.string_field () (_ BitVec 9)) (assert - (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x86))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x83 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x35) $x38))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x83))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (or $x51 (or (or (or false (= ?x77 (_ bv0 9))) (= ?x77 (_ bv1 9))) (= ?x77 (_ bv2 9))))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (or $x49 (or (or (or false (= ?x80 (_ bv0 9))) (= ?x80 (_ bv1 9))) (= ?x80 (_ bv2 9))))))))))))))))))))))) (assert - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x36 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let ((?x56 (ite (and (and true (and $x43 (not $x36))) $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let (($x66 (and true $x65))) - (let ((?x76 (ite $x66 0 (ite (and true true) 1 (- 1))))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (and (and (not $x51) true) (= ?x76 1))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let (($x69 (and true $x68))) + (let ((?x79 (ite $x69 0 (ite (and true true) 1 (- 1))))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (and (and (not $x49) true) (= ?x79 1)))))))))))))))))))))) (check-sat) ; @@ -149,45 +164,53 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun scalars.userMetadata.string_field () (_ BitVec 9)) (assert - (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x86))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x83 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x35) $x38))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x83))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (or $x51 (or (or (or false (= ?x77 (_ bv0 9))) (= ?x77 (_ bv1 9))) (= ?x77 (_ bv2 9))))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (or $x49 (or (or (or false (= ?x80 (_ bv0 9))) (= ?x80 (_ bv1 9))) (= ?x80 (_ bv2 9))))))))))))))))))))))) (assert - (let (($x41 (and true (= standard_metadata.ingress_port (concat (_ bv0 7) (_ bv2 2)))))) - (let (($x36 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1)))))) - (let (($x42 (and true $x32))) - (let ((?x62 (ite $x42 0 (ite (and true $x36) 1 (ite (and true $x41) 2 (- 1)))))) - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x53 (ite (and true (and true (= standard_metadata.ingress_port (_ bv2 9)))) 2 (- 1)))) + (let ((?x57 (ite (and true (and true (= standard_metadata.ingress_port (_ bv1 9)))) 1 ?x53))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x40 (and true $x33))) + (let ((?x62 (ite $x40 0 ?x57))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let ((?x56 (ite (and (and true (and (not $x32) (not $x36))) $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true (not $x32)) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (and (and (not $x51) true) (= ?x62 (- 1))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (and (and (not $x49) true) (= ?x62 (- 1))))))))))))))))))))))))) (check-sat) ; @@ -196,46 +219,54 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun scalars.userMetadata.string_field () (_ BitVec 9)) (assert - (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x86))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x83 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x35) $x38))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x83))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (or $x51 (or (or (or false (= ?x77 (_ bv0 9))) (= ?x77 (_ bv1 9))) (= ?x77 (_ bv2 9))))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (or $x49 (or (or (or false (= ?x80 (_ bv0 9))) (= ?x80 (_ bv1 9))) (= ?x80 (_ bv2 9))))))))))))))))))))))) (assert - (let (($x41 (and true (= standard_metadata.ingress_port (concat (_ bv0 7) (_ bv2 2)))))) - (let (($x36 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1)))))) - (let (($x42 (and true $x32))) - (let ((?x62 (ite $x42 0 (ite (and true $x36) 1 (ite (and true $x41) 2 (- 1)))))) - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x53 (ite (and true (and true (= standard_metadata.ingress_port (_ bv2 9)))) 2 (- 1)))) + (let ((?x57 (ite (and true (and true (= standard_metadata.ingress_port (_ bv1 9)))) 1 ?x53))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x40 (and true $x33))) + (let ((?x62 (ite $x40 0 ?x57))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let ((?x56 (ite (and (and true (and (not $x32) (not $x36))) $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true (not $x32)) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (let (($x144 (and (not $x51) true))) - (and $x144 (= ?x62 0))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (let (($x141 (and (not $x49) true))) + (and $x141 (= ?x62 0))))))))))))))))))))))))) (check-sat) ; @@ -244,45 +275,53 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun scalars.userMetadata.string_field () (_ BitVec 9)) (assert - (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x86))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x83 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x35) $x38))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x83))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (or $x51 (or (or (or false (= ?x77 (_ bv0 9))) (= ?x77 (_ bv1 9))) (= ?x77 (_ bv2 9))))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (or $x49 (or (or (or false (= ?x80 (_ bv0 9))) (= ?x80 (_ bv1 9))) (= ?x80 (_ bv2 9))))))))))))))))))))))) (assert - (let (($x41 (and true (= standard_metadata.ingress_port (concat (_ bv0 7) (_ bv2 2)))))) - (let (($x36 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1)))))) - (let (($x42 (and true $x32))) - (let ((?x62 (ite $x42 0 (ite (and true $x36) 1 (ite (and true $x41) 2 (- 1)))))) - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x53 (ite (and true (and true (= standard_metadata.ingress_port (_ bv2 9)))) 2 (- 1)))) + (let ((?x57 (ite (and true (and true (= standard_metadata.ingress_port (_ bv1 9)))) 1 ?x53))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x40 (and true $x33))) + (let ((?x62 (ite $x40 0 ?x57))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let ((?x56 (ite (and (and true (and (not $x32) (not $x36))) $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true (not $x32)) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (and (and (not $x51) true) (= ?x62 1)))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (and (and (not $x49) true) (= ?x62 1)))))))))))))))))))))))) (check-sat) ; @@ -291,45 +330,53 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun scalars.userMetadata.string_field () (_ BitVec 9)) (assert - (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x86))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x83 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x35) $x38))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x83))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (or $x51 (or (or (or false (= ?x77 (_ bv0 9))) (= ?x77 (_ bv1 9))) (= ?x77 (_ bv2 9))))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (or $x49 (or (or (or false (= ?x80 (_ bv0 9))) (= ?x80 (_ bv1 9))) (= ?x80 (_ bv2 9))))))))))))))))))))))) (assert - (let (($x41 (and true (= standard_metadata.ingress_port (concat (_ bv0 7) (_ bv2 2)))))) - (let (($x36 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1)))))) - (let (($x42 (and true $x32))) - (let ((?x62 (ite $x42 0 (ite (and true $x36) 1 (ite (and true $x41) 2 (- 1)))))) - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x53 (ite (and true (and true (= standard_metadata.ingress_port (_ bv2 9)))) 2 (- 1)))) + (let ((?x57 (ite (and true (and true (= standard_metadata.ingress_port (_ bv1 9)))) 1 ?x53))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x40 (and true $x33))) + (let ((?x62 (ite $x40 0 ?x57))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let ((?x56 (ite (and (and true (and (not $x32) (not $x36))) $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true (not $x32)) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (and (and (not $x51) true) (= ?x62 2)))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (and (and (not $x49) true) (= ?x62 2)))))))))))))))))))))))) (check-sat) ; @@ -338,45 +385,49 @@ (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (declare-fun scalars.userMetadata.string_field () (_ BitVec 9)) (assert - (let (($x85 (= standard_metadata.ingress_port (_ bv2 9)))) - (let (($x80 (= standard_metadata.ingress_port (_ bv1 9)))) - (let (($x86 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x80) $x85))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x86))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x83 (or (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x35) $x38))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) $x83))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (or $x51 (or (or (or false (= ?x77 (_ bv0 9))) (= ?x77 (_ bv1 9))) (= ?x77 (_ bv2 9))))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (or $x49 (or (or (or false (= ?x80 (_ bv0 9))) (= ?x80 (_ bv1 9))) (= ?x80 (_ bv2 9))))))))))))))))))))))) (assert - (let ((?x34 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x39 (concat (_ bv0 7) (_ bv2 2)))) + (let ((?x65 (concat (_ bv0 7) (_ bv2 2)))) (let ((?x29 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x41 (and true (= standard_metadata.ingress_port ?x39)))) - (let (($x32 (and true (= standard_metadata.ingress_port ?x29)))) - (let (($x43 (not $x32))) - (let (($x48 (and true (and $x43 (not (and true (= standard_metadata.ingress_port ?x34))))))) - (let ((?x56 (ite (and $x48 $x41) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) - (let (($x36 (and true (= standard_metadata.ingress_port ?x34)))) - (let (($x42 (and true $x32))) - (let ((?x63 (ite $x42 ?x39 (ite (and (and true $x43) $x36) ?x34 ?x56)))) - (let (($x65 (and true (= ?x63 ?x39)))) - (let ((?x75 (ite (and (and true (not $x65)) true) ?x34 standard_metadata.egress_spec))) - (let (($x66 (and true $x65))) - (let ((?x77 (ite $x66 ?x29 ?x75))) - (let (($x51 (= ?x77 (_ bv511 9)))) - (and (and (not $x51) true) (= (- 1) (- 1)))))))))))))))))))) + (let (($x38 (= standard_metadata.ingress_port (_ bv2 9)))) + (let (($x39 (and true $x38))) + (let (($x32 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x33 (and true $x32))) + (let (($x41 (not $x33))) + (let (($x46 (and true (and $x41 (not (and true (= standard_metadata.ingress_port (_ bv1 9)))))))) + (let ((?x54 (ite (and $x46 $x39) ?x29 (ite true ?x29 scalars.userMetadata.string_field)))) + (let (($x35 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x36 (and true $x35))) + (let (($x40 (and true $x33))) + (let ((?x66 (ite $x40 ?x65 (ite (and (and true $x41) $x36) (concat (_ bv0 8) (_ bv1 1)) ?x54)))) + (let (($x68 (and true (= ?x66 ?x65)))) + (let ((?x78 (ite (and (and true (not $x68)) true) (_ bv1 9) standard_metadata.egress_spec))) + (let (($x69 (and true $x68))) + (let ((?x80 (ite $x69 (_ bv0 9) ?x78))) + (let (($x49 (= ?x80 (_ bv511 9)))) + (and (and (not $x49) true) (= (- 1) (- 1)))))))))))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/table.smt2 b/p4_symbolic/symbolic/expected/table.smt2 index a778b36b..608c2a73 100644 --- a/p4_symbolic/symbolic/expected/table.smt2 +++ b/p4_symbolic/symbolic/expected/table.smt2 @@ -3,29 +3,30 @@ (declare-fun standard_metadata.ingress_port () (_ BitVec 9)) (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (assert - (let (($x53 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x53)))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x28)))) (assert - (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x35 (and true (not (and true (= standard_metadata.ingress_port ?x26)))))) - (let ((?x30 (concat (_ bv0 8) (_ bv1 1)))) - (let (($x28 (and true (= standard_metadata.ingress_port ?x26)))) - (let (($x33 (and true $x28))) - (let ((?x47 (ite $x33 ?x30 (ite (and $x35 $x32) ?x26 standard_metadata.egress_spec)))) - (let (($x38 (= ?x47 (_ bv511 9)))) - (or $x38 (or (or false (= ?x47 (_ bv0 9))) (= ?x47 (_ bv1 9))))))))))))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x29 (and true $x28))) + (let (($x32 (and true (not (and true (= standard_metadata.ingress_port (_ bv0 9))))))) + (let (($x25 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x26 (and true $x25))) + (let (($x30 (and true $x26))) + (let ((?x44 (ite $x30 (_ bv1 9) (ite (and $x32 $x29) (_ bv0 9) standard_metadata.egress_spec)))) + (let (($x35 (= ?x44 (_ bv511 9)))) + (or $x35 (or (or false (= ?x44 (_ bv0 9))) (= ?x44 (_ bv1 9))))))))))))) (assert - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x28 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1)))))) - (let (($x33 (and true $x28))) - (let ((?x46 (ite $x33 0 (ite (and true $x32) 1 (- 1))))) - (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) - (let ((?x44 (ite (and (and true (not $x28)) $x32) ?x26 standard_metadata.egress_spec))) - (let ((?x30 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x47 (ite $x33 ?x30 ?x44))) - (let (($x38 (= ?x47 (_ bv511 9)))) - (and (and (not $x38) true) (= ?x46 (- 1))))))))))))) + (let ((?x40 (ite (and true (and true (= standard_metadata.ingress_port (_ bv1 9)))) 1 (- 1)))) + (let (($x25 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x26 (and true $x25))) + (let (($x30 (and true $x26))) + (let ((?x43 (ite $x30 0 ?x40))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x29 (and true $x28))) + (let ((?x41 (ite (and (and true (not $x26)) $x29) (_ bv0 9) standard_metadata.egress_spec))) + (let ((?x44 (ite $x30 (_ bv1 9) ?x41))) + (let (($x35 (= ?x44 (_ bv511 9)))) + (and (and (not $x35) true) (= ?x43 (- 1)))))))))))))) (check-sat) ; @@ -33,30 +34,31 @@ (declare-fun standard_metadata.ingress_port () (_ BitVec 9)) (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (assert - (let (($x53 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x53)))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x28)))) (assert - (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x35 (and true (not (and true (= standard_metadata.ingress_port ?x26)))))) - (let ((?x30 (concat (_ bv0 8) (_ bv1 1)))) - (let (($x28 (and true (= standard_metadata.ingress_port ?x26)))) - (let (($x33 (and true $x28))) - (let ((?x47 (ite $x33 ?x30 (ite (and $x35 $x32) ?x26 standard_metadata.egress_spec)))) - (let (($x38 (= ?x47 (_ bv511 9)))) - (or $x38 (or (or false (= ?x47 (_ bv0 9))) (= ?x47 (_ bv1 9))))))))))))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x29 (and true $x28))) + (let (($x32 (and true (not (and true (= standard_metadata.ingress_port (_ bv0 9))))))) + (let (($x25 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x26 (and true $x25))) + (let (($x30 (and true $x26))) + (let ((?x44 (ite $x30 (_ bv1 9) (ite (and $x32 $x29) (_ bv0 9) standard_metadata.egress_spec)))) + (let (($x35 (= ?x44 (_ bv511 9)))) + (or $x35 (or (or false (= ?x44 (_ bv0 9))) (= ?x44 (_ bv1 9))))))))))))) (assert - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x28 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1)))))) - (let (($x33 (and true $x28))) - (let ((?x46 (ite $x33 0 (ite (and true $x32) 1 (- 1))))) - (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) - (let ((?x44 (ite (and (and true (not $x28)) $x32) ?x26 standard_metadata.egress_spec))) - (let ((?x30 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x47 (ite $x33 ?x30 ?x44))) - (let (($x38 (= ?x47 (_ bv511 9)))) - (let (($x116 (and (not $x38) true))) - (and $x116 (= ?x46 0))))))))))))) + (let ((?x40 (ite (and true (and true (= standard_metadata.ingress_port (_ bv1 9)))) 1 (- 1)))) + (let (($x25 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x26 (and true $x25))) + (let (($x30 (and true $x26))) + (let ((?x43 (ite $x30 0 ?x40))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x29 (and true $x28))) + (let ((?x41 (ite (and (and true (not $x26)) $x29) (_ bv0 9) standard_metadata.egress_spec))) + (let ((?x44 (ite $x30 (_ bv1 9) ?x41))) + (let (($x35 (= ?x44 (_ bv511 9)))) + (let (($x111 (and (not $x35) true))) + (and $x111 (= ?x43 0)))))))))))))) (check-sat) ; @@ -64,28 +66,29 @@ (declare-fun standard_metadata.ingress_port () (_ BitVec 9)) (declare-fun standard_metadata.egress_spec () (_ BitVec 9)) (assert - (let (($x53 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x53)))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x28)))) (assert - (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x35 (and true (not (and true (= standard_metadata.ingress_port ?x26)))))) - (let ((?x30 (concat (_ bv0 8) (_ bv1 1)))) - (let (($x28 (and true (= standard_metadata.ingress_port ?x26)))) - (let (($x33 (and true $x28))) - (let ((?x47 (ite $x33 ?x30 (ite (and $x35 $x32) ?x26 standard_metadata.egress_spec)))) - (let (($x38 (= ?x47 (_ bv511 9)))) - (or $x38 (or (or false (= ?x47 (_ bv0 9))) (= ?x47 (_ bv1 9))))))))))))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x29 (and true $x28))) + (let (($x32 (and true (not (and true (= standard_metadata.ingress_port (_ bv0 9))))))) + (let (($x25 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x26 (and true $x25))) + (let (($x30 (and true $x26))) + (let ((?x44 (ite $x30 (_ bv1 9) (ite (and $x32 $x29) (_ bv0 9) standard_metadata.egress_spec)))) + (let (($x35 (= ?x44 (_ bv511 9)))) + (or $x35 (or (or false (= ?x44 (_ bv0 9))) (= ?x44 (_ bv1 9))))))))))))) (assert - (let (($x32 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv1 1)))))) - (let (($x28 (and true (= standard_metadata.ingress_port (concat (_ bv0 8) (_ bv0 1)))))) - (let (($x33 (and true $x28))) - (let ((?x46 (ite $x33 0 (ite (and true $x32) 1 (- 1))))) - (let ((?x26 (concat (_ bv0 8) (_ bv0 1)))) - (let ((?x44 (ite (and (and true (not $x28)) $x32) ?x26 standard_metadata.egress_spec))) - (let ((?x30 (concat (_ bv0 8) (_ bv1 1)))) - (let ((?x47 (ite $x33 ?x30 ?x44))) - (let (($x38 (= ?x47 (_ bv511 9)))) - (and (and (not $x38) true) (= ?x46 1)))))))))))) + (let ((?x40 (ite (and true (and true (= standard_metadata.ingress_port (_ bv1 9)))) 1 (- 1)))) + (let (($x25 (= standard_metadata.ingress_port (_ bv0 9)))) + (let (($x26 (and true $x25))) + (let (($x30 (and true $x26))) + (let ((?x43 (ite $x30 0 ?x40))) + (let (($x28 (= standard_metadata.ingress_port (_ bv1 9)))) + (let (($x29 (and true $x28))) + (let ((?x41 (ite (and (and true (not $x26)) $x29) (_ bv0 9) standard_metadata.egress_spec))) + (let ((?x44 (ite $x30 (_ bv1 9) ?x41))) + (let (($x35 (= ?x44 (_ bv511 9)))) + (and (and (not $x35) true) (= ?x43 1))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/expected/vrf.smt2 b/p4_symbolic/symbolic/expected/vrf.smt2 index 5142be5e..0a0816de 100644 --- a/p4_symbolic/symbolic/expected/vrf.smt2 +++ b/p4_symbolic/symbolic/expected/vrf.smt2 @@ -8,8 +8,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -33,14 +33,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -59,20 +58,19 @@ (let (($x84 (and $x50 $x82))) (let (($x101 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x80 ?x79)))) (let (($x95 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x89))) - (let ((?x153 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) + (let ((?x148 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) (let (($x90 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x89))) (let (($x108 (and $x84 $x90))) - (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x153) (- 1)) (- 1)))) + (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x148) (- 1)) (- 1)))) (let (($x66 (ite ipv4.$valid$ (ite $x82 $x84 false) false))) (let (($x122 (and $x84 (and (and (and (not $x90) (not $x95)) (not $x101)) (not $x107))))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 (and (and (not $x90) (not $x95)) (not $x101))) $x107))) (let (($x115 (and (and $x84 (and (not $x90) (not $x95))) $x101))) - (let ((?x144 (ite $x115 ?x130 (ite $x119 ?x130 (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) + (let ((?x141 (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) (let (($x111 (and (and $x84 (not $x90)) $x95))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) ?x144)))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (and (and (not $x49) $x66) (= ?x67 (- 1)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) ?x141)))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (and (and (not $x49) $x66) (= ?x67 (- 1))))))))))))))))))))))))))))))))) (check-sat) ; @@ -85,8 +83,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -110,14 +108,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -136,21 +133,20 @@ (let (($x84 (and $x50 $x82))) (let (($x101 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x80 ?x79)))) (let (($x95 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x89))) - (let ((?x153 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) + (let ((?x148 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) (let (($x90 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x89))) (let (($x108 (and $x84 $x90))) - (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x153) (- 1)) (- 1)))) + (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x148) (- 1)) (- 1)))) (let (($x66 (ite ipv4.$valid$ (ite $x82 $x84 false) false))) (let (($x122 (and $x84 (and (and (and (not $x90) (not $x95)) (not $x101)) (not $x107))))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 (and (and (not $x90) (not $x95)) (not $x101))) $x107))) (let (($x115 (and (and $x84 (and (not $x90) (not $x95))) $x101))) - (let ((?x144 (ite $x115 ?x130 (ite $x119 ?x130 (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) + (let ((?x141 (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) (let (($x111 (and (and $x84 (not $x90)) $x95))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) ?x144)))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (let (($x341 (and (not $x49) $x66))) - (and $x341 (= ?x67 0)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) ?x141)))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (let (($x333 (and (not $x49) $x66))) + (and $x333 (= ?x67 0))))))))))))))))))))))))))))))))) (check-sat) ; @@ -163,8 +159,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -188,14 +184,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -214,20 +209,19 @@ (let (($x84 (and $x50 $x82))) (let (($x101 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x80 ?x79)))) (let (($x95 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x89))) - (let ((?x153 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) + (let ((?x148 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) (let (($x90 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x89))) (let (($x108 (and $x84 $x90))) - (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x153) (- 1)) (- 1)))) + (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x148) (- 1)) (- 1)))) (let (($x66 (ite ipv4.$valid$ (ite $x82 $x84 false) false))) (let (($x122 (and $x84 (and (and (and (not $x90) (not $x95)) (not $x101)) (not $x107))))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 (and (and (not $x90) (not $x95)) (not $x101))) $x107))) (let (($x115 (and (and $x84 (and (not $x90) (not $x95))) $x101))) - (let ((?x144 (ite $x115 ?x130 (ite $x119 ?x130 (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) + (let ((?x141 (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) (let (($x111 (and (and $x84 (not $x90)) $x95))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) ?x144)))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (and (and (not $x49) $x66) (= ?x67 1))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) ?x141)))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (and (and (not $x49) $x66) (= ?x67 1)))))))))))))))))))))))))))))))) (check-sat) ; @@ -240,8 +234,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -265,14 +259,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -291,20 +284,19 @@ (let (($x84 (and $x50 $x82))) (let (($x101 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x80 ?x79)))) (let (($x95 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x89))) - (let ((?x153 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) + (let ((?x148 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) (let (($x90 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x89))) (let (($x108 (and $x84 $x90))) - (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x153) (- 1)) (- 1)))) + (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x148) (- 1)) (- 1)))) (let (($x66 (ite ipv4.$valid$ (ite $x82 $x84 false) false))) (let (($x122 (and $x84 (and (and (and (not $x90) (not $x95)) (not $x101)) (not $x107))))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 (and (and (not $x90) (not $x95)) (not $x101))) $x107))) (let (($x115 (and (and $x84 (and (not $x90) (not $x95))) $x101))) - (let ((?x144 (ite $x115 ?x130 (ite $x119 ?x130 (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) + (let ((?x141 (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) (let (($x111 (and (and $x84 (not $x90)) $x95))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) ?x144)))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (and (and (not $x49) $x66) (= ?x67 2))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) ?x141)))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (and (and (not $x49) $x66) (= ?x67 2)))))))))))))))))))))))))))))))) (check-sat) ; @@ -317,8 +309,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -342,14 +334,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -368,20 +359,19 @@ (let (($x84 (and $x50 $x82))) (let (($x101 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv336855040 32)))) (= ?x80 ?x79)))) (let (($x95 (and (and true (= ((_ extract 31 16) ipv4.dstAddr) ((_ extract 31 16) (_ bv168427520 32)))) $x89))) - (let ((?x153 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) + (let ((?x148 (ite (and $x84 $x95) 0 (ite (and $x84 $x101) 3 (ite (and $x84 $x107) 2 (- 1)))))) (let (($x90 (and (and true (= ipv4.dstAddr (_ bv168427520 32))) $x89))) (let (($x108 (and $x84 $x90))) - (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x153) (- 1)) (- 1)))) + (let ((?x67 (ite ipv4.$valid$ (ite $x82 (ite $x108 1 ?x148) (- 1)) (- 1)))) (let (($x66 (ite ipv4.$valid$ (ite $x82 $x84 false) false))) (let (($x122 (and $x84 (and (and (and (not $x90) (not $x95)) (not $x101)) (not $x107))))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 (and (and (not $x90) (not $x95)) (not $x101))) $x107))) (let (($x115 (and (and $x84 (and (not $x90) (not $x95))) $x101))) - (let ((?x144 (ite $x115 ?x130 (ite $x119 ?x130 (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) + (let ((?x141 (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) (ite $x122 (_ bv511 9) standard_metadata.egress_spec))))) (let (($x111 (and (and $x84 (not $x90)) $x95))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) ?x144)))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (and (and (not $x49) $x66) (= ?x67 3))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) ?x141)))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (and (and (not $x49) $x66) (= ?x67 3)))))))))))))))))))))))))))))))) (check-sat) ; @@ -394,8 +384,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -419,14 +409,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) (let (($x50 (and true ipv4.$valid$))) @@ -452,14 +441,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (and (and (not $x49) $x68) (= ?x83 (- 1))))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (and (and (not $x49) $x68) (= ?x83 (- 1)))))))))))))))))))))))))))))))))) (check-sat) ; @@ -472,8 +460,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -497,14 +485,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) (let (($x50 (and true ipv4.$valid$))) @@ -530,14 +517,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (and (and (not $x49) $x68) (= ?x83 0)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (and (and (not $x49) $x68) (= ?x83 0))))))))))))))))))))))))))))))))) (check-sat) ; @@ -550,8 +536,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -575,14 +561,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) (let (($x50 (and true ipv4.$valid$))) @@ -608,14 +593,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (and (and (not $x49) $x68) (= ?x83 1)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (and (and (not $x49) $x68) (= ?x83 1))))))))))))))))))))))))))))))))) (check-sat) ; @@ -628,8 +612,8 @@ (declare-fun ipv4.dstAddr () (_ BitVec 32)) (declare-fun scalars.userMetadata.vrf_is_valid () (_ BitVec 1)) (assert - (let (($x175 (= standard_metadata.ingress_port (_ bv1 9)))) - (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x175)))) + (let (($x167 (= standard_metadata.ingress_port (_ bv1 9)))) + (and (and (distinct standard_metadata.ingress_port (_ bv511 9)) true) (or (or false (= standard_metadata.ingress_port (_ bv0 9))) $x167)))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -653,14 +637,13 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (or $x49 (or (or false (= ?x164 (_ bv0 9))) (= ?x164 (_ bv1 9)))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (or $x49 (or (or false (= ?x157 (_ bv0 9))) (= ?x157 (_ bv1 9))))))))))))))))))))))))))))))))) (assert (let ((?x73 (concat (_ bv0 9) (_ bv0 1)))) (let (($x61 (and true (= (bvand ipv4.srcAddr (_ bv555813129 32)) (_ bv555810816 32))))) @@ -684,13 +667,12 @@ (let (($x82 (bvuge ?x81 (_ bv1 1)))) (let (($x84 (and $x50 $x82))) (let ((?x124 (ite (and $x84 (and $x117 (not $x107))) (_ bv511 9) standard_metadata.egress_spec))) - (let ((?x130 (concat (_ bv0 8) (_ bv1 1)))) (let (($x119 (and (and $x84 $x117) $x107))) (let (($x115 (and (and $x84 $x113) $x101))) (let (($x111 (and (and $x84 $x109) $x95))) (let (($x108 (and $x84 $x90))) - (let ((?x164 (ite $x108 ?x130 (ite $x111 (concat (_ bv0 8) (_ bv0 1)) (ite $x115 ?x130 (ite $x119 ?x130 ?x124)))))) - (let (($x49 (= ?x164 (_ bv511 9)))) - (and (and (not $x49) true) (= (- 1) (- 1))))))))))))))))))))))))))))))))) + (let ((?x157 (ite $x108 (_ bv1 9) (ite $x111 (_ bv0 9) (ite $x115 (_ bv1 9) (ite $x119 (_ bv1 9) ?x124)))))) + (let (($x49 (= ?x157 (_ bv511 9)))) + (and (and (not $x49) true) (= (- 1) (- 1)))))))))))))))))))))))))))))))) (check-sat) diff --git a/p4_symbolic/symbolic/table.cc b/p4_symbolic/symbolic/table.cc index 66e36000..847e3e12 100644 --- a/p4_symbolic/symbolic/table.cc +++ b/p4_symbolic/symbolic/table.cc @@ -171,13 +171,17 @@ absl::StatusOr EvaluateSingleMatch( << " according to the table definition, but got entry with match: " << match_definition.ShortDebugString(); + auto GetZ3Value = + [&](const pdpi::IrValue &value) -> absl::StatusOr { + return values::FormatP4RTValue(field_name, + match_definition.type_name().name(), value, + match_definition.bitwidth(), translator); + }; + switch (match_definition.match_type()) { case p4::config::v1::MatchField::EXACT: { if (match.match_value_case() != pdpi::IrMatch::kExact) return mismatch; - ASSIGN_OR_RETURN(z3::expr value_expression, - values::FormatP4RTValue( - field_name, match_definition.type_name().name(), - match.exact(), translator)); + ASSIGN_OR_RETURN(z3::expr value_expression, GetZ3Value(match.exact())); return operators::Eq(field_expression, value_expression); } @@ -185,7 +189,7 @@ absl::StatusOr EvaluateSingleMatch( if (match.match_value_case() != pdpi::IrMatch::kLpm) return mismatch; ASSIGN_OR_RETURN(z3::expr value_expression, - values::FormatBmv2Value(match.lpm().value())); + GetZ3Value(match.lpm().value())); return operators::PrefixEq( field_expression, value_expression, static_cast(match.lpm().prefix_length())); @@ -195,9 +199,9 @@ absl::StatusOr EvaluateSingleMatch( if (match.match_value_case() != pdpi::IrMatch::kTernary) return mismatch; ASSIGN_OR_RETURN(z3::expr mask_expression, - values::FormatBmv2Value(match.ternary().mask())); + GetZ3Value(match.ternary().mask())); ASSIGN_OR_RETURN(z3::expr value_expression, - values::FormatBmv2Value(match.ternary().value())); + GetZ3Value(match.ternary().value())); ASSIGN_OR_RETURN(z3::expr masked_field, operators::BitAnd(field_expression, mask_expression)); return operators::Eq(masked_field, value_expression); @@ -211,9 +215,7 @@ absl::StatusOr EvaluateSingleMatch( // match value is present for an optional match type, it must be a // concrete value. ASSIGN_OR_RETURN(z3::expr value_expression, - values::FormatP4RTValue( - field_name, match_definition.type_name().name(), - match.optional().value(), translator)); + GetZ3Value(match.optional().value())); return operators::Eq(field_expression, value_expression); } diff --git a/p4_symbolic/symbolic/values.cc b/p4_symbolic/symbolic/values.cc index 4056e899..483f1f2b 100644 --- a/p4_symbolic/symbolic/values.cc +++ b/p4_symbolic/symbolic/values.cc @@ -21,19 +21,24 @@ #include "p4_symbolic/symbolic/values.h" #include +#include #include #include +#include "absl/status/status.h" #include "absl/strings/match.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/strings/strip.h" +#include "absl/strings/substitute.h" #include "gmpxx.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/string_encodings/byte_string.h" #include "p4_pdpi/utils/ir.h" #include "p4_symbolic/symbolic/operators.h" #include "p4_symbolic/symbolic/symbolic.h" @@ -69,34 +74,10 @@ absl::StatusOr ParseIrValue(const std::string &value) { } } -absl::StatusOr FormatBmv2Value(const pdpi::IrValue &value) { - switch (value.format_case()) { - case pdpi::IrValue::kHexStr: - return HexStringToZ3Bitvector(value.hex_str()); - case pdpi::IrValue::kIpv4: { - ASSIGN_OR_RETURN(netaddr::Ipv4Address ipv4, - netaddr::Ipv4Address::OfString(value.ipv4())); - return HexStringToZ3Bitvector(ipv4.ToHexString(), 32); - } - case pdpi::IrValue::kIpv6: { - ASSIGN_OR_RETURN(netaddr::Ipv6Address ipv6, - netaddr::Ipv6Address::OfString(value.ipv6())); - return HexStringToZ3Bitvector(ipv6.ToHexString(), 128); - } - case pdpi::IrValue::kMac: { - ASSIGN_OR_RETURN(netaddr::MacAddress mac, - netaddr::MacAddress::OfString(value.mac())); - return HexStringToZ3Bitvector(mac.ToHexString(), 48); - } - default: - return absl::UnimplementedError( - absl::StrCat("Found unsupported value type ", value.DebugString())); - } -} - absl::StatusOr FormatP4RTValue(const std::string &field_name, const std::string &type_name, const pdpi::IrValue &value, + int bitwidth, P4RuntimeTranslator *translator) { switch (value.format_case()) { case pdpi::IrValue::kStr: { @@ -111,7 +92,16 @@ absl::StatusOr FormatP4RTValue(const std::string &field_name, IdAllocator &allocator = translator->p4runtime_translation_allocators[type_name]; uint64_t int_value = allocator.AllocateId(string_value); - return Z3Context().bv_val(int_value, FindBitsize(int_value)); + + if (bitwidth == 0) { + bitwidth = FindBitsize(int_value); + } else { + return absl::InvalidArgumentError(absl::Substitute( + "Translated type '$0' is expected to have bitwidth 0, got $1", + type_name, bitwidth)); + } + + return Z3Context().bv_val(int_value, bitwidth); } default: { if (translator->fields_p4runtime_type.count(field_name)) { @@ -119,7 +109,17 @@ absl::StatusOr FormatP4RTValue(const std::string &field_name, "A table entry provides a non-string value ", value.DebugString(), "to a string translated field", field_name)); } - return FormatBmv2Value(value); + + // Rely on PDPI to convert the value since its logic is non-trivial and + // may change from time to time. Specifically, use PDPI to convert to + // NormalizedByteString and back into IR as a pdpi::HEX_STRING. + ASSIGN_OR_RETURN(const std::string byte_string, + pdpi::IrValueToNormalizedByteString(value, bitwidth)); + ASSIGN_OR_RETURN(const pdpi::IrValue normalized_value, + pdpi::ArbitraryByteStringToIrValue( + pdpi::HEX_STRING, bitwidth, byte_string)); + // Now convert the hex string internally. + return HexStringToZ3Bitvector(normalized_value.hex_str(), bitwidth); } } } diff --git a/p4_symbolic/symbolic/values.h b/p4_symbolic/symbolic/values.h index 4e7d78bb..857dbf40 100644 --- a/p4_symbolic/symbolic/values.h +++ b/p4_symbolic/symbolic/values.h @@ -22,6 +22,7 @@ #define P4_SYMBOLIC_SYMBOLIC_VALUES_H_ #include +#include #include #include @@ -81,26 +82,21 @@ struct P4RuntimeTranslator { // Transforms a hex string literal from bmv2 json to a pdpi::IrValue absl::StatusOr ParseIrValue(const std::string &value); -// Transforms a value read from bmv2 (e.g. hardcoded in the program) -// to a z3::expr. -// Essentially, this is just a formatting function that can format ipv4, ipv6 -// hexstrings, and macs as bitvectors in z3's format. -// This function does not perform any string translation, and instead assumes -// the values are already in the actual domain of values in the p4 program, -// because p4 and bmv2 both do not support string translation, it is only used -// as a logical translation at the boundry between P4RT and bmv2. -absl::StatusOr FormatBmv2Value(const pdpi::IrValue &value); - // Transforms a value read from a table entry to a z3::expr. // On top of formatting ipv4, ipv6, hexstrings, and macs as bitvectors, // this function also translates string values to unique bitvectors. // The mapping of strings to bitvectors is stored in the translator state, -// and used to map the same string to the same consistent bitvector, and to +// and used to map the same string to the same consistent bitvector, and to // do a reverse-translation when extracting values for headers and fields from // the z3 model. +// Parameter `bitwidth` is the width of the underlying PI value. For runtime +// translated values (i.e. string IrValues) the bitwidth MUST be 0, in which +// case we use the minimum number of bits to encode the resulting translated +// value. absl::StatusOr FormatP4RTValue(const std::string &field_name, const std::string &type_name, const pdpi::IrValue &value, + int bitwidth, P4RuntimeTranslator *translator); // Reverse translation: operates opposite to FormatP4RTValue(). diff --git a/p4_symbolic/symbolic/values_test.cc b/p4_symbolic/symbolic/values_test.cc index 14d4a604..0d3e2e86 100644 --- a/p4_symbolic/symbolic/values_test.cc +++ b/p4_symbolic/symbolic/values_test.cc @@ -2,19 +2,24 @@ #include "absl/container/flat_hash_map.h" #include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "gutil/status_matchers.h" #include "gutil/testing.h" #include "p4_pdpi/ir.pb.h" +#include "p4_symbolic/z3_util.h" namespace p4_symbolic::symbolic::values { namespace { +using gutil::StatusIs; + +constexpr char kFieldName[] = "dummy_field_name"; +constexpr char kFieldType[] = "dummy_field_type"; + TEST(TranslateValueToP4RT, ReverseTranslatedValuesAreEqualToTheOriginalOnes) { constexpr int kNumIds = 256; - const std::string kFieldName = "dummy_field_name"; - const std::string kFieldType = "dummy_field_type"; // Prepare the translator and expected values. P4RuntimeTranslator translator; @@ -23,8 +28,9 @@ TEST(TranslateValueToP4RT, ReverseTranslatedValuesAreEqualToTheOriginalOnes) { const std::string id = absl::StrCat("id-", i); pdpi::IrValue ir_value; ir_value.set_str(id); - ASSERT_OK_AND_ASSIGN(z3::expr expr, FormatP4RTValue(kFieldName, kFieldType, - ir_value, &translator)); + ASSERT_OK_AND_ASSIGN(z3::expr expr, + FormatP4RTValue(kFieldName, kFieldType, ir_value, + /*bitwidth=*/0, &translator)); z3_value_to_id[expr.to_string()] = id; } @@ -37,5 +43,56 @@ TEST(TranslateValueToP4RT, ReverseTranslatedValuesAreEqualToTheOriginalOnes) { } } +// Make sure the code conforms to the pecularities of PDPI's value conversion. +TEST(FormatP4RTValue, WorksFor64BitIPv6) { + P4RuntimeTranslator trasnlator; + ASSERT_OK_AND_ASSIGN(auto ir_value, + gutil::ParseTextProto( + R"pb(ipv6: "0000:ffff:ffff:ffff::")pb")); + ASSERT_OK_AND_ASSIGN(z3::expr z3_expr, + FormatP4RTValue(kFieldName, kFieldType, ir_value, + /*bitwidth=*/64, &trasnlator)); + ASSERT_EQ(Z3ValueStringToInt(z3_expr.to_string()), 0x0000'ffff'ffff'ffffULL); +} + +TEST(FormatP4RTValue, WorksForIpv4) { + P4RuntimeTranslator trasnlator; + ASSERT_OK_AND_ASSIGN(auto ir_value, gutil::ParseTextProto( + R"pb(ipv4: "127.0.0.1")pb")); + ASSERT_OK_AND_ASSIGN(z3::expr z3_expr, + FormatP4RTValue(kFieldName, kFieldType, ir_value, + /*bitwidth=*/32, &trasnlator)); + ASSERT_EQ(Z3ValueStringToInt(z3_expr.to_string()), 0x7f000001); +} + +TEST(FormatP4RTValue, WorksForMac) { + P4RuntimeTranslator trasnlator; + ASSERT_OK_AND_ASSIGN(auto ir_value, gutil::ParseTextProto( + R"pb(mac: "01:02:03:04:05:06")pb")); + ASSERT_OK_AND_ASSIGN(z3::expr z3_expr, + FormatP4RTValue(kFieldName, kFieldType, ir_value, + /*bitwidth=*/48, &trasnlator)); + ASSERT_EQ(Z3ValueStringToInt(z3_expr.to_string()), 0x01'02'03'04'05'06ULL); +} + +TEST(FormatP4RTValue, WorksForHexString) { + P4RuntimeTranslator trasnlator; + ASSERT_OK_AND_ASSIGN(auto ir_value, gutil::ParseTextProto( + R"pb(hex_str: "0xabcd")pb")); + ASSERT_OK_AND_ASSIGN(z3::expr z3_expr, + FormatP4RTValue(kFieldName, kFieldType, ir_value, + /*bitwidth=*/16, &trasnlator)); + ASSERT_EQ(Z3ValueStringToInt(z3_expr.to_string()), 0xabcd); +} + +TEST(FormatP4RTValue, FailsForStringWithNonZeroBitwidth) { + P4RuntimeTranslator trasnlator; + ASSERT_OK_AND_ASSIGN(auto ir_value, gutil::ParseTextProto( + R"pb(str: "dummy_value")pb")); + ASSERT_THAT(FormatP4RTValue(kFieldName, kFieldType, ir_value, + /*bitwidth=*/16, &trasnlator), + StatusIs(absl::StatusCode::kInvalidArgument)); +} + } // namespace } // namespace p4_symbolic::symbolic::values diff --git a/p4rt_app/p4runtime/p4info_verification_schema_test.cc b/p4rt_app/p4runtime/p4info_verification_schema_test.cc index caaf5480..45c85f8d 100644 --- a/p4rt_app/p4runtime/p4info_verification_schema_test.cc +++ b/p4rt_app/p4runtime/p4info_verification_schema_test.cc @@ -883,7 +883,7 @@ class GoogleInstantiationTest // Tests that P4RT app is always "ahead of" our SAI P4 programs, so we don't // accidentally expose features in the program that are not yet supported by -// P4RT app/GPINS. +// P4RT app/PINS. TEST_P(GoogleInstantiationTest, SchemaSupportsInstantiation) { sai::Instantiation instantiation = GetParam(); pdpi::IrP4Info p4info = sai::GetIrP4Info(instantiation); diff --git a/sai_p4/fixed/BUILD.bazel b/sai_p4/fixed/BUILD.bazel index 23e64752..2b84c4c5 100644 --- a/sai_p4/fixed/BUILD.bazel +++ b/sai_p4/fixed/BUILD.bazel @@ -22,6 +22,7 @@ filegroup( srcs = [ "bitwidths.p4", "bmv2_intrinsics.h", + "common_actions.p4", "drop_martians.p4", "headers.p4", "ids.h", diff --git a/sai_p4/fixed/common_actions.p4 b/sai_p4/fixed/common_actions.p4 new file mode 100644 index 00000000..d8df5532 --- /dev/null +++ b/sai_p4/fixed/common_actions.p4 @@ -0,0 +1,14 @@ +#ifndef SAI_FIXED_COMMON_ACTIONS_P4_ +#define SAI_FIXED_COMMON_ACTIONS_P4_ + +#include "ids.h" + +// This file lists common actions that may be used by multiple control blocks in +// the fixed pipeline. + +// Action that does nothing. Like `NoAction` in `core.p4`, but following +// Google's naming conventions. +@id(SHARED_NO_ACTION_ACTION_ID) +action no_action() {} + +#endif // SAI_FIXED_COMMON_ACTIONS_P4_ diff --git a/sai_p4/fixed/drop_martians.p4 b/sai_p4/fixed/drop_martians.p4 index d94b2553..9cebb032 100644 --- a/sai_p4/fixed/drop_martians.p4 +++ b/sai_p4/fixed/drop_martians.p4 @@ -23,62 +23,55 @@ const ipv4_addr_t IPV4_BROADCAST_VALUE = 0xff_ff_ff_ff; const ipv4_addr_t IPV4_LOOPBACK_MASK = 0xff_00_00_00; const ipv4_addr_t IPV4_LOOPBACK_VALUE = 0x7f_00_00_00; -// I/G bit = 1 means multicast. -const ethernet_addr_t MAC_MULTICAST_MASK = 0x01_00_00_00_00_00; -const ethernet_addr_t MAC_MULTICAST_VALUE = 0x01_00_00_00_00_00; +#define IS_MULTICAST_IPV6(address) \ + (address & IPV6_MULTICAST_MASK == IPV6_MULTICAST_VALUE) +#define IS_LOOPBACK_IPV6(address) \ + (address & IPV6_LOOPBACK_MASK == IPV6_LOOPBACK_VALUE) -#define IS_IPV6_MULTICAST(address) \ - (address & IPV6_MULTICAST_MASK == IPV6_MULTICAST_VALUE) +#define IS_MULTICAST_IPV4(address) \ + (address & IPV4_MULTICAST_MASK == IPV4_MULTICAST_VALUE) -#define IS_IPV6_LOOPBACK(address) \ - (address & IPV6_LOOPBACK_MASK == IPV6_LOOPBACK_VALUE) +#define IS_BROADCAST_IPV4(address) \ + (address == IPV4_BROADCAST_VALUE) -#define IS_IPV4_MULTICAST_OR_BROADCAST(address) \ - ((address & IPV4_MULTICAST_MASK == IPV4_MULTICAST_VALUE) || \ - (address == IPV4_BROADCAST_VALUE)) +#define IS_LOOPBACK_IPV4(address) \ + (address & IPV4_LOOPBACK_MASK == IPV4_LOOPBACK_VALUE) -#define IS_IPV4_LOOPBACK(address) \ - (address & IPV4_LOOPBACK_MASK == IPV4_LOOPBACK_VALUE) +// I/G bit = 1 means multicast. +#define IS_UNICAST_MAC(address) \ + (address[40:40] == 0) -#define IS_MAC_MULTICAST(address) \ - (address & MAC_MULTICAST_MASK == MAC_MULTICAST_VALUE) +#define IS_IPV4_MULTICAST_MAC(address) \ + (address[47:24] == 0x01005E && address[23:23] == 0) +#define IS_IPV6_MULTICAST_MAC(address) \ + (address[47:32] == 0x3333) control drop_martians(in headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { apply { // Drop the packet if: - // - Src/Dst IPv6 addresses are in multicast range; or - // - Src/Dst IPv4 addresses are in multicast or broadcast range; or - // - I/G bit in dst MAC address is set (i.e. a multicast address); or + // - Src IPv6 address is in multicast range; or + // - Src IPv4 address is in multicast or broadcast range; or // - Src/Dst IPv4/IPv6 address is a loopback address. // Rationale: // Src IP multicast drop: https://www.rfc-editor.org/rfc/rfc1812#section-5.3.7 - // Dst IP multicast drop: multicast is not yet modeled and our switches drop - // multicast packets for now. // Src/Dst IP loopback drop: https://en.wikipedia.org/wiki/Localhost#Packet_processing // "Packets received on a non-loopback interface with a loopback source // or destination address must be dropped." - // Dst MAC multicast drop: multicast is not yet modeled and our switches - // drop multicast packets for now. if ((headers.ipv6.isValid() && - (IS_IPV6_MULTICAST(headers.ipv6.src_addr) || - // TODO: Rework conditions under which IPMC packets - // get forwarded and remove this constraint. - IS_IPV6_MULTICAST(headers.ipv6.dst_addr) || - IS_IPV6_LOOPBACK(headers.ipv6.src_addr) || - IS_IPV6_LOOPBACK(headers.ipv6.dst_addr))) || + (IS_MULTICAST_IPV6(headers.ipv6.src_addr) || + IS_LOOPBACK_IPV6(headers.ipv6.src_addr) || + IS_LOOPBACK_IPV6(headers.ipv6.dst_addr))) || (headers.ipv4.isValid() && - (IS_IPV4_MULTICAST_OR_BROADCAST(headers.ipv4.src_addr) || - // TODO: Rework conditions under which IPMC packets - // get forwarded and update this constraint. - IS_IPV4_MULTICAST_OR_BROADCAST(headers.ipv4.dst_addr) || - IS_IPV4_LOOPBACK(headers.ipv4.src_addr) || - IS_IPV4_LOOPBACK(headers.ipv4.dst_addr))) || - (headers.ethernet.isValid() && - IS_MAC_MULTICAST(headers.ethernet.dst_addr))) { + (IS_MULTICAST_IPV4(headers.ipv4.src_addr) || + IS_BROADCAST_IPV4(headers.ipv4.src_addr) || + IS_BROADCAST_IPV4(headers.ipv4.dst_addr) || + IS_LOOPBACK_IPV4(headers.ipv4.src_addr) || + IS_LOOPBACK_IPV4(headers.ipv4.dst_addr))) + ) { mark_to_drop(standard_metadata); } diff --git a/sai_p4/fixed/ids.h b/sai_p4/fixed/ids.h index b169f602..67e46f15 100644 --- a/sai_p4/fixed/ids.h +++ b/sai_p4/fixed/ids.h @@ -35,7 +35,7 @@ // --- Actions ----------------------------------------------------------------- // IDs of fixed SAI actions (8 most significant bits = 0x01). -#define ROUTING_NO_ACTION_ACTION_ID 0x01798B9E // 24742814 +#define SHARED_NO_ACTION_ACTION_ID 0x01798B9E // 24742814 #define ROUTING_SET_DST_MAC_ACTION_ID 0x01000001 // 16777217 #define ROUTING_SET_PORT_AND_SRC_MAC_ACTION_ID 0x01000002 // 16777218 #define ROUTING_SET_PORT_AND_SRC_MAC_AND_VLAN_ID_ACTION_ID \ @@ -56,18 +56,18 @@ #define MIRRORING_MIRROR_AS_IPV4_ERSPAN_ACTION_ID 0x01000007 // 16777223 #define CLONING_INGRESS_CLONE_ACTION_ID 0x0100001C // 16777244 #define CLONING_MIRROR_WITH_VLAN_TAG_AND_IPFIX_ENCAPSULATION_ACTION_ID \ - 0x0100001D // 16777245 -#define L3_ADMIT_ACTION_ID 0x01000008 // 16777224 -#define MIRRORING_SET_PRE_SESSION_ACTION_ID 0x01000009 // 16777225 -#define SELECT_ECMP_HASH_ALGORITHM_ACTION_ID 0x010000A // 16777226 -#define COMPUTE_ECMP_HASH_IPV4_ACTION_ID 0x0100000B // 16777227 -#define COMPUTE_ECMP_HASH_IPV6_ACTION_ID 0x0100000C // 16777228 -#define COMPUTE_LAG_HASH_IPV4_ACTION_ID 0x0100000D // 16777229 -#define COMPUTE_LAG_HASH_IPV6_ACTION_ID 0x0100000E // 16777230 -#define ROUTING_SET_METADATA_AND_DROP_ACTION_ID 0x01000015 // 16777237 -#define MARK_FOR_TUNNEL_DECAP_AND_SET_VRF_ACTION_ID 0x01000016 // 16777238 -#define DISABLE_VLAN_CHECKS_ACTION_ID 0x0100001A // 16777242 -// Next available action id: 0x0100001E (16777246) + 0x0100001D // 16777245 +#define L3_ADMIT_ACTION_ID 0x01000008 // 16777224 +#define MIRRORING_SET_PRE_SESSION_ACTION_ID 0x01000009 // 16777225 +#define SELECT_ECMP_HASH_ALGORITHM_ACTION_ID 0x010000A // 16777226 +#define COMPUTE_ECMP_HASH_IPV4_ACTION_ID 0x0100000B // 16777227 +#define COMPUTE_ECMP_HASH_IPV6_ACTION_ID 0x0100000C // 16777228 +#define COMPUTE_LAG_HASH_IPV4_ACTION_ID 0x0100000D // 16777229 +#define COMPUTE_LAG_HASH_IPV6_ACTION_ID 0x0100000E // 16777230 +#define ROUTING_SET_METADATA_AND_DROP_ACTION_ID 0x01000015 // 16777237 +#define TUNNEL_DECAP_ACTION_ID 0x01000016 // 16777238 +#define DISABLE_VLAN_CHECKS_ACTION_ID 0x0100001A // 16777242 +// Next available action id: 0x0100001F (16777247) // --- Action Profiles and Selectors (8 most significant bits = 0x11) ---------- // This value should ideally be 0x11000001, but we currently have this value for diff --git a/sai_p4/fixed/packet_rewrites.p4 b/sai_p4/fixed/packet_rewrites.p4 index d8dd277b..37259e74 100644 --- a/sai_p4/fixed/packet_rewrites.p4 +++ b/sai_p4/fixed/packet_rewrites.p4 @@ -29,6 +29,8 @@ control multicast_rewrites(inout local_metadata_t local_metadata, ethernet_addr_t src_mac) { local_metadata.enable_src_mac_rewrite = true; local_metadata.packet_rewrites.src_mac = src_mac; + // Hard-coded for now. We may make the VLAN ID programmable when needed. + local_metadata.packet_rewrites.vlan_id = INTERNAL_VLAN_ID; } // Rewrites the source MAC of the multicast-replicated packet. @@ -55,10 +57,6 @@ control multicast_rewrites(inout local_metadata_t local_metadata, // This will cause the source MAC of packets generated by the group member to // be rewritten to the `src_mac` of the `set_multicast_src_mac` action of the // entry. - // - // TODO: Remove `@unsupported` annotation once the switch stack - // supports this table. - @unsupported @p4runtime_role(P4RUNTIME_ROLE_ROUTING) @id(ROUTING_MULTICAST_ROUTER_INTERFACE_TABLE_ID) table multicast_router_interface_table { diff --git a/sai_p4/fixed/routing.p4 b/sai_p4/fixed/routing.p4 index 4acae4af..a50c3e06 100644 --- a/sai_p4/fixed/routing.p4 +++ b/sai_p4/fixed/routing.p4 @@ -2,6 +2,8 @@ #define SAI_ROUTING_P4_ #include +#include "common_actions.p4" +#include "drop_martians.p4" #include "headers.p4" #include "metadata.p4" #include "ids.h" @@ -65,12 +67,6 @@ action set_nexthop_id(inout local_metadata_t local_metadata, control routing_lookup(in headers_t headers, inout local_metadata_t local_metadata, inout standard_metadata_t standard_metadata) { - // Action that does nothing. Like `NoAction` in `core.p4`, but following - // Google's naming conventions. - // TODO: Add support for CamlCase actions to the PD generator, - // so we can use `NoAction` throughout. - @id(ROUTING_NO_ACTION_ACTION_ID) - action no_action() {} // Programming this table does not affect packet forwarding directly -- the // table performs no actions -- but results in the creation/deletion of VRFs. // This is a prerequisite to using these VRFs, e.g. in the `ipv4_table` and @@ -165,9 +161,6 @@ control routing_lookup(in headers_t headers, // Calling this action will override unicast, and can itself be overriden by // `mark_to_drop`. // - // 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. @@ -226,9 +219,6 @@ control routing_lookup(in headers_t headers, // Models SAI IPMC entries of type (*,G) whose destination is an IPv4 address. @p4runtime_role(P4RUNTIME_ROLE_ROUTING) @id(ROUTING_IPV4_MULTICAST_TABLE_ID) - // TODO: Remove `@unsupported` annotation once the switch stack - // supports multicast. - @unsupported table ipv4_multicast_table { key = { // Sets `vr_id` in `sai_ipmc_entry_t`. @@ -247,9 +237,6 @@ control routing_lookup(in headers_t headers, // Models SAI IPMC entries of type (*,G) whose destination is an IPv6 address. @p4runtime_role(P4RUNTIME_ROLE_ROUTING) @id(ROUTING_IPV6_MULTICAST_TABLE_ID) - // TODO: Remove `@unsupported` annotation once the switch stack - // supports multicast. - @unsupported table ipv6_multicast_table { key = { // Sets `vr_id` in `sai_ipmc_entry_t`. @@ -266,32 +253,40 @@ control routing_lookup(in headers_t headers, } apply { - // Drop packets by default, then override in the router_interface_table. - // TODO: This should just be the default behavior of v1model: - // https://github.com/p4lang/behavioral-model/issues/992 mark_to_drop(standard_metadata); vrf_table.apply(); - if (local_metadata.admit_to_l3) { - if (headers.ipv4.isValid()) { - // TODO: Rework conditions under which uni/multicast table - // lookups occur and what happens when both tables are hit. - ipv4_table.apply(); - - // TODO: Use commented out code instead, once p4-symbolic - // supports it. - // local_metadata.ipmc_table_hit = ipv4_multicast_table.apply().hit() - ipv4_multicast_table.apply(); - local_metadata.ipmc_table_hit = standard_metadata.mcast_grp != 0; - } else if (headers.ipv6.isValid()) { - // TODO: Rework conditions under which uni/multicast table - // lookups occur and what happens when both tables are hit. - ipv6_table.apply(); - // TODO: Use commented out code instead, once p4-symbolic - // supports it. - // local_metadata.ipmc_table_hit = ipv6_multicast_table.apply().hit() - ipv6_multicast_table.apply(); - local_metadata.ipmc_table_hit = standard_metadata.mcast_grp != 0; + if (headers.ipv4.isValid()) { + if (IS_MULTICAST_IPV4(headers.ipv4.dst_addr)) { + if (IS_IPV4_MULTICAST_MAC(headers.ethernet.dst_addr)) { + ipv4_multicast_table.apply(); + local_metadata.ipmc_table_hit = standard_metadata.mcast_grp != 0; + // TODO: Use commented out code instead, once p4-symbolic + // supports it. + // local_metadata.ipmc_table_hit = ipv4_multicast_table.apply().hit() + } + } else { // IPv4 unicast. + if (IS_UNICAST_MAC(headers.ethernet.dst_addr) && + local_metadata.admit_to_l3) { + ipv4_table.apply(); + } + } + } else if (headers.ipv6.isValid()) { + if (IS_MULTICAST_IPV6(headers.ipv6.dst_addr)) { + if (local_metadata.admit_to_l3 || + // Packets with multicast DMAC are always elligible for IP multicast. + IS_IPV6_MULTICAST_MAC(headers.ethernet.dst_addr)) { + ipv6_multicast_table.apply(); + local_metadata.ipmc_table_hit = standard_metadata.mcast_grp != 0; + // TODO: Use commented out code instead, once p4-symbolic + // supports it. + // local_metadata.ipmc_table_hit = ipv6_multicast_table.apply().hit() + } + } else { // IPv6 unicast. + if (IS_UNICAST_MAC(headers.ethernet.dst_addr) && + local_metadata.admit_to_l3) { + ipv6_table.apply(); + } } } } diff --git a/sai_p4/fixed/tunnel_termination.p4 b/sai_p4/fixed/tunnel_termination.p4 index 63a8e045..31f3a806 100644 --- a/sai_p4/fixed/tunnel_termination.p4 +++ b/sai_p4/fixed/tunnel_termination.p4 @@ -17,16 +17,23 @@ #ifndef SAI_TUNNEL_TERMINATION_P4_ #define SAI_TUNNEL_TERMINATION_P4_ -// Should be applied at the beginning of the pre-ingress stage. -control tunnel_termination_lookup(in headers_t headers, +#include +#include "headers.p4" +#include "metadata.p4" +#include "ids.h" +#include "minimum_guaranteed_sizes.p4" + +// Should be applied at the end of the pre-ingress stage. +control tunnel_termination(inout headers_t headers, inout local_metadata_t local_metadata) { + bool marked_for_ip_in_ipv6_decap = false; - // Sets SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID. - @id(MARK_FOR_TUNNEL_DECAP_AND_SET_VRF_ACTION_ID) - action mark_for_tunnel_decap_and_set_vrf(vrf_id_t vrf_id) { - // Actual decap is delayed until the end of the pre-ingress stage. - local_metadata.apply_tunnel_decap_at_end_of_pre_ingress = true; - local_metadata.vrf_id = vrf_id; + @id(TUNNEL_DECAP_ACTION_ID) + @unsupported + action tunnel_decap() { + // Bmv2 does not support if statements in actions, so control metadata is + // set and decapping is performed post-action. + marked_for_ip_in_ipv6_decap = true; } // Models SAI_TUNNEL_TERM_TABLE. @@ -36,14 +43,18 @@ control tunnel_termination_lookup(in headers_t headers, @unsupported @p4runtime_role(P4RUNTIME_ROLE_ROUTING) @id(IPV6_TUNNEL_TERMINATION_TABLE_ID) + @unsupported table ipv6_tunnel_termination_table { key = { // Sets `SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP[_MASK]`. headers.ipv6.dst_addr : ternary @id(1) @name("dst_ipv6") @format(IPV6_ADDRESS); + // Sets `SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP[_MASK]`. + headers.ipv6.src_addr : ternary + @id(2) @name("src_ipv6") @format(IPV6_ADDRESS); } actions = { - @proto_id(1) mark_for_tunnel_decap_and_set_vrf; + @proto_id(1) tunnel_decap; } size = IPV6_TUNNEL_TERMINATION_TABLE_MINIMUM_GUARANTEED_SIZE; } @@ -58,15 +69,8 @@ control tunnel_termination_lookup(in headers_t headers, ipv6_tunnel_termination_table.apply(); } } - } -} - -// Should be applied at the end of the pre-ingress stage. -control tunnel_termination_decap(inout headers_t headers, - in local_metadata_t local_metadata) { - apply { - if (local_metadata.apply_tunnel_decap_at_end_of_pre_ingress) { + if (marked_for_ip_in_ipv6_decap) { // Currently, this should only ever be set for IP-in-IPv6 packets. // TODO: Remove guard once p4-symbolic suports assertions. #ifndef PLATFORM_P4SYMBOLIC diff --git a/sai_p4/instantiations/google/BUILD.bazel b/sai_p4/instantiations/google/BUILD.bazel index 50ee1794..4074db60 100644 --- a/sai_p4/instantiations/google/BUILD.bazel +++ b/sai_p4/instantiations/google/BUILD.bazel @@ -27,6 +27,7 @@ package( SHARED_DEPS = [ "acl_common_actions.p4", + "acl_egress.p4", "acl_ingress.p4", "acl_pre_ingress.p4", "ids.h", @@ -41,12 +42,10 @@ SHARED_DEPS = [ MIDDLEBLOCK_DEPS = SHARED_DEPS + ["middleblock.p4"] FABRIC_BORDER_ROUTER_DEPS = SHARED_DEPS + [ - "acl_egress.p4", "fabric_border_router.p4", ] TOR_DEPS = SHARED_DEPS + [ - "acl_egress.p4", "tor.p4", ] @@ -408,3 +407,7 @@ cc_test( ], ) +filegroup( + name = "sai_p4", + srcs = glob(["**/*.p4"]) + glob(["**/*.h"]), +) diff --git a/sai_p4/instantiations/google/acl_egress.p4 b/sai_p4/instantiations/google/acl_egress.p4 index 6c08059e..5ecba799 100644 --- a/sai_p4/instantiations/google/acl_egress.p4 +++ b/sai_p4/instantiations/google/acl_egress.p4 @@ -88,7 +88,7 @@ control acl_egress(in headers_t headers, @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2) ) @format(IPV6_ADDRESS); #endif -#if defined(SAI_INSTANTIATION_TOR) +#if defined(SAI_INSTANTIATION_TOR) || defined(SAI_INSTANTIATION_MIDDLEBLOCK) headers.ethernet.src_addr : ternary @name("src_mac") @id(10) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC) @format(MAC_ADDRESS); #endif diff --git a/sai_p4/instantiations/google/acl_ingress.p4 b/sai_p4/instantiations/google/acl_ingress.p4 index 91ff70ba..717638e6 100644 --- a/sai_p4/instantiations/google/acl_ingress.p4 +++ b/sai_p4/instantiations/google/acl_ingress.p4 @@ -263,7 +263,8 @@ control acl_ingress(in headers_t headers, @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ECN); #endif // Field for v4 IP protocol and v6 next header. - ip_protocol : ternary @name("ip_protocol") @id(13) + ip_protocol : ternary + @id(13) @name("ip_protocol") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL); #if defined(SAI_INSTANTIATION_FABRIC_BORDER_ROUTER) || defined(SAI_INSTANTIATION_TOR) headers.icmp.type : ternary @name("icmp_type") @id(19) @@ -317,7 +318,7 @@ control acl_ingress(in headers_t headers, // Only allow IP field matches for IP packets. ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1); ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1); - // Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets. + // Only allow l4_dst_port matches for TCP/UDP packets. l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17); // Forbid illegal combinations of IP_TYPE fields. is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0); @@ -328,8 +329,16 @@ control acl_ingress(in headers_t headers, is_ipv6::mask != 0 -> (is_ipv6 == 1); // Only allow icmp_type matches for ICMP packets icmpv6_type::mask != 0 -> ip_protocol == 58; +#ifdef SAI_INSTANTIATION_FABRIC_BORDER_ROUTER + // Only allow l4_dst_port matches for TCP/UDP packets. + l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17); + // Only allow icmp_type matches for ICMP packets + icmp_type::mask != 0 -> ip_protocol == 1; +#endif +#if defined(SAI_INSTANTIATION_TOR) // Only allow arp_tpa matches for ARP packets. arp_tpa::mask != 0 -> ether_type == 0x0806; +#endif ") table acl_ingress_qos_table { key = { @@ -345,15 +354,6 @@ control acl_ingress(in headers_t headers, headers.ethernet.ether_type : ternary @id(4) @name("ether_type") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE); - headers.ethernet.dst_addr : ternary - @id(5) @name("dst_mac") - @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC) @format(MAC_ADDRESS); - headers.arp.target_proto_addr : ternary - @id(6) @name("arp_tpa") - @composite_field( - @sai_udf(base=SAI_UDF_BASE_L3, offset=24, length=2), - @sai_udf(base=SAI_UDF_BASE_L3, offset=26, length=2) - ) @format(IPV4_ADDRESS); ttl : ternary @id(7) @name("ttl") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_TTL); @@ -366,12 +366,34 @@ control acl_ingress(in headers_t headers, local_metadata.l4_dst_port : ternary @id(10) @name("l4_dst_port") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT); +#ifdef SAI_INSTANTIATION_FABRIC_BORDER_ROUTER + local_metadata.l4_src_port : ternary + @id(12) @name("l4_src_port") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT); + headers.icmp.type : ternary + @id(14) @name("icmp_type") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE); + local_metadata.route_metadata : ternary + @id(15) @name("route_metadata") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META); +#endif +#if defined(SAI_INSTANTIATION_TOR) + headers.ethernet.dst_addr : ternary + @id(5) @name("dst_mac") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC) @format(MAC_ADDRESS); + headers.arp.target_proto_addr : ternary + @id(6) @name("arp_tpa") + @composite_field( + @sai_udf(base=SAI_UDF_BASE_L3, offset=24, length=2), + @sai_udf(base=SAI_UDF_BASE_L3, offset=26, length=2) + ) @format(IPV4_ADDRESS); local_metadata.ingress_port : optional @id(11) @name("in_port") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IN_PORT); local_metadata.acl_metadata : ternary @id(13) @name("acl_metadata") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META); +#endif } actions = { @proto_id(1) set_qos_queue_and_cancel_copy_above_rate_limit(); @@ -391,6 +413,7 @@ control acl_ingress(in headers_t headers, @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @id(ACL_INGRESS_COUNTING_TABLE_ID) + @sai_acl_priority(7) @sai_acl(INGRESS) @entry_restriction(" // Only allow IP field matches for IP packets. @@ -405,9 +428,11 @@ control acl_ingress(in headers_t headers, ") table acl_ingress_counting_table { key = { - headers.ipv4.isValid() || headers.ipv6.isValid() : optional @name("is_ip") - @id(1) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IP); - headers.ipv4.isValid() : optional @name("is_ipv4") @id(2) + headers.ipv4.isValid() || headers.ipv6.isValid() : optional + @id(1) @name("is_ip") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IP); + headers.ipv4.isValid() : optional + @id(2) @name("is_ipv4") @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV4ANY); headers.ipv6.isValid() : optional @name("is_ipv6") @id(3) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV6ANY); @@ -429,6 +454,7 @@ control acl_ingress(in headers_t headers, @id(ACL_INGRESS_REDIRECT_TO_NEXTHOP_ACTION_ID) action redirect_to_nexthop( @sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT) + @sai_action_param_object_type(SAI_OBJECT_TYPE_NEXT_HOP) @refers_to(nexthop_table, nexthop_id) nexthop_id_t nexthop_id) { @@ -441,9 +467,6 @@ control acl_ingress(in headers_t headers, standard_metadata.mcast_grp = 0; } - // TODO: Remove `@unsupported` annotation once the switch stack - // supports multicast. - @unsupported @id(ACL_INGRESS_REDIRECT_TO_IPMC_GROUP_ACTION_ID) @action_restriction(" // Disallow 0 since it encodes 'no multicast' in V1Model. @@ -451,8 +474,8 @@ control acl_ingress(in headers_t headers, ") action redirect_to_ipmc_group( @sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT) - // TODO: Add this once supported by PDPI and its customers. - // @refers_to(multicast_group_table, multicast_group_id) + @sai_action_param_object_type(SAI_OBJECT_TYPE_IPMC_GROUP) + @refers_to(builtin::multicast_group_table, multicast_group_id) multicast_group_id_t multicast_group_id) { standard_metadata.mcast_grp = multicast_group_id; @@ -465,6 +488,7 @@ control acl_ingress(in headers_t headers, // ACL table that mirrors and redirects packets. @id(ACL_INGRESS_MIRROR_AND_REDIRECT_TABLE_ID) @sai_acl(INGRESS) + @sai_acl_priority(15) @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @entry_restriction(" // Only allow IP field matches for IP packets. @@ -527,20 +551,14 @@ control acl_ingress(in headers_t headers, @id(5); local_metadata.vrf_id : optional - @name("vrf_id") - @sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID) - @id(8) - // TODO: Remove once the switch supports this field. - @unsupported; - + @id(8) @name("vrf_id") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID); local_metadata.ipmc_table_hit : optional - @name("ipmc_table_hit") - @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_TABLE_HIT) - @id(9) - // TODO: Remove once the switch supports this field. - @unsupported; + @id(9) @name("ipmc_table_hit") + @sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_NPU_META_DST_HIT); } actions = { + @proto_id(4) acl_forward(); @proto_id(1) acl_mirror(); @proto_id(2) redirect_to_nexthop(); @proto_id(3) redirect_to_ipmc_group(); @@ -553,6 +571,7 @@ control acl_ingress(in headers_t headers, // ACL table that only drops or denies packets, and is otherwise a no-op. @id(ACL_INGRESS_SECURITY_TABLE_ID) @sai_acl(INGRESS) + @sai_acl_priority(20) @p4runtime_role(P4RUNTIME_ROLE_SDN_CONTROLLER) @entry_restriction(" // Forbid using ether_type for IP packets (by convention, use is_ip* instead). @@ -660,6 +679,7 @@ control acl_ingress(in headers_t headers, #elif defined(SAI_INSTANTIATION_FABRIC_BORDER_ROUTER) acl_ingress_table.apply(); acl_ingress_counting_table.apply(); + acl_ingress_qos_table.apply(); #elif defined(SAI_INSTANTIATION_TOR) // These tables are currently order agnostic, but we should be careful to // ensure that the ordering is correct if we add new actions or model diff --git a/sai_p4/instantiations/google/acl_pre_ingress.p4 b/sai_p4/instantiations/google/acl_pre_ingress.p4 index ffccfc56..b3043de0 100644 --- a/sai_p4/instantiations/google/acl_pre_ingress.p4 +++ b/sai_p4/instantiations/google/acl_pre_ingress.p4 @@ -95,8 +95,10 @@ control acl_pre_ingress(in headers_t headers, @sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE/IPV6ANY); headers.ethernet.src_addr : ternary @name("src_mac") @id(4) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC) @format(MAC_ADDRESS); +#ifdef SAI_INSTANTIATION_FABRIC_BORDER_ROUTER headers.ethernet.dst_addr : ternary @name("dst_mac") @id(9) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC) @format(MAC_ADDRESS); +#endif headers.ipv4.dst_addr : ternary @name("dst_ip") @id(5) @sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_IP) @format(IPV4_ADDRESS); headers.ipv6.dst_addr[127:64] : ternary @name("dst_ipv6") @id(6) diff --git a/sai_p4/instantiations/google/fabric_border_router.p4 b/sai_p4/instantiations/google/fabric_border_router.p4 index 2c22a456..166d4748 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4 +++ b/sai_p4/instantiations/google/fabric_border_router.p4 @@ -33,11 +33,10 @@ control ingress(inout headers_t headers, apply { packet_out_decap.apply(headers, local_metadata, standard_metadata); if (!local_metadata.bypass_ingress) { - tunnel_termination_lookup.apply(headers, local_metadata); vlan_untag.apply(headers, local_metadata, standard_metadata); acl_pre_ingress.apply(headers, local_metadata, standard_metadata); ingress_vlan_checks.apply(headers, local_metadata, standard_metadata); - tunnel_termination_decap.apply(headers, local_metadata); + tunnel_termination.apply(headers, local_metadata); admit_google_system_mac.apply(headers, local_metadata); l3_admit.apply(headers, local_metadata, standard_metadata); routing_lookup.apply(headers, local_metadata, standard_metadata); 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 4402123e..5c0591d0 100644 --- a/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt +++ b/sai_p4/instantiations/google/fabric_border_router.p4info.pb.txt @@ -4,32 +4,6 @@ pkg_info { arch: "v1model" organization: "Google" } -tables { - preamble { - id: 33554507 - name: "ingress.tunnel_termination_lookup.ipv6_tunnel_termination_table" - alias: "ipv6_tunnel_termination_table" - annotations: "@unsupported" - annotations: "@p4runtime_role(\"sdn_controller\")" - } - match_fields { - id: 1 - name: "dst_ipv6" - annotations: "@format(IPV6_ADDRESS)" - bitwidth: 128 - match_type: TERNARY - } - action_refs { - id: 16777238 - annotations: "@proto_id(1)" - } - action_refs { - id: 21257015 - annotations: "@defaultonly" - scope: DEFAULT_ONLY - } - size: 126 -} tables { preamble { id: 33554509 @@ -154,6 +128,40 @@ tables { direct_resource_ids: 318767361 size: 254 } +tables { + preamble { + id: 33554507 + name: "ingress.tunnel_termination.ipv6_tunnel_termination_table" + alias: "ipv6_tunnel_termination_table" + annotations: "@unsupported" + annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@unsupported" + } + match_fields { + id: 1 + name: "dst_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } + match_fields { + id: 2 + name: "src_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } + action_refs { + id: 16777238 + annotations: "@proto_id(1)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + size: 126 +} tables { preamble { id: 33554503 @@ -317,7 +325,6 @@ tables { name: "ingress.routing_lookup.ipv4_multicast_table" alias: "ipv4_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -352,7 +359,6 @@ tables { name: "ingress.routing_lookup.ipv6_multicast_table" alias: "ipv6_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -561,12 +567,134 @@ tables { direct_resource_ids: 352321792 size: 256 } +tables { + preamble { + id: 33554695 + name: "ingress.acl_ingress.acl_ingress_qos_table" + alias: "acl_ingress_qos_table" + annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(10)" + annotations: "@p4runtime_role(\"sdn_controller\")" + 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 // 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 \")" + } + match_fields { + id: 1 + name: "is_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 2 + name: "is_ipv4" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 3 + name: "is_ipv6" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 4 + name: "ether_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 7 + name: "ttl" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_TTL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 8 + name: "ip_protocol" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 9 + name: "icmpv6_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 10 + name: "l4_dst_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 12 + name: "l4_src_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 14 + name: "icmp_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 15 + name: "route_metadata" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META)" + bitwidth: 6 + match_type: TERNARY + } + action_refs { + id: 16777484 + annotations: "@proto_id(1)" + } + action_refs { + id: 16777486 + annotations: "@proto_id(2)" + } + action_refs { + id: 16777475 + annotations: "@proto_id(3)" + } + action_refs { + id: 16777481 + annotations: "@proto_id(4)" + } + action_refs { + id: 16777488 + annotations: "@proto_id(5)" + } + action_refs { + id: 16777489 + annotations: "@proto_id(6)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + const_default_action_id: 21257015 + direct_resource_ids: 318767367 + direct_resource_ids: 352321794 + size: 255 +} tables { preamble { id: 33554697 name: "ingress.acl_ingress.acl_ingress_counting_table" alias: "acl_ingress_counting_table" annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@sai_acl_priority(7)" annotations: "@sai_acl(INGRESS)" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dscp::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || 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 \")" } @@ -851,7 +979,6 @@ tables { id: 33554508 name: "egress.packet_rewrites.multicast_rewrites.multicast_router_interface_table" alias: "multicast_router_interface_table" - annotations: "@unsupported" annotations: "@p4runtime_role(\"sdn_controller\")" } match_fields { @@ -969,6 +1096,13 @@ actions { annotations: "@noWarn(\"unused\")" } } +actions { + preamble { + id: 24742814 + name: "no_action" + alias: "no_action" + } +} actions { preamble { id: 16777221 @@ -992,20 +1126,6 @@ actions { annotations: "@sai_action(SAI_PACKET_ACTION_DROP)" } } -actions { - preamble { - id: 16777238 - name: "ingress.tunnel_termination_lookup.mark_for_tunnel_decap_and_set_vrf" - alias: "mark_for_tunnel_decap_and_set_vrf" - } - params { - id: 1 - name: "vrf_id" - type_name { - name: "vrf_id_t" - } - } -} actions { preamble { id: 16777242 @@ -1032,16 +1152,17 @@ actions { } actions { preamble { - id: 16777224 - name: "ingress.l3_admit.admit_to_l3" - alias: "admit_to_l3" + id: 16777238 + name: "ingress.tunnel_termination.tunnel_decap" + alias: "tunnel_decap" + annotations: "@unsupported" } } actions { preamble { - id: 24742814 - name: "ingress.routing_lookup.no_action" - alias: "no_action" + id: 16777224 + name: "ingress.l3_admit.admit_to_l3" + alias: "admit_to_l3" } } actions { @@ -1123,7 +1244,6 @@ actions { id: 16777240 name: "ingress.routing_lookup.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;\n \")" } params { @@ -1201,6 +1321,90 @@ actions { } } } +actions { + preamble { + id: 16777484 + name: "ingress.acl_ingress.set_qos_queue_and_cancel_copy_above_rate_limit" + alias: "set_qos_queue_and_cancel_copy_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_RED)" + } + params { + id: 1 + name: "qos_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777489 + name: "ingress.acl_ingress.set_cpu_and_multicast_queues_and_deny_above_rate_limit" + alias: "set_cpu_and_multicast_queues_and_deny_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" + annotations: "@unsupported" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } + params { + id: 2 + name: "green_multicast_queue" + annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_GREEN)" + type_name { + name: "qos_queue_t" + } + } + params { + id: 3 + name: "red_multicast_queue" + annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_RED)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777486 + name: "ingress.acl_ingress.set_cpu_queue_and_deny_above_rate_limit" + alias: "set_cpu_queue_and_deny_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777488 + name: "ingress.acl_ingress.set_cpu_queue" + alias: "set_cpu_queue" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD)" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} actions { preamble { id: 16777217 @@ -1538,6 +1742,17 @@ direct_counters { } direct_table_id: 33554688 } +direct_counters { + preamble { + id: 318767367 + name: "ingress.acl_ingress.acl_ingress_qos_counter" + alias: "acl_ingress_qos_counter" + } + spec { + unit: BOTH + } + direct_table_id: 33554695 +} direct_counters { preamble { id: 318767369 @@ -1572,6 +1787,18 @@ direct_meters { } direct_table_id: 33554688 } +direct_meters { + preamble { + id: 352321794 + name: "ingress.acl_ingress.acl_ingress_qos_meter" + alias: "acl_ingress_qos_meter" + annotations: "@mode(single_rate_two_color)" + } + spec { + unit: BYTES + } + direct_table_id: 33554695 +} controller_packet_metadata { preamble { id: 81826293 diff --git a/sai_p4/instantiations/google/middleblock.p4 b/sai_p4/instantiations/google/middleblock.p4 index de804fa0..79315251 100644 --- a/sai_p4/instantiations/google/middleblock.p4 +++ b/sai_p4/instantiations/google/middleblock.p4 @@ -20,6 +20,7 @@ #include "../../fixed/drop_martians.p4" #include "../../fixed/packet_rewrites.p4" #include "../../fixed/tunnel_termination.p4" +#include "acl_egress.p4" #include "acl_ingress.p4" #include "acl_pre_ingress.p4" #include "admit_google_system_mac.p4" @@ -33,11 +34,10 @@ control ingress(inout headers_t headers, apply { packet_out_decap.apply(headers, local_metadata, standard_metadata); if (!local_metadata.bypass_ingress) { - tunnel_termination_lookup.apply(headers, local_metadata); vlan_untag.apply(headers, local_metadata, standard_metadata); acl_pre_ingress.apply(headers, local_metadata, standard_metadata); ingress_vlan_checks.apply(headers, local_metadata, standard_metadata); - tunnel_termination_decap.apply(headers, local_metadata); + tunnel_termination.apply(headers, local_metadata); admit_google_system_mac.apply(headers, local_metadata); l3_admit.apply(headers, local_metadata, standard_metadata); routing_lookup.apply(headers, local_metadata, standard_metadata); @@ -62,6 +62,7 @@ control egress(inout headers_t headers, mirroring_encap.apply(headers, local_metadata, standard_metadata); egress_vlan_checks.apply(headers, local_metadata, standard_metadata); vlan_tag.apply(headers, local_metadata, standard_metadata); + acl_egress.apply(headers, local_metadata, standard_metadata); } } } // control egress diff --git a/sai_p4/instantiations/google/middleblock.p4info.pb.txt b/sai_p4/instantiations/google/middleblock.p4info.pb.txt index 49144381..df04af27 100755 --- a/sai_p4/instantiations/google/middleblock.p4info.pb.txt +++ b/sai_p4/instantiations/google/middleblock.p4info.pb.txt @@ -4,32 +4,6 @@ pkg_info { arch: "v1model" organization: "Google" } -tables { - preamble { - id: 33554507 - name: "ingress.tunnel_termination_lookup.ipv6_tunnel_termination_table" - alias: "ipv6_tunnel_termination_table" - annotations: "@unsupported" - annotations: "@p4runtime_role(\"sdn_controller\")" - } - match_fields { - id: 1 - name: "dst_ipv6" - annotations: "@format(IPV6_ADDRESS)" - bitwidth: 128 - match_type: TERNARY - } - action_refs { - id: 16777238 - annotations: "@proto_id(1)" - } - action_refs { - id: 21257015 - annotations: "@defaultonly" - scope: DEFAULT_ONLY - } - size: 126 -} tables { preamble { id: 33554509 @@ -94,14 +68,6 @@ tables { bitwidth: 48 match_type: TERNARY } - match_fields { - id: 9 - name: "dst_mac" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" - annotations: "@format(MAC_ADDRESS)" - bitwidth: 48 - match_type: TERNARY - } match_fields { id: 5 name: "dst_ip" @@ -154,6 +120,40 @@ tables { direct_resource_ids: 318767361 size: 254 } +tables { + preamble { + id: 33554507 + name: "ingress.tunnel_termination.ipv6_tunnel_termination_table" + alias: "ipv6_tunnel_termination_table" + annotations: "@unsupported" + annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@unsupported" + } + match_fields { + id: 1 + name: "dst_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } + match_fields { + id: 2 + name: "src_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } + action_refs { + id: 16777238 + annotations: "@proto_id(1)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + size: 126 +} tables { preamble { id: 33554503 @@ -317,7 +317,6 @@ tables { name: "ingress.routing_lookup.ipv4_multicast_table" alias: "ipv4_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -352,7 +351,6 @@ tables { name: "ingress.routing_lookup.ipv6_multicast_table" alias: "ipv6_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -552,6 +550,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_mirror_and_redirect_table" alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(15)" 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 \")" } @@ -596,7 +595,6 @@ tables { id: 8 name: "vrf_id" annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID)" - annotations: "@unsupported" match_type: OPTIONAL type_name { name: "vrf_id_t" @@ -605,11 +603,14 @@ tables { match_fields { id: 9 name: "ipmc_table_hit" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_TABLE_HIT)" - annotations: "@unsupported" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_NPU_META_DST_HIT)" bitwidth: 1 match_type: OPTIONAL } + action_refs { + id: 16777475 + annotations: "@proto_id(4)" + } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -636,6 +637,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_security_table" alias: "acl_ingress_security_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(20)" annotations: "@p4runtime_role(\"sdn_controller\")" 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\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n src_ip::mask != 0 -> is_ipv4 == 1;\n src_ipv6::mask != 0 -> is_ipv6 == 1;\n\n // TODO: This comment is required for the preprocessor to not\n // spit out nonsense.\n\n\n\n\n\n\n\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 \")" } @@ -945,7 +947,6 @@ tables { id: 33554508 name: "egress.packet_rewrites.multicast_rewrites.multicast_router_interface_table" alias: "multicast_router_interface_table" - annotations: "@unsupported" annotations: "@p4runtime_role(\"sdn_controller\")" } match_fields { @@ -975,6 +976,73 @@ tables { } size: 128 } +tables { + preamble { + id: 33554692 + name: "egress.acl_egress.acl_egress_table" + alias: "acl_egress_table" + annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@sai_acl(EGRESS)" + annotations: "@entry_restriction(\"\n\n\n\n\n\n // Only allow IP field matches for IP packets.\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n\n\n\n\n\n\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 { + id: 2 + name: "ip_protocol" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 4 + name: "out_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_OUT_PORT)" + match_type: OPTIONAL + type_name { + name: "port_id_t" + } + } + match_fields { + id: 5 + name: "is_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 6 + name: "is_ipv4" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 7 + name: "is_ipv6" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 10 + name: "src_mac" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC)" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + match_type: TERNARY + } + action_refs { + id: 16777481 + annotations: "@proto_id(1)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + const_default_action_id: 21257015 + direct_resource_ids: 318767364 + size: 127 +} actions { preamble { id: 21257015 @@ -983,6 +1051,13 @@ actions { annotations: "@noWarn(\"unused\")" } } +actions { + preamble { + id: 24742814 + name: "no_action" + alias: "no_action" + } +} actions { preamble { id: 16777221 @@ -1006,20 +1081,6 @@ actions { annotations: "@sai_action(SAI_PACKET_ACTION_DROP)" } } -actions { - preamble { - id: 16777238 - name: "ingress.tunnel_termination_lookup.mark_for_tunnel_decap_and_set_vrf" - alias: "mark_for_tunnel_decap_and_set_vrf" - } - params { - id: 1 - name: "vrf_id" - type_name { - name: "vrf_id_t" - } - } -} actions { preamble { id: 16777242 @@ -1046,16 +1107,17 @@ actions { } actions { preamble { - id: 16777224 - name: "ingress.l3_admit.admit_to_l3" - alias: "admit_to_l3" + id: 16777238 + name: "ingress.tunnel_termination.tunnel_decap" + alias: "tunnel_decap" + annotations: "@unsupported" } } actions { preamble { - id: 24742814 - name: "ingress.routing_lookup.no_action" - alias: "no_action" + id: 16777224 + name: "ingress.l3_admit.admit_to_l3" + alias: "admit_to_l3" } } actions { @@ -1137,7 +1199,6 @@ actions { id: 16777240 name: "ingress.routing_lookup.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;\n \")" } params { @@ -1225,6 +1286,7 @@ actions { id: 1 name: "nexthop_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_NEXT_HOP)" annotations: "@refers_to(nexthop_table , nexthop_id)" type_name { name: "nexthop_id_t" @@ -1236,13 +1298,14 @@ actions { id: 16777491 name: "ingress.acl_ingress.redirect_to_ipmc_group" alias: "redirect_to_ipmc_group" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_IPMC_GROUP)" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } @@ -1594,6 +1657,17 @@ direct_counters { } direct_table_id: 33554698 } +direct_counters { + preamble { + id: 318767364 + name: "egress.acl_egress.acl_egress_counter" + alias: "acl_egress_counter" + } + spec { + unit: BOTH + } + direct_table_id: 33554692 +} direct_meters { preamble { id: 352321792 diff --git a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 index 4f10e692..033c88fe 100644 --- a/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 +++ b/sai_p4/instantiations/google/minimum_guaranteed_sizes.p4 @@ -54,7 +54,8 @@ #define ROUTING_IPV4_MULTICAST_TABLE_MINIMUM_GUARANTEED_SIZE 1600 #define ROUTING_IPV6_MULTICAST_TABLE_MINIMUM_GUARANTEED_SIZE 1600 -#define ROUTING_MULTICAST_ROUTER_INTERFACE_TABLE_MINIMUM_GUARANTEED_SIZE 128 +// TODO: multicast_router_interface_table runs out of space at 110 entries, expected 128 +#define ROUTING_MULTICAST_ROUTER_INTERFACE_TABLE_MINIMUM_GUARANTEED_SIZE 110 // The maximum number of wcmp groups. #define WCMP_GROUP_TABLE_MINIMUM_GUARANTEED_SIZE 3968 @@ -89,7 +90,7 @@ #define ACL_TOR_PRE_INGRESS_TABLE_MINIMUM_GUARANTEED_SIZE 127 -#define ACL_INGRESS_QOS_TABLE_MINIMUM_GUARANTEED_SIZE 511 +#define ACL_INGRESS_QOS_TABLE_MINIMUM_GUARANTEED_SIZE 255 #define ACL_INGRESS_COUNTING_TABLE_MINIMUM_GUARANTEED_SIZE 255 diff --git a/sai_p4/instantiations/google/sai_pd.proto b/sai_p4/instantiations/google/sai_pd.proto index 1eeecf62..6f5ea170 100755 --- a/sai_p4/instantiations/google/sai_pd.proto +++ b/sai_p4/instantiations/google/sai_pd.proto @@ -206,17 +206,18 @@ message VrfTableEntry { message Ipv6TunnelTerminationTableEntry { message Match { Ternary dst_ipv6 = 1; // ternary match / Format::IPV6 / 128 bits + Ternary src_ipv6 = 2; // ternary match / Format::IPV6 / 128 bits } Match match = 1; message Action { - MarkForTunnelDecapAndSetVrfAction mark_for_tunnel_decap_and_set_vrf = 1; + // CAUTION: This action is not (yet) supported. + TunnelDecapAction tunnel_decap = 1; } Action action = 2; int32 priority = 3; bytes controller_metadata = 8; } -// CAUTION: This table is not (yet) supported. message MulticastRouterInterfaceTableEntry { message Match { string multicast_replica_port = 1; // exact match / Format::STRING @@ -247,7 +248,6 @@ message DisableVlanChecksTableEntry { bytes controller_metadata = 8; } -// CAUTION: This table is not (yet) supported. message Ipv4MulticastTableEntry { message Match { // Refers to 'vrf_table.vrf_id'. @@ -256,14 +256,12 @@ message Ipv4MulticastTableEntry { } Match match = 1; message Action { - // CAUTION: This action is not (yet) supported. SetMulticastGroupIdAction set_multicast_group_id = 1; } Action action = 2; bytes controller_metadata = 8; } -// CAUTION: This table is not (yet) supported. message Ipv6MulticastTableEntry { message Match { // Refers to 'vrf_table.vrf_id'. @@ -272,7 +270,6 @@ message Ipv6MulticastTableEntry { } Match match = 1; message Action { - // CAUTION: This action is not (yet) supported. SetMulticastGroupIdAction set_multicast_group_id = 1; } Action action = 2; @@ -566,7 +563,7 @@ message AclPreIngressMetadataTableEntry { // ## Only allow IP field matches for IP packets. // ttl::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1); // ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1); -// ## Only allow l4_dst_port and l4_src_port matches for TCP/UDP packets. +// ## Only allow l4_dst_port matches for TCP/UDP packets. // l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17); // ## Forbid illegal combinations of IP_TYPE fields. // is_ip::mask != 0 -> (is_ipv4::mask == 0 && is_ipv6::mask == 0); @@ -577,8 +574,10 @@ message AclPreIngressMetadataTableEntry { // is_ipv6::mask != 0 -> (is_ipv6 == 1); // ## Only allow icmp_type matches for ICMP packets // icmpv6_type::mask != 0 -> ip_protocol == 58; -// ## Only allow arp_tpa matches for ARP packets. -// arp_tpa::mask != 0 -> ether_type == 0x0806; +// ## Only allow l4_dst_port matches for TCP/UDP packets. +// l4_src_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17); +// ## Only allow icmp_type matches for ICMP packets +// icmp_type::mask != 0 -> ip_protocol == 1; message AclIngressQosTableEntry { message Match { Optional is_ip = 1; // optional match / Format::HEX_STRING / 1 bits @@ -592,7 +591,10 @@ message AclIngressQosTableEntry { Ternary icmpv6_type = 9; // ternary match / Format::HEX_STRING / 8 bits Ternary l4_dst_port = 10; // ternary match / Format::HEX_STRING / 16 bits Optional in_port = 11; // optional match / Format::STRING + Ternary l4_src_port = 12; // ternary match / Format::HEX_STRING / 16 bits Ternary acl_metadata = 13; // ternary match / Format::HEX_STRING / 8 bits + Ternary icmp_type = 14; // ternary match / Format::HEX_STRING / 8 bits + Ternary route_metadata = 15; // ternary match / Format::HEX_STRING / 6 bits } Match match = 1; message Action { @@ -743,9 +745,7 @@ message AclIngressMirrorAndRedirectTableEntry { Ternary dst_ipv6 = 5; // ternary match / Format::IPV6 / upper 64 bits Ternary acl_metadata = 6; // ternary match / Format::HEX_STRING / 8 bits Ternary vlan_id = 7; // ternary match / Format::HEX_STRING / 12 bits - // CAUTION: This match field is not (yet) supported. - Optional vrf_id = 8; // optional match / Format::STRING - // CAUTION: This match field is not (yet) supported. + Optional vrf_id = 8; // optional match / Format::STRING Optional ipmc_table_hit = 9; // optional match / Format::HEX_STRING / 1 bits Ternary dst_ip = 10; // ternary match / Format::IPV4 @@ -753,9 +753,9 @@ message AclIngressMirrorAndRedirectTableEntry { Match match = 1; message Action { oneof action { + AclForwardAction acl_forward = 4; AclMirrorAction acl_mirror = 1; RedirectToNexthopAction redirect_to_nexthop = 2; - // CAUTION: This action is not (yet) supported. RedirectToIpmcGroupAction redirect_to_ipmc_group = 3; } } @@ -859,9 +859,8 @@ message SetMetadataAndDropAction { string route_metadata = 1; // Format::HEX_STRING / 6 bits } -message MarkForTunnelDecapAndSetVrfAction { - string vrf_id = 1; // Format::STRING -} +// CAUTION: This action is not (yet) supported. +message TunnelDecapAction {} message SetIpNexthopAndDisableRewritesAction { // Refers to 'router_interface_table.router_interface_id'. @@ -875,7 +874,6 @@ message SetIpNexthopAndDisableRewritesAction { string disable_vlan_rewrite = 6; // Format::HEX_STRING / 1 bits } -// CAUTION: This action is not (yet) supported. message SetMulticastGroupIdAction { string multicast_group_id = 1; // Format::HEX_STRING / 16 bits } @@ -969,7 +967,6 @@ message RedirectToNexthopAction { string nexthop_id = 1; // Format::STRING } -// CAUTION: This action is not (yet) supported. message RedirectToIpmcGroupAction { string multicast_group_id = 1; // Format::HEX_STRING / 16 bits } @@ -1004,13 +1001,10 @@ message TableEntry { VrfTableEntry vrf_table_entry = 74; // CAUTION: This table is not (yet) supported. Ipv6TunnelTerminationTableEntry ipv6_tunnel_termination_table_entry = 75; - // CAUTION: This table is not (yet) supported. MulticastRouterInterfaceTableEntry multicast_router_interface_table_entry = 76; DisableVlanChecksTableEntry disable_vlan_checks_table_entry = 77; - // CAUTION: This table is not (yet) supported. Ipv4MulticastTableEntry ipv4_multicast_table_entry = 78; - // CAUTION: This table is not (yet) supported. Ipv6MulticastTableEntry ipv6_multicast_table_entry = 79; TunnelTableEntry tunnel_table_entry = 80; AclIngressTableEntry acl_ingress_table_entry = 256; diff --git a/sai_p4/instantiations/google/test_tools/BUILD.bazel b/sai_p4/instantiations/google/test_tools/BUILD.bazel index fcd4effe..2e44c215 100644 --- a/sai_p4/instantiations/google/test_tools/BUILD.bazel +++ b/sai_p4/instantiations/google/test_tools/BUILD.bazel @@ -112,6 +112,7 @@ cc_library( ":table_entry_generator_helper", "//gutil:proto", "//gutil:status", + "//gutil:testing", "//p4_pdpi:ir_cc_proto", "@com_github_google_glog//:glog", "@com_github_p4lang_p4runtime//:p4info_cc_proto", @@ -125,7 +126,7 @@ cc_library( cc_test( name = "table_entry_generator_test", srcs = ["table_entry_generator_test.cc"], - shard_count = 5, + shard_count = 50, deps = [ ":table_entry_generator", "//gutil:status_matchers", diff --git a/sai_p4/instantiations/google/test_tools/table_entry_generator.cc b/sai_p4/instantiations/google/test_tools/table_entry_generator.cc index 2a3abeec..ceb9bac5 100644 --- a/sai_p4/instantiations/google/test_tools/table_entry_generator.cc +++ b/sai_p4/instantiations/google/test_tools/table_entry_generator.cc @@ -27,6 +27,7 @@ #include "glog/logging.h" #include "gutil/proto.h" #include "gutil/status.h" +#include "gutil/testing.h" #include "p4/config/v1/p4info.pb.h" #include "p4_pdpi/ir.pb.h" #include "sai_p4/instantiations/google/test_tools/table_entry_generator_helper.h" @@ -229,11 +230,8 @@ TableEntryGenerator AclIngressQosTableGenerator( auto base_entry = gutil::ParseTextProto( R"pb(table_name: "acl_ingress_qos_table" matches { - name: "ether_type" - ternary { - value { hex_str: "0x0806" } - mask { hex_str: "0xffff" } - } + name: "is_ipv4" + optional { value { hex_str: "0x1" } } } action { name: "set_qos_queue_and_cancel_copy_above_rate_limit" @@ -244,7 +242,7 @@ TableEntryGenerator AclIngressQosTableGenerator( })pb"); if (!base_entry.ok()) LOG(FATAL) << base_entry.status(); // Crash OK generator.generator = IrMatchFieldAndPriorityGenerator( - table_definition, *base_entry, "arp_tpa"); + table_definition, *base_entry, "ip_protocol"); return generator; } @@ -261,6 +259,28 @@ TableEntryGenerator L3AdmitTableGenerator( return generator; } +TableEntryGenerator MulticastRouterInterfaceTableGenerator( + const pdpi::IrTableDefinition& table_definition) { + auto base_entry = gutil::ParseProtoOrDie(R"pb( + table_name: "multicast_router_interface_table" + matches { + name: "multicast_replica_port" + exact { str: "1" } + } + action { + name: "set_multicast_src_mac" + params { + name: "src_mac" + value { mac: "06:05:04:03:02:01" } + } + } + )pb"); + return TableEntryGenerator{ + .generator = IrMatchFieldGenerator(table_definition, base_entry, + "multicast_replica_instance"), + }; +} + const absl::flat_hash_set& KnownUnsupportedTables() { static const auto* const kUnsupportedTables = new absl::flat_hash_set({ @@ -286,7 +306,6 @@ const absl::flat_hash_set& KnownUnsupportedTables() { "ipv6_tunnel_termination_table", // TODO: Add support for these tables once the switch // supports it. - "multicast_router_interface_table", "ipv4_multicast_table", "ipv6_multicast_table", // TODO: Add support for this table once the switch @@ -317,6 +336,8 @@ absl::StatusOr GetGenerator( {"ipv4_table", Ipv4TableGenerator}, {"ipv6_table", Ipv6TableGenerator}, {"l3_admit_table", L3AdmitTableGenerator}, + {"multicast_router_interface_table", + MulticastRouterInterfaceTableGenerator}, }); const std::string& table_name = table.preamble().alias(); diff --git a/sai_p4/instantiations/google/test_tools/test_entries.cc b/sai_p4/instantiations/google/test_tools/test_entries.cc index dacb4054..e7e4a4e2 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.cc +++ b/sai_p4/instantiations/google/test_tools/test_entries.cc @@ -135,129 +135,42 @@ EntryBuilder& EntryBuilder::AddEntryPuntingAllPackets(PuntAction action) { EntryBuilder& EntryBuilder::AddDefaultRouteForwardingAllPacketsToGivenPort( absl::string_view egress_port, IpVersion ip_version, absl::string_view vrf, - const NexthopRewriteOptions& nexthop_rewrite_options, - std::optional vlan_hexstr) { + const NexthopRewriteOptions& rewrite_options) { const std::string kNexthopId = - absl::StrFormat("nexthop(%s, %s)", egress_port, vrf); - - if (ip_version == IpVersion::kIpv4 || ip_version == IpVersion::kIpv4And6) { - sai::TableEntry& entry = *entries_.add_entries(); - entry = gutil::ParseProtoOrDie(R"pb( - ipv4_table_entry { - # IP match field omitted so this entry serves as the default route. - match { vrf_id: "TBD" } - action { set_nexthop_id { nexthop_id: "nexthop" } } - } - )pb"); - entry.mutable_ipv4_table_entry()->mutable_match()->set_vrf_id( - // TODO: Pass string_view directly once proto supports it. - std::string(vrf)); - entry.mutable_ipv4_table_entry() - ->mutable_action() - ->mutable_set_nexthop_id() - ->set_nexthop_id(kNexthopId); - } - if (ip_version == IpVersion::kIpv6 || ip_version == IpVersion::kIpv4And6) { - sai::TableEntry& entry = *entries_.add_entries(); - entry = gutil::ParseProtoOrDie(R"pb( - ipv6_table_entry { - # IP match field omitted so this entry serves as the default route. - match { vrf_id: "TBD" } - action { set_nexthop_id { nexthop_id: "nexthop" } } - } - )pb"); - entry.mutable_ipv6_table_entry()->mutable_match()->set_vrf_id( - // TODO: Pass string_view directly once proto supports it. - std::string(vrf)); - entry.mutable_ipv6_table_entry() - ->mutable_action() - ->mutable_set_nexthop_id() - ->set_nexthop_id(kNexthopId); - } - - return AddNexthopRifNeighborEntries(kNexthopId, egress_port, - nexthop_rewrite_options, vlan_hexstr); -} - -EntryBuilder& EntryBuilder::AddEntriesForwardingIpPacketsToGivenPort( - absl::string_view egress_port, IpVersion ip_version, - NexthopRewriteOptions rewrite_options) { - // Create router interface entry. - sai::RouterInterfaceTableEntry& rif_entry = - *entries_.add_entries()->mutable_router_interface_table_entry(); - const netaddr::MacAddress src_mac = - rewrite_options.src_mac_rewrite.value_or(netaddr::MacAddress::AllZeros()); - const std::string rif_id = absl::StrCat(egress_port, "/", src_mac.ToString()); - rif_entry.mutable_match()->set_router_interface_id(rif_id); - auto& rif_action = - *rif_entry.mutable_action()->mutable_set_port_and_src_mac(); - // TODO: Pass string_view directly once proto supports it. - rif_action.set_port(std::string(egress_port)); - rif_action.set_src_mac(src_mac.ToString()); - - // Create neighbor table entry. - sai::NeighborTableEntry& neighbor_entry = - *entries_.add_entries()->mutable_neighbor_table_entry(); - const netaddr::MacAddress dst_mac = - rewrite_options.dst_mac_rewrite.value_or(netaddr::MacAddress::AllZeros()); - const std::string neighbor_id = dst_mac.ToLinkLocalIpv6Address().ToString(); - neighbor_entry.mutable_match()->set_router_interface_id(rif_id); - neighbor_entry.mutable_match()->set_neighbor_id(neighbor_id); - rif_entry.mutable_match()->set_router_interface_id(rif_id); - neighbor_entry.mutable_action()->mutable_set_dst_mac()->set_dst_mac( - dst_mac.ToString()); - - // Create Nexthop entry based on `rewrite_options` - sai::NexthopTableEntry& nexthop_entry = - *entries_.add_entries()->mutable_nexthop_table_entry(); - // Ideally we would use an ID that is unique for the RIF & neighbor, but - // the ID ends up being longer than BMv2 can support. - const std::string nexthop_id = rif_id; - // const std::string nexthop_id = absl::StrCat(rif_id, "/", neighbor_id); - nexthop_entry.mutable_match()->set_nexthop_id(nexthop_id); - - if (AllRewritesEnabled(rewrite_options)) { - SetIpNexthopAction& action = - *nexthop_entry.mutable_action()->mutable_set_ip_nexthop(); - action.set_router_interface_id(rif_id); - action.set_neighbor_id(neighbor_id); - } else { - SetIpNexthopAndDisableRewritesAction& action = - *nexthop_entry.mutable_action() - ->mutable_set_ip_nexthop_and_disable_rewrites(); - action.set_router_interface_id(rif_id); - action.set_neighbor_id(neighbor_id); - action.set_disable_decrement_ttl( - BoolToHexString(rewrite_options.disable_decrement_ttl)); - action.set_disable_src_mac_rewrite( - BoolToHexString(!rewrite_options.src_mac_rewrite.has_value())); - action.set_disable_dst_mac_rewrite( - BoolToHexString(!rewrite_options.dst_mac_rewrite.has_value())); - action.set_disable_vlan_rewrite( - BoolToHexString(rewrite_options.disable_vlan_rewrite)); - } - - const std::string vrf_id = "vrf"; + absl::StrFormat("nexthop(%s, %s)", egress_port, vrf) + // Ideally we would use the whole ID, but it may be longer than BMv2 + // can support. + .substr(0, 31); // Add IPv4 default route. if (ip_version == IpVersion::kIpv4 || ip_version == IpVersion::kIpv4And6) { auto& ipv4_entry = *entries_.add_entries()->mutable_ipv4_table_entry(); - ipv4_entry.mutable_match()->set_vrf_id(vrf_id); + ipv4_entry.mutable_match()->set_vrf_id(vrf); ipv4_entry.mutable_action()->mutable_set_nexthop_id()->set_nexthop_id( - nexthop_id); + kNexthopId); } // Add IPv6 default route. if (ip_version == IpVersion::kIpv6 || ip_version == IpVersion::kIpv4And6) { auto& ipv6_entry = *entries_.add_entries()->mutable_ipv6_table_entry(); - ipv6_entry.mutable_match()->set_vrf_id(vrf_id); + ipv6_entry.mutable_match()->set_vrf_id(vrf); ipv6_entry.mutable_action()->mutable_set_nexthop_id()->set_nexthop_id( - nexthop_id); + kNexthopId); } + return AddNexthopRifNeighborEntries(kNexthopId, egress_port, rewrite_options); +} + +EntryBuilder& EntryBuilder::AddEntriesForwardingIpPacketsToGivenPort( + absl::string_view egress_port, IpVersion ip_version, + const NexthopRewriteOptions& rewrite_options) { + const std::string vrf_id = "vrf"; + return AddEntryAdmittingAllPacketsToL3() .AddVrfEntry(vrf_id) - .AddPreIngressAclEntryAssigningVrfForGivenIpType(vrf_id, ip_version); + .AddPreIngressAclEntryAssigningVrfForGivenIpType(vrf_id, ip_version) + .AddDefaultRouteForwardingAllPacketsToGivenPort(egress_port, ip_version, + vrf_id, rewrite_options); } EntryBuilder& EntryBuilder::AddEntryPuntingPacketsWithTtlZeroAndOne() { @@ -320,21 +233,15 @@ EntryBuilder& EntryBuilder::AddPreIngressAclEntryAssigningVrfForGivenIpType( << "invalid ip version: " << static_cast(ip_version); } -EntryBuilder& EntryBuilder::AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf( - absl::string_view vrf) { +EntryBuilder& EntryBuilder::AddEntryDecappingAllIpInIpv6Packets() { sai::TableEntry& entry = *entries_.add_entries(); entry = gutil::ParseProtoOrDie(R"pb( ipv6_tunnel_termination_table_entry { match {} # Wildcard match - action { mark_for_tunnel_decap_and_set_vrf { vrf_id: "" } } + action { tunnel_decap {} } priority: 1 } )pb"); - entry.mutable_ipv6_tunnel_termination_table_entry() - ->mutable_action() - ->mutable_mark_for_tunnel_decap_and_set_vrf() - // TODO: Pass string_view directly once proto supports it. - ->set_vrf_id(std::string(vrf)); return *this; } @@ -463,62 +370,70 @@ EntryBuilder& EntryBuilder::AddEntrySettingVlanIdInPreIngress( EntryBuilder& EntryBuilder::AddNexthopRifNeighborEntries( absl::string_view nexthop_id, absl::string_view egress_port, - const NexthopRewriteOptions& nexthop_rewrite_options, - std::optional vlan_hexstr) { - const std::string kRifId = absl::StrFormat( - "rif(port=%s, vlan=%s)", egress_port, vlan_hexstr.value_or("none")); - { - sai::NexthopTableEntry& nexthop_entry = - *entries_.add_entries()->mutable_nexthop_table_entry(); - nexthop_entry.mutable_match()->set_nexthop_id(nexthop_id); - if (AllRewritesEnabled(nexthop_rewrite_options)) { - sai::SetIpNexthopAction& action = - *nexthop_entry.mutable_action()->mutable_set_ip_nexthop(); - action.set_router_interface_id(kRifId); - action.set_neighbor_id("fe80::2"); - } else { - sai::SetIpNexthopAndDisableRewritesAction& action = - *nexthop_entry.mutable_action() - ->mutable_set_ip_nexthop_and_disable_rewrites(); - action.set_router_interface_id(kRifId); - action.set_neighbor_id("fe80::2"); - action.set_disable_decrement_ttl( - BoolToHexString(nexthop_rewrite_options.disable_decrement_ttl)); - action.set_disable_src_mac_rewrite(BoolToHexString( - !nexthop_rewrite_options.src_mac_rewrite.has_value())); - action.set_disable_dst_mac_rewrite(BoolToHexString( - !nexthop_rewrite_options.dst_mac_rewrite.has_value())); - action.set_disable_vlan_rewrite( - BoolToHexString(nexthop_rewrite_options.disable_vlan_rewrite)); - } - } - { - sai::TableEntry& entry = *entries_.add_entries(); - entry = gutil::ParseProtoOrDie(R"pb( - neighbor_table_entry { - match { router_interface_id: "rif" neighbor_id: "fe80::2" } - action { set_dst_mac { dst_mac: "02:03:04:05:06:07" } } - } - )pb"); - entry.mutable_neighbor_table_entry() - ->mutable_match() - ->set_router_interface_id(kRifId); + const NexthopRewriteOptions& rewrite_options) { + // Create router interface entry. + sai::RouterInterfaceTableEntry& rif_entry = + *entries_.add_entries()->mutable_router_interface_table_entry(); + const netaddr::MacAddress src_mac = + rewrite_options.src_mac_rewrite.value_or(netaddr::MacAddress::AllZeros()); + const std::string kRifId = + absl::StrFormat("rif(%s,%s,%s)", egress_port, src_mac.ToString(), + rewrite_options.egress_rif_vlan.value_or("no_vlan")) + // Ideally we would use the whole ID, but it may be longer than BMv2 + // can support. + .substr(0, 32); + rif_entry.mutable_match()->set_router_interface_id(kRifId); + if (rewrite_options.egress_rif_vlan.has_value()) { + auto& rif_action = + *rif_entry.mutable_action()->mutable_set_port_and_src_mac_and_vlan_id(); + rif_action.set_vlan_id(*rewrite_options.egress_rif_vlan); + // TODO: Pass string_view directly once proto supports it. + rif_action.set_port(std::string(egress_port)); + rif_action.set_src_mac(src_mac.ToString()); + } else { + auto& rif_action = + *rif_entry.mutable_action()->mutable_set_port_and_src_mac(); + // TODO: Pass string_view directly once proto supports it. + rif_action.set_port(std::string(egress_port)); + rif_action.set_src_mac(src_mac.ToString()); } - { - sai::RouterInterfaceTableEntry& entry = - *entries_.add_entries()->mutable_router_interface_table_entry(); - entry.mutable_match()->set_router_interface_id(kRifId); - if (vlan_hexstr.has_value()) { - auto& action = - *entry.mutable_action()->mutable_set_port_and_src_mac_and_vlan_id(); - action.set_vlan_id(*vlan_hexstr); - action.set_src_mac("00:01:02:03:04:05"); - action.set_port(egress_port); - } else { - auto& action = *entry.mutable_action()->mutable_set_port_and_src_mac(); - action.set_src_mac("00:01:02:03:04:05"); - action.set_port(egress_port); - } + + // Create neighbor table entry. + sai::NeighborTableEntry& neighbor_entry = + *entries_.add_entries()->mutable_neighbor_table_entry(); + const netaddr::MacAddress dst_mac = + rewrite_options.dst_mac_rewrite.value_or(netaddr::MacAddress::AllZeros()); + const std::string neighbor_id = dst_mac.ToLinkLocalIpv6Address().ToString(); + neighbor_entry.mutable_match()->set_router_interface_id(kRifId); + neighbor_entry.mutable_match()->set_neighbor_id(neighbor_id); + rif_entry.mutable_match()->set_router_interface_id(kRifId); + neighbor_entry.mutable_action()->mutable_set_dst_mac()->set_dst_mac( + dst_mac.ToString()); + + // Create Nexthop entry based on `rewrite_options` + sai::NexthopTableEntry& nexthop_entry = + *entries_.add_entries()->mutable_nexthop_table_entry(); + nexthop_entry.mutable_match()->set_nexthop_id(nexthop_id); + + if (AllRewritesEnabled(rewrite_options)) { + SetIpNexthopAction& action = + *nexthop_entry.mutable_action()->mutable_set_ip_nexthop(); + action.set_router_interface_id(kRifId); + action.set_neighbor_id(neighbor_id); + } else { + SetIpNexthopAndDisableRewritesAction& action = + *nexthop_entry.mutable_action() + ->mutable_set_ip_nexthop_and_disable_rewrites(); + action.set_router_interface_id(kRifId); + action.set_neighbor_id(neighbor_id); + action.set_disable_decrement_ttl( + BoolToHexString(rewrite_options.disable_decrement_ttl)); + action.set_disable_src_mac_rewrite( + BoolToHexString(!rewrite_options.src_mac_rewrite.has_value())); + action.set_disable_dst_mac_rewrite( + BoolToHexString(!rewrite_options.dst_mac_rewrite.has_value())); + action.set_disable_vlan_rewrite( + BoolToHexString(rewrite_options.disable_vlan_rewrite)); } return *this; diff --git a/sai_p4/instantiations/google/test_tools/test_entries.h b/sai_p4/instantiations/google/test_tools/test_entries.h index 55875e90..72aba8dc 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries.h +++ b/sai_p4/instantiations/google/test_tools/test_entries.h @@ -53,17 +53,26 @@ struct NexthopRewriteOptions { // When present, source MAC will be rewritten to the given address. When // absent, no rewrite occurs. std::optional src_mac_rewrite = - netaddr::MacAddress(1, 2, 3, 4, 5, 6); + netaddr::MacAddress(6, 5, 4, 3, 2, 1); // When present, destination MAC will be rewritten to the given address. When // absent, no rewrite occurs. std::optional dst_mac_rewrite = netaddr::MacAddress(2, 2, 2, 2, 2, 2); + // If true, makes the nexthop use a `set_ip_nexthop_and_disable_rewrites` + // action with `disable_vlan_rewrite` set to true. If false, such an action + // may still be used based on above values (otherwise a `set_ip_nexthop` + // action will be used), but `disable_vlan_rewrite` will be set false. bool disable_vlan_rewrite = false; + // When present, causes the RIF to use a `set_port_and_src_mac_and_vlan_id` + // action with `vlan_id = egress_rif_vlan`. When absent, the RIF will instead + // use the `set_port_and_src_mac` action. + std::optional egress_rif_vlan = std::nullopt; }; enum class IpVersion { kIpv4, kIpv6, + // Targets both IPv4 and IPv6 packets. kIpv4And6, }; @@ -150,23 +159,46 @@ class EntryBuilder { netaddr::MacAddress src_mac; }; + // Adds an entry that matches all packets and punts them according to + // `action`. EntryBuilder& AddEntryPuntingAllPackets(PuntAction action); + + // Constructs all entries required to forward all `ip_version` packets to + // `egress_port` and modify them using `rewrite_options`. // Note: Cannot be combined with other entries that forward *all* IP packets // in a specific way. EntryBuilder& AddEntriesForwardingIpPacketsToGivenPort( absl::string_view egress_port, - IpVersion ip_version = IpVersion::kIpv4And6, NexthopRewriteOptions = {}); + IpVersion ip_version = IpVersion::kIpv4And6, + const NexthopRewriteOptions& rewrite_options = {}); + + // Constructs a default IP route matching packets of `ip_version` with `vrf` + // and sending them to `egress_port`. Matching packets will be modified using + // `rewrite_options`. + // Note: For packets to hit this route, additional entries are required! At a + // minimum an L3 admit entry and entries that assign the given `vrf`. + // Note: Cannot be combined with other entries that forward *all* IP packets + // in a specific way unless they specify a different `vrf`. + EntryBuilder& AddDefaultRouteForwardingAllPacketsToGivenPort( + absl::string_view egress_port, IpVersion ip_version, + absl::string_view vrf, const NexthopRewriteOptions& rewrite_options = {}); + + // Constructs an IpNexthop entry with `nexthop_id` pointing to a neighbor + // entry and RIF entry all characterized by `nexthop_rewrite_options`. The RIF + // will output packets on `egress_port`. + EntryBuilder& AddNexthopRifNeighborEntries( + absl::string_view nexthop_id, absl::string_view egress_port, + const NexthopRewriteOptions& rewrite_options = {}); + + // Warning: If you try to install the result of multiple calls to this + // function (with different `multicast_group_id`s), you will get a runtime + // error. // Note: Cannot be combined with other entries that forward *all* IP packets // in a specific way. EntryBuilder& AddEntriesForwardingIpPacketsToGivenMulticastGroup( int multicast_group_id); EntryBuilder& AddVrfEntry(absl::string_view vrf); EntryBuilder& AddEntryAdmittingAllPacketsToL3(); - EntryBuilder& AddDefaultRouteForwardingAllPacketsToGivenPort( - absl::string_view egress_port, IpVersion ip_version, - absl::string_view vrf, - const NexthopRewriteOptions& nexthop_rewrite_options = {}, - std::optional vlan_hexstr = std::nullopt); EntryBuilder& AddMulticastRoute(absl::string_view vrf, const netaddr::Ipv4Address& dst_ip, int multicast_group_id); @@ -175,8 +207,7 @@ class EntryBuilder { int multicast_group_id); EntryBuilder& AddPreIngressAclEntryAssigningVrfForGivenIpType( absl::string_view vrf, IpVersion ip_version); - EntryBuilder& AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf( - absl::string_view vrf); + EntryBuilder& AddEntryDecappingAllIpInIpv6Packets(); EntryBuilder& AddEntryPuntingPacketsWithTtlZeroAndOne(); EntryBuilder& AddMulticastGroupEntry(int multicast_group_id, absl::Span replicas); @@ -192,10 +223,6 @@ class EntryBuilder { EntryBuilder& AddEntrySettingVlanIdInPreIngress( absl::string_view set_vlan_id_hexstr, std::optional match_vlan_id_hexstr = std::nullopt); - EntryBuilder& AddNexthopRifNeighborEntries( - absl::string_view nexthop_id, absl::string_view egress_port, - const NexthopRewriteOptions& nexthop_rewrite_options = {}, - std::optional vlan_hexstr = std::nullopt); EntryBuilder& AddIngressAclEntryRedirectingToNexthop( absl::string_view nexthop_id, std::optional in_port_match = std::nullopt); 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 b5aec697..4f7d5fd4 100644 --- a/sai_p4/instantiations/google/test_tools/test_entries_test.cc +++ b/sai_p4/instantiations/google/test_tools/test_entries_test.cc @@ -285,17 +285,15 @@ TEST(EntryBuilder, AddPreIngressAclEntryAssigningVrfForGivenIpTypeAddsEntry) { EXPECT_THAT(entities.entities(), SizeIs(3)); } -TEST(EntryBuilder, AddEntryDecappingAllIpInIpv6PacketsAndSettingVrfAddsEntry) { +TEST(EntryBuilder, AddEntryDecappingAllIpInIpv6PacketsAddsEntry) { pdpi::IrP4Info kIrP4Info = GetIrP4Info(Instantiation::kFabricBorderRouter); ASSERT_OK_AND_ASSIGN( pdpi::IrEntities entities, EntryBuilder() - .AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf("vrf-1") - .AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf("vrf-2") - .AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf("vrf-3") + .AddEntryDecappingAllIpInIpv6Packets() .LogPdEntries() .GetDedupedIrEntities(kIrP4Info, /*allow_unsupported=*/true)); - EXPECT_THAT(entities.entities(), SizeIs(3)); + EXPECT_THAT(entities.entities(), SizeIs(1)); } TEST(EntryBuilder, AddMulticastGroupEntryReplicaOverloadAddsEntry) { diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_ip_multicast_integration_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_ip_multicast_integration_test.cc index 5a84dc6f..632995a0 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_ip_multicast_integration_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_ip_multicast_integration_test.cc @@ -14,11 +14,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include +#include #include #include "absl/container/flat_hash_map.h" +#include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "glog/logging.h" #include "gmock/gmock.h" @@ -36,6 +40,7 @@ #include "p4_pdpi/p4_runtime_session_extras.h" #include "p4_pdpi/packetlib/packetlib.h" #include "p4_pdpi/packetlib/packetlib.pb.h" +#include "p4_pdpi/string_encodings/hex_string.h" #include "platforms/networking/p4/p4_infra/bmv2/bmv2.h" #include "sai_p4/instantiations/google/instantiations.h" #include "sai_p4/instantiations/google/sai_p4info.h" @@ -60,36 +65,56 @@ enum class DstIpKind { kMulticast, }; -netaddr::Ipv4Address GetDstIpv4(DstIpKind dst_ip_kind) { - switch (dst_ip_kind) { - case DstIpKind::kUnicast: - return netaddr::Ipv4Address(192, 168, 100, 1); - case DstIpKind::kMulticast: - // "Source-specific multicast" address, see - // https://en.wikipedia.org/wiki/Multicast_address#IPv4 - return netaddr::Ipv4Address(232, 1, 2, 3); - } - LOG(FATAL) << "Unknown DstIpKind: " << static_cast(dst_ip_kind); +// Returns a "source-specific multicast" address, see +// https://en.wikipedia.org/wiki/Multicast_address#IPv4 +netaddr::Ipv4Address MulticastIpv4() { + return netaddr::Ipv4Address(232, 1, 2, 3); +} + +// "Source-specific multicast" address, see +// https://en.wikipedia.org/wiki/Multicast_address#IPv6 +netaddr::Ipv6Address MulticastIpv6() { + return netaddr::Ipv6Address::OfString("ff30::2").value(); } -absl::StatusOr GetDstIpv6(DstIpKind dst_ip_kind) { - switch (dst_ip_kind) { - case DstIpKind::kUnicast: - return netaddr::Ipv6Address::OfString("2001::2"); - case DstIpKind::kMulticast: - // "Source-specific multicast" address, see - // https://en.wikipedia.org/wiki/Multicast_address#IPv6 - return netaddr::Ipv6Address::OfString("ff30::2"); +// Adds a VLAN header with the given `vlan_id` to the given packet. +absl::Status AddVlanHeader(int vlan_id, packetlib::Packet& packet) { + if (packet.headers_size() < 1 || !packet.headers(0).has_ethernet_header()) { + return gutil::InvalidArgumentErrorBuilder() + << "expected packet starting with Ethernet header, but got " + << absl::StrCat(packet); } - LOG(FATAL) << "Unknown DstIpKind: " << static_cast(dst_ip_kind); + packetlib::EthernetHeader& ethernet_header = + *packet.mutable_headers(0)->mutable_ethernet_header(); + + // Define VLAN header. + packetlib::VlanHeader vlan_header; + vlan_header.set_priority_code_point("0x0"); + vlan_header.set_drop_eligible_indicator("0x0"); + vlan_header.set_vlan_identifier(pdpi::BitsetToHexString<12>(vlan_id)); + vlan_header.set_ethertype(ethernet_header.ethertype()); + + // Insert VLAN header at index 1. + ethernet_header.set_ethertype("0x8100"); + { + packetlib::Header next_header; + *next_header.mutable_vlan_header() = std::move(vlan_header); + for (int i = 1; i < packet.headers_size(); ++i) { + next_header.Swap(packet.mutable_headers(i)); + } + *packet.add_headers() = std::move(next_header); + } + + return absl::OkStatus(); } absl::StatusOr GetIpv4TestPacket( - const netaddr::Ipv4Address& dst_ip) { + const netaddr::Ipv4Address& dst_ip, const std::optional& vlan_id) { ASSIGN_OR_RETURN(auto packet, gutil::ParseTextProto(R"pb( headers { ethernet_header { - ethernet_destination: "02:03:04:05:06:07" + # IPv4 Multicast MAC. + ethernet_destination: "01:00:5e:05:06:07" ethernet_source: "00:01:02:03:04:05" ethertype: "0x0800" # IPv4 } @@ -113,17 +138,21 @@ absl::StatusOr GetIpv4TestPacket( )pb")); packet.mutable_headers(1)->mutable_ipv4_header()->set_ipv4_destination( dst_ip.ToString()); + if (vlan_id.has_value()) { + RETURN_IF_ERROR(AddVlanHeader(*vlan_id, packet)); + } RETURN_IF_ERROR(packetlib::UpdateAllComputedFields(packet).status()); RETURN_IF_ERROR(packetlib::ValidatePacket(packet)); return packet; } absl::StatusOr GetIpv6TestPacket( - const netaddr::Ipv6Address& dst_ip) { + const netaddr::Ipv6Address& dst_ip, const std::optional& vlan_id) { ASSIGN_OR_RETURN(auto packet, gutil::ParseTextProto(R"pb( headers { ethernet_header { - ethernet_destination: "02:03:04:05:06:07" + # IPv6 Multicast MAC. + ethernet_destination: "01:33:33:05:06:07" ethernet_source: "00:01:02:03:04:05" ethertype: "0x86dd" # IPv6 } @@ -144,6 +173,9 @@ absl::StatusOr GetIpv6TestPacket( )pb")); packet.mutable_headers(1)->mutable_ipv6_header()->set_ipv6_destination( dst_ip.ToString()); + if (vlan_id.has_value()) { + RETURN_IF_ERROR(AddVlanHeader(*vlan_id, packet)); + } RETURN_IF_ERROR(packetlib::UpdateAllComputedFields(packet).status()); RETURN_IF_ERROR(packetlib::ValidatePacket(packet)); return packet; @@ -151,25 +183,20 @@ absl::StatusOr GetIpv6TestPacket( struct TestParams { sai::Instantiation instantiation; - DstIpKind dst_ip_kind; + // If set, test packets will include a VLAN header with the given ID. + std::optional test_packet_vlan_id; }; using IpMulticastTest = ::testing::TestWithParam; TEST_P(IpMulticastTest, Ipv4PacketsGetMulticastedWithRewrittenSrcMacAndTtl) { const sai::Instantiation kInstantiation = GetParam().instantiation; - const DstIpKind kDstIpKind = GetParam().dst_ip_kind; const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - if (kDstIpKind == DstIpKind::kMulticast) { - GTEST_SKIP() << "TODO: Enable once SAI P4 supports forwarding " - "packets with multicast destination IP"; - } - // Install table entries. constexpr absl::string_view kVrf = "vrf"; - const netaddr::Ipv4Address kDstIp = GetDstIpv4(kDstIpKind); + const netaddr::Ipv4Address kDstIp = MulticastIpv4(); constexpr int kMulticastGroupId = 42; ASSERT_OK_AND_ASSIGN( std::vector pi_entities, @@ -206,16 +233,17 @@ TEST_P(IpMulticastTest, Ipv4PacketsGetMulticastedWithRewrittenSrcMacAndTtl) { .multicast_replica_instance = 0, .src_mac = netaddr::MacAddress(2, 0, 0, 0, 0, 0x42), }) + // Technically only needed when `GetParam().test_packet_vlan_id` is + // set. + .AddDisableVlanChecksEntry() .LogPdEntries() - .GetDedupedPiEntities(kIrP4Info, - // TODO: Remove once multicast - // source mac table is no longer `@unsupported`. - /*allow_unsupported=*/true)); + .GetDedupedPiEntities(kIrP4Info)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); // Send Ipv4 test packet and expect output packets on egress ports 1 and 2. - ASSERT_OK_AND_ASSIGN(const packetlib::Packet ipv4_test_packet, - GetIpv4TestPacket(kDstIp)); + ASSERT_OK_AND_ASSIGN( + const packetlib::Packet ipv4_test_packet, + GetIpv4TestPacket(kDstIp, GetParam().test_packet_vlan_id)); constexpr int kArbitraryIngressPort = 24; ASSERT_OK_AND_ASSIGN( (absl::flat_hash_map @@ -232,9 +260,16 @@ TEST_P(IpMulticastTest, Ipv4PacketsGetMulticastedWithRewrittenSrcMacAndTtl) { EXPECT_THAT( gutil::ProtoDiff(ipv4_test_packet, port1_output_packets[0]), IsOkAndHolds(StrEq( - R"(modified: headers[0].ethernet_header.ethernet_source: "00:01:02:03:04:05" -> "01:00:00:00:00:00" + GetParam().test_packet_vlan_id.has_value() + ? + R"(modified: headers[0].ethernet_header.ethernet_source: "00:01:02:03:04:05" -> "01:00:00:00:00:00" +modified: headers[2].ipv4_header.ttl: "0x20" -> "0x1f" +modified: headers[2].ipv4_header.checksum: "0x8a9d" -> "0x8b9d" +)" + : + R"(modified: headers[0].ethernet_header.ethernet_source: "00:01:02:03:04:05" -> "01:00:00:00:00:00" modified: headers[1].ipv4_header.ttl: "0x20" -> "0x1f" -modified: headers[1].ipv4_header.checksum: "0x4ff8" -> "0x50f8" +modified: headers[1].ipv4_header.checksum: "0x8a9d" -> "0x8b9d" )"))); // The multicast copies should differ only in their source mac. EXPECT_THAT( @@ -259,19 +294,12 @@ modified: headers[1].ipv4_header.checksum: "0x4ff8" -> "0x50f8" TEST_P(IpMulticastTest, Ipv6PacketsGetMulticastedWithRewrittenSrcMacAndTtl) { const sai::Instantiation kInstantiation = GetParam().instantiation; - const DstIpKind kDstIpKind = GetParam().dst_ip_kind; const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - if (kDstIpKind == DstIpKind::kMulticast) { - GTEST_SKIP() << "TODO: Enable once SAI P4 supports forwarding " - "packets with multicast destination IP"; - } - // Install table entries. constexpr absl::string_view kVrf = "vrf"; - ASSERT_OK_AND_ASSIGN(const netaddr::Ipv6Address kDstIp, - GetDstIpv6(kDstIpKind)); + const netaddr::Ipv6Address kDstIp = MulticastIpv6(); constexpr int kMulticastGroupId = 42; ASSERT_OK_AND_ASSIGN( std::vector pi_entities, @@ -302,16 +330,17 @@ TEST_P(IpMulticastTest, Ipv6PacketsGetMulticastedWithRewrittenSrcMacAndTtl) { .multicast_replica_instance = 0, .src_mac = netaddr::MacAddress(5, 5, 5, 5, 5, 5), }) + // Technically only needed when `GetParam().test_packet_vlan_id` is + // set. + .AddDisableVlanChecksEntry() .LogPdEntries() - .GetDedupedPiEntities(kIrP4Info, - // TODO: Remove once multicast - // source mac table is no longer `@unsupported`. - /*allow_unsupported=*/true)); + .GetDedupedPiEntities(kIrP4Info)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); // Send Ipv6 test packet and expect output packets on egress ports 7 and 5. - ASSERT_OK_AND_ASSIGN(const packetlib::Packet ipv6_test_packet, - GetIpv6TestPacket(kDstIp)); + ASSERT_OK_AND_ASSIGN( + const packetlib::Packet ipv6_test_packet, + GetIpv6TestPacket(kDstIp, GetParam().test_packet_vlan_id)); constexpr int kArbitraryIngressPort = 24; ASSERT_OK_AND_ASSIGN( (absl::flat_hash_map @@ -328,7 +357,13 @@ TEST_P(IpMulticastTest, Ipv6PacketsGetMulticastedWithRewrittenSrcMacAndTtl) { EXPECT_THAT( gutil::ProtoDiff(ipv6_test_packet, port7_output_packets[0]), IsOkAndHolds(StrEq( - R"(modified: headers[0].ethernet_header.ethernet_source: "00:01:02:03:04:05" -> "07:07:07:07:07:07" + GetParam().test_packet_vlan_id.has_value() + ? + R"(modified: headers[0].ethernet_header.ethernet_source: "00:01:02:03:04:05" -> "07:07:07:07:07:07" +modified: headers[2].ipv6_header.hop_limit: "0x03" -> "0x02" +)" + : + R"(modified: headers[0].ethernet_header.ethernet_source: "00:01:02:03:04:05" -> "07:07:07:07:07:07" modified: headers[1].ipv6_header.hop_limit: "0x03" -> "0x02" )"))); @@ -343,20 +378,13 @@ modified: headers[1].ipv6_header.hop_limit: "0x03" -> "0x02" TEST_P(IpMulticastTest, AclIngressDropActionOverridesMulticastAction) { const sai::Instantiation kInstantiation = GetParam().instantiation; - const DstIpKind kDstIpKind = GetParam().dst_ip_kind; const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - if (kDstIpKind == DstIpKind::kMulticast) { - GTEST_SKIP() << "TODO: Enable once SAI P4 supports forwarding " - "packets with multicast destination IP"; - } - // Install multicast route. constexpr absl::string_view kVrf = "vrf"; - const netaddr::Ipv4Address kDstIpv4 = GetDstIpv4(kDstIpKind); - ASSERT_OK_AND_ASSIGN(const netaddr::Ipv6Address kDstIpv6, - GetDstIpv6(kDstIpKind)); + const netaddr::Ipv4Address kDstIpv4 = MulticastIpv4(); + const netaddr::Ipv6Address kDstIpv6 = MulticastIpv6(); constexpr int kMulticastGroupId = 42; ASSERT_OK_AND_ASSIGN( std::vector pi_entities, @@ -372,20 +400,22 @@ TEST_P(IpMulticastTest, AclIngressDropActionOverridesMulticastAction) { .multicast_replica_port = "\1", .src_mac = netaddr::MacAddress(1, 2, 3, 4, 5, 6), }) + // Technically only needed when `GetParam().test_packet_vlan_id` is + // set. + .AddDisableVlanChecksEntry() .LogPdEntries() - .GetDedupedPiEntities(kIrP4Info, - // TODO: Remove once multicast - // source mac table is no longer `@unsupported`. - /*allow_unsupported=*/true)); + .GetDedupedPiEntities(kIrP4Info)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); // Send test packets and expect output. constexpr int kArbitraryIngressPort1 = 24; constexpr int kArbitraryIngressPort2 = 42; - ASSERT_OK_AND_ASSIGN(const packetlib::Packet ipv4_test_packet, - GetIpv4TestPacket(kDstIpv4)); - ASSERT_OK_AND_ASSIGN(const packetlib::Packet ipv6_test_packet, - GetIpv6TestPacket(kDstIpv6)); + ASSERT_OK_AND_ASSIGN( + const packetlib::Packet ipv4_test_packet, + GetIpv4TestPacket(kDstIpv4, GetParam().test_packet_vlan_id)); + ASSERT_OK_AND_ASSIGN( + const packetlib::Packet ipv6_test_packet, + GetIpv6TestPacket(kDstIpv6, GetParam().test_packet_vlan_id)); EXPECT_THAT(bmv2.SendPacket(kArbitraryIngressPort1, ipv4_test_packet), IsOkAndHolds(Not(IsEmpty()))); EXPECT_THAT(bmv2.SendPacket(kArbitraryIngressPort2, ipv6_test_packet), @@ -413,15 +443,19 @@ TEST_P(IpMulticastTest, AclIngressDropActionOverridesMulticastAction) { // We then send two packets, one that should hit the IPMC table entry and one // that should miss it, and verify that they hit the exact route and default // route, respectively. -TEST(IpMulticastPrefixMatchTest, IpmcTableHitQualifierWorks) { - const sai::Instantiation kInstantiation = sai::Instantiation::kTor; +TEST_P(IpMulticastTest, IpmcTableHitQualifierWorks) { + const sai::Instantiation kInstantiation = GetParam().instantiation; + if (kInstantiation == sai::Instantiation::kTor || + kInstantiation == sai::Instantiation::kFabricBorderRouter) { + GTEST_SKIP() << "not supported by " << absl::StrCat(kInstantiation); + } const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); static constexpr int kExactMatchMulticastGroupId = 1; static constexpr int kDefaultMulticastGroupId = 2; static constexpr netaddr::Ipv4Address kExactMatchIpv4Dst = - netaddr::Ipv4Address(10, 0, 0, 42); + netaddr::Ipv4Address(232, 1, 2, 3); static constexpr netaddr::Ipv4Address kDefaultMatchIpv4Dst = netaddr::Ipv4Address(10, 0, 0, 24); @@ -448,14 +482,19 @@ TEST(IpMulticastPrefixMatchTest, IpmcTableHitQualifierWorks) { sai::Replica{.egress_port = "\2"}, sai::Replica{.egress_port = "\3"}, }) + // Technically only needed when `GetParam().test_packet_vlan_id` is + // set. + .AddDisableVlanChecksEntry() .LogPdEntries() .GetDedupedPiEntities(kIrP4Info, /*allow_unsupported=*/true)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); - ASSERT_OK_AND_ASSIGN(const packetlib::Packet kExactMatchInputPacket, - GetIpv4TestPacket(kExactMatchIpv4Dst)); - ASSERT_OK_AND_ASSIGN(const packetlib::Packet kDefaultMatchInputPacket, - GetIpv4TestPacket(kDefaultMatchIpv4Dst)); + ASSERT_OK_AND_ASSIGN( + const packetlib::Packet kExactMatchInputPacket, + GetIpv4TestPacket(kExactMatchIpv4Dst, GetParam().test_packet_vlan_id)); + ASSERT_OK_AND_ASSIGN( + const packetlib::Packet kDefaultMatchInputPacket, + GetIpv4TestPacket(kDefaultMatchIpv4Dst, GetParam().test_packet_vlan_id)); ASSERT_THAT(bmv2.SendPacket(1, kExactMatchInputPacket), IsOkAndHolds(UnorderedElementsAre(Key(1)))); ASSERT_THAT(bmv2.SendPacket(1, kDefaultMatchInputPacket), @@ -465,12 +504,14 @@ TEST(IpMulticastPrefixMatchTest, IpmcTableHitQualifierWorks) { std::vector GetAllTestInstances() { std::vector instances; for (sai::Instantiation instantiation : sai::AllSaiInstantiations()) { - for (DstIpKind dst_ip_kind : {DstIpKind::kUnicast, DstIpKind::kMulticast}) { - instances.push_back(TestParams{ - .instantiation = instantiation, - .dst_ip_kind = dst_ip_kind, - }); - } + instances.push_back(TestParams{ + .instantiation = instantiation, + .test_packet_vlan_id = std::nullopt, + }); + instances.push_back(TestParams{ + .instantiation = instantiation, + .test_packet_vlan_id = 1234, + }); } return instances; } @@ -478,12 +519,11 @@ std::vector GetAllTestInstances() { INSTANTIATE_TEST_SUITE_P(IpMulticastTest, IpMulticastTest, testing::ValuesIn(GetAllTestInstances()), [&](const testing::TestParamInfo& info) { - return absl::StrCat( - info.param.instantiation, "_with_", - info.param.dst_ip_kind == DstIpKind::kMulticast - ? "multicast" - : "unicast", - "_dst_ip"); + return absl::StrFormat( + "%v_%s", info.param.instantiation, + info.param.test_packet_vlan_id.has_value() + ? "with_vlan_header" + : ""); }); } // namespace diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_redirect_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_redirect_test.cc index 677a65db..e4f9572d 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_redirect_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_redirect_test.cc @@ -29,6 +29,7 @@ #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.pb.h" #include "p4_pdpi/netaddr/ipv4_address.h" +#include "p4_pdpi/netaddr/mac_address.h" #include "p4_pdpi/p4_runtime_session_extras.h" #include "p4_pdpi/packetlib/packetlib.h" #include "p4_pdpi/packetlib/packetlib.pb.h" @@ -60,11 +61,12 @@ void PreparePacketOrDie(packetlib::Packet& packet) { } packetlib::Packet GetIpv4PacketOrDie( - netaddr::Ipv4Address ipv4_dst = netaddr::Ipv4Address(192, 168, 100, 1)) { + netaddr::Ipv4Address ipv4_dst = netaddr::Ipv4Address(192, 168, 100, 1), + netaddr::MacAddress mac_dst = netaddr::MacAddress(2, 3, 4, 5, 6, 7)) { auto packet = gutil::ParseProtoOrDie(R"pb( headers { ethernet_header { - ethernet_destination: "02:03:04:05:06:07" + ethernet_destination: "filled in below" ethernet_source: "00:01:02:03:04:05" ethertype: "0x0800" # IPv4 } @@ -86,6 +88,9 @@ packetlib::Packet GetIpv4PacketOrDie( } payload: "Untagged IPv4 packet." )pb"); + packet.mutable_headers(0) + ->mutable_ethernet_header() + ->set_ethernet_destination(mac_dst.ToString()); packet.mutable_headers(1)->mutable_ipv4_header()->set_ipv4_destination( ipv4_dst.ToString()); PreparePacketOrDie(packet); @@ -159,9 +164,9 @@ TEST(RedirectTest, RedirectToNextHopOverridesIpMulticastDecision) { constexpr absl::string_view kRedirectNexthopId = "redirect-nexthop"; constexpr absl::string_view kVrf = "vrf"; constexpr int kMulticastGroupId = 50; - // The destination IP used in the input packet. - ASSERT_OK_AND_ASSIGN(const netaddr::Ipv4Address kDstIpv4, - netaddr::Ipv4Address::OfString("192.168.100.1")); + constexpr auto kDstIpv4 = netaddr::Ipv4Address(232, 1, 2, 3); + // IPv4 multicast MAC address. + constexpr auto kDstMac = netaddr::MacAddress(0x01, 0, 0x5e, 0x01, 0x02, 0x03); // Install entries to multicast packets destined to kDstIpv4 to // kMulticastEgressPort{1,2} and redirect the ones with in_port @@ -202,7 +207,7 @@ TEST(RedirectTest, RedirectToNextHopOverridesIpMulticastDecision) { // Inject a test packet destined to kDstIpv4 though kIngressPort. ASSERT_OK_AND_ASSIGN( PacketsByPort output_by_port, - bmv2.SendPacket(kIngressPort, GetIpv4PacketOrDie(kDstIpv4))); + bmv2.SendPacket(kIngressPort, GetIpv4PacketOrDie(kDstIpv4, kDstMac))); // The packet must be multicast replicated to kMulticastEgressPort{1,2}. ASSERT_THAT(output_by_port, UnorderedElementsAre(Key(kMulticastEgressPort1), @@ -212,7 +217,8 @@ TEST(RedirectTest, RedirectToNextHopOverridesIpMulticastDecision) { // Inject a test packet destined to kDstIpv4 though kRedirectIngressPort. ASSERT_OK_AND_ASSIGN( PacketsByPort output_by_port, - bmv2.SendPacket(kRedirectIngressPort, GetIpv4PacketOrDie(kDstIpv4))); + bmv2.SendPacket(kRedirectIngressPort, + GetIpv4PacketOrDie(kDstIpv4, kDstMac))); // The packet must be forwarded to kRedirectEgressPort. ASSERT_THAT(output_by_port, ElementsAre(Key(kRedirectEgressPort))); } @@ -261,8 +267,9 @@ TEST(RedirectTest, RedirectToMulticastGroupOverridesMulticastTableAction) { static constexpr absl::string_view kOverrideIngressPortStr = "\2"; static constexpr int kDefaultMulticastGroupId = 1; static constexpr int kOverrideMulticastGroupId = 2; - static constexpr netaddr::Ipv4Address ipv4_dst = - netaddr::Ipv4Address(10, 0, 0, 42); + constexpr auto kDstIpv4 = netaddr::Ipv4Address(232, 1, 2, 3); + // IPv4 multicast MAC address. + constexpr auto kDstMac = netaddr::MacAddress(0x01, 0, 0x5e, 0x01, 0x02, 0x03); ASSERT_OK_AND_ASSIGN( std::vector pi_entities, @@ -270,7 +277,7 @@ TEST(RedirectTest, RedirectToMulticastGroupOverridesMulticastTableAction) { .AddVrfEntry("vrf") .AddEntrySettingVrfForAllPackets("vrf") .AddEntryAdmittingAllPacketsToL3() - .AddMulticastRoute("vrf", ipv4_dst, kDefaultMulticastGroupId) + .AddMulticastRoute("vrf", kDstIpv4, kDefaultMulticastGroupId) .AddIngressAclEntryRedirectingToMulticastGroup( kOverrideMulticastGroupId, sai::MirrorAndRedirectMatchFields{ @@ -289,7 +296,7 @@ TEST(RedirectTest, RedirectToMulticastGroupOverridesMulticastTableAction) { .GetDedupedPiEntities(kIrP4Info, /*allow_unsupported=*/true)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); - const packetlib::Packet kInputPacket = GetIpv4PacketOrDie(ipv4_dst); + const packetlib::Packet kInputPacket = GetIpv4PacketOrDie(kDstIpv4, kDstMac); ASSERT_THAT(bmv2.SendPacket(kDefaultIngressPort, kInputPacket), IsOkAndHolds(UnorderedElementsAre(Key(1)))); ASSERT_THAT(bmv2.SendPacket(kOverrideIngressPort, kInputPacket), diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_tunnel_termination_integration_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_tunnel_termination_integration_test.cc index cc256b11..3f6955d2 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_tunnel_termination_integration_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_tunnel_termination_integration_test.cc @@ -22,6 +22,7 @@ #include "absl/status/statusor.h" #include "absl/strings/string_view.h" +#include "absl/strings/substitute.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "gutil/proto.h" @@ -30,6 +31,7 @@ #include "gutil/status_matchers.h" #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.pb.h" +#include "p4_pdpi/netaddr/mac_address.h" #include "p4_pdpi/p4_runtime_matchers.h" #include "p4_pdpi/p4_runtime_session.h" #include "p4_pdpi/p4_runtime_session_extras.h" @@ -59,53 +61,60 @@ using ::testing::ElementsAre; using ::testing::IsEmpty; using ::testing::StrEq; +constexpr netaddr::MacAddress kSrcMac = netaddr::MacAddress(0, 1, 2, 3, 4, 5); +constexpr netaddr::MacAddress kDstMac = netaddr::MacAddress(2, 3, 4, 5, 6, 7); +; -absl::StatusOr GetIpv4InIpv6Packet() { - ASSIGN_OR_RETURN(auto packet, gutil::ParseTextProto(R"pb( - headers { - ethernet_header { - ethernet_destination: "02:03:04:05:06:07" - ethernet_source: "00:01:02:03:04:05" - ethertype: "0x86dd" # IPv6 - } - } - headers { - ipv6_header { - version: "0x6" - dscp: "0x00" - ecn: "0x0" - flow_label: "0x12345" - next_header: "0x04" # IPv4 - hop_limit: "0x03" - ipv6_source: "2001::1" - ipv6_destination: "2001::2" - } - } - headers { - ipv4_header { - version: "0x4" - ihl: "0x5" - dscp: "0x1c" - ecn: "0x0" - identification: "0x0000" - flags: "0x0" - fragment_offset: "0x0000" - ttl: "0x20" - protocol: "0xfe" - ipv4_source: "192.168.100.2" - ipv4_destination: "192.168.100.1" - } - } - payload: "A beautiful IPv4-in-IPv6 test packet." - )pb")); +absl::StatusOr GetIpv4InIpv6Packet( + const netaddr::MacAddress& src_mac, const netaddr::MacAddress& dst_mac) { + ASSIGN_OR_RETURN(auto packet, + gutil::ParseTextProto(absl::Substitute( + R"pb( + headers { + ethernet_header { + ethernet_source: "$0" + ethernet_destination: "$1" + ethertype: "0x86dd" # IPv6 + } + } + headers { + ipv6_header { + version: "0x6" + dscp: "0x00" + ecn: "0x0" + flow_label: "0x12345" + next_header: "0x04" # IPv4 + hop_limit: "0x03" + ipv6_source: "2001::1" + ipv6_destination: "2001::2" + } + } + headers { + ipv4_header { + version: "0x4" + ihl: "0x5" + dscp: "0x1c" + ecn: "0x0" + identification: "0x0000" + flags: "0x0" + fragment_offset: "0x0000" + ttl: "0x20" + protocol: "0xfe" + ipv4_source: "192.168.100.2" + ipv4_destination: "192.168.100.1" + } + } + payload: "A beautiful IPv4-in-IPv6 test packet." + )pb", + src_mac.ToString(), dst_mac.ToString()))); RETURN_IF_ERROR(packetlib::UpdateAllComputedFields(packet).status()); return packet; } using TunnelTerminationTest = testing::TestWithParam; -// Checks that decapsulation and tunnel termination VRF assignment work as -// expected for forwarded packets +// Checks that decapsulation and VRF assignment work as expected for forwarded +// packets. TEST_P(TunnelTerminationTest, PacketGetsDecapsulatedAndForwarded) { const sai::Instantiation kInstantiation = GetParam(); const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); @@ -116,9 +125,13 @@ TEST_P(TunnelTerminationTest, PacketGetsDecapsulatedAndForwarded) { ASSERT_OK_AND_ASSIGN( std::vector pi_entities, sai::EntryBuilder() - .AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf("vrf") + .AddEntrySettingVrfForAllPackets("vrf") + .AddEntryDecappingAllIpInIpv6Packets() .AddDefaultRouteForwardingAllPacketsToGivenPort( - /*egress_port=*/"\001", sai::IpVersion::kIpv4, "vrf") + /*egress_port=*/"\001", sai::IpVersion::kIpv4, "vrf", + // Rewrites to the same src and dst mac as the input packet. + sai::NexthopRewriteOptions{.src_mac_rewrite = kSrcMac, + .dst_mac_rewrite = kDstMac}) .AddEntryAdmittingAllPacketsToL3() // Needed for forwarding. .LogPdEntries() .GetDedupedPiEntities(kIrP4Info, @@ -128,7 +141,8 @@ TEST_P(TunnelTerminationTest, PacketGetsDecapsulatedAndForwarded) { ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); // Inject Ipv4-in-IPv6 test packet and expect one output packet. - ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, GetIpv4InIpv6Packet()); + ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, + GetIpv4InIpv6Packet(kSrcMac, kDstMac)); ASSERT_OK_AND_ASSIGN(std::string raw_input_packet, packetlib::SerializePacket(input_packet)); ASSERT_OK_AND_ASSIGN(std::vector output_packets, @@ -164,8 +178,6 @@ modified: headers[1].ipv4_header.checksum: "0x5003" -> "0x5103" // Checks the interaction of pre ingress ACLs and tunnel termination: // - Pre ingress ACLs see the original packet before decap. -// - VRF assignments in pre ingress ACLs override VRF assignments from -// tunnel termination. TEST_P(TunnelTerminationTest, PreIngressAclMatchesOnUndecappedPacketAndOverridesDecapVrf) { const sai::Instantiation kInstantiation = GetParam(); @@ -178,20 +190,17 @@ TEST_P(TunnelTerminationTest, ASSERT_OK_AND_ASSIGN( std::vector pi_entities, sai::EntryBuilder() - .AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf("decap-vrf") + .AddEntryDecappingAllIpInIpv6Packets() .AddPreIngressAclEntryAssigningVrfForGivenIpType( "acl-ipv4-vrf", sai::IpVersion::kIpv4) .AddPreIngressAclEntryAssigningVrfForGivenIpType( "acl-ipv6-vrf", sai::IpVersion::kIpv6) - // Route that will apply if the decap entry determines the VRF. - .AddDefaultRouteForwardingAllPacketsToGivenPort( - /*egress_port=*/"\001", sai::IpVersion::kIpv4And6, "decap-vrf") // Route that will apply if the ACL entry matching the decapped packet // determines the VRF. .AddDefaultRouteForwardingAllPacketsToGivenPort( /*egress_port=*/"\002", sai::IpVersion::kIpv4And6, "acl-ipv4-vrf") // Route that will apply if the ACL entry matching the undecapped - // packet determines the VRF.p + // packet determines the VRF. .AddDefaultRouteForwardingAllPacketsToGivenPort( /*egress_port=*/"\003", sai::IpVersion::kIpv4And6, "acl-ipv6-vrf") .AddEntryAdmittingAllPacketsToL3() // Needed for forwarding. @@ -203,7 +212,8 @@ TEST_P(TunnelTerminationTest, ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); // Inject Ipv4-in-IPv6 test packet and expect one output packet. - ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, GetIpv4InIpv6Packet()); + ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, + GetIpv4InIpv6Packet(kSrcMac, kDstMac)); ASSERT_OK_AND_ASSIGN(std::string raw_input_packet, packetlib::SerializePacket(input_packet)); ASSERT_OK_AND_ASSIGN(std::vector output_packets, @@ -226,21 +236,22 @@ TEST_P(TunnelTerminationTest, PuntedPacketIsNotDecapsulated) { // Install table entries: decap & punt to controller, so we can check that the // punted packet did not get decapped. - ASSERT_OK_AND_ASSIGN( - std::vector pi_entities, - sai::EntryBuilder() - .AddEntryDecappingAllIpInIpv6PacketsAndSettingVrf("vrf") - .AddEntryPuntingAllPackets(sai::PuntAction::kTrap) - .LogPdEntries() - .GetDedupedPiEntities(kIrP4Info, - // TODO: Remove once tunnel termination table is - // no longer `@unsupported`. - /*allow_unsupported=*/true)); + ASSERT_OK_AND_ASSIGN(std::vector pi_entities, + sai::EntryBuilder() + .AddEntryDecappingAllIpInIpv6Packets() + .AddEntryPuntingAllPackets(sai::PuntAction::kTrap) + .LogPdEntries() + .GetDedupedPiEntities( + kIrP4Info, + // TODO: Remove once tunnel + // termination table is no longer `@unsupported`. + /*allow_unsupported=*/true)); ASSERT_OK(pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities)); // Inject Ipv4-in-IPv6 test packet and expect 0 forwarded packets and 1 // punted packet. - ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, GetIpv4InIpv6Packet()); + ASSERT_OK_AND_ASSIGN(packetlib::Packet input_packet, + GetIpv4InIpv6Packet(kSrcMac, kDstMac)); ASSERT_OK_AND_ASSIGN(std::string raw_input_packet, packetlib::SerializePacket(input_packet)); ASSERT_THAT(bmv2.SendPacket(pins::PacketAtPort{ diff --git a/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc b/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc index a9a68f46..9ccd1f87 100644 --- a/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc +++ b/sai_p4/instantiations/google/tests/sai_p4_bmv2_vlan_test.cc @@ -30,6 +30,7 @@ #include "p4/v1/p4runtime.pb.h" #include "p4_pdpi/ir.pb.h" #include "p4_pdpi/p4_runtime_matchers.h" +#include "p4_pdpi/p4_runtime_session.h" #include "p4_pdpi/p4_runtime_session_extras.h" #include "p4_pdpi/packetlib/packetlib.h" #include "p4_pdpi/packetlib/packetlib.pb.h" @@ -146,7 +147,8 @@ absl::Status InstallEntries(Bmv2& bmv2, const pdpi::IrP4Info& ir_p4info, ASSIGN_OR_RETURN(std::vector pi_entities, entry_builder.LogPdEntries().GetDedupedPiEntities( ir_p4info, /*allow_unsupported=*/true)); - return pdpi::InstallPiEntities(bmv2.P4RuntimeSession(), pi_entities); + return pdpi::InstallPiEntities(&bmv2.P4RuntimeSession(), ir_p4info, + pi_entities); } TEST_P(VlanTest, VlanPacketWithNonReservedVidGetsDroppedByDefault) { @@ -280,17 +282,19 @@ absl::Status InstallEntriesOnlyForwardingPacketsMatchingVlanIdInAclPreIngress( absl::Status InstallEntriesForwardingAndRewritingVlanInRifTable( Bmv2& bmv2, const pdpi::IrP4Info& ir_p4info, - std::optional vlan_id_hexstr, - absl::string_view egress_port, bool disable_vlan_checks, - bool disable_vlan_rewrite) { - RETURN_IF_ERROR(InstallEntries( - bmv2, ir_p4info, - sai::EntryBuilder() - .AddEntrySettingVrfForAllPackets("vrf-forward") - .AddEntryAdmittingAllPacketsToL3() - .AddDefaultRouteForwardingAllPacketsToGivenPort( - egress_port, sai::IpVersion::kIpv4, "vrf-forward", - {.disable_vlan_rewrite = disable_vlan_rewrite}, vlan_id_hexstr))); + std::optional egress_rif_vlan, absl::string_view egress_port, + bool disable_vlan_checks, bool disable_vlan_rewrite) { + RETURN_IF_ERROR( + InstallEntries(bmv2, ir_p4info, + sai::EntryBuilder() + .AddEntrySettingVrfForAllPackets("vrf-forward") + .AddEntryAdmittingAllPacketsToL3() + .AddDefaultRouteForwardingAllPacketsToGivenPort( + egress_port, sai::IpVersion::kIpv4, "vrf-forward", + sai::NexthopRewriteOptions{ + .disable_vlan_rewrite = disable_vlan_rewrite, + .egress_rif_vlan = egress_rif_vlan, + }))); if (disable_vlan_checks) { return InstallEntries(bmv2, ir_p4info, @@ -305,7 +309,7 @@ TEST_P(VlanTest, const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - constexpr absl::string_view kEgressVlan = "0x003"; + const std::string kEgressVlan = "0x003"; ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( bmv2, kIrP4Info, kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/false)); @@ -366,7 +370,7 @@ TEST_P(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - constexpr absl::string_view kEgressVlan = "0x003"; + const std::string kEgressVlan = "0x003"; ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( bmv2, kIrP4Info, kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/false, /*disable_vlan_rewrite=*/false)); @@ -403,7 +407,7 @@ TEST_P(VlanTest, SettingVid4095InRifResultsOutputPacketWithNoVlanTag) { const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - constexpr absl::string_view kEgressVlan = "0xfff"; + const std::string kEgressVlan = "0xfff"; ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( bmv2, kIrP4Info, kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/false)); @@ -450,7 +454,8 @@ TEST_P(VlanTest, IngressVidGetCarriedOverToEgressWhenVlanRewriteIsDisabled) { ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( - bmv2, kIrP4Info, /*vlan_id_hexstr=*/std::nullopt, kEgressPortProto, + bmv2, kIrP4Info, /*egress_rif_vlan=*/std::nullopt, kEgressPortProto, + /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/true)); { // Inject packet without a VLAN tag. ASSERT_OK_AND_ASSIGN(PacketsByPort output_by_port, @@ -499,7 +504,7 @@ TEST_P(VlanTest, ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); ASSERT_OK(InstallEntriesForwardingAndRewritingVlanInRifTable( - bmv2, kIrP4Info, /*vlan_id_hexstr=*/"0x00c", kEgressPortProto, + bmv2, kIrP4Info, /*egress_rif_vlan=*/"0x00c", kEgressPortProto, /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/true)); { @@ -565,7 +570,7 @@ sai::TableEntries EntriesForwardingAndRewritingVlanInRifTable( TEST(VlanTest, SettingNonReservedVidInRifWithoutVlanChecksResultsInPacketWithThatId) { - const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + const sai::Instantiation kInstantiation = GetParam(); const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); @@ -573,7 +578,8 @@ TEST(VlanTest, ASSERT_OK(InstallEntries( bmv2, kIrP4Info, EntriesForwardingAndRewritingVlanInRifTable( - kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/true))); + kEgressVlan, kEgressPortProto, + /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/false))); { // Inject packet without a VLAN tag. ASSERT_OK_AND_ASSIGN(PacketsByPort output_by_port, @@ -626,7 +632,7 @@ TEST(VlanTest, } TEST(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { - const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + const sai::Instantiation kInstantiation = GetParam(); const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); @@ -634,7 +640,8 @@ TEST(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { ASSERT_OK(InstallEntries( bmv2, kIrP4Info, EntriesForwardingAndRewritingVlanInRifTable( - kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/false))); + kEgressVlan, kEgressPortProto, + /*disable_vlan_checks=*/false, /*disable_vlan_rewrite=*/false))); { // Inject packet without a VLAN tag. ASSERT_OK_AND_ASSIGN(PacketsByPort output_by_port, @@ -663,15 +670,16 @@ TEST(VlanTest, SettingNonReservedVidInRifWithVlanChecksResultsInDrop) { } TEST(VlanTest, SettingVid4095InRifResultsOutputPacketWithNoVlanTag) { - const sai::Instantiation kInstantiation = sai::Instantiation::kTor; + const sai::Instantiation kInstantiation = GetParam(); const pdpi::IrP4Info kIrP4Info = sai::GetIrP4Info(kInstantiation); ASSERT_OK_AND_ASSIGN(Bmv2 bmv2, sai::SetUpBmv2ForSaiP4(kInstantiation)); - constexpr absl::string_view kEgressVlan = "0xfff"; + const std::string kEgressVlan = "0xfff"; ASSERT_OK(InstallEntries( bmv2, kIrP4Info, EntriesForwardingAndRewritingVlanInRifTable( - kEgressVlan, kEgressPortProto, /*disable_vlan_checks=*/true))); + kEgressVlan, kEgressPortProto, + /*disable_vlan_checks=*/true, /*disable_vlan_rewrite=*/false)); { // Inject packet without a VLAN tag. ASSERT_OK_AND_ASSIGN(PacketsByPort output_by_port, diff --git a/sai_p4/instantiations/google/tor.p4info.pb.txt b/sai_p4/instantiations/google/tor.p4info.pb.txt index 89ac4245..8206f427 100644 --- a/sai_p4/instantiations/google/tor.p4info.pb.txt +++ b/sai_p4/instantiations/google/tor.p4info.pb.txt @@ -68,14 +68,6 @@ tables { bitwidth: 48 match_type: TERNARY } - match_fields { - id: 9 - name: "dst_mac" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" - annotations: "@format(MAC_ADDRESS)" - bitwidth: 48 - match_type: TERNARY - } match_fields { id: 5 name: "dst_ip" @@ -421,7 +413,6 @@ tables { name: "ingress.routing_lookup.ipv4_multicast_table" alias: "ipv4_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -456,7 +447,6 @@ tables { name: "ingress.routing_lookup.ipv6_multicast_table" alias: "ipv6_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -666,7 +656,7 @@ tables { annotations: "@sai_acl(INGRESS)" annotations: "@sai_acl_priority(10)" annotations: "@p4runtime_role(\"sdn_controller\")" - 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 // 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 and l4_src_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 // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\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 // 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 { id: 1 @@ -696,22 +686,6 @@ tables { bitwidth: 16 match_type: TERNARY } - match_fields { - id: 5 - name: "dst_mac" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" - annotations: "@format(MAC_ADDRESS)" - bitwidth: 48 - match_type: TERNARY - } - match_fields { - id: 6 - name: "arp_tpa" - annotations: "@composite_field(@ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 24 , length = 2 ) , @ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 26 , length = 2 ))" - annotations: "@format(IPV4_ADDRESS)" - bitwidth: 32 - match_type: TERNARY - } match_fields { id: 7 name: "ttl" @@ -740,6 +714,22 @@ tables { bitwidth: 16 match_type: TERNARY } + match_fields { + id: 5 + name: "dst_mac" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + match_type: TERNARY + } + match_fields { + id: 6 + name: "arp_tpa" + annotations: "@composite_field(@ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 24 , length = 2 ) , @ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 26 , length = 2 ))" + annotations: "@format(IPV4_ADDRESS)" + bitwidth: 32 + match_type: TERNARY + } match_fields { id: 11 name: "in_port" @@ -788,7 +778,7 @@ tables { const_default_action_id: 21257015 direct_resource_ids: 318767367 direct_resource_ids: 352321794 - size: 511 + size: 255 } tables { preamble { @@ -796,6 +786,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_mirror_and_redirect_table" alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(15)" 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 \")" } @@ -863,7 +854,6 @@ tables { id: 8 name: "vrf_id" annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID)" - annotations: "@unsupported" match_type: OPTIONAL type_name { name: "vrf_id_t" @@ -872,11 +862,14 @@ tables { match_fields { id: 9 name: "ipmc_table_hit" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_TABLE_HIT)" - annotations: "@unsupported" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_NPU_META_DST_HIT)" bitwidth: 1 match_type: OPTIONAL } + action_refs { + id: 16777475 + annotations: "@proto_id(4)" + } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -1130,7 +1123,6 @@ tables { id: 33554508 name: "egress.packet_rewrites.multicast_rewrites.multicast_router_interface_table" alias: "multicast_router_interface_table" - annotations: "@unsupported" annotations: "@p4runtime_role(\"sdn_controller\")" } match_fields { @@ -1313,6 +1305,13 @@ actions { annotations: "@noWarn(\"unused\")" } } +actions { + preamble { + id: 24742814 + name: "no_action" + alias: "no_action" + } +} actions { preamble { id: 16777221 @@ -1395,13 +1394,6 @@ actions { alias: "admit_to_l3" } } -actions { - preamble { - id: 24742814 - name: "ingress.routing_lookup.no_action" - alias: "no_action" - } -} actions { preamble { id: 16777222 @@ -1481,7 +1473,6 @@ actions { id: 16777240 name: "ingress.routing_lookup.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;\n \")" } params { @@ -1642,6 +1633,7 @@ actions { id: 1 name: "nexthop_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_NEXT_HOP)" annotations: "@refers_to(nexthop_table , nexthop_id)" type_name { name: "nexthop_id_t" @@ -1653,13 +1645,14 @@ actions { id: 16777491 name: "ingress.acl_ingress.redirect_to_ipmc_group" alias: "redirect_to_ipmc_group" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_IPMC_GROUP)" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } diff --git a/sai_p4/instantiations/google/unioned_p4info.pb.txt b/sai_p4/instantiations/google/unioned_p4info.pb.txt index 12b7e0d2..2cf368c1 100644 --- a/sai_p4/instantiations/google/unioned_p4info.pb.txt +++ b/sai_p4/instantiations/google/unioned_p4info.pb.txt @@ -4,32 +4,6 @@ pkg_info { arch: "v1model" organization: "Google" } -tables { - preamble { - id: 33554507 - name: "ingress.tunnel_termination_lookup.ipv6_tunnel_termination_table" - alias: "ipv6_tunnel_termination_table" - annotations: "@unsupported" - annotations: "@p4runtime_role(\"sdn_controller\")" - } - match_fields { - id: 1 - name: "dst_ipv6" - annotations: "@format(IPV6_ADDRESS)" - bitwidth: 128 - match_type: TERNARY - } - action_refs { - id: 16777238 - annotations: "@proto_id(1)" - } - action_refs { - id: 21257015 - annotations: "@defaultonly" - scope: DEFAULT_ONLY - } - size: 126 -} tables { preamble { id: 33554509 @@ -154,6 +128,40 @@ tables { direct_resource_ids: 318767361 size: 254 } +tables { + preamble { + id: 33554507 + name: "ingress.tunnel_termination.ipv6_tunnel_termination_table" + alias: "ipv6_tunnel_termination_table" + annotations: "@unsupported" + annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@unsupported" + } + match_fields { + id: 1 + name: "dst_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } + match_fields { + id: 2 + name: "src_ipv6" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 128 + match_type: TERNARY + } + action_refs { + id: 16777238 + annotations: "@proto_id(1)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + size: 126 +} tables { preamble { id: 33554503 @@ -317,7 +325,6 @@ tables { name: "ingress.routing_lookup.ipv4_multicast_table" alias: "ipv4_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -352,7 +359,6 @@ tables { name: "ingress.routing_lookup.ipv6_multicast_table" alias: "ipv6_multicast_table" annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@unsupported" } match_fields { id: 1 @@ -571,12 +577,167 @@ tables { direct_resource_ids: 352321792 size: 256 } +tables { + preamble { + id: 33554695 + name: "ingress.acl_ingress.acl_ingress_qos_table" + alias: "acl_ingress_qos_table" + annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(10)" + annotations: "@p4runtime_role(\"sdn_controller\")" + 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 // 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: "@entry_restriction(\"\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\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 { + id: 1 + name: "is_ip" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 2 + name: "is_ipv4" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 3 + name: "is_ipv6" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" + bitwidth: 1 + match_type: OPTIONAL + } + match_fields { + id: 4 + name: "ether_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 7 + name: "ttl" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_TTL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 8 + name: "ip_protocol" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 9 + name: "icmpv6_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 10 + name: "l4_dst_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 12 + name: "l4_src_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT)" + bitwidth: 16 + match_type: TERNARY + } + match_fields { + id: 14 + name: "icmp_type" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE)" + bitwidth: 8 + match_type: TERNARY + } + match_fields { + id: 15 + name: "route_metadata" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ROUTE_DST_USER_META)" + bitwidth: 6 + match_type: TERNARY + } + match_fields { + id: 5 + name: "dst_mac" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" + annotations: "@format(MAC_ADDRESS)" + bitwidth: 48 + match_type: TERNARY + } + match_fields { + id: 6 + name: "arp_tpa" + annotations: "@composite_field(@ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 24 , length = 2 ) , @ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 26 , length = 2 ))" + annotations: "@format(IPV4_ADDRESS)" + bitwidth: 32 + match_type: TERNARY + } + match_fields { + id: 11 + name: "in_port" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IN_PORT)" + match_type: OPTIONAL + type_name { + name: "port_id_t" + } + } + match_fields { + id: 13 + name: "acl_metadata" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META)" + bitwidth: 8 + match_type: TERNARY + } + action_refs { + id: 16777484 + annotations: "@proto_id(1)" + } + action_refs { + id: 16777486 + annotations: "@proto_id(2)" + } + action_refs { + id: 16777475 + annotations: "@proto_id(3)" + } + action_refs { + id: 16777481 + annotations: "@proto_id(4)" + } + action_refs { + id: 16777488 + annotations: "@proto_id(5)" + } + action_refs { + id: 16777489 + annotations: "@proto_id(6)" + } + action_refs { + id: 21257015 + annotations: "@defaultonly" + scope: DEFAULT_ONLY + } + const_default_action_id: 21257015 + direct_resource_ids: 318767367 + direct_resource_ids: 352321794 + size: 255 +} tables { preamble { id: 33554697 name: "ingress.acl_ingress.acl_ingress_counting_table" alias: "acl_ingress_counting_table" annotations: "@p4runtime_role(\"sdn_controller\")" + annotations: "@sai_acl_priority(7)" annotations: "@sai_acl(INGRESS)" annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\n dscp::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || 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 \")" } @@ -861,7 +1022,6 @@ tables { id: 33554508 name: "egress.packet_rewrites.multicast_rewrites.multicast_router_interface_table" alias: "multicast_router_interface_table" - annotations: "@unsupported" annotations: "@p4runtime_role(\"sdn_controller\")" } match_fields { @@ -899,6 +1059,7 @@ tables { annotations: "@p4runtime_role(\"sdn_controller\")" annotations: "@sai_acl(EGRESS)" annotations: "@entry_restriction(\"\n\n // Forbid using ether_type for IP packets (by convention, use is_ip* instead).\n ether_type != 0x0800 && ether_type != 0x86dd;\n dscp::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n // Only allow IP field matches for IP packets.\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n\n\n\n // Only allow l4_dst_port matches for TCP/UDP packets.\n l4_dst_port::mask != 0 -> (ip_protocol == 6 || ip_protocol == 17);\n\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\n\n\n\n\n // Only allow IP field matches for IP packets.\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n\n\n\n\n\n\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\n\n\n\n\n // Only allow IP field matches for IP packets.\n ip_protocol::mask != 0 -> (is_ip == 1 || is_ipv4 == 1 || is_ipv6 == 1);\n\n dst_ipv6::mask != 0 -> is_ipv6 == 1;\n\n\n\n\n\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 { @@ -959,14 +1120,6 @@ tables { bitwidth: 6 match_type: TERNARY } - match_fields { - id: 9 - name: "dst_ipv6" - annotations: "@composite_field(@ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD3 ) , @ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2 ))" - annotations: "@format(IPV6_ADDRESS)" - bitwidth: 64 - match_type: TERNARY - } match_fields { id: 10 name: "src_mac" @@ -975,6 +1128,14 @@ tables { bitwidth: 48 match_type: TERNARY } + match_fields { + id: 9 + name: "dst_ipv6" + annotations: "@composite_field(@ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD3 ) , @ sai_field ( SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6_WORD2 ))" + annotations: "@format(IPV6_ADDRESS)" + bitwidth: 64 + match_type: TERNARY + } action_refs { id: 16777481 annotations: "@proto_id(1)" @@ -998,6 +1159,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_mirror_and_redirect_table" alias: "acl_ingress_mirror_and_redirect_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(15)" 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 \")" } @@ -1042,7 +1204,6 @@ tables { id: 8 name: "vrf_id" annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_VRF_ID)" - annotations: "@unsupported" match_type: OPTIONAL type_name { name: "vrf_id_t" @@ -1051,8 +1212,7 @@ tables { match_fields { id: 9 name: "ipmc_table_hit" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_TABLE_HIT)" - annotations: "@unsupported" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IPMC_NPU_META_DST_HIT)" bitwidth: 1 match_type: OPTIONAL } @@ -1079,6 +1239,10 @@ tables { bitwidth: 12 match_type: TERNARY } + action_refs { + id: 16777475 + annotations: "@proto_id(4)" + } action_refs { id: 16777476 annotations: "@proto_id(1)" @@ -1105,6 +1269,7 @@ tables { name: "ingress.acl_ingress.acl_ingress_security_table" alias: "acl_ingress_security_table" annotations: "@sai_acl(INGRESS)" + annotations: "@sai_acl_priority(20)" annotations: "@p4runtime_role(\"sdn_controller\")" 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\n // Only allow IP field matches for IP packets.\n dst_ip::mask != 0 -> is_ipv4 == 1;\n src_ip::mask != 0 -> is_ipv4 == 1;\n src_ipv6::mask != 0 -> is_ipv6 == 1;\n\n // TODO: This comment is required for the preprocessor to not\n // spit out nonsense.\n\n\n\n\n\n\n\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 \")" } @@ -1313,13 +1478,12 @@ tables { } tables { preamble { - id: 33554695 - name: "ingress.acl_ingress.acl_ingress_qos_table" - alias: "acl_ingress_qos_table" - annotations: "@sai_acl(INGRESS)" - annotations: "@sai_acl_priority(10)" + id: 33554696 + name: "egress.acl_egress.acl_egress_dhcp_to_host_table" + alias: "acl_egress_dhcp_to_host_table" + annotations: "@sai_acl(EGRESS)" annotations: "@p4runtime_role(\"sdn_controller\")" - 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 // 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 and l4_src_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 // Only allow arp_tpa matches for ARP packets.\n arp_tpa::mask != 0 -> ether_type == 0x0806;\n \")" + annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\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 \")" } match_fields { id: 1 @@ -1343,141 +1507,10 @@ tables { match_type: OPTIONAL } match_fields { - id: 4 - name: "ether_type" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE)" - bitwidth: 16 - match_type: TERNARY - } - match_fields { - id: 5 - name: "dst_mac" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_DST_MAC)" - annotations: "@format(MAC_ADDRESS)" - bitwidth: 48 - match_type: TERNARY - } - match_fields { - id: 6 - name: "arp_tpa" - annotations: "@composite_field(@ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 24 , length = 2 ) , @ sai_udf ( base = SAI_UDF_BASE_L3 , offset = 26 , length = 2 ))" - annotations: "@format(IPV4_ADDRESS)" - bitwidth: 32 - match_type: TERNARY - } - match_fields { - id: 7 - name: "ttl" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_TTL)" - bitwidth: 8 - match_type: TERNARY - } - match_fields { - id: 8 - name: "ip_protocol" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" - bitwidth: 8 - match_type: TERNARY - } - match_fields { - id: 9 - name: "icmpv6_type" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE)" - bitwidth: 8 - match_type: TERNARY - } - match_fields { - id: 10 - name: "l4_dst_port" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT)" - bitwidth: 16 - match_type: TERNARY - } - match_fields { - id: 11 - name: "in_port" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IN_PORT)" - match_type: OPTIONAL - type_name { - name: "port_id_t" - } - } - match_fields { - id: 13 - name: "acl_metadata" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_USER_META)" - bitwidth: 8 - match_type: TERNARY - } - action_refs { - id: 16777484 - annotations: "@proto_id(1)" - } - action_refs { - id: 16777486 - annotations: "@proto_id(2)" - } - action_refs { - id: 16777475 - annotations: "@proto_id(3)" - } - action_refs { - id: 16777481 - annotations: "@proto_id(4)" - } - action_refs { - id: 16777488 - annotations: "@proto_id(5)" - } - action_refs { - id: 16777489 - annotations: "@proto_id(6)" - } - action_refs { - id: 21257015 - annotations: "@defaultonly" - scope: DEFAULT_ONLY - } - const_default_action_id: 21257015 - direct_resource_ids: 318767367 - direct_resource_ids: 352321794 - size: 511 -} -tables { - preamble { - id: 33554696 - name: "egress.acl_egress.acl_egress_dhcp_to_host_table" - alias: "acl_egress_dhcp_to_host_table" - annotations: "@sai_acl(EGRESS)" - annotations: "@p4runtime_role(\"sdn_controller\")" - annotations: "@entry_restriction(\"\n // Only allow IP field matches for IP packets.\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 \")" - } - match_fields { - id: 1 - name: "is_ip" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IP)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 2 - name: "is_ipv4" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV4ANY)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 3 - name: "is_ipv6" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE / IPV6ANY)" - bitwidth: 1 - match_type: OPTIONAL - } - match_fields { - id: 5 - name: "ip_protocol" - annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" - bitwidth: 8 + id: 5 + name: "ip_protocol" + annotations: "@sai_field(SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL)" + bitwidth: 8 match_type: TERNARY } match_fields { @@ -1579,6 +1612,13 @@ actions { annotations: "@noWarn(\"unused\")" } } +actions { + preamble { + id: 24742814 + name: "no_action" + alias: "no_action" + } +} actions { preamble { id: 16777221 @@ -1602,20 +1642,6 @@ actions { annotations: "@sai_action(SAI_PACKET_ACTION_DROP)" } } -actions { - preamble { - id: 16777238 - name: "ingress.tunnel_termination_lookup.mark_for_tunnel_decap_and_set_vrf" - alias: "mark_for_tunnel_decap_and_set_vrf" - } - params { - id: 1 - name: "vrf_id" - type_name { - name: "vrf_id_t" - } - } -} actions { preamble { id: 16777242 @@ -1642,16 +1668,17 @@ actions { } actions { preamble { - id: 16777224 - name: "ingress.l3_admit.admit_to_l3" - alias: "admit_to_l3" + id: 16777238 + name: "ingress.tunnel_termination.tunnel_decap" + alias: "tunnel_decap" + annotations: "@unsupported" } } actions { preamble { - id: 24742814 - name: "ingress.routing_lookup.no_action" - alias: "no_action" + id: 16777224 + name: "ingress.l3_admit.admit_to_l3" + alias: "admit_to_l3" } } actions { @@ -1733,7 +1760,6 @@ actions { id: 16777240 name: "ingress.routing_lookup.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;\n \")" } params { @@ -1814,6 +1840,90 @@ actions { } } } +actions { + preamble { + id: 16777484 + name: "ingress.acl_ingress.set_qos_queue_and_cancel_copy_above_rate_limit" + alias: "set_qos_queue_and_cancel_copy_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_RED)" + } + params { + id: 1 + name: "qos_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777489 + name: "ingress.acl_ingress.set_cpu_and_multicast_queues_and_deny_above_rate_limit" + alias: "set_cpu_and_multicast_queues_and_deny_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" + annotations: "@unsupported" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } + params { + id: 2 + name: "green_multicast_queue" + annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_GREEN)" + type_name { + name: "qos_queue_t" + } + } + params { + id: 3 + name: "red_multicast_queue" + annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_RED)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777486 + name: "ingress.acl_ingress.set_cpu_queue_and_deny_above_rate_limit" + alias: "set_cpu_queue_and_deny_above_rate_limit" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" + annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} +actions { + preamble { + id: 16777488 + name: "ingress.acl_ingress.set_cpu_queue" + alias: "set_cpu_queue" + annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD)" + } + params { + id: 1 + name: "cpu_queue" + annotations: "@sai_action_param(QOS_QUEUE)" + type_name { + name: "qos_queue_t" + } + } +} actions { preamble { id: 16777217 @@ -2136,6 +2246,7 @@ actions { id: 1 name: "nexthop_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_NEXT_HOP)" annotations: "@refers_to(nexthop_table , nexthop_id)" type_name { name: "nexthop_id_t" @@ -2147,13 +2258,14 @@ actions { id: 16777491 name: "ingress.acl_ingress.redirect_to_ipmc_group" alias: "redirect_to_ipmc_group" - annotations: "@unsupported" annotations: "@action_restriction(\"\n // Disallow 0 since it encodes \'no multicast\' in V1Model.\n multicast_group_id != 0;\n \")" } params { id: 1 name: "multicast_group_id" annotations: "@sai_action_param(SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT)" + annotations: "@sai_action_param_object_type(SAI_OBJECT_TYPE_IPMC_GROUP)" + annotations: "@refers_to(builtin : : multicast_group_table , multicast_group_id)" bitwidth: 16 } } @@ -2185,90 +2297,6 @@ actions { bitwidth: 8 } } -actions { - preamble { - id: 16777484 - name: "ingress.acl_ingress.set_qos_queue_and_cancel_copy_above_rate_limit" - alias: "set_qos_queue_and_cancel_copy_above_rate_limit" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_COPY_CANCEL , SAI_PACKET_COLOR_RED)" - } - params { - id: 1 - name: "qos_queue" - annotations: "@sai_action_param(QOS_QUEUE)" - type_name { - name: "qos_queue_t" - } - } -} -actions { - preamble { - id: 16777489 - name: "ingress.acl_ingress.set_cpu_and_multicast_queues_and_deny_above_rate_limit" - alias: "set_cpu_and_multicast_queues_and_deny_above_rate_limit" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" - annotations: "@unsupported" - } - params { - id: 1 - name: "cpu_queue" - annotations: "@sai_action_param(QOS_QUEUE)" - type_name { - name: "qos_queue_t" - } - } - params { - id: 2 - name: "green_multicast_queue" - annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_GREEN)" - type_name { - name: "qos_queue_t" - } - } - params { - id: 3 - name: "red_multicast_queue" - annotations: "@sai_action_param(MULTICAST_QOS_QUEUE , SAI_PACKET_COLOR_RED)" - type_name { - name: "qos_queue_t" - } - } -} -actions { - preamble { - id: 16777486 - name: "ingress.acl_ingress.set_cpu_queue_and_deny_above_rate_limit" - alias: "set_cpu_queue_and_deny_above_rate_limit" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD , SAI_PACKET_COLOR_GREEN)" - annotations: "@sai_action(SAI_PACKET_ACTION_DENY , SAI_PACKET_COLOR_RED)" - } - params { - id: 1 - name: "cpu_queue" - annotations: "@sai_action_param(QOS_QUEUE)" - type_name { - name: "qos_queue_t" - } - } -} -actions { - preamble { - id: 16777488 - name: "ingress.acl_ingress.set_cpu_queue" - alias: "set_cpu_queue" - annotations: "@sai_action(SAI_PACKET_ACTION_FORWARD)" - } - params { - id: 1 - name: "cpu_queue" - annotations: "@sai_action_param(QOS_QUEUE)" - type_name { - name: "qos_queue_t" - } - } -} actions { preamble { id: 16777485 @@ -2326,6 +2354,17 @@ direct_counters { } direct_table_id: 33554688 } +direct_counters { + preamble { + id: 318767367 + name: "ingress.acl_ingress.acl_ingress_qos_counter" + alias: "acl_ingress_qos_counter" + } + spec { + unit: BOTH + } + direct_table_id: 33554695 +} direct_counters { preamble { id: 318767369 @@ -2381,17 +2420,6 @@ direct_counters { } direct_table_id: 33554694 } -direct_counters { - preamble { - id: 318767367 - name: "ingress.acl_ingress.acl_ingress_qos_counter" - alias: "acl_ingress_qos_counter" - } - spec { - unit: BOTH - } - direct_table_id: 33554695 -} direct_counters { preamble { id: 318767368