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 }