net: pkt: Introduce minimum length requirement to net_pkt_get_frag()
net_pkt_get_frag() and a few other functions did not specify the allocated fragment length, incorrectly assuming that fixed-sized buffers are always used. In order to make the function work properly also with variable-sized buffers, extend the function argument list with minimum expected fragment length parameter. This allows to use net_buf_alloc_len() allocator in variable buffer length configuration, as well as verify if the fixed-sized buffer is large enough to satisfy the requirements otherwise. Update the existing codebase to provide the expected fragment length, based on the context. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
98608b3c30
commit
387a66131e
18 changed files with 112 additions and 65 deletions
|
@ -1394,16 +1394,18 @@ static bool uncompress_IPHC_header(struct net_pkt *pkt)
|
|||
cursor = frag->data + diff;
|
||||
memmove(cursor, frag->data, frag->len - diff);
|
||||
} else {
|
||||
size_t frag_len = nhc ? NET_IPV6UDPH_LEN : NET_IPV6H_LEN;
|
||||
|
||||
NET_DBG("Not enough tailroom. Get new fragment");
|
||||
cursor = pkt->buffer->data;
|
||||
frag = net_pkt_get_frag(pkt, NET_6LO_RX_PKT_TIMEOUT);
|
||||
frag = net_pkt_get_frag(pkt, frag_len, NET_6LO_RX_PKT_TIMEOUT);
|
||||
if (!frag) {
|
||||
NET_ERR("Can't get frag for uncompression");
|
||||
return false;
|
||||
}
|
||||
|
||||
net_buf_pull(pkt->buffer, compressed_hdr_size);
|
||||
net_buf_add(frag, nhc ? NET_IPV6UDPH_LEN : NET_IPV6H_LEN);
|
||||
net_buf_add(frag, frag_len);
|
||||
}
|
||||
|
||||
ipv6 = (struct net_ipv6_hdr *)(frag->data);
|
||||
|
@ -1537,7 +1539,7 @@ static inline int compress_ipv6_header(struct net_pkt *pkt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
buffer = net_pkt_get_frag(pkt, K_FOREVER);
|
||||
buffer = net_pkt_get_frag(pkt, 1, K_FOREVER);
|
||||
if (!buffer) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
|
|
@ -368,27 +368,32 @@ void net_pkt_print_frags(struct net_pkt *pkt)
|
|||
|
||||
#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
struct net_buf *net_pkt_get_reserve_data_debug(struct net_buf_pool *pool,
|
||||
size_t min_len,
|
||||
k_timeout_t timeout,
|
||||
const char *caller,
|
||||
int line)
|
||||
#else /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
|
||||
struct net_buf *net_pkt_get_reserve_data(struct net_buf_pool *pool,
|
||||
k_timeout_t timeout)
|
||||
size_t min_len, k_timeout_t timeout)
|
||||
#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
|
||||
{
|
||||
struct net_buf *frag;
|
||||
|
||||
/*
|
||||
* The reserve_head variable in the function will tell
|
||||
* the size of the link layer headers if there are any.
|
||||
*/
|
||||
|
||||
if (k_is_in_isr()) {
|
||||
frag = net_buf_alloc(pool, K_NO_WAIT);
|
||||
} else {
|
||||
frag = net_buf_alloc(pool, timeout);
|
||||
timeout = K_NO_WAIT;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
|
||||
if (min_len > CONFIG_NET_BUF_DATA_SIZE) {
|
||||
NET_ERR("Requested too large fragment. Increase CONFIG_NET_BUF_DATA_SIZE.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
frag = net_buf_alloc(pool, timeout);
|
||||
#else
|
||||
frag = net_buf_alloc_len(pool, min_len, timeout);
|
||||
#endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
|
||||
|
||||
if (!frag) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -412,11 +417,11 @@ struct net_buf *net_pkt_get_reserve_data(struct net_buf_pool *pool,
|
|||
* the data.
|
||||
*/
|
||||
#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
struct net_buf *net_pkt_get_frag_debug(struct net_pkt *pkt,
|
||||
struct net_buf *net_pkt_get_frag_debug(struct net_pkt *pkt, size_t min_len,
|
||||
k_timeout_t timeout,
|
||||
const char *caller, int line)
|
||||
#else
|
||||
struct net_buf *net_pkt_get_frag(struct net_pkt *pkt,
|
||||
struct net_buf *net_pkt_get_frag(struct net_pkt *pkt, size_t min_len,
|
||||
k_timeout_t timeout)
|
||||
#endif
|
||||
{
|
||||
|
@ -427,52 +432,54 @@ struct net_buf *net_pkt_get_frag(struct net_pkt *pkt,
|
|||
if (context && context->data_pool) {
|
||||
#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
return net_pkt_get_reserve_data_debug(context->data_pool(),
|
||||
timeout, caller, line);
|
||||
min_len, timeout,
|
||||
caller, line);
|
||||
#else
|
||||
return net_pkt_get_reserve_data(context->data_pool(), timeout);
|
||||
return net_pkt_get_reserve_data(context->data_pool(), min_len,
|
||||
timeout);
|
||||
#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
|
||||
}
|
||||
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
|
||||
|
||||
if (pkt->slab == &rx_pkts) {
|
||||
#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
return net_pkt_get_reserve_rx_data_debug(timeout,
|
||||
return net_pkt_get_reserve_rx_data_debug(min_len, timeout,
|
||||
caller, line);
|
||||
#else
|
||||
return net_pkt_get_reserve_rx_data(timeout);
|
||||
return net_pkt_get_reserve_rx_data(min_len, timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
return net_pkt_get_reserve_tx_data_debug(timeout, caller, line);
|
||||
return net_pkt_get_reserve_tx_data_debug(min_len, timeout, caller, line);
|
||||
#else
|
||||
return net_pkt_get_reserve_tx_data(timeout);
|
||||
return net_pkt_get_reserve_tx_data(min_len, timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NET_LOG_LEVEL >= LOG_LEVEL_DBG
|
||||
struct net_buf *net_pkt_get_reserve_rx_data_debug(k_timeout_t timeout,
|
||||
struct net_buf *net_pkt_get_reserve_rx_data_debug(size_t min_len, k_timeout_t timeout,
|
||||
const char *caller, int line)
|
||||
{
|
||||
return net_pkt_get_reserve_data_debug(&rx_bufs, timeout, caller, line);
|
||||
return net_pkt_get_reserve_data_debug(&rx_bufs, min_len, timeout, caller, line);
|
||||
}
|
||||
|
||||
struct net_buf *net_pkt_get_reserve_tx_data_debug(k_timeout_t timeout,
|
||||
struct net_buf *net_pkt_get_reserve_tx_data_debug(size_t min_len, k_timeout_t timeout,
|
||||
const char *caller, int line)
|
||||
{
|
||||
return net_pkt_get_reserve_data_debug(&tx_bufs, timeout, caller, line);
|
||||
return net_pkt_get_reserve_data_debug(&tx_bufs, min_len, timeout, caller, line);
|
||||
}
|
||||
|
||||
#else /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
|
||||
|
||||
struct net_buf *net_pkt_get_reserve_rx_data(k_timeout_t timeout)
|
||||
struct net_buf *net_pkt_get_reserve_rx_data(size_t min_len, k_timeout_t timeout)
|
||||
{
|
||||
return net_pkt_get_reserve_data(&rx_bufs, timeout);
|
||||
return net_pkt_get_reserve_data(&rx_bufs, min_len, timeout);
|
||||
}
|
||||
|
||||
struct net_buf *net_pkt_get_reserve_tx_data(k_timeout_t timeout)
|
||||
struct net_buf *net_pkt_get_reserve_tx_data(size_t min_len, k_timeout_t timeout)
|
||||
{
|
||||
return net_pkt_get_reserve_data(&tx_bufs, timeout);
|
||||
return net_pkt_get_reserve_data(&tx_bufs, min_len, timeout);
|
||||
}
|
||||
|
||||
#endif /* NET_LOG_LEVEL >= LOG_LEVEL_DBG */
|
||||
|
|
|
@ -92,7 +92,7 @@ static int tcp_pkt_linearize(struct net_pkt *pkt, size_t pos, size_t len)
|
|||
goto out;
|
||||
}
|
||||
|
||||
buf = net_pkt_get_frag(pkt, TCP_PKT_ALLOC_TIMEOUT);
|
||||
buf = net_pkt_get_frag(pkt, len, TCP_PKT_ALLOC_TIMEOUT);
|
||||
|
||||
if (!buf || buf->size < len) {
|
||||
if (buf) {
|
||||
|
|
|
@ -50,6 +50,12 @@ extern int net_bt_shell_init(void);
|
|||
#define net_bt_shell_init(...)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
|
||||
#define IPSP_FRAG_LEN CONFIG_NET_BUF_DATA_SIZE
|
||||
#else
|
||||
#define IPSP_FRAG_LEN L2CAP_IPSP_MTU
|
||||
#endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
|
||||
|
||||
struct bt_if_conn {
|
||||
struct net_if *iface;
|
||||
struct bt_l2cap_le_chan ipsp_chan;
|
||||
|
@ -259,7 +265,7 @@ static struct net_buf *ipsp_alloc_buf(struct bt_l2cap_chan *chan)
|
|||
{
|
||||
NET_DBG("Channel %p requires buffer", chan);
|
||||
|
||||
return net_pkt_get_reserve_rx_data(BUF_TIMEOUT);
|
||||
return net_pkt_get_reserve_rx_data(IPSP_FRAG_LEN, BUF_TIMEOUT);
|
||||
}
|
||||
|
||||
static const struct bt_l2cap_chan_ops ipsp_ops = {
|
||||
|
|
|
@ -508,8 +508,11 @@ static struct net_buf *ethernet_fill_header(struct ethernet_context *ctx,
|
|||
{
|
||||
struct net_buf *hdr_frag;
|
||||
struct net_eth_hdr *hdr;
|
||||
size_t hdr_len = IS_ENABLED(CONFIG_NET_VLAN) ?
|
||||
sizeof(struct net_eth_vlan_hdr) :
|
||||
sizeof(struct net_eth_hdr);
|
||||
|
||||
hdr_frag = net_pkt_get_frag(pkt, NET_BUF_TIMEOUT);
|
||||
hdr_frag = net_pkt_get_frag(pkt, hdr_len, NET_BUF_TIMEOUT);
|
||||
if (!hdr_frag) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -460,7 +460,8 @@ int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
|
|||
} else {
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = net_pkt_get_reserve_tx_data(PPP_BUF_ALLOC_TIMEOUT);
|
||||
buf = net_pkt_get_reserve_tx_data(sizeof(uint16_t) + len,
|
||||
PPP_BUF_ALLOC_TIMEOUT);
|
||||
if (!buf) {
|
||||
LOG_ERR("failed to allocate buffer");
|
||||
goto out_of_mem;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue