blob: 98b381237a95df1998631bd010a2bc55b6e71a02 [file] [log] [blame]
Yi Tsengbe342052017-11-03 10:21:23 -07001/*
2 * Copyright 2017-present Open Networking Foundation
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#include <core.p4>
18#include <v1model.p4>
19
20#include "../header.p4"
Yi Tsengbe342052017-11-03 10:21:23 -070021
Carmelo Casconeb5324e72018-11-25 02:26:32 -080022control Next (inout parsed_headers_t hdr,
23 inout fabric_metadata_t fabric_metadata,
24 inout standard_metadata_t standard_metadata) {
Yi Tsengbe342052017-11-03 10:21:23 -070025
Yi Tseng47eac892018-07-11 02:17:04 +080026 /*
27 * General actions.
28 */
Carmelo Casconeb5324e72018-11-25 02:26:32 -080029 @hidden
30 action output(port_num_t port_num) {
31 standard_metadata.egress_spec = port_num;
Yi Tseng20f9e7b2018-05-24 23:27:39 +080032 }
33
Carmelo Casconeb5324e72018-11-25 02:26:32 -080034 @hidden
Yi Tsengbe342052017-11-03 10:21:23 -070035 action rewrite_smac(mac_addr_t smac) {
36 hdr.ethernet.src_addr = smac;
37 }
38
Carmelo Casconeb5324e72018-11-25 02:26:32 -080039 @hidden
Yi Tsengbe342052017-11-03 10:21:23 -070040 action rewrite_dmac(mac_addr_t dmac) {
41 hdr.ethernet.dst_addr = dmac;
42 }
43
Carmelo Casconeb5324e72018-11-25 02:26:32 -080044 @hidden
45 action set_mpls_label(mpls_label_t label) {
46 fabric_metadata.mpls_label = label;
47 }
48
49 @hidden
50 action routing(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
51 rewrite_smac(smac);
52 rewrite_dmac(dmac);
53 output(port_num);
54 }
55
56 @hidden
57 action mpls_routing(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
58 mpls_label_t label) {
59 set_mpls_label(label);
60 routing(port_num, smac, dmac);
Yi Tseng1b154bd2017-11-20 17:48:19 -080061 }
62
Yi Tseng47eac892018-07-11 02:17:04 +080063 /*
Carmelo Casconeb5324e72018-11-25 02:26:32 -080064 * Next VLAN table.
65 * Modify VLAN ID based on next ID.
Yi Tseng47eac892018-07-11 02:17:04 +080066 */
Carmelo Casconeb5324e72018-11-25 02:26:32 -080067 direct_counter(CounterType.packets_and_bytes) next_vlan_counter;
Yi Tseng1d842672017-11-28 16:06:52 -080068
Carmelo Casconeb5324e72018-11-25 02:26:32 -080069 action set_vlan(vlan_id_t vlan_id) {
70 fabric_metadata.vlan_id = vlan_id;
71 next_vlan_counter.count();
Yi Tseng1b154bd2017-11-20 17:48:19 -080072 }
73
Carmelo Casconeb5324e72018-11-25 02:26:32 -080074 table next_vlan {
Yi Tseng20f9e7b2018-05-24 23:27:39 +080075 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -080076 fabric_metadata.next_id: exact @name("next_id");
Yi Tseng20f9e7b2018-05-24 23:27:39 +080077 }
Yi Tseng20f9e7b2018-05-24 23:27:39 +080078 actions = {
79 set_vlan;
Yi Tseng47eac892018-07-11 02:17:04 +080080 @defaultonly nop;
Yi Tseng20f9e7b2018-05-24 23:27:39 +080081 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -080082 const default_action = nop();
83 counters = next_vlan_counter;
Yi Tseng20f9e7b2018-05-24 23:27:39 +080084 }
85
Carmelo Casconeb5324e72018-11-25 02:26:32 -080086#ifdef WITH_XCONNECT
87 /*
88 * Cross-connect table.
89 * Bidirectional forwarding for the same next id.
90 */
91 direct_counter(CounterType.packets_and_bytes) xconnect_counter;
92
93 action output_xconnect(port_num_t port_num) {
94 output(port_num);
95 xconnect_counter.count();
96 }
97
98 action set_next_id_xconnect(next_id_t next_id) {
99 fabric_metadata.next_id = next_id;
100 xconnect_counter.count();
101 }
102
103 table xconnect {
104 key = {
105 standard_metadata.ingress_port: exact @name("ig_port");
106 fabric_metadata.next_id: exact @name("next_id");
107 }
108 actions = {
109 output_xconnect;
110 set_next_id_xconnect;
111 @defaultonly nop;
112 }
113 counters = xconnect_counter;
114 const default_action = nop();
115 }
116#endif // WITH_XCONNECT
117
118#ifdef WITH_SIMPLE_NEXT
Yi Tseng47eac892018-07-11 02:17:04 +0800119 /*
120 * Simple Table.
121 * Do a single egress action based on next id.
122 */
123 direct_counter(CounterType.packets_and_bytes) simple_counter;
124
125 action output_simple(port_num_t port_num) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800126 output(port_num);
Yi Tseng47eac892018-07-11 02:17:04 +0800127 simple_counter.count();
128 }
129
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800130 action routing_simple(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
131 routing(port_num, smac, dmac);
132 simple_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800133 }
134
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800135 action mpls_routing_simple(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
136 mpls_label_t label) {
137 mpls_routing(port_num, smac, dmac, label);
138 simple_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800139 }
140
Yi Tsengbe342052017-11-03 10:21:23 -0700141 table simple {
142 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800143 fabric_metadata.next_id: exact @name("next_id");
Yi Tsengbe342052017-11-03 10:21:23 -0700144 }
Yi Tsengbe342052017-11-03 10:21:23 -0700145 actions = {
Yi Tseng47eac892018-07-11 02:17:04 +0800146 output_simple;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800147 routing_simple;
148 mpls_routing_simple;
149 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700150 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800151 const default_action = nop();
Yi Tseng3a5731e2018-01-22 11:38:58 -0800152 counters = simple_counter;
Yi Tsengbe342052017-11-03 10:21:23 -0700153 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800154#endif // WITH_SIMPLE_NEXT
Yi Tsengbe342052017-11-03 10:21:23 -0700155
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800156#ifdef WITH_HASHED_NEXT
Yi Tseng47eac892018-07-11 02:17:04 +0800157 /*
158 * Hashed table.
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800159 * Execute an action profile selector based on next id.
Yi Tseng47eac892018-07-11 02:17:04 +0800160 */
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800161 action_selector(HashAlgorithm.crc16, 32w64, 32w16) hashed_selector;
Yi Tseng47eac892018-07-11 02:17:04 +0800162 direct_counter(CounterType.packets_and_bytes) hashed_counter;
163
164 action output_hashed(port_num_t port_num) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800165 output(port_num);
Yi Tseng47eac892018-07-11 02:17:04 +0800166 hashed_counter.count();
167 }
168
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800169 action routing_hashed(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
170 routing(port_num, smac, dmac);
171 hashed_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800172 }
173
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800174 action mpls_routing_hashed(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
175 mpls_label_t label) {
176 mpls_routing(port_num, smac, dmac, label);
177 hashed_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800178 }
179
Yi Tsengbe342052017-11-03 10:21:23 -0700180 table hashed {
181 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800182 fabric_metadata.next_id: exact @name("next_id");
Yi Tseng3d3956d2018-01-31 17:28:05 -0800183 hdr.ipv4.dst_addr: selector;
184 hdr.ipv4.src_addr: selector;
Yi Tseng1d842672017-11-28 16:06:52 -0800185 fabric_metadata.ip_proto: selector;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800186 fabric_metadata.l4_sport: selector;
187 fabric_metadata.l4_dport: selector;
Yi Tsengbe342052017-11-03 10:21:23 -0700188 }
Yi Tsengbe342052017-11-03 10:21:23 -0700189 actions = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800190 output_hashed;
191 routing_hashed;
192 mpls_routing_hashed;
193 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700194 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800195 implementation = hashed_selector;
Yi Tseng3a5731e2018-01-22 11:38:58 -0800196 counters = hashed_counter;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800197 const default_action = nop();
Yi Tsengbe342052017-11-03 10:21:23 -0700198 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800199#endif // WITH_HASHED_NEXT
Yi Tsengbe342052017-11-03 10:21:23 -0700200
201 /*
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800202 * Multicast
203 * Maps next IDs to PRE multicat group IDs.
Yi Tsengbe342052017-11-03 10:21:23 -0700204 */
Yi Tseng47eac892018-07-11 02:17:04 +0800205 direct_counter(CounterType.packets_and_bytes) multicast_counter;
206
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800207 action set_mcast_group_id(mcast_group_id_t group_id) {
208 standard_metadata.mcast_grp = group_id;
Carmelo Cascone1e8843f2018-07-19 19:01:12 +0200209 fabric_metadata.is_multicast = _TRUE;
Yi Tseng47eac892018-07-11 02:17:04 +0800210 multicast_counter.count();
Carmelo Casconea1061402018-02-03 17:39:59 -0800211 }
212
Carmelo Casconea1061402018-02-03 17:39:59 -0800213 table multicast {
Yi Tsengbe342052017-11-03 10:21:23 -0700214 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800215 fabric_metadata.next_id: exact @name("next_id");
Yi Tsengbe342052017-11-03 10:21:23 -0700216 }
217 actions = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800218 set_mcast_group_id;
219 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700220 }
Carmelo Casconea1061402018-02-03 17:39:59 -0800221 counters = multicast_counter;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800222 const default_action = nop();
Yi Tsengbe342052017-11-03 10:21:23 -0700223 }
224
225 apply {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800226#ifdef WITH_XCONNECT
227 // xconnect might set a new next_id.
228 xconnect.apply();
229#endif // WITH_XCONNECT
230#ifdef WITH_SIMPLE_NEXT
231 simple.apply();
232#endif // WITH_SIMPLE_NEXT
233#ifdef WITH_HASHED_NEXT
234 hashed.apply();
235#endif // WITH_HASHED_NEXT
236 multicast.apply();
237 next_vlan.apply();
Yi Tsengbe342052017-11-03 10:21:23 -0700238 }
239}
240
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800241control EgressNextControl (inout parsed_headers_t hdr,
242 inout fabric_metadata_t fabric_metadata,
243 inout standard_metadata_t standard_metadata) {
244 @hidden
245 action pop_mpls_if_present() {
246 hdr.mpls.setInvalid();
247 // Assuming there's an IP header after the MPLS one.
248 fabric_metadata.eth_type = fabric_metadata.ip_eth_type;
249 }
250
251 @hidden
252 action set_mpls() {
253 hdr.mpls.setValid();
254 hdr.mpls.label = fabric_metadata.mpls_label;
255 hdr.mpls.tc = 3w0;
256 hdr.mpls.bos = 1w1; // BOS = TRUE
257 hdr.mpls.ttl = fabric_metadata.mpls_ttl; // Decrement after push.
258 fabric_metadata.eth_type = ETHERTYPE_MPLS;
259 }
260
261 @hidden
262 action push_vlan() {
263 // If VLAN is already valid, we overwrite it with a potentially new VLAN
264 // ID, and same CFI, PRI, and eth_type values found in ingress.
265 hdr.vlan_tag.setValid();
266 hdr.vlan_tag.cfi = fabric_metadata.vlan_cfi;
267 hdr.vlan_tag.pri = fabric_metadata.vlan_pri;
268 hdr.vlan_tag.eth_type = fabric_metadata.eth_type;
269 hdr.vlan_tag.vlan_id = fabric_metadata.vlan_id;
270 hdr.ethernet.eth_type = ETHERTYPE_VLAN;
271 }
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800272
Yi Tseng47eac892018-07-11 02:17:04 +0800273 /*
274 * Egress VLAN Table.
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800275 * Pops the VLAN tag if the pair egress port and VLAN ID is matched.
Yi Tseng47eac892018-07-11 02:17:04 +0800276 */
277 direct_counter(CounterType.packets_and_bytes) egress_vlan_counter;
278
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800279 action pop_vlan() {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800280 hdr.ethernet.eth_type = fabric_metadata.eth_type;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800281 hdr.vlan_tag.setInvalid();
Yi Tseng47eac892018-07-11 02:17:04 +0800282 egress_vlan_counter.count();
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800283 }
284
285 table egress_vlan {
286 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800287 fabric_metadata.vlan_id: exact @name("vlan_id");
288 standard_metadata.egress_port: exact @name("eg_port");
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800289 }
290 actions = {
291 pop_vlan;
Yi Tseng47eac892018-07-11 02:17:04 +0800292 @defaultonly nop;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800293 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800294 const default_action = nop();
Yi Tseng47eac892018-07-11 02:17:04 +0800295 counters = egress_vlan_counter;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800296 }
Yi Tsengbe342052017-11-03 10:21:23 -0700297
298 apply {
Carmelo Cascone1e8843f2018-07-19 19:01:12 +0200299 if (fabric_metadata.is_multicast == _TRUE
Carmelo Casconea5400af2018-07-17 22:11:54 +0200300 && standard_metadata.ingress_port == standard_metadata.egress_port) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800301 mark_to_drop();
Carmelo Casconea5400af2018-07-17 22:11:54 +0200302 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800303
304 if (fabric_metadata.mpls_label == 0) {
305 if (hdr.mpls.isValid()) pop_mpls_if_present();
306 } else {
307 set_mpls();
308 }
309
310 if (!egress_vlan.apply().hit) {
311 // Push VLAN tag if not the default one.
312 if (fabric_metadata.vlan_id != DEFAULT_VLAN_ID) {
313 push_vlan();
314 }
315 }
316
317 // TTL decrement and check.
318 if (hdr.mpls.isValid()) {
319 hdr.mpls.ttl = hdr.mpls.ttl - 1;
320 if (hdr.mpls.ttl == 0) mark_to_drop();
321 } else {
322 if(hdr.ipv4.isValid()) {
323 hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
324 if (hdr.ipv4.ttl == 0) mark_to_drop();
325 }
326#ifdef WITH_IPV6
327 else if (hdr.ipv6.isValid()) {
328 hdr.ipv6.hop_limit = hdr.ipv6.hop_limit - 1;
329 if (hdr.ipv6.hop_limit == 0) mark_to_drop();
330 }
331#endif // WITH_IPV6
332 }
Yi Tsengbe342052017-11-03 10:21:23 -0700333 }
334}