blob: b5b8aa65cee57f776e2a4f87b690bbc8e2cbe142 [file] [log] [blame]
Carmelo Cascone9ab40612017-09-19 16:31:55 +09001// Copyright (c) 2017, Google Inc.
2//
3// P4_16 specification for a L3 forwarding app.
4// Note: This code has not been tested and is expected to contain bugs.
5
6#ifndef P4_SPEC_L3_FWD_P4_
7#define P4_SPEC_L3_FWD_P4_
8
9#include "headers.p4"
10#include "parser.p4"
11
12#ifdef P4_EXPLICIT_LAG
13#include "lag.p4"
14#endif
15
16//------------------------------------------------------------------------------
17// IPv4/v6 L3 Forwarding
18//------------------------------------------------------------------------------
19
20control l3_fwd(inout parsed_packet_t hdr,
21 inout local_metadata_t local_metadata,
22 inout standard_metadata_t standard_metadata) {
23
24
25 @proto_package("l3_fwd")
26 action set_nexthop(@proto_tag(1) PortNum port,
27 @proto_tag(2) EthernetAddress smac,
28 @proto_tag(3) EthernetAddress dmac) {
29 standard_metadata.egress_spec = port;
30 hdr.ethernet.src_addr = smac;
31 hdr.ethernet.dst_addr = dmac;
32 // if (hdr.ipv4_base.isValid()) {
33 hdr.ipv4_base.ttl = hdr.ipv4_base.ttl - 1;
34 // } else if (hdr.ipv6_base.isValid()) {
35 // hdr.ipv6_base.hop_limit = hdr.ipv6_base.hop_limit - 1;
36 // }
37 }
38
39 // Hit implies that the packet needs to be L3 forwarded.
40 // Equivalent of BCM MY_STATION table
41 @proto_package("l3_fwd")
42 table l3_routing_classifier_table {
43 key = {
44 hdr.ethernet.dst_addr : exact @proto_tag(1);
45 }
46 actions = {
47 @proto_tag(1) NoAction;
48 }
49 const default_action = NoAction();
50 }
51
52 action_selector(HashAlgorithm.crc16, 32w1024, 32w14) wcmp_action_profile;
53
54 // LPM forwarding tables for IPV4 packets.
55 @proto_package("l3_fwd")
56 table l3_ipv4_override_table {
57 key = {
58 hdr.ipv4_base.dst_addr : lpm @proto_tag(1);
59
60 hdr.ipv4_base.dst_addr : selector @proto_tag(2);
61 hdr.ipv4_base.src_addr : selector @proto_tag(3);
62 hdr.ipv4_base.protocol : selector @proto_tag(4);
63 local_metadata.l4_src_port : selector @proto_tag(5);
64 local_metadata.l4_dst_port : selector @proto_tag(6);
65 }
66 actions = {
67 @proto_tag(1) set_nexthop;
68 @proto_tag(2) NoAction;
69 }
70 const default_action = NoAction();
71 // TODO(samarabdi): do we need to specify selector size?
72 implementation = wcmp_action_profile;
73 }
74
75 @proto_package("l3_fwd")
76 table l3_ipv4_vrf_table {
77 key = {
78 local_metadata.vrf_id: exact @proto_tag(1);
79 hdr.ipv4_base.dst_addr : lpm @proto_tag(2);
80 hdr.ipv4_base.dst_addr : selector @proto_tag(3);
81 hdr.ipv4_base.src_addr : selector @proto_tag(4);
82 hdr.ipv4_base.protocol : selector @proto_tag(5);
83 local_metadata.l4_src_port : selector @proto_tag(6);
84 local_metadata.l4_dst_port : selector @proto_tag(7);
85 }
86 actions = {
87 @proto_tag(1) set_nexthop;
88 @proto_tag(2) NoAction;
89 }
90 const default_action = NoAction();
91 implementation = wcmp_action_profile;
92 }
93
94 @proto_package("l3_fwd")
95 table l3_ipv4_fallback_table {
96 key = {
97 hdr.ipv4_base.dst_addr : lpm @proto_tag(1);
98 hdr.ipv4_base.dst_addr : selector @proto_tag(2);
99 hdr.ipv4_base.src_addr : selector @proto_tag(3);
100 hdr.ipv4_base.protocol : selector @proto_tag(4);
101 local_metadata.l4_src_port : selector @proto_tag(5);
102 local_metadata.l4_dst_port : selector @proto_tag(6);
103 }
104 actions = {
105 @proto_tag(1) set_nexthop;
106 @proto_tag(2) NoAction;
107 }
108 const default_action = NoAction();
109 implementation = wcmp_action_profile;
110 }
111
112 // LPM forwarding tables for IPV6 packets.
113
114 // @proto_package("l3_fwd")
115 // table l3_ipv6_override_table {
116 // key = {
117 // hdr.ipv6_base.dst_addr : lpm @proto_tag(1);
118 // hdr.ipv6_base.dst_addr : selector @proto_tag(2);
119 // hdr.ipv6_base.src_addr : selector @proto_tag(3);
120 // hdr.ipv6_base.flow_label : selector @proto_tag(4);
121 // local_metadata.l4_src_port : selector @proto_tag(5);
122 // local_metadata.l4_dst_port : selector @proto_tag(6);
123 // }
124 // actions = {
125 // @proto_tag(1) set_nexthop;
126 // }
127 // implementation = wcmp_action_profile;
128 // }
129
130 // @proto_package("l3_fwd")
131 // table l3_ipv6_vrf_table {
132 // key = {
133 // local_metadata.vrf_id: exact @proto_tag(1);
134 // hdr.ipv6_base.dst_addr : lpm @proto_tag(2);
135 // hdr.ipv6_base.dst_addr : selector @proto_tag(3);
136 // hdr.ipv6_base.src_addr : selector @proto_tag(4);
137 // hdr.ipv6_base.flow_label : selector @proto_tag(5);
138 // local_metadata.l4_src_port : selector @proto_tag(6);
139 // local_metadata.l4_dst_port : selector @proto_tag(7);
140 // }
141 // actions = {
142 // @proto_tag(1) set_nexthop;
143 // }
144 // implementation = wcmp_action_profile;
145 // }
146
147 // @proto_package("l3_fwd")
148 // table l3_ipv6_fallback_table {
149 // key = {
150 // hdr.ipv6_base.dst_addr : lpm @proto_tag(1);
151 // hdr.ipv6_base.dst_addr : selector @proto_tag(2);
152 // hdr.ipv6_base.src_addr : selector @proto_tag(3);
153 // hdr.ipv6_base.flow_label : selector @proto_tag(4);
154 // local_metadata.l4_src_port : selector @proto_tag(5);
155 // local_metadata.l4_dst_port : selector @proto_tag(6);
156 // }
157 // actions = {
158 // @proto_tag(1) set_nexthop;
159 // }
160 // implementation = wcmp_action_profile;
161 // }
162
163 apply {
164 if(l3_routing_classifier_table.apply().hit) {
165 if (hdr.ipv4_base.isValid()) {
166 if(!l3_ipv4_override_table.apply().hit) {
167 if(!l3_ipv4_vrf_table.apply().hit) {
168 l3_ipv4_fallback_table.apply();
169 }
170 }
171 if(hdr.ipv4_base.ttl == 0) {
172 mark_to_drop();
173 return;
174 }
175 }// else if (hdr.ipv6_base.isValid()) {
176 // if(!l3_ipv6_override_table.apply().hit) {
177 // if(!l3_ipv6_vrf_table.apply().hit) {
178 // l3_ipv6_fallback_table.apply();
179 // }
180 // }
181 // if(hdr.ipv6_base.hop_limit == 0) {
182 // mark_to_drop();
183 // return;
184 // }
185 // }
186 }
187 }
188#ifdef P4_EXPLICIT_LAG
189 lag_handling() lag;
190 lag(hdr, local_metadata, standard_metadata);
191#endif
192} // end l3_fwd
193
194#endif // P4_SPEC_L3_FWD_P4_