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