【P4lang】P4环境配置及编译

作者对文中所写内容也是才开始了解,参考了不少网络资料。如有错误,会进行修正。

安装VMVare

这一步比较容易,直接去VmWare官网 https://www.vmware.com/cn.html
如果需要注册码,百度搜一下就行。

安装教程:https://blog.csdn.net/qq_43800119/article/details/123375502

安装CentOS8虚拟机

centos镜像下载地址
http://mirrors.aliyun.com/centos/8/isos/x86_64/
选择DVD版本(标准版本),最大的那个。

1. 打开VmWare,新建虚拟机

新建虚拟机

不断下一步就行(过程图没有保存)

2. 安装成功

在这里插入图片描述

3. 配置网络连接(不要忘记这一步)

在这里插入图片描述

安装Docker

注:p4编译官方是基于ubuntu的,但是被要求使用centos,按照各个教程都没法配置成功,所以出此下策。

1. 下载Docker

安装教程参考https://blog.csdn.net/qq_39505065/article/details/106986475

2. 检查Docker是否安装成功

docker version

在这里插入图片描述

3. 打开docker

	service docker start

4. 查看镜像列表

	docker images

拉取镜像

1. 拉取镜像

	docker pull p4lang/p4c

注:镜像地址 https://registry.hub.docker.com/r/p4lang/p4c

2. 运行p4c镜像

	 docker run --cap-add NET_ADMIN -it --rm p4c /bin/bash

注: 其中 –cap -addNET_ADMIN是要加上的,后面sudo那部分才不会出错

在这里插入图片描述

参考 http://hustcat.github.io/docker-config-capabilities/
● 打开指定版本镜像方法,把p4c改成p4c:tag

3. 查看镜像列表

 	docker images

在这里插入图片描述

实践(Hello world)

参考: https://www.sdnlab.com/24136.html

1. 首先更新vim等工具

apt-get update  
apt-get install
sudo apt-get install vim 
sudo apt-get install ping 

2. 新建文件

vim test.p4

test.p4内容如下

#include <core.p4>
#include <v1model.p4>

typedef bit<48> EthernetAddress;
typedef bit<32> IPv4Address;

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
}

parser my_parser(packet_in packet,
                out headers_t hd,
                inout metadata_t meta,
                inout standard_metadata_t standard_meta)
{
    state start {
        packet.extract(hd.ethernet);
        transition select(hd.ethernet.ether_type) {
            0x0800:  parse_ipv4;
            default: accept;
        }
    }

    state parse_ipv4 {
        packet.extract(hd.ipv4);
        verify(hd.ipv4.version == 4w4, error.IPv4IncorrectVersion);
        verify(hd.ipv4.ihl == 4w5, error.IPv4OptionsNotSupported);
        transition accept;
    }
}

control my_deparser(packet_out packet,
                   in headers_t hdr)
{
    apply {
        packet.emit(hdr.ethernet);
        packet.emit(hdr.ipv4);
    }
}

control my_verify_checksum(inout headers_t hdr,
                         inout metadata_t meta)
{
    apply { }
}

control my_compute_checksum(inout headers_t hdr,
                          inout metadata_t meta)
{
    apply { }
}

control my_ingress(inout headers_t hdr,
                  inout metadata_t meta,
                  inout standard_metadata_t standard_metadata)
{
    bool dropped = false;

    action drop_action() {
        mark_to_drop(standard_metadata);
        dropped = true;
    }

    action to_port_action(bit<9> port) {
        hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
        standard_metadata.egress_spec = port;
    }

    table ipv4_match {
        key = {
            hdr.ipv4.dst_addr: lpm;
        }
        actions = {
            drop_action;
            to_port_action;
        }
        size = 1024;
        default_action = drop_action;
    }

    apply {
        ipv4_match.apply();
        if (dropped) return;
    }
}

control my_egress(inout headers_t hdr,
                 inout metadata_t meta,
                 inout standard_metadata_t standard_metadata)
{
    apply { }
}

V1Switch(my_parser(),
         my_verify_checksum(),
         my_ingress(),
         my_egress(),
         my_compute_checksum(),
         my_deparser()) main;

3. 编译文件

p4c -b bmv2 test.p4 -o test.bmv2 

查看目录ls,已经生成test.bmv2

在这里插入图片描述
注:
-b:指定 target
-o:指定输出路径

4. 构建网络拓扑

在这里插入图片描述

	sudo ip link add name veth0 type veth peer name veth1
	sudo ip link set dev veth0 up
	sudo ip link set dev veth1 up
	sudo sysctl net.ipv6.conf.veth0.disable_ipv6=1
	sudo sysctl net.ipv6.conf.veth1.disable_ipv6=1

	sudo ip link add name veth2 type veth peer name veth3
	sudo ip link set dev veth2 up
	sudo ip link set dev veth3 up
	sudo sysctl net.ipv6.conf.veth2.disable_ipv6=1
	sudo sysctl net.ipv6.conf.veth3.disable_ipv6=1

	sudo ip link add name veth4 type veth peer name veth5
	sudo ip link set dev veth4 up
	sudo ip link set dev veth5 up
	sudo sysctl net.ipv6.conf.veth4.disable_ipv6=1
	sudo sysctl net.ipv6.conf.veth5.disable_ipv6=1 

5. 启动switch_simple交换机

sudo simple_switch --interface 0@veth0 --interface 1@veth2 --interface 2@veth4 test.bmv2/test.json &

接下来通过simple_switch_CLI程序来控制该P4软件交换机

6. 向交换机的路由表下发路由

启动交换机

simple_switch_CLI	

在这里插入图片描述

查看当前所有表

show_tables		

在这里插入图片描述查看指定表的信息

table_info ipv4_match

在这里插入图片描述

接下来就是控制平面,使用 table_add 命令向交换机添加路由。假设:
port 0(veth 0)连接 10.10.0.0/16 网段
port 1(veth 2)连接 20.20.0.0/16 网段
port 2(veth 4)连接 30.30.0.0/16 网段

输入如下命令

table_add ipv4_match to_port_action 10.10.0.0/16 => 0
table_add ipv4_match to_port_action 20.20.0.0/16 => 1
table_add ipv4_match to_port_action 30.30.0.0/16 => 2


使用命令table_dump确定添加的表项

table_dump ipv4_match

在这里插入图片描述

7. 测试交换机的三层转发

首先新建控制台窗口,即同一容器多个界面

docker exec -it fc9942741dca /bin/bash

注:docker exec -it /bin/bash 其中<>里面是容器id

首次使用scapy,请先安装依赖

sudo apt-get install scapy

启动scapy

sudo scapy

在这里插入图片描述
开始测试前veth3和veth5抓包情况——都没有包

sudo tcpdump -n -i veth3
sudo tcpdump -n -i veth5

在这里插入图片描述
使用 scapy 工具从 veth1 注入目的地为 20.20.0.1 的报文

p = Ether()/IP(dst="20.20.0.1")/UDP()      
sendp(p,iface="veth1")

在这里插入图片描述
抓包——三个窗口同时运行截图:scapy发送两个包,veth3都收到了,veth5无变化。

sudo tcpdump -n -i veth3
sudo tcpdump -n -i veth5

在这里插入图片描述

使用scapy从 veth1 注入目的地为 30.30.0.1 的报文

p = Ether()/IP(dst="30.30.0.1")/UDP()      
sendp(p,iface="veth1")

在这里插入图片描述
抓包——运行截图,scapy从veth1发送包,veth5收到,veth3没变化。

sudo tcpdump -n -i veth3
sudo tcpdump -n -i veth5

在这里插入图片描述
最后!保存容器
这一步真的很重要,要不然一切工具安装与更新都作废!

docker commit 容器id demo:v1.0  

demo:v1.0是想存储名字:版本号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zoetu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值