Merge pull request #10447 from miri64/gnrc_pktbuf/feat/merge
gnrc_pktbuf: add gnrc_pktbuf_merge()
This commit is contained in:
commit
1cb780ea26
@ -298,6 +298,60 @@ gnrc_pktsnip_t *gnrc_pktbuf_reverse_snips(gnrc_pktsnip_t *pkt);
|
|||||||
*/
|
*/
|
||||||
gnrc_pktsnip_t *gnrc_pktbuf_duplicate_upto(gnrc_pktsnip_t *pkt, gnrc_nettype_t type);
|
gnrc_pktsnip_t *gnrc_pktbuf_duplicate_upto(gnrc_pktsnip_t *pkt, gnrc_nettype_t type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Merge pktsnip chain to single pktsnip.
|
||||||
|
*
|
||||||
|
* Specifically it calls @ref gnrc_pktbuf_realloc_data() on @p pkt, then copies
|
||||||
|
* the data of all following packet snips into that reallocated space, and
|
||||||
|
* removes the packet snip the data was copied from afterwards.
|
||||||
|
*
|
||||||
|
* ### Example
|
||||||
|
* #### Input
|
||||||
|
*
|
||||||
|
* buffer
|
||||||
|
* +---------------------------+ +------+
|
||||||
|
* | size = 8 | data +-------->| |
|
||||||
|
* | type = NETTYPE_IPV6 |------------+ +------+
|
||||||
|
* +---------------------------+ . .
|
||||||
|
* | next . .
|
||||||
|
* v . .
|
||||||
|
* +---------------------------+ +------+
|
||||||
|
* | size = 40 | data +----------->| |
|
||||||
|
* | type = NETTYPE_UDP |---------+ +------+
|
||||||
|
* +---------------------------+ . .
|
||||||
|
* | next . .
|
||||||
|
* v
|
||||||
|
* +---------------------------+ +------+
|
||||||
|
* | size = 14 | data +-------------->| |
|
||||||
|
* | type = NETTYPE_UNDEF |------+ +------+
|
||||||
|
* +---------------------------+ . .
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* #### Output
|
||||||
|
*
|
||||||
|
* buffer
|
||||||
|
* +---------------------------+ +------+
|
||||||
|
* | size = 62 | data +-------->| |
|
||||||
|
* | type = NETTYPE_IPV6 |------------+ | |
|
||||||
|
* +---------------------------+ | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* | |
|
||||||
|
* +------+
|
||||||
|
* . .
|
||||||
|
*
|
||||||
|
* @warning @p pkt needs to write protected before calling this function.
|
||||||
|
* @note Packets in receive order need to call
|
||||||
|
* @ref gnrc_pktbuf_reverse_snips() first to get the data in the
|
||||||
|
* correct order.
|
||||||
|
*
|
||||||
|
* @param[in,out] pkt The snip to merge.
|
||||||
|
*
|
||||||
|
* @return 0, on success
|
||||||
|
* @return ENOMEM, if no space is left in the packet buffer.
|
||||||
|
*/
|
||||||
|
int gnrc_pktbuf_merge(gnrc_pktsnip_t *pkt);
|
||||||
|
|
||||||
#ifdef DEVELHELP
|
#ifdef DEVELHELP
|
||||||
/**
|
/**
|
||||||
* @brief Prints some statistics about the packet buffer to stdout.
|
* @brief Prints some statistics about the packet buffer to stdout.
|
||||||
|
|||||||
@ -109,5 +109,32 @@ gnrc_pktsnip_t *gnrc_pktbuf_reverse_snips(gnrc_pktsnip_t *pkt)
|
|||||||
return reversed;
|
return reversed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gnrc_pktbuf_merge(gnrc_pktsnip_t *pkt)
|
||||||
|
{
|
||||||
|
size_t offset = pkt->size;
|
||||||
|
size_t size = gnrc_pkt_len(pkt);
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (pkt->size == size) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-allocate data */
|
||||||
|
res = gnrc_pktbuf_realloc_data(pkt, size);
|
||||||
|
if (res != 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy data to new buffer */
|
||||||
|
for (gnrc_pktsnip_t *ptr = pkt->next; ptr != NULL; ptr = ptr->next) {
|
||||||
|
memcpy(((uint8_t *)pkt->data) + offset, ptr->data, ptr->size);
|
||||||
|
offset += ptr->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release old pktsnips and data*/
|
||||||
|
gnrc_pktbuf_release(pkt->next);
|
||||||
|
pkt->next = NULL;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
@ -653,6 +653,52 @@ static void test_pktbuf_realloc_data__success3(void)
|
|||||||
TEST_ASSERT(gnrc_pktbuf_is_empty());
|
TEST_ASSERT(gnrc_pktbuf_is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_pktbuf_merge_data__memfull(void)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, NULL, (GNRC_PKTBUF_SIZE / 4),
|
||||||
|
GNRC_NETTYPE_TEST);
|
||||||
|
|
||||||
|
pkt = gnrc_pktbuf_add(pkt, NULL, (GNRC_PKTBUF_SIZE / 4) + 1,
|
||||||
|
GNRC_NETTYPE_TEST);
|
||||||
|
TEST_ASSERT_EQUAL_INT(ENOMEM, gnrc_pktbuf_merge(pkt));
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
TEST_ASSERT(gnrc_pktbuf_is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_pktbuf_merge_data__success1(void)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, NULL, 0, GNRC_NETTYPE_TEST);
|
||||||
|
|
||||||
|
TEST_ASSERT_NOT_NULL(pkt);
|
||||||
|
TEST_ASSERT_NULL(pkt->data);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, gnrc_pktbuf_merge(pkt));
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
TEST_ASSERT(gnrc_pktbuf_is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_pktbuf_merge_data__success2(void)
|
||||||
|
{
|
||||||
|
gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, TEST_STRING4,
|
||||||
|
sizeof(TEST_STRING4),
|
||||||
|
GNRC_NETTYPE_TEST);
|
||||||
|
|
||||||
|
pkt = gnrc_pktbuf_add(pkt, TEST_STRING8, sizeof(TEST_STRING8), GNRC_NETTYPE_TEST);
|
||||||
|
pkt = gnrc_pktbuf_add(pkt, TEST_STRING16, sizeof(TEST_STRING16), GNRC_NETTYPE_TEST);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, gnrc_pktbuf_merge(pkt));
|
||||||
|
TEST_ASSERT_NULL(pkt->next);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(TEST_STRING16, pkt->data);
|
||||||
|
TEST_ASSERT_EQUAL_STRING(TEST_STRING8,
|
||||||
|
(char *) pkt->data + sizeof(TEST_STRING16));
|
||||||
|
TEST_ASSERT_EQUAL_STRING(TEST_STRING4,
|
||||||
|
(char *) pkt->data + sizeof(TEST_STRING16) +
|
||||||
|
sizeof(TEST_STRING8));
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
|
TEST_ASSERT(gnrc_pktbuf_is_empty());
|
||||||
|
TEST_ASSERT(gnrc_pktbuf_is_sane());
|
||||||
|
}
|
||||||
|
|
||||||
static void test_pktbuf_hold__pkt_null(void)
|
static void test_pktbuf_hold__pkt_null(void)
|
||||||
{
|
{
|
||||||
gnrc_pktbuf_hold(NULL, 1);
|
gnrc_pktbuf_hold(NULL, 1);
|
||||||
@ -895,6 +941,9 @@ Test *tests_pktbuf_tests(void)
|
|||||||
new_TestFixture(test_pktbuf_realloc_data__success),
|
new_TestFixture(test_pktbuf_realloc_data__success),
|
||||||
new_TestFixture(test_pktbuf_realloc_data__success2),
|
new_TestFixture(test_pktbuf_realloc_data__success2),
|
||||||
new_TestFixture(test_pktbuf_realloc_data__success3),
|
new_TestFixture(test_pktbuf_realloc_data__success3),
|
||||||
|
new_TestFixture(test_pktbuf_merge_data__memfull),
|
||||||
|
new_TestFixture(test_pktbuf_merge_data__success1),
|
||||||
|
new_TestFixture(test_pktbuf_merge_data__success2),
|
||||||
new_TestFixture(test_pktbuf_hold__pkt_null),
|
new_TestFixture(test_pktbuf_hold__pkt_null),
|
||||||
new_TestFixture(test_pktbuf_hold__pkt_external),
|
new_TestFixture(test_pktbuf_hold__pkt_external),
|
||||||
new_TestFixture(test_pktbuf_hold__success),
|
new_TestFixture(test_pktbuf_hold__success),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user