net/nbuf: Introduce the net_nbuf_linear_copy routine
This commit adds one routine previously found at the DNS resolver library. The net_nbuf_linear_copy routine allows to "linearize" an IP stack network buffer. This routine is required by functions that must jump between big chunks of data that in this case may lie between many fragments. Tracking fragments may be a tedious task, so getting a linear copy of the buffer will reduce code complexity altough it increases memory consumption. The DNS client library is updated to reflect these changes. Change-Id: Iae321f99fa9b05fae7e722b6d41baac427d82d7e Signed-off-by: Flavio Santes <flavio.santes@intel.com>
This commit is contained in:
parent
a46548ec31
commit
c015c0e2c8
3 changed files with 57 additions and 38 deletions
|
@ -511,6 +511,22 @@ static inline struct net_buf *net_nbuf_copy_all(struct net_buf *buf,
|
||||||
return net_nbuf_copy(buf, net_buf_frags_len(buf), reserve);
|
return net_nbuf_copy(buf, net_buf_frags_len(buf), reserve);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief net_nbuf_linear_copy Copy len bytes from src starting from
|
||||||
|
* offset to dst
|
||||||
|
* @details This routine assumes that dst is conformed by
|
||||||
|
* one fragment with enough space to store len
|
||||||
|
* bytes starting from offset at src.
|
||||||
|
* @param dst Destination buffer
|
||||||
|
* @param src Source buffer that may be fragmented
|
||||||
|
* @param offset Starting point to copy from
|
||||||
|
* @param len Number of bytes to copy
|
||||||
|
* @return 0 on success
|
||||||
|
* @return -ENOMEM on error
|
||||||
|
*/
|
||||||
|
int net_nbuf_linear_copy(struct net_buf *dst, struct net_buf *src,
|
||||||
|
uint16_t offset, uint16_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compact the fragment list.
|
* @brief Compact the fragment list.
|
||||||
*
|
*
|
||||||
|
|
|
@ -636,6 +636,45 @@ struct net_buf *net_nbuf_copy(struct net_buf *orig, size_t amount,
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int net_nbuf_linear_copy(struct net_buf *dst, struct net_buf *src,
|
||||||
|
uint16_t offset, uint16_t len)
|
||||||
|
{
|
||||||
|
uint16_t to_copy;
|
||||||
|
uint16_t copied;
|
||||||
|
|
||||||
|
if (dst->size < len) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the right fragment to start copying from */
|
||||||
|
while (src && offset >= src->len) {
|
||||||
|
offset -= src->len;
|
||||||
|
src = src->frags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* traverse the fragment chain until len bytes are copied */
|
||||||
|
copied = 0;
|
||||||
|
while (src && len > 0) {
|
||||||
|
to_copy = min(len, src->len - offset);
|
||||||
|
memcpy(dst->data + copied, src->data + offset, to_copy);
|
||||||
|
|
||||||
|
copied += to_copy;
|
||||||
|
/* to_copy is always <= len */
|
||||||
|
len -= to_copy;
|
||||||
|
src = src->frags;
|
||||||
|
/* after the first iteration, this value will be 0 */
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->len = copied;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool net_nbuf_is_compact(struct net_buf *buf)
|
bool net_nbuf_is_compact(struct net_buf *buf)
|
||||||
{
|
{
|
||||||
struct net_buf *last;
|
struct net_buf *last;
|
||||||
|
|
|
@ -221,10 +221,6 @@ void cb_recv(struct net_context *net_ctx, struct net_buf *buf, int status,
|
||||||
k_sem_give(&ctx->rx_sem);
|
k_sem_give(&ctx->rx_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
int nbuf_copy(struct net_buf *dst, struct net_buf *src, int offset,
|
|
||||||
int len);
|
|
||||||
|
|
||||||
static
|
static
|
||||||
int dns_read(struct dns_context *ctx, struct net_buf *dns_data,
|
int dns_read(struct dns_context *ctx, struct net_buf *dns_data,
|
||||||
uint16_t dns_id, uint8_t *cname, uint16_t *cname_len)
|
uint16_t dns_id, uint8_t *cname, uint16_t *cname_len)
|
||||||
|
@ -271,7 +267,8 @@ int dns_read(struct dns_context *ctx, struct net_buf *dns_data,
|
||||||
DNS_RESOLVER_MAX_BUF_SIZE);
|
DNS_RESOLVER_MAX_BUF_SIZE);
|
||||||
offset = net_buf_frags_len(ctx->rx_buf) - data_len;
|
offset = net_buf_frags_len(ctx->rx_buf) - data_len;
|
||||||
|
|
||||||
if (nbuf_copy(dns_data, ctx->rx_buf, offset, data_len) != 0) {
|
rc = net_nbuf_linear_copy(dns_data, ctx->rx_buf, offset, data_len);
|
||||||
|
if (rc != 0) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto exit_error;
|
goto exit_error;
|
||||||
}
|
}
|
||||||
|
@ -375,36 +372,3 @@ exit_error:
|
||||||
net_nbuf_unref(ctx->rx_buf);
|
net_nbuf_unref(ctx->rx_buf);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
int nbuf_copy(struct net_buf *dst, struct net_buf *src, int offset,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
int copied;
|
|
||||||
int to_copy;
|
|
||||||
|
|
||||||
/* find the right fragment to start copying from */
|
|
||||||
while (src && offset >= src->len) {
|
|
||||||
offset -= src->len;
|
|
||||||
src = src->frags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* traverse the fragment chain until len bytes are copied */
|
|
||||||
copied = 0;
|
|
||||||
while (src && len > 0) {
|
|
||||||
to_copy = min(len, src->len - offset);
|
|
||||||
memcpy(dst->data + copied, src->data + offset, to_copy);
|
|
||||||
|
|
||||||
copied += to_copy;
|
|
||||||
len -= to_copy;
|
|
||||||
src = src->frags;
|
|
||||||
/* after the first iteration, this value will be 0 */
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > 0) {
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue