Update appveyor OpenSSL link
[cascardo/ovs.git] / lib / dp-packet.h
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
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 DPBUF_H
18 #define DPBUF_H 1
19
20 #include <stddef.h>
21 #include <stdint.h>
22 #include "list.h"
23 #include "packets.h"
24 #include "util.h"
25 #include "netdev-dpdk.h"
26
27 #ifdef  __cplusplus
28 extern "C" {
29 #endif
30
31 enum OVS_PACKED_ENUM dp_packet_source {
32     DPBUF_MALLOC,              /* Obtained via malloc(). */
33     DPBUF_STACK,               /* Un-movable stack space or static buffer. */
34     DPBUF_STUB,                /* Starts on stack, may expand into heap. */
35     DPBUF_DPDK,                /* buffer data is from DPDK allocated memory.
36                                 * ref to build_dp_packet() in netdev-dpdk. */
37 };
38
39 /* Buffer for holding packet data.  A dp_packet is automatically reallocated
40  * as necessary if it grows too large for the available memory.
41  */
42 struct dp_packet {
43 #ifdef DPDK_NETDEV
44     struct rte_mbuf mbuf;       /* DPDK mbuf */
45 #else
46     void *base_;                /* First byte of allocated space. */
47     uint16_t allocated_;        /* Number of bytes allocated. */
48     uint16_t data_ofs;          /* First byte actually in use. */
49     uint32_t size_;             /* Number of bytes in use. */
50     uint32_t rss_hash;          /* Packet hash. */
51     bool rss_hash_valid;        /* Is the 'rss_hash' valid? */
52 #endif
53     enum dp_packet_source source;  /* Source of memory allocated as 'base'. */
54     uint8_t l2_pad_size;           /* Detected l2 padding size.
55                                     * Padding is non-pullable. */
56     uint16_t l2_5_ofs;             /* MPLS label stack offset, or UINT16_MAX */
57     uint16_t l3_ofs;               /* Network-level header offset,
58                                     * or UINT16_MAX. */
59     uint16_t l4_ofs;               /* Transport-level header offset,
60                                       or UINT16_MAX. */
61     struct pkt_metadata md;
62 };
63
64 static inline void *dp_packet_data(const struct dp_packet *);
65 static inline void dp_packet_set_data(struct dp_packet *, void *);
66 static inline void *dp_packet_base(const struct dp_packet *);
67 static inline void dp_packet_set_base(struct dp_packet *, void *);
68
69 static inline uint32_t dp_packet_size(const struct dp_packet *);
70 static inline void dp_packet_set_size(struct dp_packet *, uint32_t);
71
72 static inline uint16_t dp_packet_get_allocated(const struct dp_packet *);
73 static inline void dp_packet_set_allocated(struct dp_packet *, uint16_t);
74
75 void *dp_packet_resize_l2(struct dp_packet *, int increment);
76 void *dp_packet_resize_l2_5(struct dp_packet *, int increment);
77 static inline void *dp_packet_l2(const struct dp_packet *);
78 static inline void dp_packet_reset_offsets(struct dp_packet *);
79 static inline uint8_t dp_packet_l2_pad_size(const struct dp_packet *);
80 static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint8_t);
81 static inline void *dp_packet_l2_5(const struct dp_packet *);
82 static inline void dp_packet_set_l2_5(struct dp_packet *, void *);
83 static inline void *dp_packet_l3(const struct dp_packet *);
84 static inline void dp_packet_set_l3(struct dp_packet *, void *);
85 static inline void *dp_packet_l4(const struct dp_packet *);
86 static inline void dp_packet_set_l4(struct dp_packet *, void *);
87 static inline size_t dp_packet_l4_size(const struct dp_packet *);
88 static inline const void *dp_packet_get_tcp_payload(const struct dp_packet *);
89 static inline const void *dp_packet_get_udp_payload(const struct dp_packet *);
90 static inline const void *dp_packet_get_sctp_payload(const struct dp_packet *);
91 static inline const void *dp_packet_get_icmp_payload(const struct dp_packet *);
92 static inline const void *dp_packet_get_nd_payload(const struct dp_packet *);
93
94 void dp_packet_use(struct dp_packet *, void *, size_t);
95 void dp_packet_use_stub(struct dp_packet *, void *, size_t);
96 void dp_packet_use_const(struct dp_packet *, const void *, size_t);
97
98 void dp_packet_init_dpdk(struct dp_packet *, size_t allocated);
99
100 void dp_packet_init(struct dp_packet *, size_t);
101 void dp_packet_uninit(struct dp_packet *);
102
103 struct dp_packet *dp_packet_new(size_t);
104 struct dp_packet *dp_packet_new_with_headroom(size_t, size_t headroom);
105 struct dp_packet *dp_packet_clone(const struct dp_packet *);
106 struct dp_packet *dp_packet_clone_with_headroom(const struct dp_packet *,
107                                                 size_t headroom);
108 struct dp_packet *dp_packet_clone_data(const void *, size_t);
109 struct dp_packet *dp_packet_clone_data_with_headroom(const void *, size_t,
110                                                      size_t headroom);
111 static inline void dp_packet_delete(struct dp_packet *);
112
113 static inline void *dp_packet_at(const struct dp_packet *, size_t offset,
114                                  size_t size);
115 static inline void *dp_packet_at_assert(const struct dp_packet *,
116                                         size_t offset, size_t size);
117 static inline void *dp_packet_tail(const struct dp_packet *);
118 static inline void *dp_packet_end(const struct dp_packet *);
119
120 void *dp_packet_put_uninit(struct dp_packet *, size_t);
121 void *dp_packet_put_zeros(struct dp_packet *, size_t);
122 void *dp_packet_put(struct dp_packet *, const void *, size_t);
123 char *dp_packet_put_hex(struct dp_packet *, const char *s, size_t *n);
124 void dp_packet_reserve(struct dp_packet *, size_t);
125 void dp_packet_reserve_with_tailroom(struct dp_packet *, size_t headroom,
126                                      size_t tailroom);
127 void *dp_packet_push_uninit(struct dp_packet *, size_t);
128 void *dp_packet_push_zeros(struct dp_packet *, size_t);
129 void *dp_packet_push(struct dp_packet *, const void *, size_t);
130
131 static inline size_t dp_packet_headroom(const struct dp_packet *);
132 static inline size_t dp_packet_tailroom(const struct dp_packet *);
133 void dp_packet_prealloc_headroom(struct dp_packet *, size_t);
134 void dp_packet_prealloc_tailroom(struct dp_packet *, size_t);
135 void dp_packet_shift(struct dp_packet *, int);
136
137 static inline void dp_packet_clear(struct dp_packet *);
138 static inline void *dp_packet_pull(struct dp_packet *, size_t);
139 static inline void *dp_packet_try_pull(struct dp_packet *, size_t);
140
141 void *dp_packet_steal_data(struct dp_packet *);
142
143 char *dp_packet_to_string(const struct dp_packet *, size_t maxbytes);
144 static inline bool dp_packet_equal(const struct dp_packet *,
145                                    const struct dp_packet *);
146
147 \f
148 /* Frees memory that 'b' points to, as well as 'b' itself. */
149 static inline void
150 dp_packet_delete(struct dp_packet *b)
151 {
152     if (b) {
153         if (b->source == DPBUF_DPDK) {
154             /* If this dp_packet was allocated by DPDK it must have been
155              * created as a dp_packet */
156             free_dpdk_buf((struct dp_packet*) b);
157             return;
158         }
159
160         dp_packet_uninit(b);
161         free(b);
162     }
163 }
164
165 /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
166  * byte 'offset'.  Otherwise, returns a null pointer. */
167 static inline void *
168 dp_packet_at(const struct dp_packet *b, size_t offset, size_t size)
169 {
170     return offset + size <= dp_packet_size(b)
171            ? (char *) dp_packet_data(b) + offset
172            : NULL;
173 }
174
175 /* Returns a pointer to byte 'offset' in 'b', which must contain at least
176  * 'offset + size' bytes of data. */
177 static inline void *
178 dp_packet_at_assert(const struct dp_packet *b, size_t offset, size_t size)
179 {
180     ovs_assert(offset + size <= dp_packet_size(b));
181     return ((char *) dp_packet_data(b)) + offset;
182 }
183
184 /* Returns a pointer to byte following the last byte of data in use in 'b'. */
185 static inline void *
186 dp_packet_tail(const struct dp_packet *b)
187 {
188     return (char *) dp_packet_data(b) + dp_packet_size(b);
189 }
190
191 /* Returns a pointer to byte following the last byte allocated for use (but
192  * not necessarily in use) in 'b'. */
193 static inline void *
194 dp_packet_end(const struct dp_packet *b)
195 {
196     return (char *) dp_packet_base(b) + dp_packet_get_allocated(b);
197 }
198
199 /* Returns the number of bytes of headroom in 'b', that is, the number of bytes
200  * of unused space in dp_packet 'b' before the data that is in use.  (Most
201  * commonly, the data in a dp_packet is at its beginning, and thus the
202  * dp_packet's headroom is 0.) */
203 static inline size_t
204 dp_packet_headroom(const struct dp_packet *b)
205 {
206     return (char *) dp_packet_data(b) - (char *) dp_packet_base(b);
207 }
208
209 /* Returns the number of bytes that may be appended to the tail end of
210  * dp_packet 'b' before the dp_packet must be reallocated. */
211 static inline size_t
212 dp_packet_tailroom(const struct dp_packet *b)
213 {
214     return (char *) dp_packet_end(b) - (char *) dp_packet_tail(b);
215 }
216
217 /* Clears any data from 'b'. */
218 static inline void
219 dp_packet_clear(struct dp_packet *b)
220 {
221     dp_packet_set_data(b, dp_packet_base(b));
222     dp_packet_set_size(b, 0);
223 }
224
225 /* Removes 'size' bytes from the head end of 'b', which must contain at least
226  * 'size' bytes of data.  Returns the first byte of data removed. */
227 static inline void *
228 dp_packet_pull(struct dp_packet *b, size_t size)
229 {
230     void *data = dp_packet_data(b);
231     ovs_assert(dp_packet_size(b) - dp_packet_l2_pad_size(b) >= size);
232     dp_packet_set_data(b, (char *) dp_packet_data(b) + size);
233     dp_packet_set_size(b, dp_packet_size(b) - size);
234     return data;
235 }
236
237 /* If 'b' has at least 'size' bytes of data, removes that many bytes from the
238  * head end of 'b' and returns the first byte removed.  Otherwise, returns a
239  * null pointer without modifying 'b'. */
240 static inline void *
241 dp_packet_try_pull(struct dp_packet *b, size_t size)
242 {
243     return dp_packet_size(b) - dp_packet_l2_pad_size(b) >= size
244         ? dp_packet_pull(b, size) : NULL;
245 }
246
247 static inline bool
248 dp_packet_equal(const struct dp_packet *a, const struct dp_packet *b)
249 {
250     return dp_packet_size(a) == dp_packet_size(b) &&
251            !memcmp(dp_packet_data(a), dp_packet_data(b), dp_packet_size(a));
252 }
253
254 /* Get the start of the Ethernet frame.  'l3_ofs' marks the end of the l2
255  * headers, so return NULL if it is not set. */
256 static inline void *
257 dp_packet_l2(const struct dp_packet *b)
258 {
259     return (b->l3_ofs != UINT16_MAX) ? dp_packet_data(b) : NULL;
260 }
261
262 /* Resets all layer offsets.  'l3' offset must be set before 'l2' can be
263  * retrieved. */
264 static inline void
265 dp_packet_reset_offsets(struct dp_packet *b)
266 {
267     b->l2_pad_size = 0;
268     b->l2_5_ofs = UINT16_MAX;
269     b->l3_ofs = UINT16_MAX;
270     b->l4_ofs = UINT16_MAX;
271 }
272
273 static inline uint8_t
274 dp_packet_l2_pad_size(const struct dp_packet *b)
275 {
276     return b->l2_pad_size;
277 }
278
279 static inline void
280 dp_packet_set_l2_pad_size(struct dp_packet *b, uint8_t pad_size)
281 {
282     ovs_assert(pad_size <= dp_packet_size(b));
283     b->l2_pad_size = pad_size;
284 }
285
286 static inline void *
287 dp_packet_l2_5(const struct dp_packet *b)
288 {
289     return b->l2_5_ofs != UINT16_MAX
290            ? (char *) dp_packet_data(b) + b->l2_5_ofs
291            : NULL;
292 }
293
294 static inline void
295 dp_packet_set_l2_5(struct dp_packet *b, void *l2_5)
296 {
297     b->l2_5_ofs = l2_5
298                   ? (char *) l2_5 - (char *) dp_packet_data(b)
299                   : UINT16_MAX;
300 }
301
302 static inline void *
303 dp_packet_l3(const struct dp_packet *b)
304 {
305     return b->l3_ofs != UINT16_MAX
306            ? (char *) dp_packet_data(b) + b->l3_ofs
307            : NULL;
308 }
309
310 static inline void
311 dp_packet_set_l3(struct dp_packet *b, void *l3)
312 {
313     b->l3_ofs = l3 ? (char *) l3 - (char *) dp_packet_data(b) : UINT16_MAX;
314 }
315
316 static inline void *
317 dp_packet_l4(const struct dp_packet *b)
318 {
319     return b->l4_ofs != UINT16_MAX
320            ? (char *) dp_packet_data(b) + b->l4_ofs
321            : NULL;
322 }
323
324 static inline void
325 dp_packet_set_l4(struct dp_packet *b, void *l4)
326 {
327     b->l4_ofs = l4 ? (char *) l4 - (char *) dp_packet_data(b) : UINT16_MAX;
328 }
329
330 static inline size_t
331 dp_packet_l4_size(const struct dp_packet *b)
332 {
333     return b->l4_ofs != UINT16_MAX
334         ? (const char *)dp_packet_tail(b) - (const char *)dp_packet_l4(b)
335         - dp_packet_l2_pad_size(b)
336         : 0;
337 }
338
339 static inline const void *
340 dp_packet_get_tcp_payload(const struct dp_packet *b)
341 {
342     size_t l4_size = dp_packet_l4_size(b);
343
344     if (OVS_LIKELY(l4_size >= TCP_HEADER_LEN)) {
345         struct tcp_header *tcp = dp_packet_l4(b);
346         int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4;
347
348         if (OVS_LIKELY(tcp_len >= TCP_HEADER_LEN && tcp_len <= l4_size)) {
349             return (const char *)tcp + tcp_len;
350         }
351     }
352     return NULL;
353 }
354
355 static inline const void *
356 dp_packet_get_udp_payload(const struct dp_packet *b)
357 {
358     return OVS_LIKELY(dp_packet_l4_size(b) >= UDP_HEADER_LEN)
359         ? (const char *)dp_packet_l4(b) + UDP_HEADER_LEN : NULL;
360 }
361
362 static inline const void *
363 dp_packet_get_sctp_payload(const struct dp_packet *b)
364 {
365     return OVS_LIKELY(dp_packet_l4_size(b) >= SCTP_HEADER_LEN)
366         ? (const char *)dp_packet_l4(b) + SCTP_HEADER_LEN : NULL;
367 }
368
369 static inline const void *
370 dp_packet_get_icmp_payload(const struct dp_packet *b)
371 {
372     return OVS_LIKELY(dp_packet_l4_size(b) >= ICMP_HEADER_LEN)
373         ? (const char *)dp_packet_l4(b) + ICMP_HEADER_LEN : NULL;
374 }
375
376 static inline const void *
377 dp_packet_get_nd_payload(const struct dp_packet *b)
378 {
379     return OVS_LIKELY(dp_packet_l4_size(b) >= ND_MSG_LEN)
380         ? (const char *)dp_packet_l4(b) + ND_MSG_LEN : NULL;
381 }
382
383 #ifdef DPDK_NETDEV
384 BUILD_ASSERT_DECL(offsetof(struct dp_packet, mbuf) == 0);
385
386 static inline void *
387 dp_packet_base(const struct dp_packet *b)
388 {
389     return b->mbuf.buf_addr;
390 }
391
392 static inline void
393 dp_packet_set_base(struct dp_packet *b, void *d)
394 {
395     b->mbuf.buf_addr = d;
396 }
397
398 static inline uint32_t
399 dp_packet_size(const struct dp_packet *b)
400 {
401     return b->mbuf.pkt_len;
402 }
403
404 static inline void
405 dp_packet_set_size(struct dp_packet *b, uint32_t v)
406 {
407     /* netdev-dpdk does not currently support segmentation; consequently, for
408      * all intents and purposes, 'data_len' (16 bit) and 'pkt_len' (32 bit) may
409      * be used interchangably.
410      *
411      * On the datapath, it is expected that the size of packets
412      * (and thus 'v') will always be <= UINT16_MAX; this means that there is no
413      * loss of accuracy in assigning 'v' to 'data_len'.
414      */
415     b->mbuf.data_len = (uint16_t)v;  /* Current seg length. */
416     b->mbuf.pkt_len = v;             /* Total length of all segments linked to
417                                       * this segment. */
418 }
419
420 static inline uint16_t
421 __packet_data(const struct dp_packet *b)
422 {
423     return b->mbuf.data_off;
424 }
425
426 static inline void
427 __packet_set_data(struct dp_packet *b, uint16_t v)
428 {
429     b->mbuf.data_off = v;
430 }
431
432 static inline uint16_t
433 dp_packet_get_allocated(const struct dp_packet *b)
434 {
435     return b->mbuf.buf_len;
436 }
437
438 static inline void
439 dp_packet_set_allocated(struct dp_packet *b, uint16_t s)
440 {
441     b->mbuf.buf_len = s;
442 }
443 #else
444 static inline void *
445 dp_packet_base(const struct dp_packet *b)
446 {
447     return b->base_;
448 }
449
450 static inline void
451 dp_packet_set_base(struct dp_packet *b, void *d)
452 {
453     b->base_ = d;
454 }
455
456 static inline uint32_t
457 dp_packet_size(const struct dp_packet *b)
458 {
459     return b->size_;
460 }
461
462 static inline void
463 dp_packet_set_size(struct dp_packet *b, uint32_t v)
464 {
465     b->size_ = v;
466 }
467
468 static inline uint16_t
469 __packet_data(const struct dp_packet *b)
470 {
471     return b->data_ofs;
472 }
473
474 static inline void
475 __packet_set_data(struct dp_packet *b, uint16_t v)
476 {
477     b->data_ofs = v;
478 }
479
480 static inline uint16_t
481 dp_packet_get_allocated(const struct dp_packet *b)
482 {
483     return b->allocated_;
484 }
485
486 static inline void
487 dp_packet_set_allocated(struct dp_packet *b, uint16_t s)
488 {
489     b->allocated_ = s;
490 }
491 #endif
492
493 static inline void *
494 dp_packet_data(const struct dp_packet *b)
495 {
496     return __packet_data(b) != UINT16_MAX
497            ? (char *) dp_packet_base(b) + __packet_data(b) : NULL;
498 }
499
500 static inline void
501 dp_packet_set_data(struct dp_packet *b, void *data)
502 {
503     if (data) {
504         __packet_set_data(b, (char *) data - (char *) dp_packet_base(b));
505     } else {
506         __packet_set_data(b, UINT16_MAX);
507     }
508 }
509
510 static inline void
511 dp_packet_reset_packet(struct dp_packet *b, int off)
512 {
513     dp_packet_set_size(b, dp_packet_size(b) - off);
514     dp_packet_set_data(b, ((unsigned char *) dp_packet_data(b) + off));
515     b->l2_5_ofs = b->l3_ofs = b->l4_ofs = UINT16_MAX;
516 }
517
518 /* Returns the RSS hash of the packet 'p'.  Note that the returned value is
519  * correct only if 'dp_packet_rss_valid(p)' returns true */
520 static inline uint32_t
521 dp_packet_get_rss_hash(struct dp_packet *p)
522 {
523 #ifdef DPDK_NETDEV
524     return p->mbuf.hash.rss;
525 #else
526     return p->rss_hash;
527 #endif
528 }
529
530 static inline void
531 dp_packet_set_rss_hash(struct dp_packet *p, uint32_t hash)
532 {
533 #ifdef DPDK_NETDEV
534     p->mbuf.hash.rss = hash;
535     p->mbuf.ol_flags |= PKT_RX_RSS_HASH;
536 #else
537     p->rss_hash = hash;
538     p->rss_hash_valid = true;
539 #endif
540 }
541
542 static inline bool
543 dp_packet_rss_valid(struct dp_packet *p)
544 {
545 #ifdef DPDK_NETDEV
546     return p->mbuf.ol_flags & PKT_RX_RSS_HASH;
547 #else
548     return p->rss_hash_valid;
549 #endif
550 }
551
552 static inline void
553 dp_packet_rss_invalidate(struct dp_packet *p)
554 {
555 #ifdef DPDK_NETDEV
556     p->mbuf.ol_flags &= ~PKT_RX_RSS_HASH;
557 #else
558     p->rss_hash_valid = false;
559 #endif
560 }
561
562 #ifdef  __cplusplus
563 }
564 #endif
565
566 #endif /* dp-packet.h */