16. Deparsing
The inverse of parsing is deparsing, or packet construction. P4 does not
provide a separate language for packet deparsing; deparsing is done in a
control block that has at least one parameter of type packet_out.
For example, the following code sequence writes first an Ethernet header
and then an IPv4 header into a packet_out:
\~ Begin P4Example control TopDeparser(inout Parsed_packet p, packet_out b) { apply { b.emit(p.ethernet); b.emit(p.ip); } } \~ End P4Example
Emitting a header appends the header to the packet_out only if the
header is valid. Emitting a header stack will emit all elements of the
stack in order of increasing indices.
The packet_out datatype is defined in the P4 core library, and
reproduced below. It provides a method for appending data to an output
packet called emit:
\~ Begin P4Example extern packet_out { void emit
The emit method supports appending the data contained in a header,
header stack, struct, or header union to the output packet.
- When applied to a header,
emitappends the data in the header to the packet if it is valid and otherwise behaves like a no-op. - When applied to a header stack,
emitrecursively invokes itself to each element of the stack. - When applied to a
structor header union,emitrecursively invokes itself to each field. Note, astructmust not contain a field of typeerrororenumbecause these types cannot be serialized.
It is illegal to invoke emit on an expression whose type is a base
type, enum, or error.
We can define the meaning of the emit method in pseudocode as follows:
\~ Begin P4Pseudo packet_out { byte[] data; unsigned lengthInBits;
void initializeForWriting() { this.data.clear(); this.lengthInBits = 0;
} /// Append data to the packet. Type T must be a header, header ///
stack, header union, or struct formed recursively from those types void
emit
Here we use the special valid$ identifier to indicate the hidden valid
bit of headers and fields$ to indicate the list of fields for a struct
or header union. We also use standard for-each notation to iterate
through the elements of a stack (e : data) and list of fields for
header unions and structs (f : data.fields$). The iteration order for
a struct is the order those fields appear in the type declaration.