blob: fca2e61b84488a95924f0cb5440f6efdf59b15db [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
Carmelo Casconeb5324e72018-11-25 02:26:32 -080045 action routing(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
46 rewrite_smac(smac);
47 rewrite_dmac(dmac);
48 output(port_num);
49 }
50
Carmelo Casconeb5324e72018-11-25 02:26:32 -080051#ifdef WITH_XCONNECT
52 /*
53 * Cross-connect table.
54 * Bidirectional forwarding for the same next id.
55 */
56 direct_counter(CounterType.packets_and_bytes) xconnect_counter;
57
58 action output_xconnect(port_num_t port_num) {
59 output(port_num);
60 xconnect_counter.count();
61 }
62
63 action set_next_id_xconnect(next_id_t next_id) {
64 fabric_metadata.next_id = next_id;
65 xconnect_counter.count();
66 }
67
68 table xconnect {
69 key = {
70 standard_metadata.ingress_port: exact @name("ig_port");
71 fabric_metadata.next_id: exact @name("next_id");
72 }
73 actions = {
74 output_xconnect;
75 set_next_id_xconnect;
76 @defaultonly nop;
77 }
78 counters = xconnect_counter;
79 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -070080 size = XCONNECT_NEXT_TABLE_SIZE;
Carmelo Casconeb5324e72018-11-25 02:26:32 -080081 }
82#endif // WITH_XCONNECT
83
84#ifdef WITH_SIMPLE_NEXT
Yi Tseng47eac892018-07-11 02:17:04 +080085 /*
86 * Simple Table.
87 * Do a single egress action based on next id.
88 */
89 direct_counter(CounterType.packets_and_bytes) simple_counter;
90
91 action output_simple(port_num_t port_num) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -080092 output(port_num);
Yi Tseng47eac892018-07-11 02:17:04 +080093 simple_counter.count();
94 }
95
Carmelo Casconeb5324e72018-11-25 02:26:32 -080096 action routing_simple(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
97 routing(port_num, smac, dmac);
98 simple_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +080099 }
100
Yi Tsengbe342052017-11-03 10:21:23 -0700101 table simple {
102 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800103 fabric_metadata.next_id: exact @name("next_id");
Yi Tsengbe342052017-11-03 10:21:23 -0700104 }
Yi Tsengbe342052017-11-03 10:21:23 -0700105 actions = {
Yi Tseng47eac892018-07-11 02:17:04 +0800106 output_simple;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800107 routing_simple;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800108 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700109 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800110 const default_action = nop();
Yi Tseng3a5731e2018-01-22 11:38:58 -0800111 counters = simple_counter;
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700112 size = SIMPLE_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700113 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800114#endif // WITH_SIMPLE_NEXT
Yi Tsengbe342052017-11-03 10:21:23 -0700115
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800116#ifdef WITH_HASHED_NEXT
Yi Tseng47eac892018-07-11 02:17:04 +0800117 /*
118 * Hashed table.
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800119 * Execute an action profile selector based on next id.
Yi Tseng47eac892018-07-11 02:17:04 +0800120 */
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700121 @max_group_size(HASHED_SELECTOR_MAX_GROUP_SIZE)
Daniele Moro5a2de712019-09-24 14:34:07 -0700122 #ifdef _CUSTOM_HASHED_SELECTOR_ANNOTATION
123 _CUSTOM_HASHED_SELECTOR_ANNOTATION
124 #endif
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700125 action_selector(HashAlgorithm.crc16, HASHED_ACT_PROFILE_SIZE, 32w16) hashed_selector;
Yi Tseng47eac892018-07-11 02:17:04 +0800126 direct_counter(CounterType.packets_and_bytes) hashed_counter;
127
128 action output_hashed(port_num_t port_num) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800129 output(port_num);
Yi Tseng47eac892018-07-11 02:17:04 +0800130 hashed_counter.count();
131 }
132
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800133 action routing_hashed(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
134 routing(port_num, smac, dmac);
135 hashed_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800136 }
137
Yi Tsengbe342052017-11-03 10:21:23 -0700138 table hashed {
139 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800140 fabric_metadata.next_id: exact @name("next_id");
Robert MacDavidbec6b6a2020-05-21 21:32:38 -0400141 fabric_metadata.ipv4_src_addr: selector;
142 fabric_metadata.ipv4_dst_addr: selector;
Yi Tseng1d842672017-11-28 16:06:52 -0800143 fabric_metadata.ip_proto: selector;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800144 fabric_metadata.l4_sport: selector;
145 fabric_metadata.l4_dport: selector;
Yi Tsengbe342052017-11-03 10:21:23 -0700146 }
Yi Tsengbe342052017-11-03 10:21:23 -0700147 actions = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800148 output_hashed;
149 routing_hashed;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800150 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700151 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800152 implementation = hashed_selector;
Yi Tseng3a5731e2018-01-22 11:38:58 -0800153 counters = hashed_counter;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800154 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700155 size = HASHED_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700156 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800157#endif // WITH_HASHED_NEXT
Yi Tsengbe342052017-11-03 10:21:23 -0700158
159 /*
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800160 * Multicast
161 * Maps next IDs to PRE multicat group IDs.
Yi Tsengbe342052017-11-03 10:21:23 -0700162 */
Yi Tseng47eac892018-07-11 02:17:04 +0800163 direct_counter(CounterType.packets_and_bytes) multicast_counter;
164
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800165 action set_mcast_group_id(mcast_group_id_t group_id) {
166 standard_metadata.mcast_grp = group_id;
Carmelo Cascone1e8843f2018-07-19 19:01:12 +0200167 fabric_metadata.is_multicast = _TRUE;
Yi Tseng47eac892018-07-11 02:17:04 +0800168 multicast_counter.count();
Carmelo Casconea1061402018-02-03 17:39:59 -0800169 }
170
Carmelo Casconea1061402018-02-03 17:39:59 -0800171 table multicast {
Yi Tsengbe342052017-11-03 10:21:23 -0700172 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800173 fabric_metadata.next_id: exact @name("next_id");
Yi Tsengbe342052017-11-03 10:21:23 -0700174 }
175 actions = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800176 set_mcast_group_id;
177 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700178 }
Carmelo Casconea1061402018-02-03 17:39:59 -0800179 counters = multicast_counter;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800180 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700181 size = MULTICAST_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700182 }
183
184 apply {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800185#ifdef WITH_XCONNECT
186 // xconnect might set a new next_id.
187 xconnect.apply();
188#endif // WITH_XCONNECT
189#ifdef WITH_SIMPLE_NEXT
190 simple.apply();
191#endif // WITH_SIMPLE_NEXT
192#ifdef WITH_HASHED_NEXT
193 hashed.apply();
194#endif // WITH_HASHED_NEXT
195 multicast.apply();
Yi Tsengbe342052017-11-03 10:21:23 -0700196 }
197}
198
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800199control EgressNextControl (inout parsed_headers_t hdr,
200 inout fabric_metadata_t fabric_metadata,
201 inout standard_metadata_t standard_metadata) {
202 @hidden
203 action pop_mpls_if_present() {
204 hdr.mpls.setInvalid();
205 // Assuming there's an IP header after the MPLS one.
Daniele Moro5a2de712019-09-24 14:34:07 -0700206 hdr.eth_type.value = fabric_metadata.ip_eth_type;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800207 }
208
209 @hidden
210 action set_mpls() {
211 hdr.mpls.setValid();
212 hdr.mpls.label = fabric_metadata.mpls_label;
213 hdr.mpls.tc = 3w0;
214 hdr.mpls.bos = 1w1; // BOS = TRUE
215 hdr.mpls.ttl = fabric_metadata.mpls_ttl; // Decrement after push.
Daniele Moro5a2de712019-09-24 14:34:07 -0700216 hdr.eth_type.value = ETHERTYPE_MPLS;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800217 }
218
219 @hidden
pierventre48e78822020-12-15 17:34:54 +0100220 action push_outer_vlan() {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800221 // If VLAN is already valid, we overwrite it with a potentially new VLAN
222 // ID, and same CFI, PRI, and eth_type values found in ingress.
223 hdr.vlan_tag.setValid();
224 hdr.vlan_tag.cfi = fabric_metadata.vlan_cfi;
225 hdr.vlan_tag.pri = fabric_metadata.vlan_pri;
Daniele Moro5a2de712019-09-24 14:34:07 -0700226 hdr.vlan_tag.eth_type = ETHERTYPE_VLAN;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800227 hdr.vlan_tag.vlan_id = fabric_metadata.vlan_id;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800228 }
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800229
Daniele Moro7c3a0022019-07-12 13:38:34 -0700230#ifdef WITH_DOUBLE_VLAN_TERMINATION
231 @hidden
232 action push_inner_vlan() {
Daniele Moro5a2de712019-09-24 14:34:07 -0700233 // Push inner VLAN TAG, rewriting correclty the outer vlan eth_type
Daniele Moro7c3a0022019-07-12 13:38:34 -0700234 hdr.inner_vlan_tag.setValid();
235 hdr.inner_vlan_tag.cfi = fabric_metadata.inner_vlan_cfi;
236 hdr.inner_vlan_tag.pri = fabric_metadata.inner_vlan_pri;
237 hdr.inner_vlan_tag.vlan_id = fabric_metadata.inner_vlan_id;
Daniele Moro5a2de712019-09-24 14:34:07 -0700238 hdr.inner_vlan_tag.eth_type = ETHERTYPE_VLAN;
Daniele Moro7c3a0022019-07-12 13:38:34 -0700239 hdr.vlan_tag.eth_type = ETHERTYPE_VLAN;
240 }
241#endif // WITH_DOUBLE_VLAN_TERMINATION
242
Yi Tseng47eac892018-07-11 02:17:04 +0800243 /*
244 * Egress VLAN Table.
pierventre48e78822020-12-15 17:34:54 +0100245 * Pushes or Pops the VLAN tag if the pair egress port and VLAN ID is matched.
246 * Instead, it drops the packets on miss.
Yi Tseng47eac892018-07-11 02:17:04 +0800247 */
248 direct_counter(CounterType.packets_and_bytes) egress_vlan_counter;
249
pierventre48e78822020-12-15 17:34:54 +0100250 action push_vlan() {
251 push_outer_vlan();
252 egress_vlan_counter.count();
253 }
254
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800255 action pop_vlan() {
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800256 hdr.vlan_tag.setInvalid();
Yi Tseng47eac892018-07-11 02:17:04 +0800257 egress_vlan_counter.count();
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800258 }
259
pierventre48e78822020-12-15 17:34:54 +0100260 action drop() {
261 mark_to_drop(standard_metadata);
262 egress_vlan_counter.count();
263 }
264
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800265 table egress_vlan {
266 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800267 fabric_metadata.vlan_id: exact @name("vlan_id");
268 standard_metadata.egress_port: exact @name("eg_port");
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800269 }
270 actions = {
pierventre48e78822020-12-15 17:34:54 +0100271 push_vlan;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800272 pop_vlan;
pierventre48e78822020-12-15 17:34:54 +0100273 @defaultonly drop;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800274 }
pierventre48e78822020-12-15 17:34:54 +0100275 const default_action = drop();
Yi Tseng47eac892018-07-11 02:17:04 +0800276 counters = egress_vlan_counter;
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700277 size = EGRESS_VLAN_TABLE_SIZE;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800278 }
Yi Tsengbe342052017-11-03 10:21:23 -0700279
280 apply {
Carmelo Cascone1e8843f2018-07-19 19:01:12 +0200281 if (fabric_metadata.is_multicast == _TRUE
Carmelo Casconea5400af2018-07-17 22:11:54 +0200282 && standard_metadata.ingress_port == standard_metadata.egress_port) {
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700283 mark_to_drop(standard_metadata);
Carmelo Casconea5400af2018-07-17 22:11:54 +0200284 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800285
286 if (fabric_metadata.mpls_label == 0) {
287 if (hdr.mpls.isValid()) pop_mpls_if_present();
288 } else {
289 set_mpls();
290 }
291
Daniele Moro7c3a0022019-07-12 13:38:34 -0700292#ifdef WITH_DOUBLE_VLAN_TERMINATION
293 if (fabric_metadata.push_double_vlan == _TRUE) {
294 // Double VLAN termination.
pierventre48e78822020-12-15 17:34:54 +0100295 push_outer_vlan();
Daniele Moro7c3a0022019-07-12 13:38:34 -0700296 push_inner_vlan();
297 } else {
298 // If no push double vlan, inner_vlan_tag must be popped
299 hdr.inner_vlan_tag.setInvalid();
300#endif // WITH_DOUBLE_VLAN_TERMINATION
pierventre48e78822020-12-15 17:34:54 +0100301 // Port-based VLAN tagging; if there is no match drop the packet!
302 egress_vlan.apply();
Daniele Moro7c3a0022019-07-12 13:38:34 -0700303#ifdef WITH_DOUBLE_VLAN_TERMINATION
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800304 }
Daniele Moro7c3a0022019-07-12 13:38:34 -0700305#endif // WITH_DOUBLE_VLAN_TERMINATION
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800306
307 // TTL decrement and check.
308 if (hdr.mpls.isValid()) {
309 hdr.mpls.ttl = hdr.mpls.ttl - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700310 if (hdr.mpls.ttl == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800311 } else {
Charles Chan74ad51e2020-09-12 19:05:42 -0700312 if(hdr.ipv4.isValid() && fabric_metadata.fwd_type != FWD_BRIDGING) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800313 hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700314 if (hdr.ipv4.ttl == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800315 }
316#ifdef WITH_IPV6
Charles Chan74ad51e2020-09-12 19:05:42 -0700317 else if (hdr.ipv6.isValid() && fabric_metadata.fwd_type != FWD_BRIDGING) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800318 hdr.ipv6.hop_limit = hdr.ipv6.hop_limit - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700319 if (hdr.ipv6.hop_limit == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800320 }
321#endif // WITH_IPV6
322 }
Yi Tsengbe342052017-11-03 10:21:23 -0700323 }
324}