High-Level Programming Languages: P4 (text)

by Sasha Shkrebets last modified Mar 20, 2023 08:02 AM
In this lesson we'll talk about Protocol-Independent Packet Processing. I'll describe the need for Protocol-Independent Packet Processing, and we'll talk over this concept in some detail in the context of two examples. I will focus mostly on P4.
Welcome back.
In this lesson we'll talk about Protocol-Independent Packet Processing.
I'll describe the need for
Protocol-Independent Packet Processing, and we'll talk
over this concept in some detail in the context of two examples.
I will focus mostly on P4.
Programming protocol-independent packet processors.
Where appropriate, I'll also bring in motivation and
concepts from another related effort called Protocol Oblivious Forwarding.
Over the past five years, the number
of headers in the OpenFlow specification has proliferated.
Some might argue that this proliferation is a good thing
because it reflects a lot of activity in the community.
On the other hand, as the designers of protocol oblivious
forwarding pointed out, control and data plane are not sufficiently decoupled.
There's no easy way to modify packet formats.
And adding new features requires changing
both the forwarding element and the controller.
All of these things together make it particularly hard to
evolve SDN switches and control protocols independently from the hardware.
Ideally we would like to be able to evolve
SDN switches as well and be able to define our
control protocols according to the requirements of the control programs
and not be constrained by the capabilities of current hardware.
For this, we'll want a configurable packet parser
that's not tied to a specific header format.
We'll want flexible match action tables that can match on packets in series
or in parallel and can also match on any defined field in the packet.
And, finally, we may want general packet processing primitives.
Such as the ability to copy, add, remove, and modify fields in packet headers.
We want these operations both for the header fields
and for any meta-data that's associated with the packet.
The current generation of switch ASICs is starting to make this possible.
In one of the interviews this week we hear about
the Intel FlexPipe and in another we hear about the RMT.
Both of these architectures are beginning to
make this type of programmable packet processing possible.
Still, programming these chips is hard.
They only expose custom vendor-specific interfaces,
and the programming models are very low-level.
Essentially akin to micro-code programming.
The design of a higher level language like P4 has three goals.
One is protocol independence.
So one should be able to configure a packet parser and define a
set of typed match action tables
independently of any current control plane protocols.
The second goal is target independence.
Which provides the ability to write a program that processes
packets without having deep, intricate knowledge of the switch details.
The language essentially relies on a compiler to configure the target switch.
The compiler can take this high level
description of the packet processing and compile it
to the switch in different ways depending on
the physical capabilities or limitation of the switch.
Finally, there should be some support for reconfiguartion in the
field, to change parsing and processing without redeploying new hardware.
To draw a comparison, classic open flow had a simple control plane, where
a controller would simply install rules directly in the [INAUDIBLE].
The OpenFlow 2.0 proposal, on the other hand has two aspects.
One, which takes place on a much slower
time scale, is the configuration of the switches themselves.
This configuration specifies a parser, tables, and the
control flow of packets as they traverse the switch.
The second aspect of the control protocol
is populating those tables once they've been configured.
This second aspect is much more akin to how current open flow...
This
second aspect of populating the tables is pretty similar to how the current
control plane works with the distinction now
that we have custom tables to populate.
So this compiler that sits in between the control
plane, and the switches, has a parser that can fit...
has a module that parses this
configuration and configures the tables accordingly.
As well as a rule translator which may take rules specified in the high level
control protocol and translate them down into
physical tables that may reside on the switch.
To understand how this works a little bit better in the
context of P4, let's take a simple motivating example of data-center routing.
Consider the topology below which has top-of-rack
switches and two tiers of core switches.
Let's suppose that the top-of-rack switches would
like to perform source routing with the hierarchical
tag that contains four one-byte fields each
of which specifies a hop in the topology.
P4 allows the programmer to specify an ordered list of
fields where each field has a name and a width.
Here, we see three such example
specifications; one for the ethernet header,
one for the vlan header, and one for this custom mTag header.
In addition to the header format specification, P4 also allows the
programmer to describe each packet-processing stage
using a mechanism called typed tables.
Typed table specification allows the programmer to specify which fields are
matched, and how, and what action fuinctions are performed at each stage.
Optionally these tables can provide some hint about the maximum number of rules.
It might be inserted into that table.
Here's an example of a typed table supporting
the push of the mTag that we just explored.
This table reads the ethernet and the vlan headers and has an action to add an mTag.
P4 also has ways of specifying the control flow
of a packet from one table to the next.
This allows a programmer to express
collections of functions, conditionals, and tables.
So at a particular top of rack switch, the packet
might be coming from the core, or from local hosts.
Depending on where it's coming from, it may or may not already have an mTag.
First step in the control flow may be to
check the table for the source and then consult
a local switching table to determine whether the destination
for the packet is local to the switch or not.
If it's not local, the switch might consult the mTag table to add the
appropriate mTag and then push the packet to the appropriate egress pole.
The P4 Compiler has a parser which might be a programmable parser, in the context
of more programmable switches, or a fixed parser in the case of legacy switches.
In the latter case, the fixed parser might simply verify that the description
of what is being parsed is consistent with the capabilities of the legacy hardware.
The control program has two aspects.
One, target-independent aspect.
It's simply a table graph.
Explaining the dependencies between different match
action tables in the control form.
The second, is a target dependent mapping of logical tables to the
switch based sources depending on the
physical constraints of any particular switch.
The final component of the compiler is a rule translation module.
Which verifies that the rules agree with the logical table types, and translates
the logical rules to the physical tables which the switch is capable of supporting.
To support the goal of target independence P4
has a vision of compiling to different types
of its switches since essentially anything in a
logical table graph can be mapped for software.
When hardware switches with RAM and TCAM,
the RAM can act as a hash table for tables with exact
matches, and the TCAM can provide tables with wildcards in the matches.
Other switches might provide support for parallel
tables, in which case the compiler might want
to analyze the table graph to ensure
that possible concurrent operations don't introduce correctness problems.
Other switch architectures might instantiate tables that generate
meta-data along each stage of packet processing and
that meta-data could subsequently be used to perform
actions at the end of the processing pipeline.
This approach is similar to that which is taken by Intel's flex pipe architecture.
Finally, the compiler might need to operate on switches that
have very few physical tables, such as legacy overflow 1.0 switches.
In these cases the compiler might need to
map multiple logical physical tables to one physical table.
Composing rules for multiple logical tables into a
cross product of rules in a single physical table.
In conclusion, open flow 1.x protocols provide a
vendor-agnostic API but only for very fixed function switches.
P4 and protocol oblivious forwarding, envision
an alternate future where one can define
the hardware independently of the control
protocol, and independently of the switch targets.
This new paradigm also provides for the
ability to reconfigure a switch in the field.
P4 is a strawman proposal for a language that might allow a switch
to be reconfigured in the field, but there's much work to be done.
Just to name one particular challenge is the design
of that compiler that takes a high level language
like P4, and compiles it to different targets ranging
from legacy switches to programmable hardware like FPGAs to software.
Navigation