• p4factory下 targets/basic_rout


    p4factory/targets/basic_routing/p4src代码解读

    headers.p4

    header_type ethernet_t {
        fields {
            dstAddr : 48;
            srcAddr : 48;
            etherType : 16;
        }
    }
    
    header_type 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;
        }
    }
    

    定义了一个以太网包头,以及一个IPV4包头

    parser.p4

    parser start {
        return parse_ethernet;
    }
    
    #define ETHERTYPE_IPV4 0x0800
    
    header ethernet_t ethernet;
    
    parser parse_ethernet {
        extract(ethernet);
        return select(latest.etherType) {
            ETHERTYPE_IPV4 : parse_ipv4;
            default: ingress;
        }
    }
    
    header ipv4_t ipv4;
    
    field_list ipv4_checksum_list {         //提取包的field_list
            ipv4.version;
            ipv4.ihl;
            ipv4.diffserv;
            ipv4.totalLen;
            ipv4.identification;
            ipv4.flags;
            ipv4.fragOffset;
            ipv4.ttl;
            ipv4.protocol;
            ipv4.srcAddr;
            ipv4.dstAddr;
    }
    
    field_list_calculation ipv4_checksum {
        input {
            ipv4_checksum_list;
        }
        algorithm : csum16;
        output_width : 16;
    }             //通过实例计算出校验和
    
    calculated_field ipv4.hdrChecksum  {
        verify ipv4_checksum;
        update ipv4_checksum;
    }           //与该包的校验和想比较,看是否正确
    
    parser parse_ipv4 {
        extract(ipv4);
        return ingress;
    }
    

    解释可以看这张图

    报文进来后,直接到了parse_ethernet解析器,然后提取ethernet实例的etherType判断是否位0x800如果是在进入到parse_ipv4解析器否则,到达状态_condition_()

    中间有个field_list_calculation ipv4_checksum 可以理解成是通过实例化的其他的field字段计算出checksum

    calculated_field ipv4.hdrChecksum 计算出来的ipv4_checksum在于刚刚包的hdrChecksum作对比,判断是否一样,然后在更新他

    basic_routing.p4

    #include "headers.p4"
    #include "parser.p4"
    
    #define PORT_VLAN_TABLE_SIZE                   32768
    #define BD_TABLE_SIZE                          65536
    #define IPV4_LPM_TABLE_SIZE                    16384
    #define IPV4_HOST_TABLE_SIZE                   131072
    #define NEXTHOP_TABLE_SIZE                     32768
    #define REWRITE_MAC_TABLE_SIZE                 32768
    
    #define VRF_BIT_WIDTH                          12
    #define BD_BIT_WIDTH                           16
    #define IFINDEX_BIT_WIDTH                      10
    
    /* METADATA */
    header_type ingress_metadata_t {                //用户自定义元数据
        fields {
            vrf : VRF_BIT_WIDTH;                   /* VRF */
            bd : BD_BIT_WIDTH;                     /* ingress BD */
            nexthop_index : 16;                    /* final next hop index */
        }
    }
    
    metadata ingress_metadata_t ingress_metadata;
    
    action on_miss() {
    }
    
    action set_bd(bd) {
        modify_field(ingress_metadata.bd, bd);    //设置元数据的bd值
    }
    
    table port_mapping {
        reads {
            standard_metadata.ingress_port : exact;
        }
        actions {
            set_bd;
        }
        size : PORT_VLAN_TABLE_SIZE;
    }
    
    action set_vrf(vrf) {
        modify_field(ingress_metadata.vrf, vrf);
    }
    
    table bd {
        reads {
            ingress_metadata.bd : exact;
        }
        actions {
            set_vrf;
        }
        size : BD_TABLE_SIZE;
    }
    
    action fib_hit_nexthop(nexthop_index) {
        modify_field(ingress_metadata.nexthop_index, nexthop_index);
        subtract_from_field(ipv4.ttl, 1);              //让ipv4包ttl-1
    }
    
    table ipv4_fib {
        reads {
            ingress_metadata.vrf : exact;
            ipv4.dstAddr : exact;
        }
        actions {
            on_miss;
            fib_hit_nexthop;
        }
        size : IPV4_HOST_TABLE_SIZE;
    }
    
    table ipv4_fib_lpm {
        reads {
            ingress_metadata.vrf : exact;
            ipv4.dstAddr : lpm;
        }
        actions {
            on_miss;
            fib_hit_nexthop;
        }
        size : IPV4_LPM_TABLE_SIZE;
    }
    
    action set_egress_details(egress_spec) {
        modify_field(standard_metadata.egress_spec, egress_spec);
    }
    
    table nexthop {
        reads {
            ingress_metadata.nexthop_index : exact;
        }
        actions {
            on_miss;
            set_egress_details;
        }
        size : NEXTHOP_TABLE_SIZE;
    }
    
    control ingress {                   //ingress流控制程序,规定了匹配过程
        if (valid(ipv4)) {
            /* derive ingress_metadata.bd */
            apply(port_mapping);
    
            /* derive ingress_metadata.vrf */
            apply(bd);
    
            /* fib lookup, set ingress_metadata.nexthop_index */
            apply(ipv4_fib) {
                on_miss {
                    apply(ipv4_fib_lpm);
                }
            }
    
            /* derive standard_metadata.egress_spec from ingress_metadata.nexthop_index */
            apply(nexthop);
        }
    }
    
    action rewrite_src_dst_mac(smac, dmac) {
        modify_field(ethernet.srcAddr, smac);
        modify_field(ethernet.dstAddr, dmac);
    }
    
    table rewrite_mac {
        reads {
            ingress_metadata.nexthop_index : exact;
        }
        actions {
            on_miss;
            rewrite_src_dst_mac;
        }
        size : REWRITE_MAC_TABLE_SIZE;
    }
    
    control egress {                     //egress的流控制程序
        /* set smac and dmac from ingress_metadata.nexthop_index */
        apply(rewrite_mac);
    }
    

    这个也可以从图可得他想要实现的结果

    上图两个团员可以看作是查表,线上文字代表执行相应的动作。下面解释一下这张图

    首先一个有效ipv4实例进来后先进行端口的匹配,设置bd,然后接着匹配bd表,设置vrf,然后在匹配ipv4_fib这张表匹配到就到下一跳去处理,接下应该都比较好理解。

    处理完ingress后在进入buffer区,然后在进行egress的处理,这里egress只有匹配一张表rewite_mac。

    输出结果展示
    Packet in on port 2 length 100; first bytes:
    00010203 04050006 0708090a 08004500
    new packet, len : 100, ingress : 2
    rmt proc returns 0
    ingress_pipeline: packet dequeued          
    parsing start
    parsing parse_ethernet
    parsing parse_ipv4
    payload length: 66
    all checksums are correct            //检验和正确,开始进入相应匹配
    Applying table port_mapping
    Lookup key for port_mapping:           //端口匹配
    	standard_metadata_ingress_port: 0x00000002, 
    table hit
    
    **********
    entry at index 1:
    	key:
    		standard_metadata_ingress_port: 0x00000002 (0 0 0 2),//key值
    	action:
    		set_bd     //动作
    	action data:
    		bd: 0x0000000a (0 0 0 10),	 //等下要赋值的数据
    **********
    
    action set_bd
    action data:
    	bd: 0x0000000a (0 0 0 10),	        //执行完成
    executing next table for action
    Applying table bd
    Lookup key for bd:
    	ingress_metadata_bd: 0x0000000a,             //bd匹配
    table hit
    
    **********
    entry at index 0:
    	key:
    		ingress_metadata_bd: 0x0000000a (0 0 0 10),	  //找到了表项
    	action:
    		set_vrf
    	action data:
    		vrf: 0x0000001e (0 0 0 30),	
    **********
    
    action set_vrf
    action data:
    	vrf: 0x0000001e (0 0 0 30),	
    executing next table for action
    Applying table ipv4_fib                 //匹配路由表
    Lookup key for ipv4_fib:
    	ingress_metadata_vrf: 0x0000001e, ipv4_dstAddr: 0x0a000002, 
    table miss, applying default action
    action on_miss                     //没有匹配到,执行on_miss操作
    executing next table for action           
    Applying table ipv4_fib_lpm         //执行ipv4路由表的另一种lpm匹配、
    									//与上面ipv4_fib区别的的是 ipv4_fib是
    									//精确匹配,而ipv4_fib_lpm执行的是三									 //重匹配 
    								//“动作-匹配表的每个表项都有一个掩码,将									//掩码和字段值进行逻辑与运算,再执行匹									//配。”
    Lookup key for ipv4_fib_lpm:
    	ingress_metadata_vrf: 0x0000001e, ipv4_dstAddr: 0x0a000002, 
    table hit
    
    **********
    entry at index 1:
    	key:
    		ingress_metadata_vrf: 0x0000001e (0 0 0 30),	ipv4_dstAddr: 0x0a000000 (10 0 0 0),	
    	prefix_length:
    		40
    	action:
    		fib_hit_nexthop
    	action data:
    		nexthop_index: 0x00000003 (0 0 0 3),	
    **********
    
    action fib_hit_nexthop         
    action data:
    	nexthop_index: 0x00000003 (0 0 0 3),	 //设置下一跳索引
    executing next table for action
    Applying table nexthop
    Lookup key for nexthop:
    	ingress_metadata_nexthop_index: 0x00000003, 
    table hit
    
    **********
    entry at index 2:
    	key:
    		ingress_metadata_nexthop_index: 0x00000003 (0 0 0 3),	
    	action:
    		set_egress_details
    	action data:
    		egress_spec: 0x00000003 (0 0 0 3),	
    **********
    
    action set_egress_details
    action data:
    	egress_spec: 0x00000003 (0 0 0 3),	
    executing next table for action     //设置下一跳egress出端口
    total length for outgoing pkt: 100
    deparsing ethernet         //逆解析ethernet解析器刚刚解析的过程
    deparsing ipv4				//逆解析刚刚ipv4解析器逆解析的港城
    total length for outgoing meta: 26  //总的要进入egress元数据长度为26
    copying metadata               //赋值元数据
    deparsing standard_metadata    //逆解析固有元数据
    deparsing ingress_metadata		//你解析用户自定义元数据
    queuing system: packet dequeued
    egress port set to 3
    instance type set to 0
    egress_pipeline: packet dequeued
    parsing start
    parsing parse_ethernet
    parsing parse_ipv4            //然后在向刚刚那样解析一次
    payload length: 66
    extracting metadata           //提取元数据
    extracting all metadata for 0x7f9ef0000930
    Applying table rewrite_mac
    Lookup key for rewrite_mac:
    	ingress_metadata_nexthop_index: 0x00000003, 
    table hit
    
    **********
    entry at index 2:
    	key:
    		ingress_metadata_nexthop_index: 0x00000003 (0 0 0 3),	
    	action:
    		rewrite_src_dst_mac
    	action data:
    		smac: 0x010303030303,	dmac: 0x000303030303,	
    **********
    
    action rewrite_src_dst_mac
    action data:
    	smac: 0x010303030303,	dmac: 0x000303030303,   //重写源目mac	
    executing next table for action
    total lenth for outgoing pkt: 100
    deparsing ethernet
    deparsing ipv4              //在逆解析一次
    outgoing thread: packet dequeued
    outgoing thread: sending pkt: Size[100]: Port[3]  //包从端口3送出去
    
    
  • 相关阅读:
    SSIS ->> Excel Destination无法接受大于255个字符长度的字符字段(转载)
    在express站点中使用ejs模板引擎
    Kali Linux系列教程之OpenVas安装
    Kali Linux Web 渗透测试视频教程— 第二课 google hack 实战
    Kali Linux Web 渗透测试视频教程— 第四课 google hack 实战
    google hack 之 查询语法
    shellKali Linux Web 渗透测试— 初级教程(第三课)
    NODE-WEBKIT教程(12)全屏
    node-webkit教程(11)Platform Service之shell
    node-webkit教程(10)Platform Service之File dialogs
  • 原文地址:https://www.cnblogs.com/wpqwpq/p/5933243.html
Copyright © 2020-2023  润新知