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