net: buf: Support copying of user data
This functionality is useful on the following scenario: 1) The first buffer in a net_pkt contains user data which is relevant for the (whole) net_pkt. 2) When inserting a new buffer in front of the net_pkt, the (previously) first buffer (and its user data) are no longer accessible via net_pkt->buffer. 3) net_buf_user_data_copy() allows to simply copy the user data from the old to the new first buffer. Signed-off-by: Reto Schneider <reto.schneider@husqvarnagroup.com>
This commit is contained in:
parent
9bf0a24f2e
commit
9dd87a7194
3 changed files with 62 additions and 0 deletions
|
|
@ -1467,6 +1467,17 @@ static inline void * __must_check net_buf_user_data(const struct net_buf *buf)
|
|||
return (void *)buf->user_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy user data from one to another buffer.
|
||||
*
|
||||
* @param dst A valid pointer to a buffer gettings its user data overwritten.
|
||||
* @param src A valid pointer to a buffer gettings its user data copied. User data size must be
|
||||
* equal to or exceed @a dst.
|
||||
*
|
||||
* @return 0 on success or negative error number on failure.
|
||||
*/
|
||||
int net_buf_user_data_copy(struct net_buf *dst, const struct net_buf *src);
|
||||
|
||||
/**
|
||||
* @brief Initialize buffer with the given headroom.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -542,6 +542,24 @@ struct net_buf *net_buf_clone(struct net_buf *buf, k_timeout_t timeout)
|
|||
return clone;
|
||||
}
|
||||
|
||||
int net_buf_user_data_copy(struct net_buf *dst, const struct net_buf *src)
|
||||
{
|
||||
__ASSERT_NO_MSG(dst);
|
||||
__ASSERT_NO_MSG(src);
|
||||
|
||||
if (dst == src) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dst->user_data_size < src->user_data_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(dst->user_data, src->user_data, src->user_data_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct net_buf *net_buf_frag_last(struct net_buf *buf)
|
||||
{
|
||||
__ASSERT_NO_MSG(buf);
|
||||
|
|
|
|||
|
|
@ -756,6 +756,39 @@ ZTEST(net_buf_tests, test_net_buf_user_data)
|
|||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
ZTEST(net_buf_tests, test_net_buf_user_data_copy)
|
||||
{
|
||||
struct net_buf *buf_user_data_small, *buf_user_data_big;
|
||||
uint32_t *src_user_data, *dst_user_data;
|
||||
|
||||
buf_user_data_small = net_buf_alloc_len(&bufs_pool, 1, K_NO_WAIT);
|
||||
zassert_not_null(buf_user_data_small, "Failed to get buffer");
|
||||
src_user_data = net_buf_user_data(buf_user_data_small);
|
||||
*src_user_data = 0xAABBCCDD;
|
||||
|
||||
/* Happy case: Size of user data in destination buf is bigger than the source buf one */
|
||||
buf_user_data_big = net_buf_alloc_len(&var_pool, 1, K_NO_WAIT);
|
||||
zassert_not_null(buf_user_data_big, "Failed to get buffer");
|
||||
dst_user_data = net_buf_user_data(buf_user_data_big);
|
||||
*dst_user_data = 0x11223344;
|
||||
|
||||
zassert_ok(net_buf_user_data_copy(buf_user_data_big, buf_user_data_small));
|
||||
zassert_equal(*src_user_data, 0xAABBCCDD);
|
||||
|
||||
/* Error case: User data size of destination buffer is too small */
|
||||
zassert_not_ok(net_buf_user_data_copy(buf_user_data_small, buf_user_data_big),
|
||||
"User data size in destination buffer too small");
|
||||
|
||||
net_buf_unref(buf_user_data_big);
|
||||
|
||||
/* Corner case: Same buffer used as source and target */
|
||||
zassert_ok(net_buf_user_data_copy(buf_user_data_small, buf_user_data_small),
|
||||
"No-op is tolerated");
|
||||
zassert_equal(*src_user_data, 0xAABBCCDD, "User data remains the same");
|
||||
|
||||
net_buf_unref(buf_user_data_small);
|
||||
}
|
||||
|
||||
ZTEST(net_buf_tests, test_net_buf_comparison)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
|
|
|
|||
Loading…
Reference in a new issue