mirror of
https://github.com/apache/nuttx.git
synced 2026-05-27 19:36:35 +08:00
net/udp: Change conn->readahead to I/O buffer chain
When using IOB queue to store readahead data, we use one IOB for each UDP packet. Then if the packets are very small, like 10Bytes per packet, we'll use ~1600 IOBs just for 16KB recv buffer size, which is wasteful and dangerous. So change conn->readahead to a single IOB chain like TCP. Benefits: - Using memory and IOBs more efficiently (small packets are common in UDP) Side effects: - UDP recv buffer size may count the overhead - A little bit drop in performance (<1%, more seek & copy) Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
+59
-30
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "devif/devif.h"
|
||||
#include "udp/udp.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
@@ -71,11 +72,11 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev,
|
||||
#endif
|
||||
|
||||
uint8_t src_addr_size;
|
||||
FAR void *src_addr;
|
||||
uint8_t offset = 0;
|
||||
FAR void *src_addr;
|
||||
int offset;
|
||||
|
||||
#if CONFIG_NET_RECV_BUFSIZE > 0
|
||||
if (iob_get_queue_size(&conn->readahead) > conn->rcvbufs)
|
||||
if (conn->readahead && conn->readahead->io_pktlen > conn->rcvbufs)
|
||||
{
|
||||
netdev_iob_release(dev);
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
@@ -151,44 +152,72 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev,
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
/* Override the address info begin of io_data */
|
||||
/* Copy the meta info into the I/O buffer chain, just before data.
|
||||
* Layout: |datalen|ifindex|src_addr_size|src_addr|data|
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NETDEV_IFINDEX
|
||||
iob->io_data[offset++] = dev->d_ifindex;
|
||||
#endif
|
||||
iob->io_data[offset++] = src_addr_size;
|
||||
memcpy(&iob->io_data[offset], src_addr, src_addr_size);
|
||||
offset = (dev->d_appdata - iob->io_data) - iob->io_offset;
|
||||
|
||||
/* Trim l3/l4 offset */
|
||||
|
||||
iob = iob_trimhead(iob, (dev->d_appdata - iob->io_data) -
|
||||
iob->io_offset);
|
||||
|
||||
/* Add the new I/O buffer chain to the tail of the read-ahead queue */
|
||||
|
||||
ret = iob_tryadd_queue(iob, &conn->readahead);
|
||||
offset -= src_addr_size;
|
||||
ret = iob_trycopyin(iob, src_addr, src_addr_size, offset, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
|
||||
|
||||
iob_free_chain(iob);
|
||||
buflen = 0;
|
||||
goto errout;
|
||||
}
|
||||
#ifdef CONFIG_NET_UDP_NOTIFIER
|
||||
else
|
||||
|
||||
offset -= sizeof(src_addr_size);
|
||||
ret = iob_trycopyin(iob, &src_addr_size, sizeof(src_addr_size),
|
||||
offset, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
ninfo("Buffered %d bytes\n", buflen);
|
||||
|
||||
/* Provided notification(s) that additional UDP read-ahead data is
|
||||
* available.
|
||||
*/
|
||||
|
||||
udp_readahead_signal(conn);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NETDEV_IFINDEX
|
||||
offset -= sizeof(dev->d_ifindex);
|
||||
ret = iob_trycopyin(iob, &dev->d_ifindex, sizeof(dev->d_ifindex),
|
||||
offset, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
offset -= sizeof(buflen);
|
||||
ret = iob_trycopyin(iob, (FAR const uint8_t *)&buflen, sizeof(buflen),
|
||||
offset, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Trim l3/l4 offset, src_addr + 4Bytes should be less than header size. */
|
||||
|
||||
DEBUGASSERT(offset >= 0);
|
||||
iob = iob_trimhead(iob, offset);
|
||||
|
||||
/* Concat the iob to readahead */
|
||||
|
||||
net_iob_concat(&conn->readahead, &iob);
|
||||
|
||||
#ifdef CONFIG_NET_UDP_NOTIFIER
|
||||
ninfo("Buffered %d bytes\n", buflen);
|
||||
|
||||
/* Provided notification(s) that additional UDP read-ahead data is
|
||||
* available.
|
||||
*/
|
||||
|
||||
udp_readahead_signal(conn);
|
||||
#endif
|
||||
|
||||
netdev_iob_clear(dev);
|
||||
return buflen;
|
||||
|
||||
errout:
|
||||
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
|
||||
|
||||
netdev_iob_release(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user