-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrte_mbuf.h
2013 lines (1837 loc) · 55.2 KB
/
rte_mbuf.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2014 Intel Corporation.
* Copyright 2014 6WIND S.A.
*/
#ifndef _RTE_MBUF_H_
#define _RTE_MBUF_H_
/**
* @file
* RTE Mbuf
*
* The mbuf library provides the ability to create and destroy buffers
* that may be used by the RTE application to store message
* buffers. The message buffers are stored in a mempool, using the
* RTE mempool library.
*
* The preferred way to create a mbuf pool is to use
* rte_pktmbuf_pool_create(). However, in some situations, an
* application may want to have more control (ex: populate the pool with
* specific memory), in this case it is possible to use functions from
* rte_mempool. See how rte_pktmbuf_pool_create() is implemented for
* details.
*
* This library provides an API to allocate/free packet mbufs, which are
* used to carry network packets.
*
* To understand the concepts of packet buffers or mbufs, you
* should read "TCP/IP Illustrated, Volume 2: The Implementation,
* Addison-Wesley, 1995, ISBN 0-201-63354-X from Richard Stevens"
* http://www.kohala.com/start/tcpipiv2.html
*/
#include <stdint.h>
#include <rte_common.h>
#include <rte_config.h>
#include <rte_mempool.h>
#include <rte_prefetch.h>
#include <rte_branch_prediction.h>
#include <rte_mbuf_ptype.h>
#include <rte_mbuf_core.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Get the name of a RX offload flag
*
* @param mask
* The mask describing the flag.
* @return
* The name of this flag, or NULL if it's not a valid RX flag.
*/
const char *rte_get_rx_ol_flag_name(uint64_t mask);
/**
* Dump the list of RX offload flags in a buffer
*
* @param mask
* The mask describing the RX flags.
* @param buf
* The output buffer.
* @param buflen
* The length of the buffer.
* @return
* 0 on success, (-1) on error.
*/
int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
/**
* Get the name of a TX offload flag
*
* @param mask
* The mask describing the flag. Usually only one bit must be set.
* Several bits can be given if they belong to the same mask.
* Ex: RTE_MBUF_F_TX_L4_MASK.
* @return
* The name of this flag, or NULL if it's not a valid TX flag.
*/
const char *rte_get_tx_ol_flag_name(uint64_t mask);
/**
* Dump the list of TX offload flags in a buffer
*
* @param mask
* The mask describing the TX flags.
* @param buf
* The output buffer.
* @param buflen
* The length of the buffer.
* @return
* 0 on success, (-1) on error.
*/
int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
/**
* Prefetch the first part of the mbuf
*
* The first 64 bytes of the mbuf corresponds to fields that are used early
* in the receive path. If the cache line of the architecture is higher than
* 64B, the second part will also be prefetched.
*
* @param m
* The pointer to the mbuf.
*/
static inline void
rte_mbuf_prefetch_part1(struct rte_mbuf *m)
{
rte_prefetch0(m);
}
/**
* Prefetch the second part of the mbuf
*
* The next 64 bytes of the mbuf corresponds to fields that are used in the
* transmit path. If the cache line of the architecture is higher than 64B,
* this function does nothing as it is expected that the full mbuf is
* already in cache.
*
* @param m
* The pointer to the mbuf.
*/
static inline void
rte_mbuf_prefetch_part2(struct rte_mbuf *m)
{
#if RTE_CACHE_LINE_SIZE == 64
rte_prefetch0(RTE_PTR_ADD(m, RTE_CACHE_LINE_MIN_SIZE));
#else
RTE_SET_USED(m);
#endif
}
static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
/**
* Get the IOVA address of the mbuf data buffer.
*
* @param m
* The pointer to the mbuf.
* @return
* The IOVA address of the mbuf.
*/
static inline rte_iova_t
rte_mbuf_iova_get(const struct rte_mbuf *m)
{
#if RTE_IOVA_IN_MBUF
return m->buf_iova;
#else
return (rte_iova_t)m->buf_addr;
#endif
}
/**
* Set the IOVA address of the mbuf data buffer.
*
* @param m
* The pointer to the mbuf.
* @param iova
* Value to set as IOVA address of the mbuf.
*/
static inline void
rte_mbuf_iova_set(struct rte_mbuf *m, rte_iova_t iova)
{
#if RTE_IOVA_IN_MBUF
m->buf_iova = iova;
#else
RTE_SET_USED(m);
RTE_SET_USED(iova);
#endif
}
/**
* Return the IO address of the beginning of the mbuf data
*
* @param mb
* The pointer to the mbuf.
* @return
* The IO address of the beginning of the mbuf data
*/
static inline rte_iova_t
rte_mbuf_data_iova(const struct rte_mbuf *mb)
{
return rte_mbuf_iova_get(mb) + mb->data_off;
}
/**
* Return the default IO address of the beginning of the mbuf data
*
* This function is used by drivers in their receive function, as it
* returns the location where data should be written by the NIC, taking
* the default headroom in account.
*
* @param mb
* The pointer to the mbuf.
* @return
* The IO address of the beginning of the mbuf data
*/
static inline rte_iova_t
rte_mbuf_data_iova_default(const struct rte_mbuf *mb)
{
return rte_mbuf_iova_get(mb) + RTE_PKTMBUF_HEADROOM;
}
/**
* Return the mbuf owning the data buffer address of an indirect mbuf.
*
* @param mi
* The pointer to the indirect mbuf.
* @return
* The address of the direct mbuf corresponding to buffer_addr.
*/
static inline struct rte_mbuf *
rte_mbuf_from_indirect(struct rte_mbuf *mi)
{
return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
}
/**
* Return address of buffer embedded in the given mbuf.
*
* The return value shall be same as mb->buf_addr if the mbuf is already
* initialized and direct. However, this API is useful if mempool of the
* mbuf is already known because it doesn't need to access mbuf contents in
* order to get the mempool pointer.
*
* @param mb
* The pointer to the mbuf.
* @param mp
* The pointer to the mempool of the mbuf.
* @return
* The pointer of the mbuf buffer.
*/
static inline char *
rte_mbuf_buf_addr(struct rte_mbuf *mb, struct rte_mempool *mp)
{
return (char *)mb + sizeof(*mb) + rte_pktmbuf_priv_size(mp);
}
/**
* Return the default address of the beginning of the mbuf data.
*
* @param mb
* The pointer to the mbuf.
* @return
* The pointer of the beginning of the mbuf data.
*/
static inline char *
rte_mbuf_data_addr_default(struct rte_mbuf *mb)
{
return rte_mbuf_buf_addr(mb, mb->pool) + RTE_PKTMBUF_HEADROOM;
}
/**
* Return address of buffer embedded in the given mbuf.
*
* @note: Accessing mempool pointer of a mbuf is expensive because the
* pointer is stored in the 2nd cache line of mbuf. If mempool is known, it
* is better not to reference the mempool pointer in mbuf but calling
* rte_mbuf_buf_addr() would be more efficient.
*
* @param md
* The pointer to the mbuf.
* @return
* The address of the data buffer owned by the mbuf.
*/
static inline char *
rte_mbuf_to_baddr(struct rte_mbuf *md)
{
return rte_mbuf_buf_addr(md, md->pool);
}
/**
* Return the starting address of the private data area embedded in
* the given mbuf.
*
* Note that no check is made to ensure that a private data area
* actually exists in the supplied mbuf.
*
* @param m
* The pointer to the mbuf.
* @return
* The starting address of the private data area of the given mbuf.
*/
static inline void *
rte_mbuf_to_priv(struct rte_mbuf *m)
{
return RTE_PTR_ADD(m, sizeof(struct rte_mbuf));
}
/**
* Private data in case of pktmbuf pool.
*
* A structure that contains some pktmbuf_pool-specific data that are
* appended after the mempool structure (in private data).
*/
struct rte_pktmbuf_pool_private {
uint16_t mbuf_data_room_size; /**< Size of data space in each mbuf. */
uint16_t mbuf_priv_size; /**< Size of private area in each mbuf. */
uint32_t flags; /**< reserved for future use. */
};
/**
* Return the flags from private data in an mempool structure.
*
* @param mp
* A pointer to the mempool structure.
* @return
* The flags from the private data structure.
*/
static inline uint32_t
rte_pktmbuf_priv_flags(struct rte_mempool *mp)
{
struct rte_pktmbuf_pool_private *mbp_priv;
mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
return mbp_priv->flags;
}
/**
* When set, pktmbuf mempool will hold only mbufs with pinned external
* buffer. The external buffer will be attached to the mbuf at the
* memory pool creation and will never be detached by the mbuf free calls.
* mbuf should not contain any room for data after the mbuf structure.
*/
#define RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF (1 << 0)
/**
* Returns non zero if given mbuf has a pinned external buffer, or zero
* otherwise. The pinned external buffer is allocated at pool creation
* time and should not be freed on mbuf freeing.
*
* External buffer is a user-provided anonymous buffer.
*/
#define RTE_MBUF_HAS_PINNED_EXTBUF(mb) \
(rte_pktmbuf_priv_flags(mb->pool) & RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF)
#ifdef RTE_LIBRTE_MBUF_DEBUG
/** check mbuf type in debug mode */
#define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
#else /* RTE_LIBRTE_MBUF_DEBUG */
/** check mbuf type in debug mode */
#define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
#endif /* RTE_LIBRTE_MBUF_DEBUG */
#ifdef RTE_MBUF_REFCNT_ATOMIC
/**
* Reads the value of an mbuf's refcnt.
* @param m
* Mbuf to read
* @return
* Reference count number.
*/
static inline uint16_t
rte_mbuf_refcnt_read(const struct rte_mbuf *m)
{
return rte_atomic_load_explicit(&m->refcnt, rte_memory_order_relaxed);
}
/**
* Sets an mbuf's refcnt to a defined value.
* @param m
* Mbuf to update
* @param new_value
* Value set
*/
static inline void
rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
{
rte_atomic_store_explicit(&m->refcnt, new_value, rte_memory_order_relaxed);
}
/* internal */
static inline uint16_t
__rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
{
return rte_atomic_fetch_add_explicit(&m->refcnt, value,
rte_memory_order_acq_rel) + value;
}
/**
* Adds given value to an mbuf's refcnt and returns its new value.
* @param m
* Mbuf to update
* @param value
* Value to add/subtract
* @return
* Updated value
*/
static inline uint16_t
rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
{
/*
* The atomic_add is an expensive operation, so we don't want to
* call it in the case where we know we are the unique holder of
* this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
* operation has to be used because concurrent accesses on the
* reference counter can occur.
*/
if (likely(rte_mbuf_refcnt_read(m) == 1)) {
++value;
rte_mbuf_refcnt_set(m, (uint16_t)value);
return (uint16_t)value;
}
return __rte_mbuf_refcnt_update(m, value);
}
#else /* ! RTE_MBUF_REFCNT_ATOMIC */
/* internal */
static inline uint16_t
__rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
{
m->refcnt = (uint16_t)(m->refcnt + value);
return m->refcnt;
}
/**
* Adds given value to an mbuf's refcnt and returns its new value.
*/
static inline uint16_t
rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
{
return __rte_mbuf_refcnt_update(m, value);
}
/**
* Reads the value of an mbuf's refcnt.
*/
static inline uint16_t
rte_mbuf_refcnt_read(const struct rte_mbuf *m)
{
return m->refcnt;
}
/**
* Sets an mbuf's refcnt to the defined value.
*/
static inline void
rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
{
m->refcnt = new_value;
}
#endif /* RTE_MBUF_REFCNT_ATOMIC */
/**
* Reads the refcnt of an external buffer.
*
* @param shinfo
* Shared data of the external buffer.
* @return
* Reference count number.
*/
static inline uint16_t
rte_mbuf_ext_refcnt_read(const struct rte_mbuf_ext_shared_info *shinfo)
{
return rte_atomic_load_explicit(&shinfo->refcnt, rte_memory_order_relaxed);
}
/**
* Set refcnt of an external buffer.
*
* @param shinfo
* Shared data of the external buffer.
* @param new_value
* Value set
*/
static inline void
rte_mbuf_ext_refcnt_set(struct rte_mbuf_ext_shared_info *shinfo,
uint16_t new_value)
{
rte_atomic_store_explicit(&shinfo->refcnt, new_value, rte_memory_order_relaxed);
}
/**
* Add given value to refcnt of an external buffer and return its new
* value.
*
* @param shinfo
* Shared data of the external buffer.
* @param value
* Value to add/subtract
* @return
* Updated value
*/
static inline uint16_t
rte_mbuf_ext_refcnt_update(struct rte_mbuf_ext_shared_info *shinfo,
int16_t value)
{
if (likely(rte_mbuf_ext_refcnt_read(shinfo) == 1)) {
++value;
rte_mbuf_ext_refcnt_set(shinfo, (uint16_t)value);
return (uint16_t)value;
}
return rte_atomic_fetch_add_explicit(&shinfo->refcnt, value,
rte_memory_order_acq_rel) + value;
}
/** Mbuf prefetch */
#define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
if ((m) != NULL) \
rte_prefetch0(m); \
} while (0)
/**
* Sanity checks on an mbuf.
*
* Check the consistency of the given mbuf. The function will cause a
* panic if corruption is detected.
*
* @param m
* The mbuf to be checked.
* @param is_header
* True if the mbuf is a packet header, false if it is a sub-segment
* of a packet (in this case, some fields like nb_segs are not checked)
*/
void
rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
/**
* Sanity checks on a mbuf.
*
* Almost like rte_mbuf_sanity_check(), but this function gives the reason
* if corruption is detected rather than panic.
*
* @param m
* The mbuf to be checked.
* @param is_header
* True if the mbuf is a packet header, false if it is a sub-segment
* of a packet (in this case, some fields like nb_segs are not checked)
* @param reason
* A reference to a string pointer where to store the reason why a mbuf is
* considered invalid.
* @return
* - 0 if no issue has been found, reason is left untouched.
* - -1 if a problem is detected, reason then points to a string describing
* the reason why the mbuf is deemed invalid.
*/
int rte_mbuf_check(const struct rte_mbuf *m, int is_header,
const char **reason);
/**
* Sanity checks on a reinitialized mbuf in debug mode.
*
* Check the consistency of the given reinitialized mbuf.
* The function will cause a panic if corruption is detected.
*
* Check that the mbuf is properly reinitialized (refcnt=1, next=NULL,
* nb_segs=1), as done by rte_pktmbuf_prefree_seg().
*
* @param m
* The mbuf to be checked.
*/
static __rte_always_inline void
__rte_mbuf_raw_sanity_check(__rte_unused const struct rte_mbuf *m)
{
RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1);
RTE_ASSERT(m->next == NULL);
RTE_ASSERT(m->nb_segs == 1);
__rte_mbuf_sanity_check(m, 0);
}
/** For backwards compatibility. */
#define MBUF_RAW_ALLOC_CHECK(m) __rte_mbuf_raw_sanity_check(m)
/**
* Allocate an uninitialized mbuf from mempool *mp*.
*
* This function can be used by PMDs (especially in RX functions) to
* allocate an uninitialized mbuf. The driver is responsible of
* initializing all the required fields. See rte_pktmbuf_reset().
* For standard needs, prefer rte_pktmbuf_alloc().
*
* The caller can expect that the following fields of the mbuf structure
* are initialized: buf_addr, buf_iova, buf_len, refcnt=1, nb_segs=1,
* next=NULL, pool, priv_size. The other fields must be initialized
* by the caller.
*
* @param mp
* The mempool from which mbuf is allocated.
* @return
* - The pointer to the new mbuf on success.
* - NULL if allocation failed.
*/
static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp)
{
union {
void *ptr;
struct rte_mbuf *m;
} ret;
if (rte_mempool_get(mp, &ret.ptr) < 0)
return NULL;
__rte_mbuf_raw_sanity_check(ret.m);
return ret.m;
}
/**
* Put mbuf back into its original mempool.
*
* The caller must ensure that the mbuf is direct and properly
* reinitialized (refcnt=1, next=NULL, nb_segs=1), as done by
* rte_pktmbuf_prefree_seg().
*
* This function should be used with care, when optimization is
* required. For standard needs, prefer rte_pktmbuf_free() or
* rte_pktmbuf_free_seg().
*
* @param m
* The mbuf to be freed.
*/
static __rte_always_inline void
rte_mbuf_raw_free(struct rte_mbuf *m)
{
RTE_ASSERT(!RTE_MBUF_CLONED(m) &&
(!RTE_MBUF_HAS_EXTBUF(m) || RTE_MBUF_HAS_PINNED_EXTBUF(m)));
__rte_mbuf_raw_sanity_check(m);
rte_mempool_put(m->pool, m);
}
/**
* The packet mbuf constructor.
*
* This function initializes some fields in the mbuf structure that are
* not modified by the user once created (origin pool, buffer start
* address, and so on). This function is given as a callback function to
* rte_mempool_obj_iter() or rte_mempool_create() at pool creation time.
*
* This function expects that the mempool private area was previously
* initialized with rte_pktmbuf_pool_init().
*
* @param mp
* The mempool from which mbufs originate.
* @param opaque_arg
* A pointer that can be used by the user to retrieve useful information
* for mbuf initialization. This pointer is the opaque argument passed to
* rte_mempool_obj_iter() or rte_mempool_create().
* @param m
* The mbuf to initialize.
* @param i
* The index of the mbuf in the pool table.
*/
void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
void *m, unsigned i);
/**
* A packet mbuf pool constructor.
*
* This function initializes the mempool private data in the case of a
* pktmbuf pool. This private data is needed by the driver. The
* function must be called on the mempool before it is used, or it
* can be given as a callback function to rte_mempool_create() at
* pool creation. It can be extended by the user, for example, to
* provide another packet size.
*
* The mempool private area size must be at least equal to
* sizeof(struct rte_pktmbuf_pool_private).
*
* @param mp
* The mempool from which mbufs originate.
* @param opaque_arg
* A pointer that can be used by the user to retrieve useful information
* for mbuf initialization. This pointer is the opaque argument passed to
* rte_mempool_create().
*/
void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
/**
* Create a mbuf pool.
*
* This function creates and initializes a packet mbuf pool. It is
* a wrapper to rte_mempool functions.
*
* @param name
* The name of the mbuf pool.
* @param n
* The number of elements in the mbuf pool. The optimum size (in terms
* of memory usage) for a mempool is when n is a power of two minus one:
* n = (2^q - 1).
* @param cache_size
* Size of the per-core object cache. See rte_mempool_create() for
* details.
* @param priv_size
* Size of application private are between the rte_mbuf structure
* and the data buffer. This value must be aligned to RTE_MBUF_PRIV_ALIGN.
* @param data_room_size
* Size of data buffer in each mbuf, including RTE_PKTMBUF_HEADROOM.
* @param socket_id
* The socket identifier where the memory should be allocated. The
* value can be *SOCKET_ID_ANY* if there is no NUMA constraint for the
* reserved zone.
* @return
* The pointer to the new allocated mempool, on success. NULL on error
* with rte_errno set appropriately. Possible rte_errno values include:
* - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
* - EINVAL - cache size provided is too large, or priv_size is not aligned.
* - ENOSPC - the maximum number of memzones has already been allocated
* - EEXIST - a memzone with the same name already exists
* - ENOMEM - no appropriate memory area found in which to create memzone
*/
struct rte_mempool *
rte_pktmbuf_pool_create(const char *name, unsigned n,
unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
int socket_id);
/**
* Create a mbuf pool with a given mempool ops name
*
* This function creates and initializes a packet mbuf pool. It is
* a wrapper to rte_mempool functions.
*
* @param name
* The name of the mbuf pool.
* @param n
* The number of elements in the mbuf pool. The optimum size (in terms
* of memory usage) for a mempool is when n is a power of two minus one:
* n = (2^q - 1).
* @param cache_size
* Size of the per-core object cache. See rte_mempool_create() for
* details.
* @param priv_size
* Size of application private are between the rte_mbuf structure
* and the data buffer. This value must be aligned to RTE_MBUF_PRIV_ALIGN.
* @param data_room_size
* Size of data buffer in each mbuf, including RTE_PKTMBUF_HEADROOM.
* @param socket_id
* The socket identifier where the memory should be allocated. The
* value can be *SOCKET_ID_ANY* if there is no NUMA constraint for the
* reserved zone.
* @param ops_name
* The mempool ops name to be used for this mempool instead of
* default mempool. The value can be *NULL* to use default mempool.
* @return
* The pointer to the new allocated mempool, on success. NULL on error
* with rte_errno set appropriately. Possible rte_errno values include:
* - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
* - EINVAL - cache size provided is too large, or priv_size is not aligned.
* - ENOSPC - the maximum number of memzones has already been allocated
* - EEXIST - a memzone with the same name already exists
* - ENOMEM - no appropriate memory area found in which to create memzone
*/
struct rte_mempool *
rte_pktmbuf_pool_create_by_ops(const char *name, unsigned int n,
unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size,
int socket_id, const char *ops_name);
/** A structure that describes the pinned external buffer segment. */
struct rte_pktmbuf_extmem {
void *buf_ptr; /**< The virtual address of data buffer. */
rte_iova_t buf_iova; /**< The IO address of the data buffer. */
size_t buf_len; /**< External buffer length in bytes. */
uint16_t elt_size; /**< mbuf element size in bytes. */
};
/**
* Create a mbuf pool with external pinned data buffers.
*
* This function creates and initializes a packet mbuf pool that contains
* only mbufs with external buffer. It is a wrapper to rte_mempool functions.
*
* @param name
* The name of the mbuf pool.
* @param n
* The number of elements in the mbuf pool. The optimum size (in terms
* of memory usage) for a mempool is when n is a power of two minus one:
* n = (2^q - 1).
* @param cache_size
* Size of the per-core object cache. See rte_mempool_create() for
* details.
* @param priv_size
* Size of application private are between the rte_mbuf structure
* and the data buffer. This value must be aligned to RTE_MBUF_PRIV_ALIGN.
* @param data_room_size
* Size of data buffer in each mbuf, including RTE_PKTMBUF_HEADROOM.
* @param socket_id
* The socket identifier where the memory should be allocated. The
* value can be *SOCKET_ID_ANY* if there is no NUMA constraint for the
* reserved zone.
* @param ext_mem
* Pointer to the array of structures describing the external memory
* for data buffers. It is caller responsibility to register this memory
* with rte_extmem_register() (if needed), map this memory to appropriate
* physical device, etc.
* @param ext_num
* Number of elements in the ext_mem array.
* @return
* The pointer to the new allocated mempool, on success. NULL on error
* with rte_errno set appropriately. Possible rte_errno values include:
* - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
* - EINVAL - cache size provided is too large, or priv_size is not aligned.
* - ENOSPC - the maximum number of memzones has already been allocated
* - EEXIST - a memzone with the same name already exists
* - ENOMEM - no appropriate memory area found in which to create memzone
*/
struct rte_mempool *
rte_pktmbuf_pool_create_extbuf(const char *name, unsigned int n,
unsigned int cache_size, uint16_t priv_size,
uint16_t data_room_size, int socket_id,
const struct rte_pktmbuf_extmem *ext_mem,
unsigned int ext_num);
/**
* Get the data room size of mbufs stored in a pktmbuf_pool
*
* The data room size is the amount of data that can be stored in a
* mbuf including the headroom (RTE_PKTMBUF_HEADROOM).
*
* @param mp
* The packet mbuf pool.
* @return
* The data room size of mbufs stored in this mempool.
*/
static inline uint16_t
rte_pktmbuf_data_room_size(struct rte_mempool *mp)
{
struct rte_pktmbuf_pool_private *mbp_priv;
mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
return mbp_priv->mbuf_data_room_size;
}
/**
* Get the application private size of mbufs stored in a pktmbuf_pool
*
* The private size of mbuf is a zone located between the rte_mbuf
* structure and the data buffer where an application can store data
* associated to a packet.
*
* @param mp
* The packet mbuf pool.
* @return
* The private size of mbufs stored in this mempool.
*/
static inline uint16_t
rte_pktmbuf_priv_size(struct rte_mempool *mp)
{
struct rte_pktmbuf_pool_private *mbp_priv;
mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
return mbp_priv->mbuf_priv_size;
}
/**
* Reset the data_off field of a packet mbuf to its default value.
*
* The given mbuf must have only one segment, which should be empty.
*
* @param m
* The packet mbuf's data_off field has to be reset.
*/
static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m)
{
m->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM,
(uint16_t)m->buf_len);
}
/**
* Reset the fields of a packet mbuf to their default values.
*
* The given mbuf must have only one segment.
*
* @param m
* The packet mbuf to be reset.
*/
static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
{
m->next = NULL;
m->pkt_len = 0;
m->tx_offload = 0;
m->vlan_tci = 0;
m->vlan_tci_outer = 0;
m->nb_segs = 1;
m->port = RTE_MBUF_PORT_INVALID;
m->ol_flags &= RTE_MBUF_F_EXTERNAL;
m->packet_type = 0;
rte_pktmbuf_reset_headroom(m);
m->data_len = 0;
__rte_mbuf_sanity_check(m, 1);
}
/**
* Allocate a new mbuf from a mempool.
*
* This new mbuf contains one segment, which has a length of 0. The pointer
* to data is initialized to have some bytes of headroom in the buffer
* (if buffer size allows).
*
* @param mp
* The mempool from which the mbuf is allocated.
* @return
* - The pointer to the new mbuf on success.
* - NULL if allocation failed.
*/
static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
{
struct rte_mbuf *m;
if ((m = rte_mbuf_raw_alloc(mp)) != NULL)
rte_pktmbuf_reset(m);
return m;
}
/**
* Allocate a bulk of mbufs, initialize refcnt and reset the fields to default
* values.
*
* @param pool
* The mempool from which mbufs are allocated.
* @param mbufs
* Array of pointers to mbufs
* @param count
* Array size
* @return
* - 0: Success
* - -ENOENT: Not enough entries in the mempool; no mbufs are retrieved.
*/
static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
struct rte_mbuf **mbufs, unsigned count)
{
unsigned idx = 0;
int rc;
rc = rte_mempool_get_bulk(pool, (void **)mbufs, count);
if (unlikely(rc))
return rc;
/* To understand duff's device on loop unwinding optimization, see
* https://en.wikipedia.org/wiki/Duff's_device.
* Here while() loop is used rather than do() while{} to avoid extra
* check if count is zero.
*/
switch (count % 4) {
case 0:
while (idx != count) {
__rte_mbuf_raw_sanity_check(mbufs[idx]);
rte_pktmbuf_reset(mbufs[idx]);
idx++;
/* fall-through */
case 3:
__rte_mbuf_raw_sanity_check(mbufs[idx]);
rte_pktmbuf_reset(mbufs[idx]);
idx++;
/* fall-through */
case 2:
__rte_mbuf_raw_sanity_check(mbufs[idx]);
rte_pktmbuf_reset(mbufs[idx]);
idx++;
/* fall-through */
case 1:
__rte_mbuf_raw_sanity_check(mbufs[idx]);
rte_pktmbuf_reset(mbufs[idx]);
idx++;
/* fall-through */
}
}
return 0;
}
/**
* Initialize shared data at the end of an external buffer before attaching
* to a mbuf by ``rte_pktmbuf_attach_extbuf()``. This is not a mandatory
* initialization but a helper function to simply spare a few bytes at the
* end of the buffer for shared data. If shared data is allocated
* separately, this should not be called but application has to properly
* initialize the shared data according to its need.
*
* Free callback and its argument is saved and the refcnt is set to 1.
*
* @warning
* The value of buf_len will be reduced to RTE_PTR_DIFF(shinfo, buf_addr)
* after this initialization. This shall be used for
* ``rte_pktmbuf_attach_extbuf()``
*
* @param buf_addr
* The pointer to the external buffer.
* @param [in,out] buf_len
* The pointer to length of the external buffer. Input value must be
* larger than the size of ``struct rte_mbuf_ext_shared_info`` and
* padding for alignment. If not enough, this function will return NULL.
* Adjusted buffer length will be returned through this pointer.
* @param free_cb
* Free callback function to call when the external buffer needs to be
* freed.
* @param fcb_opaque
* Argument for the free callback function.
*
* @return
* A pointer to the initialized shared data on success, return NULL