porting/nimble: os_mbuf_pack_chains

Adding the os_mbuf_pack_chains API from mynewt-core.
This commit is contained in:
Will San Filippo
2019-11-05 11:03:40 -08:00
committed by Prasad Alatkar
parent 204c3482b4
commit 0d5c955fea
2 changed files with 105 additions and 0 deletions
+19
View File
@@ -614,6 +614,25 @@ struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
*/
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
+86
View File
@@ -1037,3 +1037,89 @@ os_mbuf_trim_front(struct os_mbuf *om)
return om;
}
struct os_mbuf *
os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2)
{
uint16_t rem_len;
uint16_t copylen;
uint8_t *dptr;
struct os_mbuf *cur;
struct os_mbuf *next;
/* If m1 is NULL, return NULL */
if (m1 == NULL) {
return NULL;
}
/*
* Concatenate the two chains to start. This will discard packet header in
* m2 and adjust packet length in m1 if m1 has a packet header.
*/
if (m2 != NULL) {
os_mbuf_concat(m1, m2);
}
cur = m1;
while (1) {
/* If there is leading space in the mbuf, move data up */
if (OS_MBUF_LEADINGSPACE(cur)) {
dptr = &cur->om_databuf[0];
if (OS_MBUF_IS_PKTHDR(cur)) {
dptr += cur->om_pkthdr_len;
}
memmove(dptr, cur->om_data, cur->om_len);
cur->om_data = dptr;
}
/* Set pointer to where we will begin copying data in current mbuf */
dptr = cur->om_data + cur->om_len;
/* Get a pointer to the next buf we want to absorb */
next = SLIST_NEXT(cur, om_next);
/*
* Is there trailing space in the mbuf? If so, copy data from
* following mbufs into the current mbuf
*/
rem_len = OS_MBUF_TRAILINGSPACE(cur);
while (rem_len && next) {
copylen = min(rem_len, next->om_len);
memcpy(dptr, next->om_data, copylen);
cur->om_len += copylen;
dptr += copylen;
rem_len -= copylen;
/*
* We copied bytes from the next mbuf. Move the data pointer
* and subtract from its length
*/
next->om_data += copylen;
next->om_len -= copylen;
/*
* Keep removing and freeing consecutive zero length mbufs,
* stopping when we find one with data in it or we have
* reached the end. This will prevent any zero length mbufs
* from remaining in the chain.
*/
while (next->om_len == 0) {
SLIST_NEXT(cur, om_next) = SLIST_NEXT(next, om_next);
os_mbuf_free(next);
next = SLIST_NEXT(cur, om_next);
if (next == NULL) {
break;
}
}
}
/* If no mbufs are left, we are done */
if (next == NULL) {
break;
}
/* Move cur to next as we filled up current */
cur = next;
}
return m1;
}