zoukankan      html  css  js  c++  java
  • 【P4语言学习】Parser解析器

    参考文章:王垠:谈谈Parser

    簡單介紹 P4 語言(一)- Parser

    什么是Parser

    传统的parser,一般出现在编译器和编译原理课程中,援引《谈谈Parser》的定义:

    首先来科普一下。所谓 parser,一般是指把某种格式的文本(字符串)转换成某种数据结构的过程。最常见的 parser,是把程序文本转换成编译器内部的一种叫做“抽象语法树”(AST)的数据结构。也有简单一些的 parser,用于处理 CSV,JSON,XML 之类的格式。
    

    也就是说,parser 是编译器用来 将人们编写的程序代码,转换成编译器读的懂的代码 的工具,parsing 是这个过程。
    机器本身能够读懂的代码,往往具有复杂的逻辑数据结构,不能直接读懂程序员写的代码,这个时候就需要parser了。

    那么在P4语言中的parser,我认为和编译过程中的parser相类似:数据包到达Switch的时候,并不能马上进行Match-Action匹配,需要 parser解析器 进行处理加工成MA单元能够匹配的程序。那么这个过程,可以通过P4程序代码的Parser模块进行定义。

    P4中的Parser

    P4中的Parser解析器模块,包括两个方面:
    (1)Header,说明底层解析器解析数据报的时候,有哪些格式(字段长度,值限制等等)的Header可以使用,这些格式下Header的处理细节是什么。
    (2)Parser,说明处理该格式Header下的解析工具。

    Header定义代码:

    header_type ethernet_t {        //header类型:以太网类型
        fields {                    //域
            dst_addr : 48;          //目的地址字段长度:48bit
            src_addr : 48;          //源地址字段长度:48bit
            ether_type : 16;        //以太网类型字段长度:16bit
        }
    }
    

    Header实例化代码:

    header ethernet_t ethernet;
    

    Header可以类比为C语言中的Structure,在以太网格式域内,将一些特定属性(字段字节长度)说明清楚。
    我们可以写一个独立的说明Header的p4程序,并将它include到比较重要的p4程序中。
    也就是说,定义的时候说明一些固有属性;那么我们要使用它的时候,就需要把它实例化出来了。

    类比,C语言中的Structure定义如下:

    struct Node{
        int data;
        Node* next;
    }
    

    实例化如下:

    struct Node n;
    

    类比之后,就发现其实不难理解。Header实例化的过程,也可以叫做 header instance。

    Parser

    parser也一样,可以在一个p4程序里面(比如命名为parser.p4)定义,方便编程重构。

    按照我的理解,parser工具和工具之间有相互调用的关系,可以通过类似if-else的逻辑判断选用何种parser。

    在P4程序中,永远有一个起始的parser,和一个结束的节点。
    起始parser,我们叫做start:

    parser start {
        return next_parser;    //next_parser 特定协议格式的parser
    }
    

    终止节点,一般是:

    return ingress;
    

    结束解析器处理阶段,来到Match-Action的Ingress阶段。

    援引《简单介绍 P4语言》的这段话:

    在每一個 parser 中都會依據目前所分析的內容來決定下一個 parser,直到回傳的內容為 “ingress”(或其他 control function) 為止.
    

    这个目前所分析的内容,我认为是协议类型,当前所要处理的数据报的协议类型(比如IPv4,比如Ethernet等等)决定了要使用的下一个parser工具。
    当最后return ingress进入Ingress阶段,或者其他功能模块的时候,结束parsing解析过程。

    代码分析(以 处理IPv4数据报 为例):

    parser start {                //parsing,开始调用parser工具。
        return parse_ethernet;    //当前处理的是以太网协议字段,调用处理以太网的parser。
    }
    
    parser parse_ethernet {       //处理以太网协议的parser
        extract(ethernet);        //extract,parser工具解析 格式为以太网的Header实例ethernet。
        return select(latest.ether_type) {        //select,类似if-else的逻辑判断,判断条件是以太网字段的长度,根据判断条件决定调用何种工具。
            0x0800 : parse_ipv4;                  //latest.ether_type : 0x0800 ---> 调用处理Ipv4的parser。
            default : ingress;                    //latest.ether_type 属性不为 0x0800 ---> 调用ingress,结束解析。
        }
    }
    
    parser parse_ipv4 {            //处理Ipv4协议的parser。
        extract(ipv4);             //解析Ipv4协议。
        return ingress;            //调用ingress,结束。
    }
    
    
    這邊有幾個需要補充的東西:
    
       1) extract : 將目前的 Packet 以特定的 header 取出來,取出來的資料長度以 header 定義的為主
       2) return : 透過 return 的方式決定要前往哪個 parser、control function(後面會補充),可以直接 return 或是使用 select。
       3) select(select_exp) : 蠻像 C 語言中的 switch case,依據特定的 field 數值去決定要哪一個 parser 或是 control function。
       4) select_exp : 依據 spec,他可以是:
          *  field_ref : 如 ethernet.ether_type
          *  latest.field_name : 以最後 extract 的 header 為主,取用他的 field
          *  current (offset, length) : 以目前的 packet offset 位置開始某固定長度所取得的數值。
    
    

    说明一下 select(select_exp),我们可以根据Header的某些特定属性,来决定调用何种parser。这个属性可以是前面提到的 1)当前parser所处理的协议,所属的Header域属性,也可以是 2)最后解析的Header的域(不一定是当前处理的),还可以是 3)current,参考上文。
    类比于C语言中的if-else,就很好理解了。

    parser 异常处理 exception

    parser 也提供了异常处理exception,格式如下:

    parser_error parser_exception_name;
    

    parser_exception_name 有很多种,比如 p4_pe_out_of_packet 等等。

    如果我们要执行一个exception,我们需要先定义好 exception handler。

    parser_exception p4_pe_out_of_packet {
        /* statements */
        /* return or parser_drop */
    }
    

    处理一个exception的方法有很多,但是最后的结果只会有两个,(1)运行指定的function,(2)将该包drop掉。

    Egress阶段

    与Ingress之前的解析器处理阶段相对应的是 Match-Action 的动作逻辑阶段,需要把Ingress时做的修改,比如add header、modiffy header等等,重新装到packet里面去。

    2016/9/28

  • 相关阅读:
    The Quad
    将OrCAD Capture CIS的设计文件(.dsn)导入到PADS Logic VX.2.3
    OrCAD Capture CIS 16.6 将版本16.6的设计文件另存为版本16.2的设计文件
    Eclipse IDE 添加jar包到Java工程中
    PADS Logic VX.2.3 修改软件界面语言
    切换Allegro PCB Editor
    Allegro PCB Design GXL (legacy) 将brd文件另存为低版本文件
    Allegro PCB Design GXL (legacy) 设置自动保存brd文件
    Could not create an acl object: Role '16'
    windows 下apache开启FastCGI
  • 原文地址:https://www.cnblogs.com/qq952693358/p/5914554.html
Copyright © 2011-2022 走看看