【p4tutorials】P4 v1.1 Simple Router

fork了p4tutorials,想从里面窥探一些门道。

本文相关的原文链接:ReadMe

说明:

下面的这个P4程序,是当下最著名的 simple_router 程序的一个版本,是根据P4的1.1版本描述的。
除了这个程序之外,这个版本的p4可以根据失效的TTL字段跟踪Drop的IPv4报文;这个程序是用来说明P41.1版本的一些潜在功能,具体请移步P4.org。

Look at the P4 program and observe some of the P4 v1.1 additions:

  • strong typing in header type definitions and action declarations
  • assignment with = instead of modify_field (extension to the v1.1 spec)
  • register indexing
  • support for the ternary operator (extension to the v1.1 spec)

跑这个demo

他们提供了一个小的demo来帮助你测试这个程序,在跑这个程序之前,请确保env.sh这个文件(在这篇ReadMe的上层目录)是处在最新状态的。

To run the demo:

  • start the switch in Mininet with ./run_switch.sh
  • in another terminal, populate the table entries with ./add_entries.sh
  • you should now be able to ping h2 from h1 by typing h1 ping h2 in the Mininet CLI

Once you have the basic demo running, you can start sending packets with a TTL of 1, activate packet drop tracking in the switch and observe the count go up. To do this:

  • activate the tracking with ./register_on_off.sh on
  • send ICMP packets with a TTL of 1 from the Mininet CLI: h1 ping h2 -t 1. The packets are now dropped by the switch, so you should not be able to observe a reply

To get the drop count, simply run ./read_register.sh.

P4程序 位于 ../tutorials/p4v1_1/simple_router/p4src 目录下

/* Copyright 2013-present Barefoot Networks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

header_type ethernet_t {
    fields {
        bit<48> dstAddr;
        bit<48> srcAddr;
        bit<16> etherType;
    }
}

header_type ipv4_t {
    fields {
        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;
    }
}

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 {
    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;
}


action _drop() {
    drop();
}

header_type routing_metadata_t {
    fields {
        bit<32> nhop_ipv4;
    }
}

metadata routing_metadata_t routing_metadata;

register drops_register {
    width: 32;
    static: drop_expired;
    instance_count: 16;
}

register drops_register_enabled {
    width: 1;
    static: drop_expired;
    instance_count: 16;
}

action do_drop_expired() {
    drops_register[0] = drops_register[0] + ((drops_register_enabled[0] == 1) ? (bit<32>)1 : 0);
    drop();
}

table drop_expired {
    actions { do_drop_expired; }
    size: 0;
}        

action set_nhop(in bit<32> nhop_ipv4, in bit<9> port) {
    routing_metadata.nhop_ipv4 = nhop_ipv4;
    standard_metadata.egress_spec = port;
    ipv4.ttl = ipv4.ttl - 1;
}

table ipv4_lpm {
    reads {
        ipv4.dstAddr : lpm;
    }
    actions {
        set_nhop;
        _drop;
    }
    size: 1024;
}

action set_dmac(in bit<48> dmac) {
    ethernet.dstAddr = dmac;
    // modify_field still valid
    // modify_field(ethernet.dstAddr, dmac);
}

table forward {
    reads {
        routing_metadata.nhop_ipv4 : exact;
    }
    actions {
        set_dmac;
        _drop;
    }
    size: 512;
}

action rewrite_mac(in bit<48> smac) {
    ethernet.srcAddr = smac;
}

table send_frame {
    reads {
        standard_metadata.egress_port: exact;
    }
    actions {
        rewrite_mac;
        _drop;
    }
    size: 256;
}

control ingress {
    if(valid(ipv4)) {
        if(ipv4.ttl > 1) {
            apply(ipv4_lpm);
            apply(forward);
        } else {
            apply(drop_expired);
        }
    }
}

control egress {
    apply(send_frame);
}

posted @ 2016-09-27 15:03  Wasdns  阅读(882)  评论(0编辑  收藏  举报