285d42f9a1fa628026955801177585b31469a83f
[samplevnf.git] / VNFs / DPPD-PROX / pkt_parser.h
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
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 #ifndef _PKT_PARSER_H_
18 #define _PKT_PARSER_H_
19
20 #include <rte_mbuf.h>
21 #include <rte_ether.h>
22 #include <rte_ip.h>
23 #include <rte_udp.h>
24 #include <rte_tcp.h>
25 #include <rte_byteorder.h>
26
27 #include "log.h"
28 #include "etypes.h"
29
30 struct pkt_tuple {
31         uint32_t src_addr;
32         uint32_t dst_addr;
33         uint8_t proto_id;
34         uint16_t src_port;
35         uint16_t dst_port;
36         uint16_t l2_types[4];
37 } __attribute__((packed));
38
39 struct l4_meta {
40         uint8_t *l4_hdr;
41         uint8_t *payload;
42         uint16_t len;
43 };
44
45 static void pkt_tuple_debug2(const struct pkt_tuple *pt)
46 {
47         plogx_info("src_ip : %#010x\n", pt->src_addr);
48         plogx_info("dst_ip : %#010x\n", pt->dst_addr);
49         plogx_info("dst_port : %#06x\n", pt->dst_port);
50         plogx_info("src_port : %#06x\n", pt->src_port);
51         plogx_info("proto_id : %#04x\n", pt->proto_id);
52         plogx_info("l2 types: \n");
53         for (int i = 0; i < 4; ++i)
54                 plogx_info("  - %#04x\n", pt->l2_types[i]);
55 }
56
57 static void pkt_tuple_debug(const struct pkt_tuple *pt)
58 {
59         plogx_dbg("src_ip : %#010x\n", pt->src_addr);
60         plogx_dbg("dst_ip : %#010x\n", pt->dst_addr);
61         plogx_dbg("dst_port : %#06x\n", pt->dst_port);
62         plogx_dbg("src_port : %#06x\n", pt->src_port);
63         plogx_dbg("proto_id : %#04x\n", pt->proto_id);
64         plogx_dbg("l2 types: \n");
65         for (int i = 0; i < 4; ++i)
66                 plogx_dbg("  - %#04x\n", pt->l2_types[i]);
67 }
68
69 /* Return 0 on success, i.e. packets parsed without any error. */
70 static int parse_pkt(struct rte_mbuf *mbuf, struct pkt_tuple *pt, struct l4_meta *l4_meta)
71 {
72         struct ether_hdr *peth = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
73         size_t l2_types_count = 0;
74         struct ipv4_hdr* pip = 0;
75
76         /* L2 */
77         pt->l2_types[l2_types_count++] = peth->ether_type;
78
79         switch (peth->ether_type) {
80         case ETYPE_IPv4:
81                         pip = (struct ipv4_hdr *)(peth + 1);
82                 break;
83         case ETYPE_VLAN: {
84                 struct vlan_hdr *vlan = (struct vlan_hdr *)(peth + 1);
85                 pt->l2_types[l2_types_count++] = vlan->eth_proto;
86                 if (vlan->eth_proto == ETYPE_IPv4) {
87                         pip = (struct ipv4_hdr *)(peth + 1);
88                 }
89                 else if (vlan->eth_proto == ETYPE_VLAN) {
90                         struct vlan_hdr *vlan = (struct vlan_hdr *)(peth + 1);
91                         pt->l2_types[l2_types_count++] = vlan->eth_proto;
92                         if (vlan->eth_proto == ETYPE_IPv4) {
93                                 pip = (struct ipv4_hdr *)(peth + 1);
94                         }
95                         else if (vlan->eth_proto == ETYPE_IPv6) {
96                                 return 1;
97                         }
98                         else {
99                                 /* TODO: handle BAD PACKET */
100                                 return 1;
101                         }
102                 }
103         }
104                 break;
105         case ETYPE_8021ad: {
106                 struct vlan_hdr *vlan = (struct vlan_hdr *)(peth + 1);
107                 pt->l2_types[l2_types_count++] = vlan->eth_proto;
108                 if (vlan->eth_proto == ETYPE_VLAN) {
109                         struct vlan_hdr *vlan = (struct vlan_hdr *)(peth + 1);
110                         pt->l2_types[l2_types_count++] = vlan->eth_proto;
111                         if (vlan->eth_proto == ETYPE_IPv4) {
112                                 pip = (struct ipv4_hdr *)(peth + 1);
113                         }
114                         else {
115                                 return 1;
116                         }
117                 }
118                 else {
119                         return 1;
120                 }
121         }
122                 break;
123         case ETYPE_MPLSU:
124                 return -1;
125                 break;
126         default:
127                 plogx_err("Parsing error: unknown packet ether type = %#06x\n", peth->ether_type);
128                 return -1;
129                 break;
130         }
131
132         /* L3 */
133         if ((pip->version_ihl >> 4) == 4) {
134
135                 if ((pip->version_ihl & 0x0f) != 0x05) {
136                         /* TODO: optional fields */
137                         return 1;
138                 }
139
140                 pt->proto_id = pip->next_proto_id;
141                 pt->src_addr = pip->src_addr;
142                 pt->dst_addr = pip->dst_addr;
143         }
144         else {
145                 /* TODO: IPv6 and bad packets */
146                 return 1;
147         }
148
149         /* L4 parser */
150         if (pt->proto_id == IPPROTO_UDP) {
151                 struct udp_hdr *udp = (struct udp_hdr*)(pip + 1);
152                 l4_meta->l4_hdr = (uint8_t*)udp;
153                 pt->src_port = udp->src_port;
154                 pt->dst_port = udp->dst_port;
155                 l4_meta->payload = ((uint8_t*)udp) + sizeof(struct udp_hdr);
156                 l4_meta->len = rte_be_to_cpu_16(udp->dgram_len) - sizeof(struct udp_hdr);
157         }
158         else if (pt->proto_id == IPPROTO_TCP) {
159                 struct tcp_hdr *tcp = (struct tcp_hdr*)(pip + 1);
160                 l4_meta->l4_hdr = (uint8_t*)tcp;
161                 pt->src_port = tcp->src_port;
162                 pt->dst_port = tcp->dst_port;
163
164                 l4_meta->payload = ((uint8_t*)tcp) + ((tcp->data_off >> 4)*4);
165                 l4_meta->len = rte_be_to_cpu_16(pip->total_length) - sizeof(struct ipv4_hdr) - ((tcp->data_off >> 4)*4);
166         }
167         else {
168                 plog_err("unsupported protocol %d\n", pt->proto_id);
169                 return 1;
170         }
171
172         for (; l2_types_count < sizeof(pt->l2_types)/sizeof(pt->l2_types[0]); ++l2_types_count)
173                 pt->l2_types[l2_types_count] = 0;
174
175         return 0;
176 }
177
178 #endif /* _PKT_PARSER_H_ */