xref: /nrf52832-nimble/packages/NimBLE-latest/porting/nimble/include/os/os_mbuf.h (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 
21 /**
22  * @addtogroup OSKernel
23  * @{
24  *   @defgroup OSMbuf Chained Memory Buffers
25  *   @{
26  */
27 
28 
29 #ifndef _OS_MBUF_H
30 #define _OS_MBUF_H
31 
32 #include "os/os.h"
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /**
39  * A mbuf pool from which to allocate mbufs. This contains a pointer to the os
40  * mempool to allocate mbufs out of, the total number of elements in the pool,
41  * and the amount of "user" data in a non-packet header mbuf. The total pool
42  * size, in bytes, should be:
43  *  os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
44  */
45 struct os_mbuf_pool {
46     /**
47      * Total length of the databuf in each mbuf.  This is the size of the
48      * mempool block, minus the mbuf header
49      */
50     uint16_t omp_databuf_len;
51     /**
52      * The memory pool which to allocate mbufs out of
53      */
54     struct os_mempool *omp_pool;
55 
56     STAILQ_ENTRY(os_mbuf_pool) omp_next;
57 };
58 
59 
60 /**
61  * A packet header structure that preceeds the mbuf packet headers.
62  */
63 struct os_mbuf_pkthdr {
64     /**
65      * Overall length of the packet.
66      */
67     uint16_t omp_len;
68     /**
69      * Flags
70      */
71     uint16_t omp_flags;
72 
73     STAILQ_ENTRY(os_mbuf_pkthdr) omp_next;
74 };
75 
76 /**
77  * Chained memory buffer.
78  */
79 struct os_mbuf {
80     /**
81      * Current pointer to data in the structure
82      */
83     uint8_t *om_data;
84     /**
85      * Flags associated with this buffer, see OS_MBUF_F_* defintions
86      */
87     uint8_t om_flags;
88     /**
89      * Length of packet header
90      */
91     uint8_t om_pkthdr_len;
92     /**
93      * Length of data in this buffer
94      */
95     uint16_t om_len;
96 
97     /**
98      * The mbuf pool this mbuf was allocated out of
99      */
100     struct os_mbuf_pool *om_omp;
101 
102     SLIST_ENTRY(os_mbuf) om_next;
103 
104     /**
105      * Pointer to the beginning of the data, after this buffer
106      */
107     uint8_t om_databuf[0];
108 };
109 
110 /**
111  * Structure representing a queue of mbufs.
112  */
113 struct os_mqueue {
114     STAILQ_HEAD(, os_mbuf_pkthdr) mq_head;
115     /** Event to post when new buffers are available on the queue. */
116     struct ble_npl_event mq_ev;
117 };
118 
119 /*
120  * Given a flag number, provide the mask for it
121  *
122  * @param __n The number of the flag in the mask
123  */
124 #define OS_MBUF_F_MASK(__n) (1 << (__n))
125 
126 /*
127  * Checks whether a given mbuf is a packet header mbuf
128  *
129  * @param __om The mbuf to check
130  */
131 #define OS_MBUF_IS_PKTHDR(__om) \
132     ((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr))
133 
134 /** Get a packet header pointer given an mbuf pointer */
135 #define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *)     \
136     ((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf)))
137 
138 /** Given a mbuf packet header pointer, return a pointer to the mbuf */
139 #define OS_MBUF_PKTHDR_TO_MBUF(__hdr)   \
140      (struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
141 
142 /**
143  * Gets the length of an entire mbuf chain.  The specified mbuf must have a
144  * packet header.
145  */
146 #define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
147 
148 /**
149  * Access the data of a mbuf, and cast it to type
150  *
151  * @param __om The mbuf to access, and cast
152  * @param __type The type to cast it to
153  */
154 #define OS_MBUF_DATA(__om, __type) \
155      (__type) ((__om)->om_data)
156 
157 /**
158  * Access the "user header" in the head of an mbuf chain.
159  *
160  * @param om                    Pointer to the head of an mbuf chain.
161  */
162 #define OS_MBUF_USRHDR(om)                              \
163     (void *)((uint8_t *)om + sizeof (struct os_mbuf) +  \
164              sizeof (struct os_mbuf_pkthdr))
165 
166 /**
167  * Retrieves the length of the user header in an mbuf.
168  *
169  * @param om                    Pointer to the mbuf to query.
170  */
171 #define OS_MBUF_USRHDR_LEN(om) \
172     ((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr))
173 
174 
175 /** @cond INTERNAL_HIDDEN */
176 
177 /*
178  * Called by OS_MBUF_LEADINGSPACE() macro
179  */
180 static inline uint16_t
_os_mbuf_leadingspace(struct os_mbuf * om)181 _os_mbuf_leadingspace(struct os_mbuf *om)
182 {
183     uint16_t startoff;
184     uint16_t leadingspace;
185 
186     startoff = 0;
187     if (OS_MBUF_IS_PKTHDR(om)) {
188         startoff = om->om_pkthdr_len;
189     }
190 
191     leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) -
192         ((uint8_t *) &om->om_databuf[0] + startoff));
193 
194     return (leadingspace);
195 }
196 
197 /** @endcond */
198 
199 /**
200  * Returns the leading space (space at the beginning) of the mbuf.
201  * Works on both packet header, and regular mbufs, as it accounts
202  * for the additional space allocated to the packet header.
203  *
204  * @param __omp Is the mbuf pool (which contains packet header length.)
205  * @param __om  Is the mbuf in that pool to get the leadingspace for
206  *
207  * @return Amount of leading space available in the mbuf
208  */
209 #define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om)
210 
211 
212 /** @cond INTERNAL_HIDDEN */
213 
214 /* Called by OS_MBUF_TRAILINGSPACE() macro. */
215 static inline uint16_t
_os_mbuf_trailingspace(struct os_mbuf * om)216 _os_mbuf_trailingspace(struct os_mbuf *om)
217 {
218     struct os_mbuf_pool *omp;
219 
220     omp = om->om_omp;
221 
222     return (&om->om_databuf[0] + omp->omp_databuf_len) -
223       (om->om_data + om->om_len);
224 }
225 
226 /** @endcond */
227 
228 /**
229  * Returns the trailing space (space at the end) of the mbuf.
230  * Works on both packet header and regular mbufs.
231  *
232  * @param __omp The mbuf pool for this mbuf
233  * @param __om  Is the mbuf in that pool to get trailing space for
234  *
235  * @return The amount of trailing space available in the mbuf
236  */
237 #define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
238 
239 
240 /**
241  * Initializes an mqueue.  An mqueue is a queue of mbufs that ties to a
242  * particular task's event queue.  Mqueues form a helper API around a common
243  * paradigm: wait on an event queue until at least one packet is available,
244  * then process a queue of packets.
245  *
246  * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
247  * will be posted to the task's mbuf queue.
248  *
249  * @param mq                    The mqueue to initialize
250  * @param ev_cb                 The callback to associate with the mqeueue
251  *                                  event.  Typically, this callback pulls each
252  *                                  packet off the mqueue and processes them.
253  * @param arg                   The argument to associate with the mqueue event.
254  *
255  * @return                      0 on success, non-zero on failure.
256  */
257 int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
258 
259 /**
260  * Remove and return a single mbuf from the mbuf queue.  Does not block.
261  *
262  * @param mq The mbuf queue to pull an element off of.
263  *
264  * @return The next mbuf in the queue, or NULL if queue has no mbufs.
265  */
266 struct os_mbuf *os_mqueue_get(struct os_mqueue *);
267 
268 /**
269  * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
270  * with the mqueue gets posted to the specified eventq.
271  *
272  * @param mq                    The mbuf queue to append the mbuf to.
273  * @param evq                   The event queue to post an event to.
274  * @param m                     The mbuf to append to the mbuf queue.
275  *
276  * @return 0 on success, non-zero on failure.
277  */
278 int os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
279 
280 /**
281  * MSYS is a system level mbuf registry.  Allows the system to share
282  * packet buffers amongst the various networking stacks that can be running
283  * simultaeneously.
284  *
285  * Mbuf pools are created in the system initialization code, and then when
286  * a mbuf is allocated out of msys, it will try and find the best fit based
287  * upon estimated mbuf size.
288  *
289  * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
290  * allocate mbufs out of it.
291  *
292  * @param new_pool The pool to register with MSYS
293  *
294  * @return 0 on success, non-zero on failure
295  */
296 int os_msys_register(struct os_mbuf_pool *);
297 
298 /**
299  * Allocate a mbuf from msys.  Based upon the data size requested,
300  * os_msys_get() will choose the mbuf pool that has the best fit.
301  *
302  * @param dsize The estimated size of the data being stored in the mbuf
303  * @param leadingspace The amount of leadingspace to allocate in the mbuf
304  *
305  * @return A freshly allocated mbuf on success, NULL on failure.
306  */
307 struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace);
308 
309 /**
310  * De-registers all mbuf pools from msys.
311  */
312 void os_msys_reset(void);
313 
314 /**
315  * Allocate a packet header structure from the MSYS pool.  See
316  * os_msys_register() for a description of MSYS.
317  *
318  * @param dsize The estimated size of the data being stored in the mbuf
319  * @param user_hdr_len The length to allocate for the packet header structure
320  *
321  * @return A freshly allocated mbuf on success, NULL on failure.
322  */
323 struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
324 
325 /**
326  * Count the number of blocks in all the mbuf pools that are allocated.
327  *
328  * @return total number of blocks allocated in Msys
329  */
330 int os_msys_count(void);
331 
332 /**
333  * Return the number of free blocks in Msys
334  *
335  * @return Number of free blocks available in Msys
336  */
337 int os_msys_num_free(void);
338 
339 /**
340  * Initialize a pool of mbufs.
341  *
342  * @param omp     The mbuf pool to initialize
343  * @param mp      The memory pool that will hold this mbuf pool
344  * @param buf_len The length of the buffer itself.
345  * @param nbufs   The number of buffers in the pool
346  *
347  * @return 0 on success, error code on failure.
348  */
349 int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
350         uint16_t, uint16_t);
351 
352 /**
353  * Get an mbuf from the mbuf pool.  The mbuf is allocated, and initialized
354  * prior to being returned.
355  *
356  * @param omp The mbuf pool to return the packet from
357  * @param leadingspace The amount of leadingspace to put before the data
358  *     section by default.
359  *
360  * @return An initialized mbuf on success, and NULL on failure.
361  */
362 struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
363 
364 /**
365  * Allocate a new packet header mbuf out of the os_mbuf_pool.
366  *
367  * @param omp The mbuf pool to allocate out of
368  * @param user_pkthdr_len The packet header length to reserve for the caller.
369  *
370  * @return A freshly allocated mbuf on success, NULL on failure.
371  */
372 struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
373         uint8_t pkthdr_len);
374 
375 /**
376  * Duplicate a chain of mbufs.  Return the start of the duplicated chain.
377  *
378  * @param omp The mbuf pool to duplicate out of
379  * @param om  The mbuf chain to duplicate
380  *
381  * @return A pointer to the new chain of mbufs
382  */
383 struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
384 
385 /**
386  * Locates the specified absolute offset within an mbuf chain.  The offset
387  * can be one past than the total length of the chain, but no greater.
388  *
389  * @param om                    The start of the mbuf chain to seek within.
390  * @param off                   The absolute address to find.
391  * @param out_off               On success, this points to the relative offset
392  *                                  within the returned mbuf.
393  *
394  * @return                      The mbuf containing the specified offset on
395  *                                  success.
396  *                              NULL if the specified offset is out of bounds.
397  */
398 struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
399                             uint16_t *out_off);
400 
401 
402 /*
403  * Copy data from an mbuf chain starting "off" bytes from the beginning,
404  * continuing for "len" bytes, into the indicated buffer.
405  *
406  * @param m The mbuf chain to copy from
407  * @param off The offset into the mbuf chain to begin copying from
408  * @param len The length of the data to copy
409  * @param dst The destination buffer to copy into
410  *
411  * @return                      0 on success;
412  *                              -1 if the mbuf does not contain enough data.
413  */
414 int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
415 
416 /**
417  * Append data onto a mbuf
418  *
419  * @param om   The mbuf to append the data onto
420  * @param data The data to append onto the mbuf
421  * @param len  The length of the data to append
422  *
423  * @return 0 on success, and an error code on failure
424  */
425 int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
426 
427 /**
428  * Reads data from one mbuf and appends it to another.  On error, the specified
429  * data range may be partially appended.  Neither mbuf is required to contain
430  * an mbuf packet header.
431  *
432  * @param dst                   The mbuf to append to.
433  * @param src                   The mbuf to copy data from.
434  * @param src_off               The absolute offset within the source mbuf
435  *                                  chain to read from.
436  * @param len                   The number of bytes to append.
437  *
438  * @return                      0 on success;
439  *                              OS_EINVAL if the specified range extends beyond
440  *                                  the end of the source mbuf chain.
441  */
442 int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
443                        uint16_t src_off, uint16_t len);
444 
445 /**
446  * Release a mbuf back to the pool
447  *
448  * @param omp The Mbuf pool to release back to
449  * @param om  The Mbuf to release back to the pool
450  *
451  * @return 0 on success, -1 on failure
452  */
453 int os_mbuf_free(struct os_mbuf *mb);
454 
455 /**
456  * Free a chain of mbufs
457  *
458  * @param omp The mbuf pool to free the chain of mbufs into
459  * @param om  The starting mbuf of the chain to free back into the pool
460  *
461  * @return 0 on success, -1 on failure
462  */
463 int os_mbuf_free_chain(struct os_mbuf *om);
464 
465 /**
466  * Adjust the length of a mbuf, trimming either from the head or the tail
467  * of the mbuf.
468  *
469  * @param mp The mbuf chain to adjust
470  * @param req_len The length to trim from the mbuf.  If positive, trims
471  *                from the head of the mbuf, if negative, trims from the
472  *                tail of the mbuf.
473  */
474 void os_mbuf_adj(struct os_mbuf *mp, int req_len);
475 
476 
477 /**
478  * Performs a memory compare of the specified region of an mbuf chain against a
479  * flat buffer.
480  *
481  * @param om                    The start of the mbuf chain to compare.
482  * @param off                   The offset within the mbuf chain to start the
483  *                                  comparison.
484  * @param data                  The flat buffer to compare.
485  * @param len                   The length of the flat buffer.
486  *
487  * @return                      0 if both memory regions are identical;
488  *                              A memcmp return code if there is a mismatch;
489  *                              INT_MAX if the mbuf is too short.
490  */
491 int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
492 
493 /**
494  * Compares the contents of two mbuf chains.  The ranges of the two chains to
495  * be compared are specified via the two offset parameters and the len
496  * parameter.  Neither mbuf chain is required to contain a packet header.
497  *
498  * @param om1                   The first mbuf chain to compare.
499  * @param offset1               The absolute offset within om1 at which to
500  *                                  start the comparison.
501  * @param om2                   The second mbuf chain to compare.
502  * @param offset2               The absolute offset within om2 at which to
503  *                                  start the comparison.
504  * @param len                   The number of bytes to compare.
505  *
506  * @return                      0 if both mbuf segments are identical;
507  *                              A memcmp() return code if the segment contents
508  *                                  differ;
509  *                              INT_MAX if a specified range extends beyond the
510  *                                  end of its corresponding mbuf chain.
511  */
512 int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
513                  const struct os_mbuf *om2, uint16_t offset2,
514                  uint16_t len);
515 
516 /**
517  * Increases the length of an mbuf chain by adding data to the front.  If there
518  * is insufficient room in the leading mbuf, additional mbufs are allocated and
519  * prepended as necessary.  If this function fails to allocate an mbuf, the
520  * entire chain is freed.
521  *
522  * The specified mbuf chain does not need to contain a packet header.
523  *
524  * @param omp                   The mbuf pool to allocate from.
525  * @param om                    The head of the mbuf chain.
526  * @param len                   The number of bytes to prepend.
527  *
528  * @return                      The new head of the chain on success;
529  *                              NULL on failure.
530  */
531 struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
532 
533 /**
534  * Prepends a chunk of empty data to the specified mbuf chain and ensures the
535  * chunk is contiguous.  If either operation fails, the specified mbuf chain is
536  * freed and NULL is returned.
537  *
538  * @param om                    The mbuf chain to prepend to.
539  * @param len                   The number of bytes to prepend and pullup.
540  *
541  * @return                      The modified mbuf on success;
542  *                              NULL on failure (and the mbuf chain is freed).
543  */
544 struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
545 
546 /**
547  * Copies the contents of a flat buffer into an mbuf chain, starting at the
548  * specified destination offset.  If the mbuf is too small for the source data,
549  * it is extended as necessary.  If the destination mbuf contains a packet
550  * header, the header length is updated.
551  *
552  * @param omp                   The mbuf pool to allocate from.
553  * @param om                    The mbuf chain to copy into.
554  * @param off                   The offset within the chain to copy to.
555  * @param src                   The source buffer to copy from.
556  * @param len                   The number of bytes to copy.
557  *
558  * @return                      0 on success; nonzero on failure.
559  */
560 int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
561 
562 /**
563  * Attaches a second mbuf chain onto the end of the first.  If the first chain
564  * contains a packet header, the header's length is updated.  If the second
565  * chain has a packet header, its header is cleared.
566  *
567  * @param first                 The mbuf chain being attached to.
568  * @param second                The mbuf chain that gets attached.
569  */
570 void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
571 
572 
573 /**
574  * Increases the length of an mbuf chain by the specified amount.  If there is
575  * not sufficient room in the last buffer, a new buffer is allocated and
576  * appended to the chain.  It is an error to request more data than can fit in
577  * a single buffer.
578  *
579  * @param omp
580  * @param om                    The head of the chain to extend.
581  * @param len                   The number of bytes to extend by.
582  *
583  * @return                      A pointer to the new data on success;
584  *                              NULL on failure.
585  */
586 void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
587 
588 /**
589  * Rearrange a mbuf chain so that len bytes are contiguous,
590  * and in the data area of an mbuf (so that OS_MBUF_DATA() will
591  * work on a structure of size len.)  Returns the resulting
592  * mbuf chain on success, free's it and returns NULL on failure.
593  *
594  * If there is room, it will add up to "max_protohdr - len"
595  * extra bytes to the contiguous region, in an attempt to avoid being
596  * called next time.
597  *
598  * @param omp The mbuf pool to take the mbufs out of
599  * @param om The mbuf chain to make contiguous
600  * @param len The number of bytes in the chain to make contiguous
601  *
602  * @return The contiguous mbuf chain on success, NULL on failure.
603  */
604 struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
605 
606 
607 /**
608  * Removes and frees empty mbufs from the front of a chain.  If the chain
609  * contains a packet header, it is preserved.
610  *
611  * @param om                    The mbuf chain to trim.
612  *
613  * @return                      The head of the trimmed mbuf chain.
614  */
615 struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
616 
617 #ifdef __cplusplus
618 }
619 #endif
620 
621 #endif /* _OS_MBUF_H */
622 
623 
624 /**
625  *   @} OSMbuf
626  * @} OSKernel
627  */
628