研究了好几天终于把P4编程环境成功搭建好,特此记录
安装时间:2020-10-29
主要参考P4官网github的安装流程
https://github.com/p4lang/tutorials/blob/master/vm/user-bootstrap.sh
参考神秘网友安装教程
https://www.tqwba.com/x_d/jishu/175044.html
参考jiang1436的博客运行P4案例程序
https://www.cnblogs.com/jiang1436/p/12055436.html
对以上教程进行一些补充
安装过程
编译环境
Ubuntu16.04(内核 4.10.0)
Python 2.7.12
pip 8.1.1 from /usr/lib/python2.7/dist-packages (python 2.7)
建议将虚拟机设置为4核 8G内存 以及足够多的硬盘空间 这样make命令可以改为make -j4加快速度
注意:一些安装过程中的报错可能是因为网络原因所导致,建议使用良好的网络来配置P4环境,以免出现一些意料之外的错误。
建立工作目录
mkdir ~/P4
cd ~/P4
echo "P4_HOME=$(pwd)" >> ~/.bashrc
source ~/.bashrc
安装依赖项
sudo apt-get update
sudo apt-get install automake cmake libjudy-dev libpcap-dev libboost-dev libboost-test-dev libboost-program-options-dev libboost-system-dev libboost-filesystem-dev libboost-thread-dev libevent-dev libtool flex bison pkg-config g++ libssl-dev -y
sudo apt-get install 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-scapy python-ipaddr python-ply tcpdump curl -y
sudo apt-get install libreadline6 libreadline6-dev python-pip -y
sudo pip install psutil
sudo pip install crcmod
设置版本信息
版本相当重要,每一步的checkout都十分关键,如果使用新的版本可能会出现各种问题,严格按照教程中使用2019的旧版本
P4_HOME=$HOME/P4
BMV2_COMMIT="b447ac4c0cfd83e5e72a3cc6120251c1e91128ab" # August 10, 2019
PI_COMMIT="41358da0ff32c94fa13179b9cee0ab597c9ccbcc" # August 10, 2019
P4C_COMMIT="69e132d0d663e3408d740aaf8ed534ecefc88810" # August 10, 2019
PROTOBUF_COMMIT="v3.2.0"
GRPC_COMMIT="v1.3.2"
Mininet部分
#--- Mininet ---
git clone git://github.com/mininet/mininet mininet
sudo ./mininet/util/install.sh -nwv
protobuf部分
git clone https://github.com/google/protobuf.git
cd protobuf
git checkout ${PROTOBUF_COMMIT}
./autogen.sh
./configure --prefix=/usr
Make
sudo make install
sudo ldconfig
# Force install python module
cd python
sudo python setup.py install
cd ../..
注意:
1.git checkout后可以使用git branch检查
2.若git clone https://github.com/google/protobuf.git 速度太慢可以改为git clone https://gitee.com/tonysw/protobuf.git
gRPC部分
git clone https://github.com/grpc/grpc.git
cd grpc
git checkout ${GRPC_COMMIT}
git submodule update --init —recursive
注意:
1.若git clone https://github.com/grpc/grpc.git速度过慢 可以改为 git clone https://gitee.com/tonysw/grpc.git
2.获取子模块时可能会出现关于 third_party/boringssl-with-bazel 链接失败问题,原因是资源网站被墙了无法访问。
解决方法:修改.gitmodules文件 将 third_party/boringssl-with-bazel 的url进行修改
新的url:

修改过后使用 git submodule sync 进行更新 ,这样url才会被正确的修改。
继续安装
make
sudo make install
sudo ldconfig
cd ..
# Install gRPC Python Package
sudo pip install grpcio
bmv2依赖
git clone https://github.com/p4lang/behavioral-model.git
cd behavioral-model
git checkout ${BMV2_COMMIT}
#From bmv2's install_deps.sh, we can skip apt-get install.
#Nanomsg is required by p4runtime, p4runtime is needed by BMv2...
tmpdir=`mktemp -d -p .`
cd ${tmpdir}
bash ../travis/install-thrift.sh
bash ../travis/install-nanomsg.sh
sudo ldconfig
bash ../travis/install-nnpy.sh
cd ..
sudo rm -rf $tmpdir
cd ..
PI部分
git clone https://github.com/p4lang/PI.git
cd PI
git checkout ${PI_COMMIT}
git submodule update --init --recursive
./autogen.sh
./configure --with-proto
make
sudo make install
sudo ldconfig
cd ..
正式安装bmv2
cd behavioral-model
./autogen.sh
./configure --enable-debugger --with-pi
make
sudo make install
sudo ldconfig
# Simple_switch_grpc target
cd targets/simple_switch_grpc
./autogen.sh
./configure --with-thrift
make
sudo make install
sudo ldconfig
cd ../../..
p4c部分
git clone https://github.com/p4lang/p4c
cd p4c
git checkout ${P4C_COMMIT}
git submodule update --init --recursive
mkdir -p build
cd build
cmake ..
make
sudo make install
sudo ldconfig
cd ../..
安装教程目录
git clone https://github.com/p4lang/tutorials
安装完成!
安装完成之后P4目录如下:
P4
├── behavioral-model ## BMv2 软件交换机
├── grpc ## 作为BMv2的依赖
├── mininet ## mininet 网络仿真
├── p4c ## p4c 编译器
├── PI ## PI P4 runtime库
├── protobuf ## 作为依赖
└── tutorials #### 教程目录,以及以后主要的学习,实验
实现tutorials中basic示例
进入 P4/tutorials/exercises/basic 目录
将basic.p4补充完整
完整代码如下:
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>
const bit<16> TYPE_IPV4 = 0x800;
/*************************************************************************
*********************** H E A D E R S ***********************************
*************************************************************************/
typedef bit<9> egressSpec_t;
typedef bit<48> macAddr_t;
typedef bit<32> ip4Addr_t;
header ethernet_t {
macAddr_t dstAddr;
macAddr_t srcAddr;
bit<16> etherType;
}
header ipv4_t {
bit<4> version;
bit<4> ihl;
bit<8> diffserv;
bit<16> totalLen;
bit<16> identification;
bit<3> flags;
bit<13> fragOffset;
bit<8> ttl;
bit<8> protocol;
bit<16> hdrChecksum;
ip4Addr_t srcAddr;
ip4Addr_t dstAddr;
}
struct metadata {
/* empty */
}
struct headers {
ethernet_t ethernet;
ipv4_t ipv4;
}
/*************************************************************************
*********************** P A R S E R ***********************************
*************************************************************************/
parser MyParser(packet_in packet,
out headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
state start {
transition parse_ethernet;
}
state parse_ethernet {
packet.extract(hdr.ethernet);
transition select(hdr.ethernet.etherType) {
TYPE_IPV4: parse_ipv4;
default: accept;
}
}
state parse_ipv4 {
packet.extract(hdr.ipv4);
transition accept;
}
}
/*************************************************************************
************ C H E C K S U M V E R I F I C A T I O N *************
*************************************************************************/
control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
apply { }
}
/*************************************************************************
************** I N G R E S S P R O C E S S I N G *******************
*************************************************************************/
control MyIngress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
action drop() {
mark_to_drop(standard_metadata);
}
action ipv4_forward(macAddr_t dstAddr, egressSpec_t port) {
standard_metadata.egress_spec = port;
hdr.ethernet.srcAddr = hdr.ethernet.dstAddr;
hdr.ethernet.dstAddr = dstAddr;
hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
}
table ipv4_lpm {
key = {
hdr.ipv4.dstAddr: lpm;
}
actions = {
ipv4_forward;
drop;
NoAction;
}
size = 1024;
default_action = drop();
}
apply {
if (hdr.ipv4.isValid()) {
ipv4_lpm.apply();
}
}
}
/*************************************************************************
**************** E G R E S S P R O C E S S I N G *******************
*************************************************************************/
control MyEgress(inout headers hdr,
inout metadata meta,
inout standard_metadata_t standard_metadata) {
apply { }
}
/*************************************************************************
************* C H E C K S U M C O M P U T A T I O N **************
*************************************************************************/
control MyComputeChecksum(inout headers hdr, inout metadata meta) {
apply {
update_checksum(
hdr.ipv4.isValid(),
{ hdr.ipv4.version,
hdr.ipv4.ihl,
hdr.ipv4.diffserv,
hdr.ipv4.totalLen,
hdr.ipv4.identification,
hdr.ipv4.flags,
hdr.ipv4.fragOffset,
hdr.ipv4.ttl,
hdr.ipv4.protocol,
hdr.ipv4.srcAddr,
hdr.ipv4.dstAddr },
hdr.ipv4.hdrChecksum,
HashAlgorithm.csum16);
}
}
/*************************************************************************
*********************** D E P A R S E R *******************************
*************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) {
apply {
packet.emit(hdr.ethernet);
packet.emit(hdr.ipv4);
}
}
/*************************************************************************
*********************** S W I T C H *******************************
*************************************************************************/
V1Switch(
MyParser(),
MyVerifyChecksum(),
MyIngress(),
MyEgress(),
MyComputeChecksum(),
MyDeparser()
) main;
在basic.p4文件所在目录下打开终端,输入make run编译运行


输入如下命令进行连通性测试,连通则补充正确,并查看网络拓扑结构


成功!