• P4语法(1)基础数据类型和Header


    文章学习自:P4语言编程详解
    由于原文有一点的年份,所以也继续阅读了相关的最新规范。
    P4语言规范


    基础数据类型

    布尔型(bool)

    运算符 描述
    and 双目运算符,结果为布尔型
    or 双目运算符,结果为布尔型
    not 单目运算符,结果为布尔型
    ==,!= 相等或不等,结果为布尔型

    无符号整型(bit)

    又称之为位串(bit-string),对位串进行数学运算的时候,位串长度必须是8的整数倍。

    运算符 描述
    ==,!= 是否相等或不等,运算结果为布尔型。
    <,>,<=,>= 无符号数比较,操作数的长度(W)要求相同,运算结果为布尔型。
    &,|,^ 按位运算符(分别是与,或和异或),操作数的长度(W)要求相同,运算结果为无符号整型。
    运算结果为操作数的补码。
    <<,>> 左移运算符操作数为无符号整型,右移运算符操作数必须是无符号数或非负整数。此运算符为逻辑位移。
    +(单目) 单目加运算,效果同no-op。(无意义)
    -(单目) 单目减运算,计算结果为2W减去操作数,W为操作数长度。
    +(双目) 二目加运算,操作数的长度(W)要求相同。计算结果为操作数的算术和,且运算结果长度也必须为W,超过则截断。
    -(双目) 二目减运算,操作数的长度(W)要求相同。计算结果为操作数的算术差。
    * 无符号乘法运算,操作数的长度(W)要求相同,计算结果为无符号数且长度与操作数相等。

    有符号整数型(int(W))

    大致与无符号整数相同

    运算符 描述
    -(单目) 单目减运算,运算结果伟有符号整型,长度和操作数相等
    +(双目) 二目加运算,操作数数据类型必须相同,运算结果也为同类型。
    -(双目) 二目减运算,操作数数据类型必须相同,运算结果也为同类型。
    * 有符号乘法运算,操作数的长度(W)要求相同,计算结果为有符号数且长度与操作数相等。

    变长位串(varbit)

    该数据类型,不支持算术、比较和位运算,也不支持类型转换,该数据类型在定义时会指定一个静态的最大宽度值,解析器会提取变长位串数据并设置一个值作为长度。

    无限精度整型(int)

    运算符 描述
    ==,!= 是否相等或不等,运算结果为布尔型。
    <,>,<=,>= 有符号数比较,运算结果为布尔型。
    <<,>> 右移运算符操作数必须为正整数;左移运算结果和操作数相同。a<<b等价于ax2b,a>>b等价于a/2b。
    +(单目) 单目加运算,效果同no-op。(无意义)
    -(单目) 单目减运算,运算结果为整型,且该运算不会导致溢出。
    +(双目) 二目加运算,操作数类型都必须是整型,运算结果为整型,且该运算不会导致溢出。
    -(双目) 二目减运算,操作数类型都必须是整型,计算结果为整型,且该运算不会导致溢出。
    * 无符号乘法运算,操作数必须都是整形,计算结果为整形,该运算不会导致溢出。
    /,% 二目有符号除法和取模运算,操作数必须是正整数,运算结果为正整数。

    数据类型转换

    可以看出,上述的很多运算都是建立在相同数据类型的前提下,但是对于某些数据类型是不能相互转换的,p4也提供了合法的数据类型转换。

    from to 描述
    bit<1> bool 0代表false,1代表true(中括号里的1代表的是字节数,不是0和1,下同)
    bool bit<1> 同上
    bit<w> int<w> 保留所有比特位不变
    int<w> bit<w> 同上
    bit<w> bit<w> 当w>w1时,保留低位w1位长度的数据,小于时新增位补0
    int<w> int<w> 当W>W1时,保留低位W1长度的数字,当W<W1时新增位补符号位.(补符号位?)
    int bit<w> 保留低位W位长度数据,溢出需要发出警告并转化为负数。
    int intt<w> 保留低位W位长度数据,溢出需要发出警告。

    这些属于显式类型转换,p4中同样存在隐式类型转换,在运算中会进行强制转换,这个和大部分语言类似。也容易发生溢出错误。


    基础语言组件

    之前有学到过,p4程序主要由五个组建构成:header,parser,table,action,和controller

    这个类似于固定属性一样的东西,有多个成员字段,Header分为两种,一种是包头(Packet Header),一种是元数据(Metadata)。

    包头

    ipv4例子

    header ipv4_t{
        fields{
            version:4;
            ihl:4;
            diffserv:8;
            totallen:16;
            identification:16;
            flags:3;
            fragoffset:13;
            ttl:8;
            protocol:8;
            hdrchecksum:16;
            srcaddr:32;
            dstaddr:32;
            option:*;
        }
    }
    

    里面的数字都是以bit为单位的,所以其实应该也能写成这样。

    header ipv4_t{
        field{
            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;
            bit<32> srcaddr;
            bit<32> dstaddr;
        }
    }
    

    类比写下ipv6的

    header ipv6_t{
        field{
            bit<4> version;
            bit<8> trafficclass;//这个在ipv6中类似于ipv4的diffserv。
            bit<20> flowlabel;
            bit<20> payloadlen;
            bit<8> nxthdr;
            bit<8> hoplimit;
            bit<128> srcaddr;
            bit<128> dstaddr;
            
        }
    }
    

    元数据

    元数据是用来携带数据和配置性和西,元数据的申明与包头类似,但在实例化的时候有所不同,而且包头和元数据在字段值的约束上存在一定的差别。元数据分为两种,一种是用来携带P4程序运行过程中产生的数据的用户自定义元数据(User-Defined Metadata),如首部字段的运算结果等。另一种是固有元数据(Intrinsic Metadata),用于携带交换机自身的配置信息,如数据包进入交换机时的端口号等。

    struct ingress_metadata_t{
    
    }
    metadate ingress_metadata_t ingress_metadata;
    

    有8种固有元数据,这些元数据携带了数据包相关的状态信息。

    字段 描述
    ingress_port 数据包的入端口,解析之前设置,只读
    packet_length 数据包的字节数,当交换机在快速转发模式下,该元数据不能在动作(action)中匹配或引用。只读。
    egress_spec 在入端口流水线的匹配-动作过程之后设置,指定数据包出端口,可以是物理端口、逻辑端口或者多播组。
    egress_instance 用于区分复制后数据包实例的标识符。只读。
    instance_type 数据包实例类型:正常(Normal)、入端口复制(ingress clone)、出端口复制(egress clone)、再循环(recirculated)。
    parser_sratus 解析器解析结果,0表示无错误,其实数字代表了对应的错误类型。
    parser_error_location 指向P4程序错误发生处。

    注意点:

    • 包头类型的长度需要字节对齐,即长度必须是8bit的整数倍。
    • 包头中字段长度可以是可变值,也可以是首部中其他字段值计算后的值。而元数据中的字段长度只能是定值。
    • 只有包头能够实例化成数组,元数据则不行。
    • 实例化时,首部中已定义名称的字段的值会被初始化成程序中的指定值,如果首部中只定义字段名称而未指定值,字段的值将会被初始化成0。
  • 相关阅读:
    在IIS上搭建WebSocket服务器(一)
    ngnix 一 入门指南
    博客园的打赏功能
    Java基础(十)内部类
    Java虚拟机之垃圾回收详解一
    Servlet问题:servlet cannot be resolved to a type解决办法
    WIN7局域网文件共享设置方法
    基于tcp的socket通信
    java基础之抽象类的介绍
    Hdfs详解
  • 原文地址:https://www.cnblogs.com/pullself/p/10362254.html
Copyright © 2020-2023  润新知