ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P4基础

2022-05-23 13:03:17  阅读:253  来源: 互联网

标签:hdr P4 基础 packet parse ipv4 ethernet metadata


basic实验

步骤 1:运行(不完整的)初学者代码

h1 ping h2 失败

图片1.png

pingall 失败

图片2.png

步骤 2:实现 L3 转发

Parser解析数据包

从start状态开始,每一个状态便解析一种协议,然后根据低层协议的类型字段,选择解析高一层协议的状态,然后transition到该状态解析上层协议,最后transition到accept。

parser MyParser(packet_in packet,
                out headers hdr,	//out相当于输出的数据,type是headers
                inout metadata meta,	//inout同时作为输入和输出值,类似c++里面的引用
                inout standard_metadata_t standard_metadata) {

    state start {//①
        transition parse_ethernet;      //转移到parse_ethernet状态(解析以太网包头)
    }

    state parse_ethernet {
        packet.extract(hdr.ethernet);   //提取以太网包头
        transition select(hdr.ethernet.etherType) { //根据etherType的值(协议类型)选择下一个状态
            //类似switch...case
            TYPE_IPV4: parse_ipv4;      //转换到parse_ipv4状态(解析ip包头)
            default: accept;            //默认是接受,进入下一步处理
        }  
    }

    state parse_ipv4 {
        packet.extract(hdr.ipv4);       //提取ip包头
        transition accept;              //接受,进入下一步处理
    }

}

Ingress输入处理

定义一个用于转发的流表,定义匹配域和动作。

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;               //递减生存时间TTL
    }

    table ipv4_lpm {
        key = {                        //匹配域
            hdr.ipv4.dstAddr: lpm;     //匹配字段是数据包头部字段中的ipv4头部的目标地址
                                       //lpm是最长前缀匹配 
        }
        actions = {                    //动作类型集合
            ipv4_forward;              //自定义的转发动作
            drop;                      //丢弃动作
            NoAction;                  //空动作
        }
        size = 1024;                   //流表可以容纳多少流表项
        default_action = drop();       //默认是丢弃
    }

    apply {//③
        if (hdr.ipv4.isValid()) { 
            ipv4_lpm.apply();          //仅当解析成功时,应用ipv4_lpm
        }
    }

}

Deparser逆解析器

control MyDeparser(packet_out packet, in headers hdr) {
    apply {//④
        packet.emit(hdr.ethernet);      //按顺序,发射
        packet.emit(hdr.ipv4);
    }
}

步骤 3:运行解决方案

h1 ping h2 成功

图片3.png

pingall 成功

图片4.png

basic_tunnel实验

步骤 1:实现基本隧道

Parser解析数据包

parser MyParser(packet_in packet,
                out headers hdr,	//out相当于输出的数据,type是headers
                inout metadata meta,	//inout同时作为输入和输出值,类似c++里面的引用
                inout standard_metadata_t standard_metadata) {

    state start {
        transition parse_ethernet;      //转移到parse_ethernet状态(解析以太网包头)
    }

    state parse_ethernet {
        packet.extract(hdr.ethernet);   //提取以太网包头
        transition select(hdr.ethernet.etherType) { //根据etherType的值(协议类型)选择下一个状态
            //类似switch
            TYPE_MYTUNNEL: parse_myTunnel; //转移到parse_myTunnel状态(隧道)
            TYPE_IPV4: parse_ipv4;      //转换到parse_ipv4状态(解析ip包头)
            default: accept;            //默认是接受,进入下一步处理
        }  
    }

    state parse_myTunnel {//①
        packet.extract(hdr.myTunnel);
        transition select(hdr.myTunnel.proto_id) {
            TYPE_IPV4: parse_ipv4;
            default: accept;
        }
    }

    state parse_ipv4 {
        packet.extract(hdr.ipv4);       //提取ip包头
        transition accept;              //接受,进入下一步处理
    }

}

Ingress输入处理

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;               //递减生存时间TTL
    }

    table ipv4_lpm {
        key = {                        //匹配域
            hdr.ipv4.dstAddr: lpm;     //匹配字段是数据包头部字段中的ipv4头部的目标地址
                                       //lpm是最长前缀匹配 
        }
        actions = {                    //动作类型集合
            ipv4_forward;              //自定义的转发动作
            drop;                      //丢弃动作
            NoAction;                  //空动作
        }
        size = 1024;                   //流表可以容纳多少流表项
        default_action = drop();       //默认是丢弃
    }

    //②将出口端口号设置为控制平面提供的端口号
    action myTunnel_forward(egressSpec_t port) {
        standard_metadata.egress_spec = port;
    }

    //③如果表中myTunnel_forward存在匹配项,则该表应调用该drop动作,否则应调用该动作。
    table myTunnel_exact {
        key = {
            hdr.myTunnel.dst_id: exact;//要匹配的动作和模式,exact是精准匹配
        }
        actions = {                    //可选动作
            myTunnel_forward;
            drop;
        }
        size = 1024;
        default_action = drop();       //默认是丢弃
    }

    apply {//④
        if (hdr.myTunnel.isValid()) {   //隧道包
            myTunnel_exact.apply();
        }
        else if (hdr.ipv4.isValid()) {  //ipv4包
            ipv4_lpm.apply();
        }
    }

}

Deparser逆解析器

control MyDeparser(packet_out packet, in headers hdr) {//⑤
    apply {
        packet.emit(hdr.ethernet);      //按顺序,发射
        packet.emit(hdr.myTunnel);      //加上隧道包
        packet.emit(hdr.ipv4);
    }
}

步骤 2:运行解决方案

(1)h1运行 ./send.py 10.0.2.2 "P4 is cool" ,只设置IPv4转发,h2成功接收,并且含有ip头;

(2)h1运行 ./send.py 10.0.2.2 "P4 is cool" --dst_id 2 ,同时设置IPv4转发和隧道转发,目标都是h2,h2成功接收,并且包头解析到隧道信息;

(3)h1运行 ./send.py 10.0.3.3 "P4 is cool" ,同时设置IPv4转发给h3和隧道转发给h2,验证转发优先级,结果h2成功接收,并且包头解析到隧道信息,而h3不会接收;

思考

1.如果将basic和basic_tunnel项目文件移出tutorials/exercise目录,能否继续运行?如果不能运行,怎样才能运行。

5.png

不能。因为 basic 和 basic_tunnel 项目文件的 Makefile 中使用了include ../../utils/Makefile,include 关键字的含义是把别的 Makefile 文件包含进来,而将 basic 和 basic_tunnel 项目文件移出 tutorials/exercise目录,此处引用的 Makefile 的路径出现错误。根据路径进一步查看 tutorials/utils/Makefile 文件,由于 basic 项目中的 Makefile 文件已有 TOPO 的另行定义,因此会覆盖此处 TOPO=topology.json 的定义。而 RUN_SCRIPT 涉及 run_exercise.py ,需要将该 python 代码运行所需的相关包文件全部拷贝。

图片1.png

图片2.png

新建一个 p4examples 目录,把 tutorials/exercise/basic/ 整体拷入,将原有拓扑文件整合到新建的 topo 目录,修改 topology.json 文件中每台交换机配置文件的目录,以s1交换机为例,改成 “topo/s1-runtime.json”,新建 script 目录,整合所需要构建的包含P4交换机的网络拓扑的 Python 代码,并修改 Makefile 文件。如此,在 p4examples/basic 目录下即可运行成功。

2.阅读basic实验提供的send.py和receive.py脚本,分析程序导入的python包scapy,说明各自的实现逻辑是什么样的?

send.py:

①首先使用 gethostbyname() 函数,用域名或主机名获取IP地址;
②使用自定义的 get_if() 函数获取源主机的发送端口,作为发送数据的端口;
③使用 Ether() 函数设置发送方和接收方的 MAC 地址;
④使用 IP() 和 TCP() 构造一个 HTTP 数据包;
⑤最后使用 sendp() 函数发送 Ether 数据包。

receive.py:

①使用 os.listdir() 返回 /sys/class/net/ 列表中包含 “eth” 的名称,即物理网卡、子网卡、虚拟VLAN网卡,赋值给ifaces;iface为ifaces中第0个元素;
②使用sys.stdout.flush()显示地让缓冲区的内容输出;
③sniff(iface = iface,prn = lambda x: handle_pkt(x))对于指定的网络接口进行抓包。同时prn定义回调函数handle_pkt(),当符合filter的流量被捕获时,就会执行回调函数,把收到的包里面的东西立刻打印出来。

3.同样的拓扑在传统网络中是如何实现IPv4转发的,网关在这当中起到了什么作用,basic实验项目的相关流规则设置是如何应用的?

pod-topo.png

IPv4转发的实现:

主机 ( h1, h2, h3, h4) 发送数据报,交换机 ( s1, s2, s3, s4) 对数据报进行转发。具体过程如下:
①主机发送 ARP 广播获取网关 MAC 地址;
②交换机形成该主机的 MAC 表项,并用网关 MAC 地址回应该主机的 ARP 请求;
③该主机把网关 MAC 地址当作目的主机的 MAC 地址,来访问目的主机;
④交换机接收到一个数据报,将这个数据报头部的目的 MAC 信息提取出来,与自身的 MAC 地址表比较:如果找到对应项,则按 MAC 表进行转发;如果没找到对应项,则在除了接收到数据包以外的所有端口进行转发(广播)。

网关的作用:

连接相同或不同类型网络,并且能找到网络中数据传输最合适的路径,即路由选择。

相关流规则设置的应用:

载入静态流表项时采用 runtime 方法:在 sx-runtime.json 文件中,定义一个个具体的流表项,标明了流表项所处的位置,匹配域,匹配模式,动作名,以及动作参数。而这些字段依赖于 P4 代码中Ingress 输入处理模块所自定义的流表,匹配域和动作。

图片1.png

标签:hdr,P4,基础,packet,parse,ipv4,ethernet,metadata
来源: https://www.cnblogs.com/dump16/p/16300803.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有