08 15 operations on sets
Some P4 expressions denote sets of values (set<T>, for some type T;
see Section Set types). These expressions can appear only in a
few contexts—parsers and table entries. For example, the select
expression (Section Select expressions) has the following structure:
select (expression) {
set1: state1;
set2: state2;
// More labels omitted
}
Here the expressions set1, set2, etc. evaluate to sets of values and
the select expression tests whether expression belongs to the sets
used as labels.
keysetExpression
: tupleKeysetExpression
| simpleKeysetExpression
;
tupleKeysetExpression
: "(" simpleKeysetExpression "," simpleExpressionList ")"
| "(" reducedSimpleKeysetExpression ")"
;
simpleExpressionList
: simpleKeysetExpression
| simpleExpressionList "," simpleKeysetExpression
;
reducedSimpleKeysetExpression
: expression "&&&" expression
| expression ".." expression
| DEFAULT
| "_"
;
simpleKeysetExpression
: expression
| expression "&&&" expression
| expression ".." expression
| DEFAULT
| "_"
;
The mask (&&&) and range (..) operators have the same precedence;
the just above the ?: operator.
Singleton sets
In a set context, expressions denote singleton sets. For example, in the following program fragment,
select (hdr.ipv4.version) {
4: continue;
}
The label 4 denotes the singleton set containing the int value 4.
The universal set
In a set context, the expressions default or _ denote the universal
set, which contains all possible values of a given type:
select (hdr.ipv4.version) {
4: continue;
_: reject;
}
Masks
The infix operator &&& takes two arguments of the same numeric type
(Section Numeric types), and creates a value of the same
type. The right value is used as a “mask”, where each bit set to 0 in
the mask indicates a “don’t care” bit. More formally, the set denoted by
a &&& b is defined as follows:
a &&& b = { c where a & b = c & b }
For example:
8w0x0A &&& 8w0x0F
denotes a set that contains 16 different bit<8> values, whose
bit-pattern is XXXX1010, where the value of an X can be any bit.
Note that there may be multiple ways to express a keyset using a mask
operator—e.g., 8w0xFA &&& 8w0x0F denotes the same keyset as in the
example above.
Similar to other binary operations, the mask operator allows the compiler to automatically insert casts to unify the argument types in certain situations (section Implicit casts).
P4 architectures may impose additional restrictions on the expressions on the left and right-hand side of a mask operator: for example, they may require that either or both sub-expressions be compile-time known values.
Ranges
The infix operator .. takes two arguments of the same numeric type T
(Section Numeric types), and creates a value of the type
set<T>. The set contains all values numerically between the first and
the second, inclusively. For example:
4s5 .. 4s8
denotes a set of 4 consecutive int<4> values 4s5, 4s6, 4s7, and
4s8.
Similar to other binary operations, the range operator allows the compiler to automatically insert casts to unify the argument types in certain situations (section Implicit casts).
A range where the second value is smaller than the first one represents an empty set.
Products
Multiple sets can be combined using Cartesian product:
select(hdr.ipv4.ihl, hdr.ipv4.protocol) {
(4w0x5, 8w0x1): parse_icmp;
(4w0x5, 8w0x6): parse_tcp;
(4w0x5, 8w0x11): parse_udp;
(_, _): accept; }
The type of a product of sets is a set of tuples.