1. 安装ubuntu16.04(18.04)并更新依赖

# sudo apt 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 python-scapy -y 
 
# sudo pip install psutil
# sudo pip install crcmod

2. 执行安装脚本

#!/bin/bash
##############################################################
# author : P4 Lang
# modified by: SEU Hox Zheng
##############################################################
 
# 打印脚本命令.
set -x
# 在有错误输出时停止.
set -e
 
# 设置相关路径和版本变量
P4_HOME=$HOME/work/P4
BMV2_COMMIT="7e25eeb19d01eee1a8e982dc7ee90ee438c10a05"
PI_COMMIT="219b3d67299ec09b49f433d7341049256ab5f512"
P4C_COMMIT="48a57a6ae4f96961b74bd13f6bdeac5add7bb815"
PROTOBUF_COMMIT="v3.2.0"
GRPC_COMMIT="v1.3.2"
#获得cpu核数,与某些软件的编译选项相关
NUM_CORES=`grep -c ^processor /proc/cpuinfo`
 
cd $P4_HOME
# 安装Mininet
git clone https://github.com/mininet/mininet mininet
cd mininet
sudo ./util/install.sh -nwv
cd ..
 
# 安装Protobuf
git clone https://github.com/google/protobuf.git
cd protobuf
git checkout ${PROTOBUF_COMMIT}
export CFLAGS="-Os"
export CXXFLAGS="-Os"
export LDFLAGS="-Wl,-s"
./autogen.sh
./configure --prefix=/usr
make -j${NUM_CORES}
sudo make install
sudo ldconfig
unset CFLAGS CXXFLAGS LDFLAGS
# force install python module
cd python
sudo python setup.py install
cd ../..
 
# 安装gRPC
git clone https://github.com/grpc/grpc.git
cd grpc
git checkout ${GRPC_COMMIT}
git submodule update --init --recursive
export LDFLAGS="-Wl,-s"
make -j${NUM_CORES} #CFLAGS='-Wno-implicit-fallthrough'
sudo make install
sudo ldconfig
unset LDFLAGS
cd ..
# Install gRPC Python Package
sudo pip install grpcio
 
# 安装BMv2的依赖,下面PI编译时会用到。
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/P4Runtime
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 -j${NUM_CORES}
sudo make install
sudo ldconfig
cd ..
 
# 安装Bmv2  
cd behavioral-model
./autogen.sh
./configure --enable-debugger --with-pi
make -j${NUM_CORES}
sudo make install
sudo ldconfig
# Simple_switch_grpc target
cd targets/simple_switch_grpc
./autogen.sh
./configure --with-thrift
make -j${NUM_CORES}
sudo make install
sudo ldconfig
cd ..
cd ..
cd ..
 
# 安装P4C,省去了check步骤(太费时间了)
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 -j${NUM_CORES}
sudo make install
sudo ldconfig
cd ..
cd ..
 
# 最后获得p4 tutorials
git clone https://github.com/p4lang/tutorials

3. 安装过程中排错

# grpc编译错误:把Makefile 339行中 -Werror去掉
# CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1
# CPPFLAGS += -g -Wall -Wextra -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1

4. 说明

目录结构

P4
├── behavioral-model  ## BMv2 软件交换机
├── grpc              ## 作为BMv2的依赖
├── mininet           ## mininet 网络仿真
├── p4c		      ## p4c 编译器
├── PI                ## PI P4 runtime库
├── protobuf          ## 作为依赖
└── tutorials         #### 教程目录,以及以后主要的学习,实验

我们主要的工作目录时tutorials,其余的都是被使用的工具组件。细看tutorials:

tutorials/
├── exercises   # 存放各种练习
├── utils       # 工具脚本目录
└── vm          # 用于vagrant构建虚拟机的目录,可以无视

其中utils里面存放了一些用于调用各个组件(mininet, bmv2, PI, p4c)的脚本, 有了这些脚本,我们可以专注于p4代码的开发,控制面的编写,以及拓扑的构建, 而不需要费神去了解bmv2的启动命令,p4c的调用选项等等。 具体如何使用,也是非常的简单,我们进入一个具体的例子查看:

# 我们切换进入 exercises/basic 这个例子
basic
├── basic.p4   # 要编写的p4代码
├── build      # 生成文件的目录
├── logs       # 日志文件, 在调试的时候真的非常重要!
├── Makefile   ### 通过Makefile 来调用utils下的脚本!
├── pcaps      # 生成的pcap包,可以使用wireshark等工具来分析
├── README.md  # 详细的指导
├── receive.py ## 利用scapy写的抓取和分析数据包的工具
├── s1-runtime.json  #
├── s2-runtime.json  # 在运行同时加载入交换机的控制面代码,这里有争议,稍后再谈
├── s3-runtime.json  #
├── send.py    ## 利用scapy写的构建和发送数据包的工具
├── solution   # 这里有这个例子的示例代码(答案)
└── topology.json  # 描述拓扑的json文件

可以看到,通过Makefile,我们可以调用utils下的脚本,让我们的p4代码跑起来:

make run  # 启动命令
### ...启动过程中的输出

mininet>  # mininet 命令行
### ... 你的一些实验操作
mininet> exit  # 退出mininet 命令行
make clean # 清理上次运行留下的缓存文件和遗留的进程,重要,否则下次运行会可能使用旧的代码。

调用make run,我们可以运行当前目录下(以basic目录为例)的代码,它将执行以下几个步骤:

  • 编译basic.p4 代码,生成basic.json
  • 解析topology.json, 并且构建相应的mininet仿真拓扑,按照该拓扑启动一台或者多台BMv2交换机,以及一些host
  • 启动BMv2的同时会将p4代码编译产生的json文件导入
  • 启动BMv2后会解析 sN-runtime.json 文件,将其载入 交换机sN流表之中
  • 进入mininet命令行,同时开始记录log以及搜集pcap文件

在新版本的tutorials中,载入静态流表项时采用了runtime方法,而非之前的CLI方法,我们查看一下s1-runtime.json的部分

...
{
      "table": "MyIngress.ipv4_lpm",
      "match": {
        "hdr.ipv4.dstAddr": ["10.0.1.1", 32]
      },
      "action_name": "MyIngress.ipv4_forward",
      "action_params": {
        "dstAddr": "00:00:00:00:01:01",
        "port": 1
      }
}
...

这是一个json文件,可以看到,其作用是定义一个个具体的流表项, 标明了流表项所处的位置,匹配域,匹配模式,动作名,以及动作参数。 这些字段都依赖于我们P4代码中所自定义的流表,匹配域和动作。

5. P4相关资料

https://github.com/p4lang/

https://www.sdnlab.com/17882.html

https://www.sdnlab.com/17795.html