Home | History | Annotate | Download | only in testprograms
      1 /*
      2 Copyright 2013-present Barefoot Networks, Inc.
      3 
      4 Licensed under the Apache License, Version 2.0 (the "License");
      5 you may not use this file except in compliance with the License.
      6 You may obtain a copy of the License at
      7 
      8     http://www.apache.org/licenses/LICENSE-2.0
      9 
     10 Unless required by applicable law or agreed to in writing, software
     11 distributed under the License is distributed on an "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 See the License for the specific language governing permissions and
     14 limitations under the License.
     15 */
     16 
     17 header_type ethernet_t {
     18     fields {
     19         dstAddr : 48;
     20         srcAddr : 48;
     21         etherType : 16;
     22     }
     23 }
     24 
     25 header_type ipv4_t {
     26     fields {
     27         version : 4;
     28         ihl : 4;
     29         diffserv : 8;
     30         totalLen : 16;
     31         identification : 16;
     32         flags : 3;
     33         fragOffset : 13;
     34         ttl : 8;
     35         protocol : 8;
     36         hdrChecksum : 16;
     37         srcAddr : 32;
     38         dstAddr: 32;
     39     }
     40 }
     41 
     42 parser start {
     43     return parse_ethernet;
     44 }
     45 
     46 #define ETHERTYPE_IPV4 0x0800
     47 
     48 header ethernet_t ethernet;
     49 
     50 parser parse_ethernet {
     51     extract(ethernet);
     52     return select(latest.etherType) {
     53         ETHERTYPE_IPV4 : parse_ipv4;
     54         default: ingress;
     55     }
     56 }
     57 
     58 header ipv4_t ipv4;
     59 
     60 /* Not yet supported on EBPF target
     61 
     62 field_list ipv4_checksum_list {
     63         ipv4.version;
     64         ipv4.ihl;
     65         ipv4.diffserv;
     66         ipv4.totalLen;
     67         ipv4.identification;
     68         ipv4.flags;
     69         ipv4.fragOffset;
     70         ipv4.ttl;
     71         ipv4.protocol;
     72         ipv4.srcAddr;
     73         ipv4.dstAddr;
     74 }
     75 
     76 field_list_calculation ipv4_checksum {
     77     input {
     78         ipv4_checksum_list;
     79     }
     80     algorithm : csum16;
     81     output_width : 16;
     82 }
     83 
     84 calculated_field ipv4.hdrChecksum  {
     85     verify ipv4_checksum;
     86     update ipv4_checksum;
     87 }
     88 */
     89 
     90 parser parse_ipv4 {
     91     extract(ipv4);
     92     return ingress;
     93 }
     94 
     95 #define PORT_VLAN_TABLE_SIZE                   32768
     96 #define BD_TABLE_SIZE                          65536
     97 #define IPV4_LPM_TABLE_SIZE                    16384
     98 #define IPV4_HOST_TABLE_SIZE                   131072
     99 #define NEXTHOP_TABLE_SIZE                     32768
    100 #define REWRITE_MAC_TABLE_SIZE                 32768
    101 
    102 #define VRF_BIT_WIDTH                          12
    103 #define BD_BIT_WIDTH                           16
    104 #define IFINDEX_BIT_WIDTH                      10
    105 
    106 /* METADATA */
    107 header_type ingress_metadata_t {
    108     fields {
    109         vrf : VRF_BIT_WIDTH;                   /* VRF */
    110         bd : BD_BIT_WIDTH;                     /* ingress BD */
    111         nexthop_index : 16;                    /* final next hop index */
    112     }
    113 }
    114 
    115 metadata ingress_metadata_t ingress_metadata;
    116 
    117 action on_miss() {
    118 }
    119 
    120 action set_bd(bd) {
    121     modify_field(ingress_metadata.bd, bd);
    122 }
    123 
    124 table port_mapping {
    125     reads {
    126         standard_metadata.ingress_port : exact;
    127     }
    128     actions {
    129         set_bd;
    130     }
    131     size : PORT_VLAN_TABLE_SIZE;
    132 }
    133 
    134 action set_vrf(vrf) {
    135     modify_field(ingress_metadata.vrf, vrf);
    136 }
    137 
    138 table bd {
    139     reads {
    140         ingress_metadata.bd : exact;
    141     }
    142     actions {
    143         set_vrf;
    144     }
    145     size : BD_TABLE_SIZE;
    146 }
    147 
    148 action fib_hit_nexthop(nexthop_index) {
    149     modify_field(ingress_metadata.nexthop_index, nexthop_index);
    150     subtract_from_field(ipv4.ttl, 1);
    151 }
    152 
    153 table ipv4_fib {
    154     reads {
    155         ingress_metadata.vrf : exact;
    156         ipv4.dstAddr : exact;
    157     }
    158     actions {
    159         on_miss;
    160         fib_hit_nexthop;
    161     }
    162     size : IPV4_HOST_TABLE_SIZE;
    163 }
    164 
    165 table ipv4_fib_lpm {
    166     reads {
    167         ingress_metadata.vrf : exact;
    168         ipv4.dstAddr : exact; // lpm not supported
    169     }
    170     actions {
    171         on_miss;
    172         fib_hit_nexthop;
    173     }
    174     size : IPV4_LPM_TABLE_SIZE;
    175 }
    176 
    177 action set_egress_details(egress_spec) {
    178     modify_field(standard_metadata.egress_spec, egress_spec);
    179 }
    180 
    181 table nexthop {
    182     reads {
    183         ingress_metadata.nexthop_index : exact;
    184     }
    185     actions {
    186         on_miss;
    187         set_egress_details;
    188     }
    189     size : NEXTHOP_TABLE_SIZE;
    190 }
    191 
    192 control ingress {
    193     if (valid(ipv4)) {
    194         /* derive ingress_metadata.bd */
    195         apply(port_mapping);
    196 
    197         /* derive ingress_metadata.vrf */
    198         apply(bd);
    199 
    200         /* fib lookup, set ingress_metadata.nexthop_index */
    201         apply(ipv4_fib) {
    202             on_miss {
    203                 apply(ipv4_fib_lpm);
    204             }
    205         }
    206 
    207         /* derive standard_metadata.egress_spec from ingress_metadata.nexthop_index */
    208         apply(nexthop);
    209     }
    210 }
    211 
    212 action rewrite_src_dst_mac(smac, dmac) {
    213     modify_field(ethernet.srcAddr, smac);
    214     modify_field(ethernet.dstAddr, dmac);
    215 }
    216 
    217 table rewrite_mac {
    218     reads {
    219         ingress_metadata.nexthop_index : exact;
    220     }
    221     actions {
    222         on_miss;
    223         rewrite_src_dst_mac;
    224     }
    225     size : REWRITE_MAC_TABLE_SIZE;
    226 }
    227 
    228 control egress {
    229     /* set smac and dmac from ingress_metadata.nexthop_index */
    230     apply(rewrite_mac);
    231 }