Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for adding GenericTable #419

Closed
wants to merge 13 commits into from
136 changes: 136 additions & 0 deletions docs/v1/P4Runtime-Spec.mdk
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,49 @@ The `Digest` message defines the following fields:
notification using a `P4DataTypeSpec` message (see section on [Representation
of Arbitrary P4 Types](#sec-representation-of-arbitrary-p4-types)).

### `GenericTable` { #sec-p4info-generic-table}
`GenericTable` messages are used to map non-PSA P4-externs or non-P4 target-
specific "fixed" features to their implementation in a generic way. The same can be achieved
via `Extern`, but GenericTable provides a structured way in which every feature is
represented as a set of match-fields and data-fields. The data consists of unions
wihch are similar to actions. One use of GenericTable in a server backend is
with TDI [Table Driven Interface](https://github.com/p4lang/tdi), but targets
can use Generic table to map to their own specific feature implementations as
well.
It defines the following fields

* `preamble`, a `Preamble` message with the ID, name, and alias of this
GenericTable.

* `match_fields`, a repeated field of type `MatchField` representing the data to
be used to construct the lookup key matched in this table. For information check
the match_fields info in the [Table section](#sec-table)

* `union_refs`, a repeated `UnionRef` field representing the set of possible
unions for this table. Functionally, it behaves same as that of ActionRefs.
Hence it has been kept as ActionRefs itself.
Please check the action_refs info in the [Table section](#sec-table)

* `const_default_union_id`, if this table has a constant default union, this
field will carry the `uint32` identifier of that action, otherwise its value
will be 0. A default union is the data when the key is null. It is similar to
a default action for Match Tables.
Being constant means that the control plane cannot
set a different default union at runtime or change the default union's
arguments.

* `size`, an `int64` describing the desired number of table entries that the
target should support for the table. See the "Size" subsection within the
"Table Properties" section of the P4~16~ language specification for details
[@P4TableProperties].

* `is_const_table`, a boolean flag indicating that the table cannot be modified
by the control plane at runtime.

* `other_properties`, an `Any` Protobuf message [@ProtoAny] to embed
architecture-specific or target-specific table properties [@P4TableProperties]
that the target wants to convey.

### `Extern` { #sec-p4info-extern}

`Extern` messages are used to specify all extern instances across all extern
Expand Down Expand Up @@ -2933,6 +2976,26 @@ tables {
}
~ End Prototext

### GenericData

`GenericData` is an addition to p4data.proto- which aims at adding support for
data types which aren't covered by P4Data. This incorporates all the data types
used as primitive data types like bytes, float, strings.

* bitstring : Bytes type used for simple unsigned integers or bytes
* float : Floating type values
* bool : Boolean type values
* generic_struct : Used to define a structure that can contain
one or more of the other members. So one structure can contain
different members of different types in GenericData
* generic_list : Used to define a list of same types. Even though the def
is same as that of generic_struct, this only allows for a variable list
of the same type. It can also be a list of generic_structs
* string : Used to define control plane strings. The max string length is
defined by the size
* enum : String representation with which safe enums are realized
* enum_val : bytes value with which unsafe/serializable enums are defined

# P4 Entity Messages { #sec-p4-entity-msgs}

P4Runtime covers P4 entities that are either part of the P4~16~ language, or
Expand Down Expand Up @@ -4787,6 +4850,79 @@ message should be defined in a separate architecture-specific Protobuf file. See
section on [Extending P4Runtime for non-PSA
Architectures](#sec-extending-p4runtime) for more information.

## `GenericTableEntry` { #sec-generic-table-entry}

GenericTableEntry can be used to program non-PSA externs or non-P4 target-specific
"fixed" features to their implementation in a generic way. This provides an alternative
to `Extern` in a structured way and within p4runtime guidelines and semantics.
The idea has been borrowed from TDI [Table Driven Interface](https://github.com/p4lang/tdi),
that every state can be representated as a table or multiple tables. A table here is any
data structure with one or more entries and each entry can be represented as a set of
key fields and data fields.
Actions in P4 tables behave like unions and that has been borrowed here in GenericTable.
This can be potentially used targets to map to either TDI based backends, or even non-TDI
based backends. If using TDI, then potentially, for every new feature to be added, only
TDI backend support and remote client code will be required to make use of that function.
All other middle layers should theoretically remain unchanged.

P4Runtime supports inserting, modifying, deleting and reading GenericTable entries with
the `GenericTableEntry` entity, which has the following fields:

* `table_id`, which identifies the table instance; the `table_id` is determined
by the P4Info message.

* `match`, a repeated field of `GenericFieldMatch` messages. Each element in the
repeated field is used to provide a value for the corresponding element in the
p4info.

* `union`, which indicates which of the table's unions to execute in case of
match and with which argument values.

* `priority`, a 32-bit integer used to order entries when the table's match key
includes an optional, ternary or range match.

* `is_default_action`, a boolean flag which indicates whether the table entry is
the default entry for the table. See [Default entry](#sec-default-entry)
section for more information.

* `metadata`, an arbitrary `bytes` value which is opaque to the
target. There is no requirement of where this is stored, but it must be
returned by the server along with the rest of the entry when the client
performs a read on the entry.

The `priority` field must be set to a non-zero value if the match key includes a
ternary match (&ie; in the case of PSA if the P4Info entry for the table
indicates that one or more of its match fields has an `OPTIONAL`, `TERNARY` or
`RANGE` match
type) or to zero otherwise. A higher priority number indicates that the entry
must be given higher priority when performing a table lookup. Clients must allow
multiple entries to be added with the same priority value. If a packet can
match multiple entries with the same priority, it is not deterministic in the
data plane which entry a packet will match. If a client wishes to make the
matching behavior deterministic, it must use different priority values for any
pair of table entries that the same packet matches.

The `match` and `priority` fields are used to uniquely identify an entry within
a table. Therefore, these fields cannot be modified after the entry has been
inserted and must be provided for `MODIFY` and `DELETE` updates. When deleting
an entry, these key fields (along with `is_default_action`) are the only fields
considered by the server. All other fields must be ignored, even if they have
nonsensical values (such as an invalid action field). In the case of a *keyless*
table (the table has an empty match key), the server must reject all attempts to
`INSERT` a match entry and return an `INVALID_ARGUMENT` error.

The number of match entries that a table *should* support is indicated in P4Info
(`size` field of `Table` message). The guarantees provided to the P4Runtime
client are the same as the ones described in the P4~16~ specification for the
`size` property [@P4TableProperties]. In particular, some implementations may
not be able to always accommodate an arbitrary set of entries up to the
requested size, and other implementations may provide the P4Runtime client with
more entries than requested. The P4Runtime server must return
`RESOURCE_EXHAUSTED` when a table entry cannot be inserted because of a size
limitation. It is recommended that, for the sake of portability, P4Runtime
clients do not try to insert additional entries once the size indicated in
P4Info has been reached.

# Error Reporting Messages { #sec-error-reporting-messages}

P4Runtime is based on gRPC and all RPCs return a status to indicate success or
Expand Down
108 changes: 108 additions & 0 deletions proto/p4/GenericTable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# GenericTable example p4info

Below is an example for realizing MulticastGroupEntry as a GenericTable.
The key (MatchFields) comprise of only the group_id. 2 different ways of
defining the data fields has been presented. Only 1 of them is required.

```
generic_tables {
generic_table_type_id : 145
generic_table_type_name : "MulticastGroup"
saynb marked this conversation as resolved.
Show resolved Hide resolved
preamble {
id: 45332650
name: "MulticastGroup"
alias: "multicast_group"
}
generic_match_fields {
id: 1
name: "multicast_group_id"
match_type: EXACT
type {
type : "bytes"
width : 32
}
}
union_refs {
id: 23557840
}
size: 1024
}
```

In the below one, both `instance` and `port` are separate
repeated fields. So the check on `len(instance_array) == len(port_array)`
needs to be a runtime check. This however keeps implementation simpler
and faster since we avoid further recursive nesting.

`port` is a varbytes of max size 64 bits each. The field is repeated so it
is defined as list of varbits through p4info.

```
unions {
preamble {
id: 23557840
name: "multicast_group_member_add"
alias: "multicast_group_member_add"
}
params {
id: 1
name: "instance"
repeated: true
saynb marked this conversation as resolved.
Show resolved Hide resolved
type {
type : "bytes"
width : 32
}
}
params {
id: 2
name: "port"
repeated: true
type {
type : "varbytes"
max_bit_width : 64
}
}
}

```

The below one is similar to the above but both `instance` and `port` have
been converted to a list of structs.

```
unions {
preamble {
id: 23557841
name: "multicast_group_member_add_2"
alias: "multicast_group_member_add_2"
}
params {
id: 1
name: "replica"
repeated: true
type {
type : "list"
}
params {
param {
id: 1
name: "instance"
repeated: true
type {
type : "bytes"
width : 32
}
}
param : {
id: 2
name: "port"
repeated: true
type {
type : "varbytes"
max_bit_width : 64
}
}
}
}
}
```
103 changes: 103 additions & 0 deletions proto/p4/config/v1/p4info.proto
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ message P4Info {
repeated ValueSet value_sets = 10;
repeated Register registers = 11;
repeated Digest digests = 12;
repeated GenericTable generic_tables = 13;
repeated Union unions = 14;
repeated Extern externs = 100;
P4TypeInfo type_info = 200;
}
Expand Down Expand Up @@ -103,6 +105,7 @@ message P4Ids {
DIRECT_METER = 0x15;
REGISTER = 0x16;
DIGEST = 0x17;
GENERIC_TABLE = 0x18;

// externs for other architectures (vendor extensions)
OTHER_EXTERNS_START = 0x80;
Expand All @@ -114,6 +117,22 @@ message P4Ids {
}
}

// A subtype of P4IDs for GenericTables
message GenericTableType {
// The ID space is for Generic tables. In the Preamble ID, the MSB will be
// 0x18 but the next MSB is reserved for this enum. This shortens the ID
// space for tables in each type but it is still 64k (16 bits) for each table
enum Prefix {

GENERIC_TABLES_START = 0x00;

// max value for an unsigned 8-bit byte
MAX = 0xff;
// requires protoc >= 3.5.0
// reserved 0x100 to max;
}
}

message Preamble {
// ids share the same number-space; e.g. table ids cannot overlap with counter
// ids. Even though this is irrelevant to this proto definition, the ids are
Expand Down Expand Up @@ -397,3 +416,87 @@ message Digest {
Preamble preamble = 1;
P4DataTypeSpec type_spec = 2;
}

message GenericMatchField {
uint32 id = 1;
string name = 2;
bool repeated = 3;
GenericDataTypeSpec type_spec = 4;
enum MatchType {
UNSPECIFIED = 0;
EXACT = 2;
LPM = 3;
TERNARY = 4;
RANGE = 5;
OPTIONAL = 6;
}
oneof match {
MatchType match_type = 5;
// used for architecture-specific match types which are not part of the core
// P4 language or of the PSA architecture.
string other_match_type = 6;
}
// Documentation of the match field
Documentation doc = 7;
repeated string annotations = 8;
// Optional. If present, the location of `annotations[i]` is given by
// `annotation_locations[i]`.
repeated StructuredAnnotation structured_annotations = 9;
repeated SourceLocation annotation_locations = 10;
}

// used to list all possible unions in a Table
message UnionRef {
uint32 id = 1;
enum Scope {
TABLE_AND_DEFAULT = 0;
TABLE_ONLY = 1;
DEFAULT_ONLY = 2;
}
Scope scope = 3;
repeated string annotations = 2;
// Optional. If present, the location of `annotations[i]` is given by
// `annotation_locations[i]`.
repeated SourceLocation annotation_locations = 5;
repeated StructuredAnnotation structured_annotations = 4;
}

message Union {
Preamble preamble = 1;
message Param {
uint32 id = 1;
string name = 2;
bool repeated = 3;
repeated string annotations = 4;
GenericDataTypeSpec type_spec = 5;
// Documentation of the Param
Documentation doc = 6;
repeated StructuredAnnotation structured_annotations = 7;
// Optional. If present, the location of `annotations[i]` is given by
// `annotation_locations[i]`.
repeated SourceLocation annotation_locations = 8;
}
repeated Param params = 2;
}

// All Tables of one type will be grouped in one message.
message GenericTable {
uint32 generic_table_type_id = 1;
string generic_table_type_name = 2;
repeated GenericTableInstance instances = 3;
}

message GenericTableInstance {
Preamble preamble = 1;
repeated GenericMatchField match_fields = 2;
repeated UnionRef union_refs = 3;
// 0 (default value) means that the table does not have a const default action
uint32 const_default_union_id= 4;
int64 size = 5; // max number of entries in table
// Const table, cannot be modified at runtime
bool is_const_table = 6;
// architecture-specific table properties which are not part of the core P4
// language or of the PSA architecture.
google.protobuf.Any other_properties = 100;
}

Loading