blob: 2ea719ac6d85daa396ef13a67b78da2f68d7e526 [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
Daniele Moro7c3a0022019-07-12 13:38:34 -070074#ifdef WITH_DOUBLE_VLAN_TERMINATION
75 action set_double_vlan(vlan_id_t outer_vlan_id, vlan_id_t inner_vlan_id) {
76 set_vlan(outer_vlan_id);
77 fabric_metadata.push_double_vlan = _TRUE;
78 fabric_metadata.inner_vlan_id = inner_vlan_id;
79 }
80#endif // WITH_DOUBLE_VLAN_TERMINATION
81
Carmelo Casconeb5324e72018-11-25 02:26:32 -080082 table next_vlan {
Yi Tseng20f9e7b2018-05-24 23:27:39 +080083 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -080084 fabric_metadata.next_id: exact @name("next_id");
Yi Tseng20f9e7b2018-05-24 23:27:39 +080085 }
Yi Tseng20f9e7b2018-05-24 23:27:39 +080086 actions = {
87 set_vlan;
Daniele Moro7c3a0022019-07-12 13:38:34 -070088#ifdef WITH_DOUBLE_VLAN_TERMINATION
89 set_double_vlan;
90#endif // WITH_DOUBLE_VLAN_TERMINATION
Yi Tseng47eac892018-07-11 02:17:04 +080091 @defaultonly nop;
Yi Tseng20f9e7b2018-05-24 23:27:39 +080092 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -080093 const default_action = nop();
94 counters = next_vlan_counter;
Carmelo Cascone70e816b2019-03-19 16:15:47 -070095 size = NEXT_VLAN_TABLE_SIZE;
Yi Tseng20f9e7b2018-05-24 23:27:39 +080096 }
97
Carmelo Casconeb5324e72018-11-25 02:26:32 -080098#ifdef WITH_XCONNECT
99 /*
100 * Cross-connect table.
101 * Bidirectional forwarding for the same next id.
102 */
103 direct_counter(CounterType.packets_and_bytes) xconnect_counter;
104
105 action output_xconnect(port_num_t port_num) {
106 output(port_num);
107 xconnect_counter.count();
108 }
109
110 action set_next_id_xconnect(next_id_t next_id) {
111 fabric_metadata.next_id = next_id;
112 xconnect_counter.count();
113 }
114
115 table xconnect {
116 key = {
117 standard_metadata.ingress_port: exact @name("ig_port");
118 fabric_metadata.next_id: exact @name("next_id");
119 }
120 actions = {
121 output_xconnect;
122 set_next_id_xconnect;
123 @defaultonly nop;
124 }
125 counters = xconnect_counter;
126 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700127 size = XCONNECT_NEXT_TABLE_SIZE;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800128 }
129#endif // WITH_XCONNECT
130
131#ifdef WITH_SIMPLE_NEXT
Yi Tseng47eac892018-07-11 02:17:04 +0800132 /*
133 * Simple Table.
134 * Do a single egress action based on next id.
135 */
136 direct_counter(CounterType.packets_and_bytes) simple_counter;
137
138 action output_simple(port_num_t port_num) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800139 output(port_num);
Yi Tseng47eac892018-07-11 02:17:04 +0800140 simple_counter.count();
141 }
142
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800143 action routing_simple(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
144 routing(port_num, smac, dmac);
145 simple_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800146 }
147
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800148 action mpls_routing_simple(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
149 mpls_label_t label) {
150 mpls_routing(port_num, smac, dmac, label);
151 simple_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800152 }
153
Yi Tsengbe342052017-11-03 10:21:23 -0700154 table simple {
155 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800156 fabric_metadata.next_id: exact @name("next_id");
Yi Tsengbe342052017-11-03 10:21:23 -0700157 }
Yi Tsengbe342052017-11-03 10:21:23 -0700158 actions = {
Yi Tseng47eac892018-07-11 02:17:04 +0800159 output_simple;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800160 routing_simple;
161 mpls_routing_simple;
162 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700163 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800164 const default_action = nop();
Yi Tseng3a5731e2018-01-22 11:38:58 -0800165 counters = simple_counter;
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700166 size = SIMPLE_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700167 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800168#endif // WITH_SIMPLE_NEXT
Yi Tsengbe342052017-11-03 10:21:23 -0700169
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800170#ifdef WITH_HASHED_NEXT
Yi Tseng47eac892018-07-11 02:17:04 +0800171 /*
172 * Hashed table.
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800173 * Execute an action profile selector based on next id.
Yi Tseng47eac892018-07-11 02:17:04 +0800174 */
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700175 @max_group_size(HASHED_SELECTOR_MAX_GROUP_SIZE)
Daniele Moro5a2de712019-09-24 14:34:07 -0700176 #ifdef _CUSTOM_HASHED_SELECTOR_ANNOTATION
177 _CUSTOM_HASHED_SELECTOR_ANNOTATION
178 #endif
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700179 action_selector(HashAlgorithm.crc16, HASHED_ACT_PROFILE_SIZE, 32w16) hashed_selector;
Yi Tseng47eac892018-07-11 02:17:04 +0800180 direct_counter(CounterType.packets_and_bytes) hashed_counter;
181
182 action output_hashed(port_num_t port_num) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800183 output(port_num);
Yi Tseng47eac892018-07-11 02:17:04 +0800184 hashed_counter.count();
185 }
186
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800187 action routing_hashed(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
188 routing(port_num, smac, dmac);
189 hashed_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800190 }
191
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800192 action mpls_routing_hashed(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
193 mpls_label_t label) {
194 mpls_routing(port_num, smac, dmac, label);
195 hashed_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800196 }
197
Yi Tsengbe342052017-11-03 10:21:23 -0700198 table hashed {
199 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800200 fabric_metadata.next_id: exact @name("next_id");
Yi Tseng3d3956d2018-01-31 17:28:05 -0800201 hdr.ipv4.dst_addr: selector;
202 hdr.ipv4.src_addr: selector;
Yi Tseng1d842672017-11-28 16:06:52 -0800203 fabric_metadata.ip_proto: selector;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800204 fabric_metadata.l4_sport: selector;
205 fabric_metadata.l4_dport: selector;
Yi Tsengbe342052017-11-03 10:21:23 -0700206 }
Yi Tsengbe342052017-11-03 10:21:23 -0700207 actions = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800208 output_hashed;
209 routing_hashed;
210 mpls_routing_hashed;
211 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700212 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800213 implementation = hashed_selector;
Yi Tseng3a5731e2018-01-22 11:38:58 -0800214 counters = hashed_counter;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800215 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700216 size = HASHED_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700217 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800218#endif // WITH_HASHED_NEXT
Yi Tsengbe342052017-11-03 10:21:23 -0700219
220 /*
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800221 * Multicast
222 * Maps next IDs to PRE multicat group IDs.
Yi Tsengbe342052017-11-03 10:21:23 -0700223 */
Yi Tseng47eac892018-07-11 02:17:04 +0800224 direct_counter(CounterType.packets_and_bytes) multicast_counter;
225
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800226 action set_mcast_group_id(mcast_group_id_t group_id) {
227 standard_metadata.mcast_grp = group_id;
Carmelo Cascone1e8843f2018-07-19 19:01:12 +0200228 fabric_metadata.is_multicast = _TRUE;
Yi Tseng47eac892018-07-11 02:17:04 +0800229 multicast_counter.count();
Carmelo Casconea1061402018-02-03 17:39:59 -0800230 }
231
Carmelo Casconea1061402018-02-03 17:39:59 -0800232 table multicast {
Yi Tsengbe342052017-11-03 10:21:23 -0700233 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800234 fabric_metadata.next_id: exact @name("next_id");
Yi Tsengbe342052017-11-03 10:21:23 -0700235 }
236 actions = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800237 set_mcast_group_id;
238 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700239 }
Carmelo Casconea1061402018-02-03 17:39:59 -0800240 counters = multicast_counter;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800241 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700242 size = MULTICAST_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700243 }
244
245 apply {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800246#ifdef WITH_XCONNECT
247 // xconnect might set a new next_id.
248 xconnect.apply();
249#endif // WITH_XCONNECT
250#ifdef WITH_SIMPLE_NEXT
251 simple.apply();
252#endif // WITH_SIMPLE_NEXT
253#ifdef WITH_HASHED_NEXT
254 hashed.apply();
255#endif // WITH_HASHED_NEXT
256 multicast.apply();
257 next_vlan.apply();
Yi Tsengbe342052017-11-03 10:21:23 -0700258 }
259}
260
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800261control EgressNextControl (inout parsed_headers_t hdr,
262 inout fabric_metadata_t fabric_metadata,
263 inout standard_metadata_t standard_metadata) {
264 @hidden
265 action pop_mpls_if_present() {
266 hdr.mpls.setInvalid();
267 // Assuming there's an IP header after the MPLS one.
Daniele Moro5a2de712019-09-24 14:34:07 -0700268 hdr.eth_type.value = fabric_metadata.ip_eth_type;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800269 }
270
271 @hidden
272 action set_mpls() {
273 hdr.mpls.setValid();
274 hdr.mpls.label = fabric_metadata.mpls_label;
275 hdr.mpls.tc = 3w0;
276 hdr.mpls.bos = 1w1; // BOS = TRUE
277 hdr.mpls.ttl = fabric_metadata.mpls_ttl; // Decrement after push.
Daniele Moro5a2de712019-09-24 14:34:07 -0700278 hdr.eth_type.value = ETHERTYPE_MPLS;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800279 }
280
281 @hidden
282 action push_vlan() {
283 // If VLAN is already valid, we overwrite it with a potentially new VLAN
284 // ID, and same CFI, PRI, and eth_type values found in ingress.
285 hdr.vlan_tag.setValid();
286 hdr.vlan_tag.cfi = fabric_metadata.vlan_cfi;
287 hdr.vlan_tag.pri = fabric_metadata.vlan_pri;
Daniele Moro5a2de712019-09-24 14:34:07 -0700288 hdr.vlan_tag.eth_type = ETHERTYPE_VLAN;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800289 hdr.vlan_tag.vlan_id = fabric_metadata.vlan_id;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800290 }
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800291
Daniele Moro7c3a0022019-07-12 13:38:34 -0700292#ifdef WITH_DOUBLE_VLAN_TERMINATION
293 @hidden
294 action push_inner_vlan() {
Daniele Moro5a2de712019-09-24 14:34:07 -0700295 // Push inner VLAN TAG, rewriting correclty the outer vlan eth_type
Daniele Moro7c3a0022019-07-12 13:38:34 -0700296 hdr.inner_vlan_tag.setValid();
297 hdr.inner_vlan_tag.cfi = fabric_metadata.inner_vlan_cfi;
298 hdr.inner_vlan_tag.pri = fabric_metadata.inner_vlan_pri;
299 hdr.inner_vlan_tag.vlan_id = fabric_metadata.inner_vlan_id;
Daniele Moro5a2de712019-09-24 14:34:07 -0700300 hdr.inner_vlan_tag.eth_type = ETHERTYPE_VLAN;
Daniele Moro7c3a0022019-07-12 13:38:34 -0700301 hdr.vlan_tag.eth_type = ETHERTYPE_VLAN;
302 }
303#endif // WITH_DOUBLE_VLAN_TERMINATION
304
Yi Tseng47eac892018-07-11 02:17:04 +0800305 /*
306 * Egress VLAN Table.
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800307 * Pops the VLAN tag if the pair egress port and VLAN ID is matched.
Yi Tseng47eac892018-07-11 02:17:04 +0800308 */
309 direct_counter(CounterType.packets_and_bytes) egress_vlan_counter;
310
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800311 action pop_vlan() {
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800312 hdr.vlan_tag.setInvalid();
Yi Tseng47eac892018-07-11 02:17:04 +0800313 egress_vlan_counter.count();
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800314 }
315
316 table egress_vlan {
317 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800318 fabric_metadata.vlan_id: exact @name("vlan_id");
319 standard_metadata.egress_port: exact @name("eg_port");
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800320 }
321 actions = {
322 pop_vlan;
Yi Tseng47eac892018-07-11 02:17:04 +0800323 @defaultonly nop;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800324 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800325 const default_action = nop();
Yi Tseng47eac892018-07-11 02:17:04 +0800326 counters = egress_vlan_counter;
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700327 size = EGRESS_VLAN_TABLE_SIZE;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800328 }
Yi Tsengbe342052017-11-03 10:21:23 -0700329
330 apply {
Carmelo Cascone1e8843f2018-07-19 19:01:12 +0200331 if (fabric_metadata.is_multicast == _TRUE
Carmelo Casconea5400af2018-07-17 22:11:54 +0200332 && standard_metadata.ingress_port == standard_metadata.egress_port) {
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700333 mark_to_drop(standard_metadata);
Carmelo Casconea5400af2018-07-17 22:11:54 +0200334 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800335
336 if (fabric_metadata.mpls_label == 0) {
337 if (hdr.mpls.isValid()) pop_mpls_if_present();
338 } else {
339 set_mpls();
340 }
341
Daniele Moro7c3a0022019-07-12 13:38:34 -0700342#ifdef WITH_DOUBLE_VLAN_TERMINATION
343 if (fabric_metadata.push_double_vlan == _TRUE) {
344 // Double VLAN termination.
345 push_vlan();
346 push_inner_vlan();
347 } else {
348 // If no push double vlan, inner_vlan_tag must be popped
349 hdr.inner_vlan_tag.setInvalid();
350#endif // WITH_DOUBLE_VLAN_TERMINATION
351 // Port-based VLAN tagging (by default all
352 // ports are assumed tagged)
353 if (!egress_vlan.apply().hit) {
354 // Push VLAN tag if not the default one.
355 if (fabric_metadata.vlan_id != DEFAULT_VLAN_ID) {
356 push_vlan();
357 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800358 }
Daniele Moro7c3a0022019-07-12 13:38:34 -0700359#ifdef WITH_DOUBLE_VLAN_TERMINATION
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800360 }
Daniele Moro7c3a0022019-07-12 13:38:34 -0700361#endif // WITH_DOUBLE_VLAN_TERMINATION
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800362
363 // TTL decrement and check.
364 if (hdr.mpls.isValid()) {
365 hdr.mpls.ttl = hdr.mpls.ttl - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700366 if (hdr.mpls.ttl == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800367 } else {
368 if(hdr.ipv4.isValid()) {
369 hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700370 if (hdr.ipv4.ttl == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800371 }
372#ifdef WITH_IPV6
373 else if (hdr.ipv6.isValid()) {
374 hdr.ipv6.hop_limit = hdr.ipv6.hop_limit - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700375 if (hdr.ipv6.hop_limit == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800376 }
377#endif // WITH_IPV6
378 }
Yi Tsengbe342052017-11-03 10:21:23 -0700379 }
380}