blob: 82b61ebad33958d8bb68c1bc1ce827d61fe1fa8f [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;
Carmelo Cascone70e816b2019-03-19 16:15:47 -070084 size = NEXT_VLAN_TABLE_SIZE;
Yi Tseng20f9e7b2018-05-24 23:27:39 +080085 }
86
Carmelo Casconeb5324e72018-11-25 02:26:32 -080087#ifdef WITH_XCONNECT
88 /*
89 * Cross-connect table.
90 * Bidirectional forwarding for the same next id.
91 */
92 direct_counter(CounterType.packets_and_bytes) xconnect_counter;
93
94 action output_xconnect(port_num_t port_num) {
95 output(port_num);
96 xconnect_counter.count();
97 }
98
99 action set_next_id_xconnect(next_id_t next_id) {
100 fabric_metadata.next_id = next_id;
101 xconnect_counter.count();
102 }
103
104 table xconnect {
105 key = {
106 standard_metadata.ingress_port: exact @name("ig_port");
107 fabric_metadata.next_id: exact @name("next_id");
108 }
109 actions = {
110 output_xconnect;
111 set_next_id_xconnect;
112 @defaultonly nop;
113 }
114 counters = xconnect_counter;
115 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700116 size = XCONNECT_NEXT_TABLE_SIZE;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800117 }
118#endif // WITH_XCONNECT
119
120#ifdef WITH_SIMPLE_NEXT
Yi Tseng47eac892018-07-11 02:17:04 +0800121 /*
122 * Simple Table.
123 * Do a single egress action based on next id.
124 */
125 direct_counter(CounterType.packets_and_bytes) simple_counter;
126
127 action output_simple(port_num_t port_num) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800128 output(port_num);
Yi Tseng47eac892018-07-11 02:17:04 +0800129 simple_counter.count();
130 }
131
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800132 action routing_simple(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
133 routing(port_num, smac, dmac);
134 simple_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800135 }
136
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800137 action mpls_routing_simple(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
138 mpls_label_t label) {
139 mpls_routing(port_num, smac, dmac, label);
140 simple_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800141 }
142
Yi Tsengbe342052017-11-03 10:21:23 -0700143 table simple {
144 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800145 fabric_metadata.next_id: exact @name("next_id");
Yi Tsengbe342052017-11-03 10:21:23 -0700146 }
Yi Tsengbe342052017-11-03 10:21:23 -0700147 actions = {
Yi Tseng47eac892018-07-11 02:17:04 +0800148 output_simple;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800149 routing_simple;
150 mpls_routing_simple;
151 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700152 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800153 const default_action = nop();
Yi Tseng3a5731e2018-01-22 11:38:58 -0800154 counters = simple_counter;
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700155 size = SIMPLE_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700156 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800157#endif // WITH_SIMPLE_NEXT
Yi Tsengbe342052017-11-03 10:21:23 -0700158
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800159#ifdef WITH_HASHED_NEXT
Yi Tseng47eac892018-07-11 02:17:04 +0800160 /*
161 * Hashed table.
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800162 * Execute an action profile selector based on next id.
Yi Tseng47eac892018-07-11 02:17:04 +0800163 */
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700164 @max_group_size(HASHED_SELECTOR_MAX_GROUP_SIZE)
165 action_selector(HashAlgorithm.crc16, HASHED_ACT_PROFILE_SIZE, 32w16) hashed_selector;
Yi Tseng47eac892018-07-11 02:17:04 +0800166 direct_counter(CounterType.packets_and_bytes) hashed_counter;
167
168 action output_hashed(port_num_t port_num) {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800169 output(port_num);
Yi Tseng47eac892018-07-11 02:17:04 +0800170 hashed_counter.count();
171 }
172
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800173 action routing_hashed(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac) {
174 routing(port_num, smac, dmac);
175 hashed_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800176 }
177
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800178 action mpls_routing_hashed(port_num_t port_num, mac_addr_t smac, mac_addr_t dmac,
179 mpls_label_t label) {
180 mpls_routing(port_num, smac, dmac, label);
181 hashed_counter.count();
Yi Tseng47eac892018-07-11 02:17:04 +0800182 }
183
Yi Tsengbe342052017-11-03 10:21:23 -0700184 table hashed {
185 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800186 fabric_metadata.next_id: exact @name("next_id");
Yi Tseng3d3956d2018-01-31 17:28:05 -0800187 hdr.ipv4.dst_addr: selector;
188 hdr.ipv4.src_addr: selector;
Yi Tseng1d842672017-11-28 16:06:52 -0800189 fabric_metadata.ip_proto: selector;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800190 fabric_metadata.l4_sport: selector;
191 fabric_metadata.l4_dport: selector;
Yi Tsengbe342052017-11-03 10:21:23 -0700192 }
Yi Tsengbe342052017-11-03 10:21:23 -0700193 actions = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800194 output_hashed;
195 routing_hashed;
196 mpls_routing_hashed;
197 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700198 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800199 implementation = hashed_selector;
Yi Tseng3a5731e2018-01-22 11:38:58 -0800200 counters = hashed_counter;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800201 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700202 size = HASHED_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700203 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800204#endif // WITH_HASHED_NEXT
Yi Tsengbe342052017-11-03 10:21:23 -0700205
206 /*
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800207 * Multicast
208 * Maps next IDs to PRE multicat group IDs.
Yi Tsengbe342052017-11-03 10:21:23 -0700209 */
Yi Tseng47eac892018-07-11 02:17:04 +0800210 direct_counter(CounterType.packets_and_bytes) multicast_counter;
211
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800212 action set_mcast_group_id(mcast_group_id_t group_id) {
213 standard_metadata.mcast_grp = group_id;
Carmelo Cascone1e8843f2018-07-19 19:01:12 +0200214 fabric_metadata.is_multicast = _TRUE;
Yi Tseng47eac892018-07-11 02:17:04 +0800215 multicast_counter.count();
Carmelo Casconea1061402018-02-03 17:39:59 -0800216 }
217
Carmelo Casconea1061402018-02-03 17:39:59 -0800218 table multicast {
Yi Tsengbe342052017-11-03 10:21:23 -0700219 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800220 fabric_metadata.next_id: exact @name("next_id");
Yi Tsengbe342052017-11-03 10:21:23 -0700221 }
222 actions = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800223 set_mcast_group_id;
224 @defaultonly nop;
Yi Tsengbe342052017-11-03 10:21:23 -0700225 }
Carmelo Casconea1061402018-02-03 17:39:59 -0800226 counters = multicast_counter;
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800227 const default_action = nop();
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700228 size = MULTICAST_NEXT_TABLE_SIZE;
Yi Tsengbe342052017-11-03 10:21:23 -0700229 }
230
231 apply {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800232#ifdef WITH_XCONNECT
233 // xconnect might set a new next_id.
234 xconnect.apply();
235#endif // WITH_XCONNECT
236#ifdef WITH_SIMPLE_NEXT
237 simple.apply();
238#endif // WITH_SIMPLE_NEXT
239#ifdef WITH_HASHED_NEXT
240 hashed.apply();
241#endif // WITH_HASHED_NEXT
242 multicast.apply();
243 next_vlan.apply();
Yi Tsengbe342052017-11-03 10:21:23 -0700244 }
245}
246
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800247control EgressNextControl (inout parsed_headers_t hdr,
248 inout fabric_metadata_t fabric_metadata,
249 inout standard_metadata_t standard_metadata) {
250 @hidden
251 action pop_mpls_if_present() {
252 hdr.mpls.setInvalid();
253 // Assuming there's an IP header after the MPLS one.
254 fabric_metadata.eth_type = fabric_metadata.ip_eth_type;
255 }
256
257 @hidden
258 action set_mpls() {
259 hdr.mpls.setValid();
260 hdr.mpls.label = fabric_metadata.mpls_label;
261 hdr.mpls.tc = 3w0;
262 hdr.mpls.bos = 1w1; // BOS = TRUE
263 hdr.mpls.ttl = fabric_metadata.mpls_ttl; // Decrement after push.
264 fabric_metadata.eth_type = ETHERTYPE_MPLS;
265 }
266
267 @hidden
268 action push_vlan() {
269 // If VLAN is already valid, we overwrite it with a potentially new VLAN
270 // ID, and same CFI, PRI, and eth_type values found in ingress.
271 hdr.vlan_tag.setValid();
272 hdr.vlan_tag.cfi = fabric_metadata.vlan_cfi;
273 hdr.vlan_tag.pri = fabric_metadata.vlan_pri;
274 hdr.vlan_tag.eth_type = fabric_metadata.eth_type;
275 hdr.vlan_tag.vlan_id = fabric_metadata.vlan_id;
276 hdr.ethernet.eth_type = ETHERTYPE_VLAN;
277 }
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800278
Yi Tseng47eac892018-07-11 02:17:04 +0800279 /*
280 * Egress VLAN Table.
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800281 * Pops the VLAN tag if the pair egress port and VLAN ID is matched.
Yi Tseng47eac892018-07-11 02:17:04 +0800282 */
283 direct_counter(CounterType.packets_and_bytes) egress_vlan_counter;
284
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800285 action pop_vlan() {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800286 hdr.ethernet.eth_type = fabric_metadata.eth_type;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800287 hdr.vlan_tag.setInvalid();
Yi Tseng47eac892018-07-11 02:17:04 +0800288 egress_vlan_counter.count();
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800289 }
290
291 table egress_vlan {
292 key = {
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800293 fabric_metadata.vlan_id: exact @name("vlan_id");
294 standard_metadata.egress_port: exact @name("eg_port");
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800295 }
296 actions = {
297 pop_vlan;
Yi Tseng47eac892018-07-11 02:17:04 +0800298 @defaultonly nop;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800299 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800300 const default_action = nop();
Yi Tseng47eac892018-07-11 02:17:04 +0800301 counters = egress_vlan_counter;
Carmelo Cascone70e816b2019-03-19 16:15:47 -0700302 size = EGRESS_VLAN_TABLE_SIZE;
Yi Tseng20f9e7b2018-05-24 23:27:39 +0800303 }
Yi Tsengbe342052017-11-03 10:21:23 -0700304
305 apply {
Carmelo Cascone1e8843f2018-07-19 19:01:12 +0200306 if (fabric_metadata.is_multicast == _TRUE
Carmelo Casconea5400af2018-07-17 22:11:54 +0200307 && standard_metadata.ingress_port == standard_metadata.egress_port) {
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700308 mark_to_drop(standard_metadata);
Carmelo Casconea5400af2018-07-17 22:11:54 +0200309 }
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800310
311 if (fabric_metadata.mpls_label == 0) {
312 if (hdr.mpls.isValid()) pop_mpls_if_present();
313 } else {
314 set_mpls();
315 }
316
317 if (!egress_vlan.apply().hit) {
318 // Push VLAN tag if not the default one.
319 if (fabric_metadata.vlan_id != DEFAULT_VLAN_ID) {
320 push_vlan();
321 }
322 }
323
324 // TTL decrement and check.
325 if (hdr.mpls.isValid()) {
326 hdr.mpls.ttl = hdr.mpls.ttl - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700327 if (hdr.mpls.ttl == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800328 } else {
329 if(hdr.ipv4.isValid()) {
330 hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700331 if (hdr.ipv4.ttl == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800332 }
333#ifdef WITH_IPV6
334 else if (hdr.ipv6.isValid()) {
335 hdr.ipv6.hop_limit = hdr.ipv6.hop_limit - 1;
Carmelo Cascone9b607da2019-05-08 14:03:01 -0700336 if (hdr.ipv6.hop_limit == 0) mark_to_drop(standard_metadata);
Carmelo Casconeb5324e72018-11-25 02:26:32 -0800337 }
338#endif // WITH_IPV6
339 }
Yi Tsengbe342052017-11-03 10:21:23 -0700340 }
341}