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