1 /*
2  * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
7  */
8 /*
9  * Licensed to the Apache Software Foundation (ASF) under one
10  * or more contributor license agreements.  See the NOTICE file
11  * distributed with this work for additional information
12  * regarding copyright ownership.  The ASF licenses this file
13  * to you under the Apache License, Version 2.0 (the
14  * "License"); you may not use this file except in compliance
15  * with the License.  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  * Unless required by applicable law or agreed to in writing,
20  * software distributed under the License is distributed on an
21  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22  * KIND, either express or implied.  See the License for the
23  * specific language governing permissions and limitations
24  * under the License.
25  */
26 
27 
28 /**
29  * @addtogroup OSKernel
30  * @{
31  *   @defgroup OSMbuf Chained Memory Buffers
32  *   @{
33  */
34 
35 
36 #ifndef _OS_MBUF_H
37 #define _OS_MBUF_H
38 
39 #include "os/os.h"
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /**
46  * A mbuf pool from which to allocate mbufs. This contains a pointer to the os
47  * mempool to allocate mbufs out of, the total number of elements in the pool,
48  * and the amount of "user" data in a non-packet header mbuf. The total pool
49  * size, in bytes, should be:
50  *  os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
51  */
52 struct os_mbuf_pool {
53     /**
54      * Total length of the databuf in each mbuf.  This is the size of the
55      * mempool block, minus the mbuf header
56      */
57     uint16_t omp_databuf_len;
58     /**
59      * The memory pool which to allocate mbufs out of
60      */
61     struct os_mempool *omp_pool;
62 
63     STAILQ_ENTRY(os_mbuf_pool) omp_next;
64 };
65 
66 
67 /**
68  * A packet header structure that preceeds the mbuf packet headers.
69  */
70 struct os_mbuf_pkthdr {
71     /**
72      * Overall length of the packet.
73      */
74     uint16_t omp_len;
75     /**
76      * Flags
77      */
78     uint16_t omp_flags;
79 
80     STAILQ_ENTRY(os_mbuf_pkthdr) omp_next;
81 };
82 
83 /**
84  * Chained memory buffer.
85  */
86 struct os_mbuf {
87     /**
88      * Current pointer to data in the structure
89      */
90     uint8_t *om_data;
91     /**
92      * Flags associated with this buffer, see OS_MBUF_F_* defintions
93      */
94     uint8_t om_flags;
95     /**
96      * Length of packet header
97      */
98     uint8_t om_pkthdr_len;
99     /**
100      * Length of data in this buffer
101      */
102     uint16_t om_len;
103 
104     /**
105      * The mbuf pool this mbuf was allocated out of
106      */
107     struct os_mbuf_pool *om_omp;
108 
109     SLIST_ENTRY(os_mbuf) om_next;
110 
111     /**
112      * Pointer to the beginning of the data, after this buffer
113      */
114     uint8_t om_databuf[0];
115 };
116 
117 /**
118  * Structure representing a queue of mbufs.
119  */
120 struct os_mqueue {
121     STAILQ_HEAD(, os_mbuf_pkthdr) mq_head;
122     /** Event to post when new buffers are available on the queue. */
123     struct ble_npl_event mq_ev;
124 };
125 
126 /*
127  * Given a flag number, provide the mask for it
128  *
129  * @param __n The number of the flag in the mask
130  */
131 #define OS_MBUF_F_MASK(__n) (1 << (__n))
132 
133 /*
134  * Checks whether a given mbuf is a packet header mbuf
135  *
136  * @param __om The mbuf to check
137  */
138 #define OS_MBUF_IS_PKTHDR(__om) \
139     ((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr))
140 
141 /** Get a packet header pointer given an mbuf pointer */
142 #define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *)     \
143     (void *)((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf)))
144 
145 /** Given a mbuf packet header pointer, return a pointer to the mbuf */
146 #define OS_MBUF_PKTHDR_TO_MBUF(__hdr)   \
147      (struct os_mbuf *)(void *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
148 
149 /**
150  * Gets the length of an entire mbuf chain.  The specified mbuf must have a
151  * packet header.
152  */
153 #define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
154 
155 /**
156  * Access the data of a mbuf, and cast it to type
157  *
158  * @param __om The mbuf to access, and cast
159  * @param __type The type to cast it to
160  */
161 #define OS_MBUF_DATA(__om, __type) \
162      (__type) ((__om)->om_data)
163 
164 /**
165  * Access the "user header" in the head of an mbuf chain.
166  *
167  * @param om                    Pointer to the head of an mbuf chain.
168  */
169 #define OS_MBUF_USRHDR(om)                              \
170     (void *)((uint8_t *)om + sizeof (struct os_mbuf) +  \
171              sizeof (struct os_mbuf_pkthdr))
172 
173 /**
174  * Retrieves the length of the user header in an mbuf.
175  *
176  * @param om                    Pointer to the mbuf to query.
177  */
178 #define OS_MBUF_USRHDR_LEN(om) \
179     ((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr))
180 
181 
182 /** @cond INTERNAL_HIDDEN */
183 
184 /*
185  * Called by OS_MBUF_LEADINGSPACE() macro
186  */
187 static inline uint16_t
_os_mbuf_leadingspace(struct os_mbuf * om)188 _os_mbuf_leadingspace(struct os_mbuf *om)
189 {
190     uint16_t startoff;
191     uint16_t leadingspace;
192 
193     startoff = 0;
194     if (OS_MBUF_IS_PKTHDR(om)) {
195         startoff = om->om_pkthdr_len;
196     }
197 
198     leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) -
199                                ((uint8_t *) &om->om_databuf[0] + startoff));
200 
201     return (leadingspace);
202 }
203 
204 /** @endcond */
205 
206 /**
207  * Returns the leading space (space at the beginning) of the mbuf.
208  * Works on both packet header, and regular mbufs, as it accounts
209  * for the additional space allocated to the packet header.
210  *
211  * @param __omp Is the mbuf pool (which contains packet header length.)
212  * @param __om  Is the mbuf in that pool to get the leadingspace for
213  *
214  * @return Amount of leading space available in the mbuf
215  */
216 #define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om)
217 
218 
219 /** @cond INTERNAL_HIDDEN */
220 
221 /* Called by OS_MBUF_TRAILINGSPACE() macro. */
222 static inline uint16_t
_os_mbuf_trailingspace(struct os_mbuf * om)223 _os_mbuf_trailingspace(struct os_mbuf *om)
224 {
225     struct os_mbuf_pool *omp;
226 
227     omp = om->om_omp;
228 
229     return (&om->om_databuf[0] + omp->omp_databuf_len) -
230            (om->om_data + om->om_len);
231 }
232 
233 /** @endcond */
234 
235 /**
236  * Returns the trailing space (space at the end) of the mbuf.
237  * Works on both packet header and regular mbufs.
238  *
239  * @param __omp The mbuf pool for this mbuf
240  * @param __om  Is the mbuf in that pool to get trailing space for
241  *
242  * @return The amount of trailing space available in the mbuf
243  */
244 #define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
245 
246 
247 #if SOC_ESP_NIMBLE_CONTROLLER
248 /**
249  * Initializes an mqueue.  An mqueue is a queue of mbufs that ties to a
250  * particular task's event queue.  Mqueues form a helper API around a common
251  * paradigm: wait on an event queue until at least one packet is available,
252  * then process a queue of packets.
253  *
254  * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
255  * will be posted to the task's mbuf queue.
256  *
257  * @param mq                    The mqueue to initialize
258  * @param ev_cb                 The callback to associate with the mqeueue
259  *                                  event.  Typically, this callback pulls each
260  *                                  packet off the mqueue and processes them.
261  * @param arg                   The argument to associate with the mqueue event.
262  *
263  * @return                      0 on success, non-zero on failure.
264  */
265 int r_os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
266 #define os_mqueue_init r_os_mqueue_init
267 
268 
269 /**
270  * Remove and return a single mbuf from the mbuf queue.  Does not block.
271  *
272  * @param mq The mbuf queue to pull an element off of.
273  *
274  * @return The next mbuf in the queue, or NULL if queue has no mbufs.
275  */
276 struct os_mbuf *r_os_mqueue_get(struct os_mqueue *);
277 #define os_mqueue_get r_os_mqueue_get
278 /**
279  * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
280  * with the mqueue gets posted to the specified eventq.
281  *
282  * @param mq                    The mbuf queue to append the mbuf to.
283  * @param evq                   The event queue to post an event to.
284  * @param m                     The mbuf to append to the mbuf queue.
285  *
286  * @return 0 on success, non-zero on failure.
287  */
288 int r_os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
289 #define os_mqueue_put r_os_mqueue_put
290 
291 
292 /**
293  * MSYS is a system level mbuf registry.  Allows the system to share
294  * packet buffers amongst the various networking stacks that can be running
295  * simultaeneously.
296  *
297  * Mbuf pools are created in the system initialization code, and then when
298  * a mbuf is allocated out of msys, it will try and find the best fit based
299  * upon estimated mbuf size.
300  *
301  * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
302  * allocate mbufs out of it.
303  *
304  * @param new_pool The pool to register with MSYS
305  *
306  * @return 0 on success, non-zero on failure
307  */
308 int r_os_msys_register(struct os_mbuf_pool *);
309 #define os_msys_register r_os_msys_register
310 
311 
312 /**
313  * Allocate a mbuf from msys.  Based upon the data size requested,
314  * os_msys_get() will choose the mbuf pool that has the best fit.
315  *
316  * @param dsize The estimated size of the data being stored in the mbuf
317  * @param leadingspace The amount of leadingspace to allocate in the mbuf
318  *
319  * @return A freshly allocated mbuf on success, NULL on failure.
320  */
321 struct os_mbuf *r_os_msys_get(uint16_t dsize, uint16_t leadingspace);
322 #define os_msys_get r_os_msys_get
323 /**
324  * De-registers all mbuf pools from msys.
325  */
326 void r_os_msys_reset(void);
327 #define os_msys_reset r_os_msys_reset
328 
329 
330 /**
331  * Allocate a packet header structure from the MSYS pool.  See
332  * os_msys_register() for a description of MSYS.
333  *
334  * @param dsize The estimated size of the data being stored in the mbuf
335  * @param user_hdr_len The length to allocate for the packet header structure
336  *
337  * @return A freshly allocated mbuf on success, NULL on failure.
338  */
339 struct os_mbuf *r_os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
340 #define os_msys_get_pkthdr r_os_msys_get_pkthdr
341 /**
342  * Count the number of blocks in all the mbuf pools that are allocated.
343  *
344  * @return total number of blocks allocated in Msys
345  */
346 int r_os_msys_count(void);
347 #define os_msys_count r_os_msys_count
348 
349 
350 /**
351  * Return the number of free blocks in Msys
352  *
353  * @return Number of free blocks available in Msys
354  */
355 int r_os_msys_num_free(void);
356 #define os_msys_num_free r_os_msys_num_free
357 
358 
359 /**
360  * Initialize a pool of mbufs.
361  *
362  * @param omp     The mbuf pool to initialize
363  * @param mp      The memory pool that will hold this mbuf pool
364  * @param buf_len The length of the buffer itself.
365  * @param nbufs   The number of buffers in the pool
366  *
367  * @return 0 on success, error code on failure.
368  */
369 int r_os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
370                       uint16_t, uint16_t);
371 #define os_mbuf_pool_init r_os_mbuf_pool_init
372 /**
373  * Get an mbuf from the mbuf pool.  The mbuf is allocated, and initialized
374  * prior to being returned.
375  *
376  * @param omp The mbuf pool to return the packet from
377  * @param leadingspace The amount of leadingspace to put before the data
378  *     section by default.
379  *
380  * @return An initialized mbuf on success, and NULL on failure.
381  */
382 struct os_mbuf *r_os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
383 #define os_mbuf_get r_os_mbuf_get
384 /**
385  * Allocate a new packet header mbuf out of the os_mbuf_pool.
386  *
387  * @param omp The mbuf pool to allocate out of
388  * @param user_pkthdr_len The packet header length to reserve for the caller.
389  *
390  * @return A freshly allocated mbuf on success, NULL on failure.
391  */
392 struct os_mbuf *r_os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
393                                    uint8_t pkthdr_len);
394 #define os_mbuf_get_pkthdr r_os_mbuf_get_pkthdr
395 /**
396  * Duplicate a chain of mbufs.  Return the start of the duplicated chain.
397  *
398  * @param omp The mbuf pool to duplicate out of
399  * @param om  The mbuf chain to duplicate
400  *
401  * @return A pointer to the new chain of mbufs
402  */
403 struct os_mbuf *r_os_mbuf_dup(struct os_mbuf *m);
404 #define os_mbuf_dup r_os_mbuf_dup
405 /**
406  * Locates the specified absolute offset within an mbuf chain.  The offset
407  * can be one past than the total length of the chain, but no greater.
408  *
409  * @param om                    The start of the mbuf chain to seek within.
410  * @param off                   The absolute address to find.
411  * @param out_off               On success, this points to the relative offset
412  *                                  within the returned mbuf.
413  *
414  * @return                      The mbuf containing the specified offset on
415  *                                  success.
416  *                              NULL if the specified offset is out of bounds.
417  */
418 struct os_mbuf *r_os_mbuf_off(const struct os_mbuf *om, int off,
419                             uint16_t *out_off);
420 #define os_mbuf_off r_os_mbuf_off
421 
422 /*
423  * Copy data from an mbuf chain starting "off" bytes from the beginning,
424  * continuing for "len" bytes, into the indicated buffer.
425  *
426  * @param m The mbuf chain to copy from
427  * @param off The offset into the mbuf chain to begin copying from
428  * @param len The length of the data to copy
429  * @param dst The destination buffer to copy into
430  *
431  * @return                      0 on success;
432  *                              -1 if the mbuf does not contain enough data.
433  */
434 int r_os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
435 #define os_mbuf_copydata r_os_mbuf_copydata
436 
437 
438 /**
439  * @brief Calculates the length of an mbuf chain.
440  *
441  * Calculates the length of an mbuf chain.  If the mbuf contains a packet
442  * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to
443  * this function.
444  *
445  * @param om                    The mbuf to measure.
446  *
447  * @return                      The length, in bytes, of the provided mbuf
448  *                                  chain.
449  */
450 uint16_t r_os_mbuf_len(const struct os_mbuf *om);
451 #define os_mbuf_len r_os_mbuf_len
452 
453 
454 /**
455  * Append data onto a mbuf
456  *
457  * @param om   The mbuf to append the data onto
458  * @param data The data to append onto the mbuf
459  * @param len  The length of the data to append
460  *
461  * @return 0 on success, and an error code on failure
462  */
463 int r_os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
464 #define os_mbuf_append r_os_mbuf_append
465 
466 
467 /**
468  * Reads data from one mbuf and appends it to another.  On error, the specified
469  * data range may be partially appended.  Neither mbuf is required to contain
470  * an mbuf packet header.
471  *
472  * @param dst                   The mbuf to append to.
473  * @param src                   The mbuf to copy data from.
474  * @param src_off               The absolute offset within the source mbuf
475  *                                  chain to read from.
476  * @param len                   The number of bytes to append.
477  *
478  * @return                      0 on success;
479  *                              OS_EINVAL if the specified range extends beyond
480  *                                  the end of the source mbuf chain.
481  */
482 int r_os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
483                        uint16_t src_off, uint16_t len);
484 #define os_mbuf_appendfrom r_os_mbuf_appendfrom
485 /**
486  * Release a mbuf back to the pool
487  *
488  * @param omp The Mbuf pool to release back to
489  * @param om  The Mbuf to release back to the pool
490  *
491  * @return 0 on success, -1 on failure
492  */
493 int r_os_mbuf_free(struct os_mbuf *mb);
494 #define os_mbuf_free r_os_mbuf_free
495 
496 
497 /**
498  * Free a chain of mbufs
499  *
500  * @param omp The mbuf pool to free the chain of mbufs into
501  * @param om  The starting mbuf of the chain to free back into the pool
502  *
503  * @return 0 on success, -1 on failure
504  */
505 int r_os_mbuf_free_chain(struct os_mbuf *om);
506 #define os_mbuf_free_chain r_os_mbuf_free_chain
507 
508 
509 /**
510  * Adjust the length of a mbuf, trimming either from the head or the tail
511  * of the mbuf.
512  *
513  * @param mp The mbuf chain to adjust
514  * @param req_len The length to trim from the mbuf.  If positive, trims
515  *                from the head of the mbuf, if negative, trims from the
516  *                tail of the mbuf.
517  */
518 void r_os_mbuf_adj(struct os_mbuf *mp, int req_len);
519 #define os_mbuf_adj r_os_mbuf_adj
520 
521 
522 
523 /**
524  * Performs a memory compare of the specified region of an mbuf chain against a
525  * flat buffer.
526  *
527  * @param om                    The start of the mbuf chain to compare.
528  * @param off                   The offset within the mbuf chain to start the
529  *                                  comparison.
530  * @param data                  The flat buffer to compare.
531  * @param len                   The length of the flat buffer.
532  *
533  * @return                      0 if both memory regions are identical;
534  *                              A memcmp return code if there is a mismatch;
535  *                              INT_MAX if the mbuf is too short.
536  */
537 int r_os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
538 #define os_mbuf_cmpf r_os_mbuf_cmpf
539 
540 
541 /**
542  * Compares the contents of two mbuf chains.  The ranges of the two chains to
543  * be compared are specified via the two offset parameters and the len
544  * parameter.  Neither mbuf chain is required to contain a packet header.
545  *
546  * @param om1                   The first mbuf chain to compare.
547  * @param offset1               The absolute offset within om1 at which to
548  *                                  start the comparison.
549  * @param om2                   The second mbuf chain to compare.
550  * @param offset2               The absolute offset within om2 at which to
551  *                                  start the comparison.
552  * @param len                   The number of bytes to compare.
553  *
554  * @return                      0 if both mbuf segments are identical;
555  *                              A memcmp() return code if the segment contents
556  *                                  differ;
557  *                              INT_MAX if a specified range extends beyond the
558  *                                  end of its corresponding mbuf chain.
559  */
560 int r_os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
561                  const struct os_mbuf *om2, uint16_t offset2,
562                  uint16_t len);
563 #define os_mbuf_cmpm r_os_mbuf_cmpm
564 /**
565  * Increases the length of an mbuf chain by adding data to the front.  If there
566  * is insufficient room in the leading mbuf, additional mbufs are allocated and
567  * prepended as necessary.  If this function fails to allocate an mbuf, the
568  * entire chain is freed.
569  *
570  * The specified mbuf chain does not need to contain a packet header.
571  *
572  * @param omp                   The mbuf pool to allocate from.
573  * @param om                    The head of the mbuf chain.
574  * @param len                   The number of bytes to prepend.
575  *
576  * @return                      The new head of the chain on success;
577  *                              NULL on failure.
578  */
579 struct os_mbuf *r_os_mbuf_prepend(struct os_mbuf *om, int len);
580 #define os_mbuf_prepend r_os_mbuf_prepend
581 /**
582  * Prepends a chunk of empty data to the specified mbuf chain and ensures the
583  * chunk is contiguous.  If either operation fails, the specified mbuf chain is
584  * freed and NULL is returned.
585  *
586  * @param om                    The mbuf chain to prepend to.
587  * @param len                   The number of bytes to prepend and pullup.
588  *
589  * @return                      The modified mbuf on success;
590  *                              NULL on failure (and the mbuf chain is freed).
591  */
592 struct os_mbuf *r_os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
593 #define os_mbuf_prepend_pullup r_os_mbuf_prepend_pullup
594 /**
595  * Copies the contents of a flat buffer into an mbuf chain, starting at the
596  * specified destination offset.  If the mbuf is too small for the source data,
597  * it is extended as necessary.  If the destination mbuf contains a packet
598  * header, the header length is updated.
599  *
600  * @param omp                   The mbuf pool to allocate from.
601  * @param om                    The mbuf chain to copy into.
602  * @param off                   The offset within the chain to copy to.
603  * @param src                   The source buffer to copy from.
604  * @param len                   The number of bytes to copy.
605  *
606  * @return                      0 on success; nonzero on failure.
607  */
608 int r_os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
609 #define os_mbuf_copyinto r_os_mbuf_copyinto
610 
611 
612 /**
613  * Attaches a second mbuf chain onto the end of the first.  If the first chain
614  * contains a packet header, the header's length is updated.  If the second
615  * chain has a packet header, its header is cleared.
616  *
617  * @param first                 The mbuf chain being attached to.
618  * @param second                The mbuf chain that gets attached.
619  */
620 void r_os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
621 #define os_mbuf_concat r_os_mbuf_concat
622 
623 
624 
625 /**
626  * Increases the length of an mbuf chain by the specified amount.  If there is
627  * not sufficient room in the last buffer, a new buffer is allocated and
628  * appended to the chain.  It is an error to request more data than can fit in
629  * a single buffer.
630  *
631  * @param omp
632  * @param om                    The head of the chain to extend.
633  * @param len                   The number of bytes to extend by.
634  *
635  * @return                      A pointer to the new data on success;
636  *                              NULL on failure.
637  */
638 void *r_os_mbuf_extend(struct os_mbuf *om, uint16_t len);
639 #define os_mbuf_extend r_os_mbuf_extend
640 /**
641  * Rearrange a mbuf chain so that len bytes are contiguous,
642  * and in the data area of an mbuf (so that OS_MBUF_DATA() will
643  * work on a structure of size len.)  Returns the resulting
644  * mbuf chain on success, free's it and returns NULL on failure.
645  *
646  * If there is room, it will add up to "max_protohdr - len"
647  * extra bytes to the contiguous region, in an attempt to avoid being
648  * called next time.
649  *
650  * @param omp The mbuf pool to take the mbufs out of
651  * @param om The mbuf chain to make contiguous
652  * @param len The number of bytes in the chain to make contiguous
653  *
654  * @return The contiguous mbuf chain on success, NULL on failure.
655  */
656 struct os_mbuf *r_os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
657 #define os_mbuf_pullup r_os_mbuf_pullup
658 
659 /**
660  * Removes and frees empty mbufs from the front of a chain.  If the chain
661  * contains a packet header, it is preserved.
662  *
663  * @param om                    The mbuf chain to trim.
664  *
665  * @return                      The head of the trimmed mbuf chain.
666  */
667 struct os_mbuf *r_os_mbuf_trim_front(struct os_mbuf *om);
668 #define os_mbuf_trim_front r_os_mbuf_trim_front
669 /**
670  * Increases the length of an mbuf chain by inserting a gap at the specified
671  * offset.  The contents of the gap are indeterminate.  If the mbuf chain
672  * contains a packet header, its total length is increased accordingly.
673  *
674  * This function never frees the provided mbuf chain.
675  *
676  * @param om                    The mbuf chain to widen.
677  * @param off                   The offset at which to insert the gap.
678  * @param len                   The size of the gap to insert.
679  *
680  * @return                      0 on success; SYS_[...] error code on failure.
681  */
682 int r_os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len);
683 #define os_mbuf_widen r_os_mbuf_widen
684 
685 
686 
687 /**
688  * Creates a single chained mbuf from m1 and m2 utilizing all
689  * the available buffer space in all mbufs in the resulting
690  * chain. In other words, ensures there is no leading space in
691  * any mbuf in the resulting chain and trailing space only in
692  * the last mbuf in the chain. Mbufs from either chain may be
693  * freed if not needed. No mbufs are allocated. Note that mbufs
694  * from m2 are added to the end of m1. If m1 has a packet
695  * header, it is retained and length updated. If m2 has a packet
696  * header it is discarded. If m1 is NULL, NULL is returned and
697  * m2 is left untouched.
698  *
699  * @param m1 Pointer to first mbuf chain to pack
700  * @param m2 Pointer to second mbuf chain to pack
701  *
702  * @return struct os_mbuf* Pointer to resulting mbuf chain
703  */
704 struct os_mbuf *r_os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2);
705 #define os_mbuf_pack_chains r_os_mbuf_pack_chains
706 
707 #else
708 /**
709  * Initializes an mqueue.  An mqueue is a queue of mbufs that ties to a
710  * particular task's event queue.  Mqueues form a helper API around a common
711  * paradigm: wait on an event queue until at least one packet is available,
712  * then process a queue of packets.
713  *
714  * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
715  * will be posted to the task's mbuf queue.
716  *
717  * @param mq                    The mqueue to initialize
718  * @param ev_cb                 The callback to associate with the mqeueue
719  *                                  event.  Typically, this callback pulls each
720  *                                  packet off the mqueue and processes them.
721  * @param arg                   The argument to associate with the mqueue event.
722  *
723  * @return                      0 on success, non-zero on failure.
724  */
725 int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg);
726 
727 /**
728  * Remove and return a single mbuf from the mbuf queue.  Does not block.
729  *
730  * @param mq The mbuf queue to pull an element off of.
731  *
732  * @return The next mbuf in the queue, or NULL if queue has no mbufs.
733  */
734 struct os_mbuf *os_mqueue_get(struct os_mqueue *);
735 
736 /**
737  * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
738  * with the mqueue gets posted to the specified eventq.
739  *
740  * @param mq                    The mbuf queue to append the mbuf to.
741  * @param evq                   The event queue to post an event to.
742  * @param m                     The mbuf to append to the mbuf queue.
743  *
744  * @return 0 on success, non-zero on failure.
745  */
746 int os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *);
747 
748 /**
749  * MSYS is a system level mbuf registry.  Allows the system to share
750  * packet buffers amongst the various networking stacks that can be running
751  * simultaeneously.
752  *
753  * Mbuf pools are created in the system initialization code, and then when
754  * a mbuf is allocated out of msys, it will try and find the best fit based
755  * upon estimated mbuf size.
756  *
757  * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
758  * allocate mbufs out of it.
759  *
760  * @param new_pool The pool to register with MSYS
761  *
762  * @return 0 on success, non-zero on failure
763  */
764 int os_msys_register(struct os_mbuf_pool *);
765 
766 /**
767  * Allocate a mbuf from msys.  Based upon the data size requested,
768  * os_msys_get() will choose the mbuf pool that has the best fit.
769  *
770  * @param dsize The estimated size of the data being stored in the mbuf
771  * @param leadingspace The amount of leadingspace to allocate in the mbuf
772  *
773  * @return A freshly allocated mbuf on success, NULL on failure.
774  */
775 struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace);
776 
777 /**
778  * De-registers all mbuf pools from msys.
779  */
780 void os_msys_reset(void);
781 
782 /**
783  * Allocate a packet header structure from the MSYS pool.  See
784  * os_msys_register() for a description of MSYS.
785  *
786  * @param dsize The estimated size of the data being stored in the mbuf
787  * @param user_hdr_len The length to allocate for the packet header structure
788  *
789  * @return A freshly allocated mbuf on success, NULL on failure.
790  */
791 struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
792 
793 /**
794  * Count the number of blocks in all the mbuf pools that are allocated.
795  *
796  * @return total number of blocks allocated in Msys
797  */
798 int os_msys_count(void);
799 
800 /**
801  * Return the number of free blocks in Msys
802  *
803  * @return Number of free blocks available in Msys
804  */
805 int os_msys_num_free(void);
806 
807 /**
808  * Initialize a pool of mbufs.
809  *
810  * @param omp     The mbuf pool to initialize
811  * @param mp      The memory pool that will hold this mbuf pool
812  * @param buf_len The length of the buffer itself.
813  * @param nbufs   The number of buffers in the pool
814  *
815  * @return 0 on success, error code on failure.
816  */
817 int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
818                       uint16_t, uint16_t);
819 
820 /**
821  * Get an mbuf from the mbuf pool.  The mbuf is allocated, and initialized
822  * prior to being returned.
823  *
824  * @param omp The mbuf pool to return the packet from
825  * @param leadingspace The amount of leadingspace to put before the data
826  *     section by default.
827  *
828  * @return An initialized mbuf on success, and NULL on failure.
829  */
830 struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
831 
832 /**
833  * Allocate a new packet header mbuf out of the os_mbuf_pool.
834  *
835  * @param omp The mbuf pool to allocate out of
836  * @param user_pkthdr_len The packet header length to reserve for the caller.
837  *
838  * @return A freshly allocated mbuf on success, NULL on failure.
839  */
840 struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
841                                    uint8_t pkthdr_len);
842 
843 /**
844  * Duplicate a chain of mbufs.  Return the start of the duplicated chain.
845  *
846  * @param omp The mbuf pool to duplicate out of
847  * @param om  The mbuf chain to duplicate
848  *
849  * @return A pointer to the new chain of mbufs
850  */
851 struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
852 
853 /**
854  * Locates the specified absolute offset within an mbuf chain.  The offset
855  * can be one past than the total length of the chain, but no greater.
856  *
857  * @param om                    The start of the mbuf chain to seek within.
858  * @param off                   The absolute address to find.
859  * @param out_off               On success, this points to the relative offset
860  *                                  within the returned mbuf.
861  *
862  * @return                      The mbuf containing the specified offset on
863  *                                  success.
864  *                              NULL if the specified offset is out of bounds.
865  */
866 struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
867                             uint16_t *out_off);
868 
869 
870 /*
871  * Copy data from an mbuf chain starting "off" bytes from the beginning,
872  * continuing for "len" bytes, into the indicated buffer.
873  *
874  * @param m The mbuf chain to copy from
875  * @param off The offset into the mbuf chain to begin copying from
876  * @param len The length of the data to copy
877  * @param dst The destination buffer to copy into
878  *
879  * @return                      0 on success;
880  *                              -1 if the mbuf does not contain enough data.
881  */
882 int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
883 
884 /**
885  * @brief Calculates the length of an mbuf chain.
886  *
887  * Calculates the length of an mbuf chain.  If the mbuf contains a packet
888  * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to
889  * this function.
890  *
891  * @param om                    The mbuf to measure.
892  *
893  * @return                      The length, in bytes, of the provided mbuf
894  *                                  chain.
895  */
896 uint16_t os_mbuf_len(const struct os_mbuf *om);
897 
898 /**
899  * Append data onto a mbuf
900  *
901  * @param om   The mbuf to append the data onto
902  * @param data The data to append onto the mbuf
903  * @param len  The length of the data to append
904  *
905  * @return 0 on success, and an error code on failure
906  */
907 int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
908 
909 /**
910  * Reads data from one mbuf and appends it to another.  On error, the specified
911  * data range may be partially appended.  Neither mbuf is required to contain
912  * an mbuf packet header.
913  *
914  * @param dst                   The mbuf to append to.
915  * @param src                   The mbuf to copy data from.
916  * @param src_off               The absolute offset within the source mbuf
917  *                                  chain to read from.
918  * @param len                   The number of bytes to append.
919  *
920  * @return                      0 on success;
921  *                              OS_EINVAL if the specified range extends beyond
922  *                                  the end of the source mbuf chain.
923  */
924 int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
925                        uint16_t src_off, uint16_t len);
926 
927 /**
928  * Release a mbuf back to the pool
929  *
930  * @param omp The Mbuf pool to release back to
931  * @param om  The Mbuf to release back to the pool
932  *
933  * @return 0 on success, -1 on failure
934  */
935 int os_mbuf_free(struct os_mbuf *mb);
936 
937 /**
938  * Free a chain of mbufs
939  *
940  * @param omp The mbuf pool to free the chain of mbufs into
941  * @param om  The starting mbuf of the chain to free back into the pool
942  *
943  * @return 0 on success, -1 on failure
944  */
945 int os_mbuf_free_chain(struct os_mbuf *om);
946 
947 /**
948  * Adjust the length of a mbuf, trimming either from the head or the tail
949  * of the mbuf.
950  *
951  * @param mp The mbuf chain to adjust
952  * @param req_len The length to trim from the mbuf.  If positive, trims
953  *                from the head of the mbuf, if negative, trims from the
954  *                tail of the mbuf.
955  */
956 void os_mbuf_adj(struct os_mbuf *mp, int req_len);
957 
958 
959 /**
960  * Performs a memory compare of the specified region of an mbuf chain against a
961  * flat buffer.
962  *
963  * @param om                    The start of the mbuf chain to compare.
964  * @param off                   The offset within the mbuf chain to start the
965  *                                  comparison.
966  * @param data                  The flat buffer to compare.
967  * @param len                   The length of the flat buffer.
968  *
969  * @return                      0 if both memory regions are identical;
970  *                              A memcmp return code if there is a mismatch;
971  *                              INT_MAX if the mbuf is too short.
972  */
973 int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
974 
975 /**
976  * Compares the contents of two mbuf chains.  The ranges of the two chains to
977  * be compared are specified via the two offset parameters and the len
978  * parameter.  Neither mbuf chain is required to contain a packet header.
979  *
980  * @param om1                   The first mbuf chain to compare.
981  * @param offset1               The absolute offset within om1 at which to
982  *                                  start the comparison.
983  * @param om2                   The second mbuf chain to compare.
984  * @param offset2               The absolute offset within om2 at which to
985  *                                  start the comparison.
986  * @param len                   The number of bytes to compare.
987  *
988  * @return                      0 if both mbuf segments are identical;
989  *                              A memcmp() return code if the segment contents
990  *                                  differ;
991  *                              INT_MAX if a specified range extends beyond the
992  *                                  end of its corresponding mbuf chain.
993  */
994 int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
995                  const struct os_mbuf *om2, uint16_t offset2,
996                  uint16_t len);
997 
998 /**
999  * Increases the length of an mbuf chain by adding data to the front.  If there
1000  * is insufficient room in the leading mbuf, additional mbufs are allocated and
1001  * prepended as necessary.  If this function fails to allocate an mbuf, the
1002  * entire chain is freed.
1003  *
1004  * The specified mbuf chain does not need to contain a packet header.
1005  *
1006  * @param omp                   The mbuf pool to allocate from.
1007  * @param om                    The head of the mbuf chain.
1008  * @param len                   The number of bytes to prepend.
1009  *
1010  * @return                      The new head of the chain on success;
1011  *                              NULL on failure.
1012  */
1013 struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
1014 
1015 /**
1016  * Prepends a chunk of empty data to the specified mbuf chain and ensures the
1017  * chunk is contiguous.  If either operation fails, the specified mbuf chain is
1018  * freed and NULL is returned.
1019  *
1020  * @param om                    The mbuf chain to prepend to.
1021  * @param len                   The number of bytes to prepend and pullup.
1022  *
1023  * @return                      The modified mbuf on success;
1024  *                              NULL on failure (and the mbuf chain is freed).
1025  */
1026 struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
1027 
1028 /**
1029  * Copies the contents of a flat buffer into an mbuf chain, starting at the
1030  * specified destination offset.  If the mbuf is too small for the source data,
1031  * it is extended as necessary.  If the destination mbuf contains a packet
1032  * header, the header length is updated.
1033  *
1034  * @param omp                   The mbuf pool to allocate from.
1035  * @param om                    The mbuf chain to copy into.
1036  * @param off                   The offset within the chain to copy to.
1037  * @param src                   The source buffer to copy from.
1038  * @param len                   The number of bytes to copy.
1039  *
1040  * @return                      0 on success; nonzero on failure.
1041  */
1042 int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
1043 
1044 /**
1045  * Attaches a second mbuf chain onto the end of the first.  If the first chain
1046  * contains a packet header, the header's length is updated.  If the second
1047  * chain has a packet header, its header is cleared.
1048  *
1049  * @param first                 The mbuf chain being attached to.
1050  * @param second                The mbuf chain that gets attached.
1051  */
1052 void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
1053 
1054 
1055 /**
1056  * Increases the length of an mbuf chain by the specified amount.  If there is
1057  * not sufficient room in the last buffer, a new buffer is allocated and
1058  * appended to the chain.  It is an error to request more data than can fit in
1059  * a single buffer.
1060  *
1061  * @param omp
1062  * @param om                    The head of the chain to extend.
1063  * @param len                   The number of bytes to extend by.
1064  *
1065  * @return                      A pointer to the new data on success;
1066  *                              NULL on failure.
1067  */
1068 void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
1069 
1070 /**
1071  * Rearrange a mbuf chain so that len bytes are contiguous,
1072  * and in the data area of an mbuf (so that OS_MBUF_DATA() will
1073  * work on a structure of size len.)  Returns the resulting
1074  * mbuf chain on success, free's it and returns NULL on failure.
1075  *
1076  * If there is room, it will add up to "max_protohdr - len"
1077  * extra bytes to the contiguous region, in an attempt to avoid being
1078  * called next time.
1079  *
1080  * @param omp The mbuf pool to take the mbufs out of
1081  * @param om The mbuf chain to make contiguous
1082  * @param len The number of bytes in the chain to make contiguous
1083  *
1084  * @return The contiguous mbuf chain on success, NULL on failure.
1085  */
1086 struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
1087 
1088 
1089 /**
1090  * Removes and frees empty mbufs from the front of a chain.  If the chain
1091  * contains a packet header, it is preserved.
1092  *
1093  * @param om                    The mbuf chain to trim.
1094  *
1095  * @return                      The head of the trimmed mbuf chain.
1096  */
1097 struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
1098 
1099 /**
1100  * Increases the length of an mbuf chain by inserting a gap at the specified
1101  * offset.  The contents of the gap are indeterminate.  If the mbuf chain
1102  * contains a packet header, its total length is increased accordingly.
1103  *
1104  * This function never frees the provided mbuf chain.
1105  *
1106  * @param om                    The mbuf chain to widen.
1107  * @param off                   The offset at which to insert the gap.
1108  * @param len                   The size of the gap to insert.
1109  *
1110  * @return                      0 on success; SYS_[...] error code on failure.
1111  */
1112 int os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len);
1113 
1114 
1115 /**
1116  * Creates a single chained mbuf from m1 and m2 utilizing all
1117  * the available buffer space in all mbufs in the resulting
1118  * chain. In other words, ensures there is no leading space in
1119  * any mbuf in the resulting chain and trailing space only in
1120  * the last mbuf in the chain. Mbufs from either chain may be
1121  * freed if not needed. No mbufs are allocated. Note that mbufs
1122  * from m2 are added to the end of m1. If m1 has a packet
1123  * header, it is retained and length updated. If m2 has a packet
1124  * header it is discarded. If m1 is NULL, NULL is returned and
1125  * m2 is left untouched.
1126  *
1127  * @param m1 Pointer to first mbuf chain to pack
1128  * @param m2 Pointer to second mbuf chain to pack
1129  *
1130  * @return struct os_mbuf* Pointer to resulting mbuf chain
1131  */
1132 struct os_mbuf *os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2);
1133 
1134 #endif
1135 #ifdef __cplusplus
1136 }
1137 #endif
1138 
1139 #endif /* _OS_MBUF_H */
1140 
1141 
1142 /**
1143  *   @} OSMbuf
1144  * @} OSKernel
1145  */
1146