ref: fc5424cb72e477c5f1bbfaeddb5c50b851a965ae
src/libs/mynewt-nimble/porting/nimble/include/os/os_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 |
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * @addtogroup OSKernel * @{ * @defgroup OSMbuf Chained Memory Buffers * @{ */ #ifndef _OS_MBUF_H #define _OS_MBUF_H #include "os/os.h" #ifdef __cplusplus extern "C" { #endif /** * A mbuf pool from which to allocate mbufs. This contains a pointer to the os * mempool to allocate mbufs out of, the total number of elements in the pool, * and the amount of "user" data in a non-packet header mbuf. The total pool * size, in bytes, should be: * os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf)) */ struct os_mbuf_pool { /** * Total length of the databuf in each mbuf. This is the size of the * mempool block, minus the mbuf header */ uint16_t omp_databuf_len; /** * The memory pool which to allocate mbufs out of */ struct os_mempool *omp_pool; STAILQ_ENTRY(os_mbuf_pool) omp_next; }; /** * A packet header structure that preceeds the mbuf packet headers. */ struct os_mbuf_pkthdr { /** * Overall length of the packet. */ uint16_t omp_len; /** * Flags */ uint16_t omp_flags; STAILQ_ENTRY(os_mbuf_pkthdr) omp_next; }; /** * Chained memory buffer. */ struct os_mbuf { /** * Current pointer to data in the structure */ uint8_t *om_data; /** * Flags associated with this buffer, see OS_MBUF_F_* defintions */ uint8_t om_flags; /** * Length of packet header */ uint8_t om_pkthdr_len; /** * Length of data in this buffer */ uint16_t om_len; /** * The mbuf pool this mbuf was allocated out of */ struct os_mbuf_pool *om_omp; SLIST_ENTRY(os_mbuf) om_next; /** * Pointer to the beginning of the data, after this buffer */ uint8_t om_databuf[0]; }; /** * Structure representing a queue of mbufs. */ struct os_mqueue { STAILQ_HEAD(, os_mbuf_pkthdr) mq_head; /** Event to post when new buffers are available on the queue. */ struct ble_npl_event mq_ev; }; /* * Given a flag number, provide the mask for it * * @param __n The number of the flag in the mask */ #define OS_MBUF_F_MASK(__n) (1 << (__n)) /* * Checks whether a given mbuf is a packet header mbuf * * @param __om The mbuf to check */ #define OS_MBUF_IS_PKTHDR(__om) \ ((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr)) /** Get a packet header pointer given an mbuf pointer */ #define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *) \ ((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf))) /** Given a mbuf packet header pointer, return a pointer to the mbuf */ #define OS_MBUF_PKTHDR_TO_MBUF(__hdr) \ (struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf)) /** * Gets the length of an entire mbuf chain. The specified mbuf must have a * packet header. */ #define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len) /** * Access the data of a mbuf, and cast it to type * * @param __om The mbuf to access, and cast * @param __type The type to cast it to */ #define OS_MBUF_DATA(__om, __type) \ (__type) ((__om)->om_data) /** * Access the "user header" in the head of an mbuf chain. * * @param om Pointer to the head of an mbuf chain. */ #define OS_MBUF_USRHDR(om) \ (void *)((uint8_t *)om + sizeof (struct os_mbuf) + \ sizeof (struct os_mbuf_pkthdr)) /** * Retrieves the length of the user header in an mbuf. * * @param om Pointer to the mbuf to query. */ #define OS_MBUF_USRHDR_LEN(om) \ ((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr)) /** @cond INTERNAL_HIDDEN */ /* * Called by OS_MBUF_LEADINGSPACE() macro */ static inline uint16_t _os_mbuf_leadingspace(struct os_mbuf *om) { uint16_t startoff; uint16_t leadingspace; startoff = 0; if (OS_MBUF_IS_PKTHDR(om)) { startoff = om->om_pkthdr_len; } leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) - ((uint8_t *) &om->om_databuf[0] + startoff)); return (leadingspace); } /** @endcond */ /** * Returns the leading space (space at the beginning) of the mbuf. * Works on both packet header, and regular mbufs, as it accounts * for the additional space allocated to the packet header. * * @param __omp Is the mbuf pool (which contains packet header length.) * @param __om Is the mbuf in that pool to get the leadingspace for * * @return Amount of leading space available in the mbuf */ #define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om) /** @cond INTERNAL_HIDDEN */ /* Called by OS_MBUF_TRAILINGSPACE() macro. */ static inline uint16_t _os_mbuf_trailingspace(struct os_mbuf *om) { struct os_mbuf_pool *omp; omp = om->om_omp; return (&om->om_databuf[0] + omp->omp_databuf_len) - (om->om_data + om->om_len); } /** @endcond */ /** * Returns the trailing space (space at the end) of the mbuf. * Works on both packet header and regular mbufs. * * @param __omp The mbuf pool for this mbuf * @param __om Is the mbuf in that pool to get trailing space for * * @return The amount of trailing space available in the mbuf */ #define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om) /** * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a * particular task's event queue. Mqueues form a helper API around a common * paradigm: wait on an event queue until at least one packet is available, * then process a queue of packets. * * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA * will be posted to the task's mbuf queue. * * @param mq The mqueue to initialize * @param ev_cb The callback to associate with the mqeueue * event. Typically, this callback pulls each * packet off the mqueue and processes them. * @param arg The argument to associate with the mqueue event. * * @return 0 on success, non-zero on failure. */ int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg); /** * Remove and return a single mbuf from the mbuf queue. Does not block. * * @param mq The mbuf queue to pull an element off of. * * @return The next mbuf in the queue, or NULL if queue has no mbufs. */ struct os_mbuf *os_mqueue_get(struct os_mqueue *); /** * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated * with the mqueue gets posted to the specified eventq. * * @param mq The mbuf queue to append the mbuf to. * @param evq The event queue to post an event to. * @param m The mbuf to append to the mbuf queue. * * @return 0 on success, non-zero on failure. */ int os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *); /** * MSYS is a system level mbuf registry. Allows the system to share * packet buffers amongst the various networking stacks that can be running * simultaeneously. * * Mbuf pools are created in the system initialization code, and then when * a mbuf is allocated out of msys, it will try and find the best fit based * upon estimated mbuf size. * * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to * allocate mbufs out of it. * * @param new_pool The pool to register with MSYS * * @return 0 on success, non-zero on failure */ int os_msys_register(struct os_mbuf_pool *); /** * Allocate a mbuf from msys. Based upon the data size requested, * os_msys_get() will choose the mbuf pool that has the best fit. * * @param dsize The estimated size of the data being stored in the mbuf * @param leadingspace The amount of leadingspace to allocate in the mbuf * * @return A freshly allocated mbuf on success, NULL on failure. */ struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace); /** * De-registers all mbuf pools from msys. */ void os_msys_reset(void); /** * Allocate a packet header structure from the MSYS pool. See * os_msys_register() for a description of MSYS. * * @param dsize The estimated size of the data being stored in the mbuf * @param user_hdr_len The length to allocate for the packet header structure * * @return A freshly allocated mbuf on success, NULL on failure. */ struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len); /** * Count the number of blocks in all the mbuf pools that are allocated. * * @return total number of blocks allocated in Msys */ int os_msys_count(void); /** * Return the number of free blocks in Msys * * @return Number of free blocks available in Msys */ int os_msys_num_free(void); /** * Initialize a pool of mbufs. * * @param omp The mbuf pool to initialize * @param mp The memory pool that will hold this mbuf pool * @param buf_len The length of the buffer itself. * @param nbufs The number of buffers in the pool * * @return 0 on success, error code on failure. */ int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp, uint16_t, uint16_t); /** * Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized * prior to being returned. * * @param omp The mbuf pool to return the packet from * @param leadingspace The amount of leadingspace to put before the data * section by default. * * @return An initialized mbuf on success, and NULL on failure. */ struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t); /** * Allocate a new packet header mbuf out of the os_mbuf_pool. * * @param omp The mbuf pool to allocate out of * @param user_pkthdr_len The packet header length to reserve for the caller. * * @return A freshly allocated mbuf on success, NULL on failure. */ struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp, uint8_t pkthdr_len); /** * Duplicate a chain of mbufs. Return the start of the duplicated chain. * * @param omp The mbuf pool to duplicate out of * @param om The mbuf chain to duplicate * * @return A pointer to the new chain of mbufs */ struct os_mbuf *os_mbuf_dup(struct os_mbuf *m); /** * Locates the specified absolute offset within an mbuf chain. The offset * can be one past than the total length of the chain, but no greater. * * @param om The start of the mbuf chain to seek within. * @param off The absolute address to find. * @param out_off On success, this points to the relative offset * within the returned mbuf. * * @return The mbuf containing the specified offset on * success. * NULL if the specified offset is out of bounds. */ struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off, uint16_t *out_off); /* * Copy data from an mbuf chain starting "off" bytes from the beginning, * continuing for "len" bytes, into the indicated buffer. * * @param m The mbuf chain to copy from * @param off The offset into the mbuf chain to begin copying from * @param len The length of the data to copy * @param dst The destination buffer to copy into * * @return 0 on success; * -1 if the mbuf does not contain enough data. */ int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst); /** * Append data onto a mbuf * * @param om The mbuf to append the data onto * @param data The data to append onto the mbuf * @param len The length of the data to append * * @return 0 on success, and an error code on failure */ int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t); /** * Reads data from one mbuf and appends it to another. On error, the specified * data range may be partially appended. Neither mbuf is required to contain * an mbuf packet header. * * @param dst The mbuf to append to. * @param src The mbuf to copy data from. * @param src_off The absolute offset within the source mbuf * chain to read from. * @param len The number of bytes to append. * * @return 0 on success; * OS_EINVAL if the specified range extends beyond * the end of the source mbuf chain. */ int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src, uint16_t src_off, uint16_t len); /** * Release a mbuf back to the pool * * @param omp The Mbuf pool to release back to * @param om The Mbuf to release back to the pool * * @return 0 on success, -1 on failure */ int os_mbuf_free(struct os_mbuf *mb); /** * Free a chain of mbufs * * @param omp The mbuf pool to free the chain of mbufs into * @param om The starting mbuf of the chain to free back into the pool * * @return 0 on success, -1 on failure */ int os_mbuf_free_chain(struct os_mbuf *om); /** * Adjust the length of a mbuf, trimming either from the head or the tail * of the mbuf. * * @param mp The mbuf chain to adjust * @param req_len The length to trim from the mbuf. If positive, trims * from the head of the mbuf, if negative, trims from the * tail of the mbuf. */ void os_mbuf_adj(struct os_mbuf *mp, int req_len); /** * Performs a memory compare of the specified region of an mbuf chain against a * flat buffer. * * @param om The start of the mbuf chain to compare. * @param off The offset within the mbuf chain to start the * comparison. * @param data The flat buffer to compare. * @param len The length of the flat buffer. * * @return 0 if both memory regions are identical; * A memcmp return code if there is a mismatch; * INT_MAX if the mbuf is too short. */ int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len); /** * Compares the contents of two mbuf chains. The ranges of the two chains to * be compared are specified via the two offset parameters and the len * parameter. Neither mbuf chain is required to contain a packet header. * * @param om1 The first mbuf chain to compare. * @param offset1 The absolute offset within om1 at which to * start the comparison. * @param om2 The second mbuf chain to compare. * @param offset2 The absolute offset within om2 at which to * start the comparison. * @param len The number of bytes to compare. * * @return 0 if both mbuf segments are identical; * A memcmp() return code if the segment contents * differ; * INT_MAX if a specified range extends beyond the * end of its corresponding mbuf chain. */ int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1, const struct os_mbuf *om2, uint16_t offset2, uint16_t len); /** * Increases the length of an mbuf chain by adding data to the front. If there * is insufficient room in the leading mbuf, additional mbufs are allocated and * prepended as necessary. If this function fails to allocate an mbuf, the * entire chain is freed. * * The specified mbuf chain does not need to contain a packet header. * * @param omp The mbuf pool to allocate from. * @param om The head of the mbuf chain. * @param len The number of bytes to prepend. * * @return The new head of the chain on success; * NULL on failure. */ struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len); /** * Prepends a chunk of empty data to the specified mbuf chain and ensures the * chunk is contiguous. If either operation fails, the specified mbuf chain is * freed and NULL is returned. * * @param om The mbuf chain to prepend to. * @param len The number of bytes to prepend and pullup. * * @return The modified mbuf on success; * NULL on failure (and the mbuf chain is freed). */ struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len); /** * Copies the contents of a flat buffer into an mbuf chain, starting at the * specified destination offset. If the mbuf is too small for the source data, * it is extended as necessary. If the destination mbuf contains a packet * header, the header length is updated. * * @param omp The mbuf pool to allocate from. * @param om The mbuf chain to copy into. * @param off The offset within the chain to copy to. * @param src The source buffer to copy from. * @param len The number of bytes to copy. * * @return 0 on success; nonzero on failure. */ int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len); /** * Attaches a second mbuf chain onto the end of the first. If the first chain * contains a packet header, the header's length is updated. If the second * chain has a packet header, its header is cleared. * * @param first The mbuf chain being attached to. * @param second The mbuf chain that gets attached. */ void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second); /** * Increases the length of an mbuf chain by the specified amount. If there is * not sufficient room in the last buffer, a new buffer is allocated and * appended to the chain. It is an error to request more data than can fit in * a single buffer. * * @param omp * @param om The head of the chain to extend. * @param len The number of bytes to extend by. * * @return A pointer to the new data on success; * NULL on failure. */ void *os_mbuf_extend(struct os_mbuf *om, uint16_t len); /** * Rearrange a mbuf chain so that len bytes are contiguous, * and in the data area of an mbuf (so that OS_MBUF_DATA() will * work on a structure of size len.) Returns the resulting * mbuf chain on success, free's it and returns NULL on failure. * * If there is room, it will add up to "max_protohdr - len" * extra bytes to the contiguous region, in an attempt to avoid being * called next time. * * @param omp The mbuf pool to take the mbufs out of * @param om The mbuf chain to make contiguous * @param len The number of bytes in the chain to make contiguous * * @return The contiguous mbuf chain on success, NULL on failure. */ struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len); /** * Removes and frees empty mbufs from the front of a chain. If the chain * contains a packet header, it is preserved. * * @param om The mbuf chain to trim. * * @return The head of the trimmed mbuf chain. */ struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om); /** * Creates a single chained mbuf from m1 and m2 utilizing all * the available buffer space in all mbufs in the resulting * chain. In other words, ensures there is no leading space in * any mbuf in the resulting chain and trailing space only in * the last mbuf in the chain. Mbufs from either chain may be * freed if not needed. No mbufs are allocated. Note that mbufs * from m2 are added to the end of m1. If m1 has a packet * header, it is retained and length updated. If m2 has a packet * header it is discarded. If m1 is NULL, NULL is returned and * m2 is left untouched. * * @param m1 Pointer to first mbuf chain to pack * @param m2 Pointer to second mbuf chain to pack * * @return struct os_mbuf* Pointer to resulting mbuf chain */ struct os_mbuf *os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2); #ifdef __cplusplus } #endif #endif /* _OS_MBUF_H */ /** * @} OSMbuf * @} OSKernel */ |