Академический Документы
Профессиональный Документы
Культура Документы
Editor Note: This post was originally written by Bruno Rijsman for his personal blog
(https://hikingandcoding.wordpress.com/). We are re-publishing it here (with permission) as it provides an
excellent introduction to getting started with the P4 language using the software tools that have been
developed by the open-source community.
Introduction
I recently got serious about learning P4, a programming language for the data plan in networking devices
such as routers, switches, and Network Interface Cards (NICs).
It took me a while to gure out the exact sequence of steps for writing a minimal P4 program, compiling it,
actually getting it to run on a simulated software switch, injecting some packets, and observing how the
P4 program forwards the injected packets. To save you the aggravation of guring it out for yourself, I’ve
documented the equivalent of “hello world” for P4.
Create an AWS t2.large instance running Ubuntu 18.04 LTS and assign it 20GB of disk storage. Smaller
instances are not suf cient: they will run out of disk space and/or out of memory.
Use an SSH client to log in to your newly created AWS instance (here I use the macOS ssh client). Replace
<private-key> with the name of your SSH private key le and replace <aws-instance> with the IPv4
address of your AWS instance.
sudo apt-get install -y cmake g++ git automake libtool libgc-dev bison flex libfl-dev libgmp-
dev libboost-dev libboost-iostreams-dev libboost-graph-dev llvm pkg-config python python-scap
y python-ipaddr python-ply tcpdump doxygen graphviz texlive-full
In the make step there are some warning (not errors), for example:
In the make check step there are also warnings, for example:
And since warnings are being treated as errors, this causes make check to fail (we ignore this):
cd ~/p4c
mkdir build
cd build
cmake ..
make -j4
make -j4 check
In the make -j4 step, there are some warnings, for example:
In the make -j4 check step, multiple test cases fail, for example. The test failures are all related to eBPF,
which we will not be using.
cd
git clone https://github.com/p4lang/behavioral-model.git
cd behavioral-model
./install_deps.sh
./autogen.sh
./configure
make
The steps up until now are pretty time consuming, so it is worthwhile taking a snapshot of your AWS
instance for future P4 projects.
Write a P4 program
Our minimal P4 program will only process IPv4 over Ethernet packets and it will contain only a single table
that does a longest-pre x-match lookup on the destination IP address to decide the outgoing port. That’s
it. The focus is not on producing a useful or interesting P4 program. Instead the focus is on documenting
the steps required to get started with P4 programming.
https://p4.org/p4/getting-started-with-p4.html 4/13
12/5/2019 Getting Started with P4
mkdir ~/test
cd ~/test
Use an editor (e.g. vim, which is installed by default on the AWS instance) to create a ~/test/test.p4
program with the following contents:
#include <core.p4>
#include <v1model.p4>
header ethernet_t {
EthernetAddress dst_addr;
EthernetAddress src_addr;
bit<16> ether_type;
}
header ipv4_t {
bit<4> version;
bit<4> ihl;
bit<8> diffserv;
bit<16> total_len;
bit<16> identification;
bit<3> flags;
bit<13> frag_offset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdr_checksum;
IPv4Address src_addr;
IPv4Address dst_addr;
}
struct headers_t {
ethernet_t ethernet;
ipv4_t ipv4;
}
struct metadata_t {
}
error {
IPv4IncorrectVersion,
IPv4OptionsNotSupported
}
state parse_ipv4 {
packet.extract(hd.ipv4);
verify(hd.ipv4.version == 4w4, error.IPv4IncorrectVersion);
verify(hd.ipv4.ihl == 4w5, error.IPv4OptionsNotSupported);
transition accept;
}
}
action drop_action() {
mark_to_drop(standard_metadata);
dropped = true;
}
table ipv4_match {
key = {
https://p4.org/p4/getting-started-with-p4.html 6/13
12/5/2019 Getting Started with P4
hdr.ipv4.dst_addr: lpm;
}
actions = {
drop_action;
to_port_action;
}
size = 1024;
default_action = drop_action;
}
apply {
ipv4_match.apply();
if (dropped) return;
}
}
V1Switch(my_parser(),
my_verify_checksum(),
my_ingress(),
my_egress(),
my_compute_checksum(),
my_deparser()) main;
This is an extremely simple program. It has a single lookup table, which does a longest-pre x-match (LPF)
on the destination IP address in the received packet. The action is either drop the packet, or forward the
packet to a speci c output port.
Note: Personally, instead of editing the les directly on the AWS instance, I prefer to run the Visual Studio
Code editor locally on my MacBook and use it to remotely edit the les on the AWS instance:
This compiler generates a directory test.bmv2 which contains a le test.json which the generated
“executable” code which is run by the software switch.
https://p4.org/p4/getting-started-with-p4.html 7/13
12/5/2019 Getting Started with P4
A veth interface is a virtual (i.e. fake) Ethernet interface on which an application (the software switch in
our case) can send and receive Ethernet packets in the same way a a real Ethernet interface. However, in
the case of a veth interface the packets do not go out a real Ethernet port. Instead, veth interfaces are
always created in pairs. We will create three pairs: veth0-veth1 , veth2-veth3 , and veth4-veth5 . When
the application sends packet on one veth interface it arrives on the other veth interface of the pair.
Create the three pairs of virtual Ethernet interfaces. We set the Message Transfer Unit (MTU) of each
interface to 9500 to allow us to send and receive jumbo packets. And we disable IPv6 on each interface to
stop the kernel from sending router solicitation and multicast listener reports (this does not prevent the
software switch from sending IPv6 packets over the interface).
In the rst SSH session start the software switch as a background process:
https://p4.org/p4/getting-started-with-p4.html 8/13
12/5/2019 Getting Started with P4
In the rst SSH session, start the software switch as a background process:
In the same SSH session, start the Command Line Interface (CLI) for the software switch:
simple_switch_CLI
At this point we have a running P4 software switch with 3 interfaces as shown in Figure 1.
RuntimeCmd: help
RuntimeCmd: show_tables
my_ingress.ipv4_match [implementation=None, mk=ipv4.dst_addr(lpm, 32)]
tbl_test87 [implementation=None, mk=]
The table_dump command shows the entries that we added to the table:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth3, link-type EN10MB (Ethernet), capture size 262144 bytes
https://p4.org/p4/getting-started-with-p4.html 11/13
12/5/2019 Getting Started with P4
sudo scapy
Using Scapy, inject a packet with destination IP address 11.11.1.1 into interface veth1:
>>> p = Ether()/IP(dst="11.11.1.1")/UDP()
>>> sendp(p, iface="veth1")
.
Sent 1 packets.
The packet arrives in the software switch on port 0 (interface veth0 ). It matches route 11.11.0.0/16 and is
forwarded to port 1 (interface veth2, which is connected to interface veth3).
In the second SSH session, where tcpdump is running, we can see that the packet arrived:
Back in the third SSH session, where scapy is running, send a packet with destination IP address 12.12.1.1
on interface veth0:
>>> p = Ether()/IP(dst="12.12.1.1")/UDP()
>>> sendp(p, iface="veth1")
.
Sent 1 packets.
This time, the packet is forwarded to port 2 (interface veth4, which is connected to interface veth5).
Tcpdump does not report any received packet because it is monitoring interface veth3 and not interface
veth5.
But the speci c trigger for rolling up my sleeves and getting my hands dirty writing an actual P4 program
was a series of seminars (https://github.com/brunorijsman/qutech-seminars) that I presented at QuTech
(https://qutech.nl/) at the Delft University of Technology (https://www.tudelft.nl/en/) (my alma mater) in the
Netherlands.
I presented these seminars to the physicists and mathematicians working on the Quantum Internet
(https://qutech.nl/roadmap/quantum-internet/). Most of the professors, postdocs, PhDs, and students
working in this group have a very strong background in physics and quantum mechanics, but less practical
experience in the eld of networking (they call it “classical networks” to distinguish it from “quantum
networks”). The purpose of these seminars was to bring them up to speed with basic concepts and recent
developments in the eld of classical networking.
Further reading
The P4-16 speci cation (https://p4.org/p4-spec/docs/P4-16-v1.1.0-spec.html)
The Portable Switch Architecture (PSA) speci cation (https://p4.org/p4-spec/docs/PSA-v1.1.0.html)
P4 tutorials (https://github.com/p4lang/tutorials/)
Simple switch tutorial (https://github.com/ja ngerhut/p4-guide/blob/master/README-using-
bmv2.md)
Scapy documentation (https://scapy.readthedocs.io/en/latest/)
(https://github.com/p4lang/) (https://twitter.com/p4lang/)
(https://www.youtube.com/channel/UCOQAFkDKucJWr-KafdJsdIQ)
(https://p4-lang.slack.com)
https://p4.org/p4/getting-started-with-p4.html 13/13