1+ /* -*- P4_16 -*- */
2+ #include <core .p4 >
3+ #include <v1model .p4 >
4+
5+ const bit <16 > TYPE_IPV4 = 0x800 ;
6+
7+ /* TODO 1.1: Create a new etherType for MPLS protocol, which will be used to identify it from the ethernet header. */
8+
9+ #define CONST_MAX_PORTS 32
10+ #define CONST_MAX_LABELS 10
11+
12+ /* ************************************************************************
13+ *********************** H E A D E R S ***********************************
14+ *************************************************************************/
15+
16+ typedef bit <9 > egressSpec_t ;
17+ typedef bit <48 > macAddr_t ;
18+ typedef bit <32 > ip4Addr_t ;
19+
20+ header ethernet_t {
21+ macAddr_t dstAddr ;
22+ macAddr_t srcAddr ;
23+ bit <16 > etherType ;
24+ }
25+
26+ /* TODO 1.2: Create a header for MPLS protocol, called "mpls_t". The header should have 4 fields like we described in the README. */
27+
28+ header ipv4_t {
29+ bit <4 > version ;
30+ bit <4 > ihl ;
31+ bit <8 > diffserv ;
32+ bit <16 > totalLen ;
33+ bit <16 > identification ;
34+ bit <3 > flags ;
35+ bit <13 > fragOffset ;
36+ bit <8 > ttl ;
37+ bit <8 > protocol ;
38+ bit <16 > hdrChecksum ;
39+ ip4Addr_t srcAddr ;
40+ ip4Addr_t dstAddr ;
41+ }
42+
43+ /* TODO 2.1: Note that we have created this metadata struct, which will help us identify packets read from ingress and egress routers. */
44+
45+ struct metadata {
46+ bit <1 > is_ingress_border ;
47+ bit <1 > is_egress_border ;
48+ }
49+
50+ /* TODO 1.3: Add the newly-defined "mpls_t" header to the struct "headers". The "mpls_t" header should go in between of "ethernet_t" and "ipv4_t". */
51+
52+ struct headers {
53+ ethernet_t ethernet ;
54+ ipv4_t ipv4 ;
55+ }
56+
57+ /* ************************************************************************
58+ *********************** P A R S E R ***********************************
59+ *************************************************************************/
60+
61+ parser MyParser (packet_in packet ,
62+ out headers hdr ,
63+ inout metadata meta ,
64+ inout standard_metadata_t standard_metadata ) {
65+
66+ state start {
67+ transition parse_ethernet ;
68+ }
69+
70+ state parse_ethernet {
71+ packet .extract (hdr .ethernet );
72+ transition select (hdr .ethernet .etherType ) {
73+
74+ /* TODO 1.5: Call the MPLS parser in case an MPLS packet is detected. */
75+
76+ TYPE_IPV4 : parse_ipv4 ;
77+ default : accept ;
78+ }
79+ }
80+
81+ /* TODO 1.4: Create a parser that extracts the MPLS header that you have created. */
82+
83+ state parse_ipv4 {
84+ packet .extract (hdr .ipv4 );
85+ transition accept ;
86+ }
87+ }
88+
89+ /* ************************************************************************
90+ ************ C H E C K S U M V E R I F I C A T I O N *************
91+ *************************************************************************/
92+
93+ control MyVerifyChecksum (inout headers hdr , inout metadata meta ) {
94+ apply { }
95+ }
96+
97+
98+ /* ************************************************************************
99+ ************** I N G R E S S P R O C E S S I N G *******************
100+ *************************************************************************/
101+
102+ control MyIngress (inout headers hdr ,
103+ inout metadata meta ,
104+ inout standard_metadata_t standard_metadata ) {
105+
106+ action drop () {
107+ mark_to_drop (standard_metadata );
108+ }
109+
110+ /* TODO 2.3: Create the action set_is_ingress_border. */
111+
112+ /* TODO 2.2: Create the table check_is_ingress_border. */
113+
114+ action add_mpls_header (bit <20 > tag ) {
115+
116+ // We add the mpls header
117+ hdr .mpls .setValid ();
118+ hdr .mpls .label = tag ;
119+ hdr .ethernet .etherType = TYPE_MPLS ;
120+ }
121+
122+ /* TODO 2.5: Create the table fec_to_label. */
123+
124+ action mpls_forward (macAddr_t dstAddr , egressSpec_t port ) {
125+ hdr .ethernet .srcAddr = hdr .ethernet .dstAddr ;
126+ hdr .ethernet .dstAddr = dstAddr ;
127+
128+ standard_metadata .egress_spec = port ;
129+ hdr .mpls .ttl = hdr .mpls .ttl - 1 ;
130+ }
131+
132+ /* TODO 3.2: Create the table mpls_tbl. */
133+
134+ /* TODO 3.5: Create the action ipv4_forward. */
135+
136+ /* TODO 3.4: Create the table ipv4_lpm. */
137+
138+ apply {
139+
140+ // We check if it is an ingress border port
141+ check_is_ingress_border .apply ();
142+
143+ if (meta .is_ingress_border == 1 ){
144+
145+ // We need to check if the header is valid since mpls label is based on dst ip
146+ if (hdr .ipv4 .isValid ()){
147+
148+ // We add the label based on the destination
149+ fec_to_label .apply ();
150+ }
151+ }
152+
153+ /* TODO 3.1: Uncomment the following lines. */
154+
155+ // We select the egress port based on the mpls label
156+ // if(hdr.mpls.isValid()){
157+ // mpls_tbl.apply();
158+ // }
159+
160+ /* TODO 3.4 Uncomment the following lines. */
161+
162+ // Normal forwarding
163+ // else if (hdr.ipv4.isValid())
164+ // {
165+ // ipv4_lpm.apply();
166+ // }
167+
168+ }
169+ }
170+
171+ /* ************************************************************************
172+ **************** E G R E S S P R O C E S S I N G *******************
173+ *************************************************************************/
174+
175+ control MyEgress (inout headers hdr ,
176+ inout metadata meta ,
177+ inout standard_metadata_t standard_metadata ) {
178+
179+ action is_egress_border (){
180+
181+ // We remove the mpls header
182+ hdr .mpls .setInvalid ();
183+ hdr .ethernet .etherType = TYPE_IPV4 ;
184+ hdr .ipv4 .ttl = hdr .ipv4 .ttl - 1 ;
185+ }
186+
187+ /* TODO 4.1: Create the table check_is_egress_border. */
188+
189+ apply {
190+ // We check if it is an egress border port
191+ if (hdr .mpls .isValid ()){
192+ check_is_egress_border .apply ();
193+ }
194+ }
195+ }
196+
197+ /* ************************************************************************
198+ ************* C H E C K S U M C O M P U T A T I O N **************
199+ *************************************************************************/
200+
201+ control MyComputeChecksum (inout headers hdr , inout metadata meta ) {
202+
203+ /* TODO 3.6 Uncomment to update the checksum field once the ttl changes. */
204+
205+ // apply {
206+ // update_checksum(
207+ // hdr.ipv4.isValid(),
208+ // { hdr.ipv4.version,
209+ // hdr.ipv4.ihl,
210+ // hdr.ipv4.diffserv,
211+ // hdr.ipv4.totalLen,
212+ // hdr.ipv4.identification,
213+ // hdr.ipv4.flags,
214+ // hdr.ipv4.fragOffset,
215+ // hdr.ipv4.ttl,
216+ // hdr.ipv4.protocol,
217+ // hdr.ipv4.srcAddr,
218+ // hdr.ipv4.dstAddr },
219+ // hdr.ipv4.hdrChecksum,
220+ // HashAlgorithm.csum16);
221+ // }
222+ }
223+
224+ /* ************************************************************************
225+ *********************** D E P A R S E R *******************************
226+ *************************************************************************/
227+
228+ control MyDeparser (packet_out packet , in headers hdr ) {
229+ apply {
230+ packet .emit (hdr .ethernet );
231+ packet .emit (hdr .mpls );
232+ packet .emit (hdr .ipv4 );
233+ }
234+ }
235+
236+ /* ************************************************************************
237+ *********************** S W I T C H *******************************
238+ *************************************************************************/
239+
240+ V1Switch (
241+ MyParser (),
242+ MyVerifyChecksum (),
243+ MyIngress (),
244+ MyEgress (),
245+ MyComputeChecksum (),
246+ MyDeparser ()
247+ ) main ;
0 commit comments