Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions p4_infra/p4_pdpi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
![build](https://github.com/google/p4-pdpi/workflows/build/badge.svg)
![test](https://github.com/google/p4-pdpi/workflows/test/badge.svg)

# P4 PDPI

P4Runtime generally uses a program-independent representation (or PI) for P4
entities such as table entries, counters, etc. This is achieved by using numeric
IDs instead of names. The downside of this is that the representation is hard to
read by humans. In contrast, a program-dependent (or PD) representation uses
names and is generally more friendly to humans.

This repository provides several PD-like representations, and code to
automatically convert between them.

This is a work in progress.

This is not an officially supported Google product.

214 changes: 214 additions & 0 deletions p4_infra/p4_pdpi/built_ins.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "p4_infra/p4_pdpi/built_ins.h"

#include <string>

#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "gutil/gutil/status.h"
#include "p4_infra/p4_pdpi/ir.pb.h"

namespace pdpi {

namespace {
// General string constants.
constexpr absl::string_view kBuiltInPrefix = "builtin::";

// Multicast group table-related string constants.
constexpr absl::string_view kMulticastGroupTableString =
"multicast_group_table";
constexpr absl::string_view kMulticastGroupIdString = "multicast_group_id";
constexpr absl::string_view kReplicaString = "replica";
constexpr absl::string_view kReplicaPortString = "replica.port";
constexpr absl::string_view kReplicaInstanceString = "replica.instance";

// Clone session table-related string constants.
constexpr absl::string_view kCloneSessionTableString = "clone_session_table";

} // namespace

std::string GetMulticastGroupTableName() {
return absl::StrCat(kBuiltInPrefix, kMulticastGroupTableString);
}

std::string GetReplicaActionName() {
return absl::StrCat(kBuiltInPrefix, kReplicaString);
}

std::string GetCloneSessionTableName() {
return absl::StrCat(kBuiltInPrefix, kCloneSessionTableString);
}

bool IsBuiltInTable(absl::string_view table_name) {
return StringToIrBuiltInTable(table_name).ok();
}

bool IsBuiltInAction(absl::string_view action_name) {
return StringToIrBuiltInAction(action_name).ok();
}

bool BuiltInTableHasMatchField(IrBuiltInTable table,
IrBuiltInMatchField field) {
switch (table) {
case BUILT_IN_TABLE_MULTICAST_GROUP_TABLE: {
return field == BUILT_IN_MATCH_FIELD_MULTICAST_GROUP_ID;
}
default: {
return false;
}
}
}

bool BuiltInTableHasAction(IrBuiltInTable table, IrBuiltInAction action) {
switch (table) {
case BUILT_IN_TABLE_MULTICAST_GROUP_TABLE: {
return action == BUILT_IN_ACTION_REPLICA;
}
default: {
return false;
}
}
}

bool BuiltInActionHasParameter(IrBuiltInAction action,
IrBuiltInParameter parameter) {
switch (action) {
case BUILT_IN_TABLE_MULTICAST_GROUP_TABLE: {
return parameter == BUILT_IN_PARAMETER_REPLICA_PORT ||
parameter == BUILT_IN_PARAMETER_REPLICA_INSTANCE;
}
default: {
return false;
}
}
}

absl::StatusOr<IrBuiltInAction> GetBuiltInActionFromBuiltInParameter(
IrBuiltInParameter parameter) {
switch (parameter) {
case BUILT_IN_PARAMETER_REPLICA_PORT: {
return BUILT_IN_ACTION_REPLICA;
}
case BUILT_IN_PARAMETER_REPLICA_INSTANCE: {
return BUILT_IN_ACTION_REPLICA;
}
default: {
return gutil::InvalidArgumentErrorBuilder()
<< "Unknown built-in parameter: "
<< IrBuiltInParameter_Name(parameter);
}
}
}

absl::StatusOr<std::string> IrBuiltInTableToString(IrBuiltInTable table) {
switch (table) {
case pdpi::BUILT_IN_TABLE_MULTICAST_GROUP_TABLE:
return GetMulticastGroupTableName();
case pdpi::BUILT_IN_TABLE_CLONE_SESSION_TABLE:
return GetCloneSessionTableName();
default: {
return gutil::InvalidArgumentErrorBuilder()
<< "Unknown built-in table: " << IrBuiltInTable_Name(table);
}
}
}

absl::StatusOr<std::string> IrBuiltInMatchFieldToString(
IrBuiltInMatchField field) {
switch (field) {
case BUILT_IN_MATCH_FIELD_MULTICAST_GROUP_ID: {
return std::string(kMulticastGroupIdString);
}
default: {
return gutil::InvalidArgumentErrorBuilder()
<< "Unknown built-in match field: "
<< IrBuiltInMatchField_Name(field);
}
}
}

absl::StatusOr<std::string> IrBuiltInActionToString(IrBuiltInAction action) {
switch (action) {
case BUILT_IN_ACTION_REPLICA: {
return absl::StrCat(kBuiltInPrefix, kReplicaString);
}
default: {
return gutil::InvalidArgumentErrorBuilder()
<< "Unknown built-in action: " << IrBuiltInAction_Name(action);
}
}
}

absl::StatusOr<std::string> IrBuiltInParameterToString(
IrBuiltInParameter parameter) {
switch (parameter) {
case BUILT_IN_PARAMETER_REPLICA_PORT: {
return std::string(kReplicaPortString);
}
case BUILT_IN_PARAMETER_REPLICA_INSTANCE: {
return std::string(kReplicaInstanceString);
}
default: {
return gutil::InvalidArgumentErrorBuilder()
<< "Unknown built-in parameter: "
<< IrBuiltInParameter_Name(parameter);
}
}
}

absl::StatusOr<IrBuiltInTable> StringToIrBuiltInTable(absl::string_view table) {
if (table == GetMulticastGroupTableName()) {
return pdpi::BUILT_IN_TABLE_MULTICAST_GROUP_TABLE;
}
if (table == GetCloneSessionTableName()) {
return pdpi::BUILT_IN_TABLE_CLONE_SESSION_TABLE;
}
return gutil::InvalidArgumentErrorBuilder()
<< "'" << table << "' is not a built-in table.";
}

absl::StatusOr<IrBuiltInMatchField> StringToIrBuiltInMatchField(
absl::string_view field) {
if (field == kMulticastGroupIdString) {
return BUILT_IN_MATCH_FIELD_MULTICAST_GROUP_ID;
}
return gutil::InvalidArgumentErrorBuilder()
<< "'" << field << "' is not a built-in match field.";
}

absl::StatusOr<IrBuiltInAction> StringToIrBuiltInAction(
absl::string_view action) {
if (action == absl::StrCat(kBuiltInPrefix, kReplicaString)) {
return BUILT_IN_ACTION_REPLICA;
}
return gutil::InvalidArgumentErrorBuilder()
<< "'" << action << "' is not a built-in action.";
}

absl::StatusOr<IrBuiltInParameter> StringToIrBuiltInParameter(
absl::string_view parameter) {
if (parameter == kReplicaPortString) {
return BUILT_IN_PARAMETER_REPLICA_PORT;
}
if (parameter == kReplicaInstanceString) {
return BUILT_IN_PARAMETER_REPLICA_INSTANCE;
}
return gutil::InvalidArgumentErrorBuilder()
<< "'" << parameter << "' is not a built-in paramter.";
}

} // namespace pdpi
109 changes: 109 additions & 0 deletions p4_infra/p4_pdpi/built_ins.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
// This file contains functions for translating between proto enum and string
// representation for `pdpi::IrBuiltTable` and `pdpi::IrBuiltInField` (defined
// in ir.proto). It also contains functions for checking the validity of
// built-in table and field pairings.

#ifndef PINS_P4_INFRA_P4_PDPI_BUILT_INS_H_
#define PINS_P4_INFRA_P4_PDPI_BUILT_INS_H_

#include <string>

#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "p4_infra/p4_pdpi/ir.pb.h"

namespace pdpi {

// Returns the PDPI name for the multicast group table.
std::string GetMulticastGroupTableName();

// Returns the PDPI name for the clone session table.
std::string GetCloneSessionTableName();

// Returns the PDPI name for the replica action.
std::string GetReplicaActionName();

// Returns true if `table_name` is a known built_in table.
// Useful for branching on table type.
bool IsBuiltInTable(absl::string_view table_name);

// Returns true if `action_name` is a known built_in table.
// Useful for branching on action type.
bool IsBuiltInAction(absl::string_view action_name);

// Returns true if built-in `table` has built-in `field`.
bool BuiltInTableHasMatchField(IrBuiltInTable table, IrBuiltInMatchField field);

// Returns true if built-in `table` has built-in `action`.
bool BuiltInTableHasAction(IrBuiltInTable table, IrBuiltInAction action);

// Returns true if built-in `action` has built-in `parameter`.
bool BuiltInActionHasParameter(IrBuiltInAction action,
IrBuiltInParameter parameter);

// Returns enum `IrBuiltInAction` that built-in `parameter` belongs to.
// Returns InvalidArgumentError if built-in `parameter` holds invalid/unknown
// enum.
absl::StatusOr<IrBuiltInAction> GetBuiltInActionFromBuiltInParameter(
IrBuiltInParameter parameter);

// Returns string representation of built-in `table`.
// Returns InvalidArgumentError if built-in `table` holds invalid/unknown enum.
absl::StatusOr<std::string> IrBuiltInTableToString(IrBuiltInTable table);

// Returns string representation of built-in `field`.
// Returns InvalidArgumentError if built-in `field` holds invalid/unknown enum.
absl::StatusOr<std::string> IrBuiltInMatchFieldToString(
IrBuiltInMatchField field);

// Returns string representation of built-in `action`.
// Returns InvalidArgumentError if built-in `action` holds invalid/unknown enum.
absl::StatusOr<std::string> IrBuiltInActionToString(IrBuiltInAction action);

// Returns string representation of built-in `parameter`.
// Returns InvalidArgumentError if built-in `parameter` holds invalid/unknown
// enum.
absl::StatusOr<std::string> IrBuiltInParameterToString(
IrBuiltInParameter parameter);

// Returns enum `IrBuiltInTable` whose string representation is `table_name`.
// Returns InvalidArgumentError if no `IrBuiltInTable` has string representation
// `table_name` (i.e. if `IsBuiltInTable(table_name)` is false).
absl::StatusOr<IrBuiltInTable> StringToIrBuiltInTable(
absl::string_view table_name);

// Returns enum `IrBuiltInMatchField` whose string representation is
// `field_name`. Returns InvalidArgumentError if no IrBuiltInMatchField has
// string representation `field_name`.
absl::StatusOr<IrBuiltInMatchField> StringToIrBuiltInMatchField(
absl::string_view field_name);

// Returns enum `IrBuiltInAction` whose string representation is `action_name`.
// Returns InvalidArgumentError if no IrBuiltInAction has string representation
// `action_name`.
absl::StatusOr<IrBuiltInAction> StringToIrBuiltInAction(
absl::string_view action_name);

// Returns enum `IrBuiltInParameter` whose string representation is
// `parameter_name`. Returns InvalidArgumentError if no IrBuiltInParameter has
// string representation `parameter_name`.
absl::StatusOr<IrBuiltInParameter> StringToIrBuiltInParameter(
absl::string_view parameter_name);

} // namespace pdpi

#endif // PINS_P4_INFRA_P4_PDPI_BUILT_INS_H_
Loading