blob: e9b0c77d166a99a6c71de95d898f4d3f36df65a5 [file] [log] [blame]
Carmelo Cascone9ab40612017-09-19 16:31:55 +09001// Copyright (c) 2017, Google Inc.
2//
3// P4_16 specification for a packet parser.
4// Note: This code has not been tested and is expected to contain bugs.
5
6#ifndef P4_SPEC_PARSER_P4_
7#define P4_SPEC_PARSER_P4_
8
9#include <v1model.p4>
10#include "headers.p4"
11
12//------------------------------------------------------------------------------
13// Global defines
14//------------------------------------------------------------------------------
15
16#define ETHERTYPE_VLAN1 0x8100
17#define ETHERTYPE_VLAN2 0x9100
18#define ETHERTYPE_VLAN3 0x9200
19#define ETHERTYPE_VLAN4 0x9300
20
21#define ETHERTYPE_IPV4 0x0800
22#define ETHERTYPE_IPV6 0x86dd
23#define ETHERTYPE_ARP 0x0806
24#define ETHERTYPE_ND 0x6007
25#define ETHERTYPE_LLDP 0x88CC
26
27#define IP_PROTOCOLS_TCP 6
28#define IP_PROTOCOLS_UDP 17
29#define IP_PROTOCOLS_ICMP 1
30#define IP_PROTOCOLS_ICMPv6 58
31
32#ifndef CPU_PORT
33// TODO(samarabdi) Change once we move from 9 to 32 bits
34#define CPU_PORT 0xFD // 0xFFFFFFFD
35#endif
36#define VLAN_DEPTH 2
37
38//------------------------------------------------------------------------------
39// List of all recognized headers
40//------------------------------------------------------------------------------
41
42struct parsed_packet_t {
43 ethernet_t ethernet;
44 ipv4_base_t ipv4_base;
45 ipv6_base_t ipv6_base;
46 icmp_header_t icmp_header;
47 tcp_t tcp;
48 udp_t udp;
49 vlan_tag_t[VLAN_DEPTH] vlan_tag; // header stack
50 arp_t arp;
51 packet_in_header_t packet_in;
52 packet_out_header_t packet_out;
53}
54
55//------------------------------------------------------------------------------
56// Parser
57//------------------------------------------------------------------------------
58
59parser pkt_parser(packet_in pk, out parsed_packet_t hdr,
60 inout local_metadata_t local_metadata,
61 inout standard_metadata_t standard_metadata) {
62 state start {
63 transition select(standard_metadata.ingress_port) {
64 CPU_PORT : parse_cpu_header;
65 _ : parse_ethernet;
66 }
67 }
68
69 state parse_ethernet {
70 pk.extract(hdr.ethernet);
71 transition select(hdr.ethernet.ether_type) {
72 ETHERTYPE_VLAN1: parse_vlan;
73 ETHERTYPE_VLAN2: parse_vlan;
74 ETHERTYPE_VLAN3: parse_vlan;
75 ETHERTYPE_VLAN4: parse_vlan;
76 ETHERTYPE_IPV4: parse_ipv4;
77 ETHERTYPE_IPV6: parse_ipv6;
78 ETHERTYPE_ARP: parse_arp;
79 _ : accept;
80 }
81 }
82
83 state parse_vlan {
84 // reference the next element in header stack
85 pk.extract(hdr.vlan_tag.next);
86 transition select(hdr.vlan_tag.last.ether_type) {
87 ETHERTYPE_VLAN1: parse_vlan;
88 ETHERTYPE_VLAN2: parse_vlan;
89 ETHERTYPE_VLAN3: parse_vlan;
90 ETHERTYPE_VLAN4: parse_vlan;
91 ETHERTYPE_IPV4 : parse_ipv4;
92 ETHERTYPE_IPV6 : parse_ipv6;
93 _ : accept;
94 }
95 }
96
97 state parse_ipv4 {
98 pk.extract(hdr.ipv4_base);
99 // TODO(samarabdi): confirm if below concats the two fields
100 transition select(hdr.ipv4_base.frag_offset ++ hdr.ipv4_base.protocol) {
101 IP_PROTOCOLS_ICMP : parse_icmp;
102 IP_PROTOCOLS_TCP : parse_tcp;
103 IP_PROTOCOLS_UDP : parse_udp;
104 _ : accept;
105 }
106 }
107
108 state parse_ipv6 {
109 pk.extract(hdr.ipv6_base);
110 transition select(hdr.ipv6_base.next_header) {
111 IP_PROTOCOLS_ICMPv6: parse_icmp;
112 IP_PROTOCOLS_TCP : parse_tcp;
113 IP_PROTOCOLS_UDP : parse_udp;
114 _ : accept;
115 }
116 }
117
118 state parse_tcp {
119 pk.extract(hdr.tcp);
120 // Normalize TCP port metadata to common port metadata
121 local_metadata.l4_src_port = hdr.tcp.src_port;
122 local_metadata.l4_dst_port = hdr.tcp.dst_port;
123 transition accept;
124 }
125
126 state parse_udp {
127 pk.extract(hdr.udp);
128 // Normalize UDP port metadata to common port metadata
129 local_metadata.l4_src_port = hdr.udp.src_port;
130 local_metadata.l4_dst_port = hdr.udp.dst_port;
131 transition accept;
132 }
133
134 state parse_icmp {
135 pk.extract(hdr.icmp_header);
136 transition accept;
137 }
138
139 state parse_arp {
140 pk.extract(hdr.arp);
141 transition accept;
142 }
143
144 state parse_cpu_header {
145 pk.extract(hdr.packet_out);
146 transition parse_ethernet;
147 }
148} // end pkt_parser
149
150control pkt_deparser(packet_out b, in parsed_packet_t hdr) {
151 apply {
152 // packet_out is not a valid header in a packet destined to CPU_PORT
153 b.emit(hdr.packet_in);
154 b.emit(hdr.ethernet);
155 b.emit(hdr.vlan_tag);
156 b.emit(hdr.ipv4_base);
157 b.emit(hdr.ipv6_base);
158 b.emit(hdr.arp);
159 b.emit(hdr.icmp_header);
160 b.emit(hdr.tcp);
161 b.emit(hdr.udp);
162 }
163}
164
165#endif // P4_SPEC_PARSER_P4_