net/devif_poll: optimize device buffer alloc in txpoll

Allocate the device buffer only if the protocol really need to send data.
not all protocols require the driver to prepare additional iob before
sending, especially UDP, each iob reserves l2/l3 header in advance
after prepare write buffer, net device could reuse this entry to send directly

Signed-off-by: chao an <anchao@xiaomi.com>
This commit is contained in:
chao an 2023-01-11 16:09:20 +08:00 committed by Xiang Xiao
parent 0cbbbb9215
commit 8a63d29c6e
19 changed files with 96 additions and 83 deletions

View File

@ -75,8 +75,18 @@
void arp_format(FAR struct net_driver_s *dev, in_addr_t ipaddr) void arp_format(FAR struct net_driver_s *dev, in_addr_t ipaddr)
{ {
FAR struct arp_hdr_s *arp = ARPBUF; FAR struct arp_hdr_s *arp;
FAR struct eth_hdr_s *eth = ETHBUF; FAR struct eth_hdr_s *eth;
/* Prepare device buffer before format arp */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
return;
}
arp = ARPBUF;
eth = ETHBUF;
/* Construct the ARP packet. Creating both the Ethernet and ARP headers */ /* Construct the ARP packet. Creating both the Ethernet and ARP headers */

View File

@ -66,9 +66,8 @@ void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn)
/* Setup for the application callback */ /* Setup for the application callback */
dev->d_appdata = IPBUF(0); dev->d_len = 0;
dev->d_len = 0; dev->d_sndlen = 0;
dev->d_sndlen = 0;
/* Perform the application callback */ /* Perform the application callback */

View File

@ -821,13 +821,6 @@ static int devif_iob_poll(FAR struct net_driver_s *dev,
{ {
int bstop; int bstop;
/* Device polling, prepare iob buffer */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
return true;
}
/* Perform all connections poll */ /* Perform all connections poll */
bstop = devif_poll_connections(dev, callback); bstop = devif_poll_connections(dev, callback);
@ -920,15 +913,6 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
do do
{ {
/* Device polling, prepare iob buffer */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
nwarn("WARNING: IOB Prepare failed for dev %s!\n", dev->d_ifname);
bstop = true;
break;
}
/* Perform all connections poll */ /* Perform all connections poll */
bstop = devif_poll_connections(dev, devif_poll_callback); bstop = devif_poll_connections(dev, devif_poll_callback);

View File

@ -78,12 +78,19 @@ void devif_send(FAR struct net_driver_s *dev, FAR const void *buf,
return; return;
} }
iob_update_pktlen(dev->d_iob, offset);
/* Copy in iob to target device buffer */ /* Copy in iob to target device buffer */
if (len <= iob_navail(false) * CONFIG_IOB_BUFSIZE) if (len <= iob_navail(false) * CONFIG_IOB_BUFSIZE)
{ {
/* Prepare device buffer before poll callback */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
return;
}
iob_update_pktlen(dev->d_iob, offset);
dev->d_sndlen = iob_trycopyin(dev->d_iob, buf, len, offset, false); dev->d_sndlen = iob_trycopyin(dev->d_iob, buf, len, offset, false);
} }
else else

View File

@ -66,9 +66,8 @@ void icmp_poll(FAR struct net_driver_s *dev, FAR struct icmp_conn_s *conn)
/* Setup for the application callback */ /* Setup for the application callback */
dev->d_appdata = IPBUF(IPICMP_HDRLEN); dev->d_len = 0;
dev->d_len = 0; dev->d_sndlen = 0;
dev->d_sndlen = 0;
/* Perform the application callback */ /* Perform the application callback */

View File

@ -125,6 +125,13 @@ static uint16_t icmpv6_router_eventhandler(FAR struct net_driver_s *dev,
return flags; return flags;
} }
/* Prepare device buffer */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
return flags;
}
/* It looks like we are good to send the data. /* It looks like we are good to send the data.
* *
* Copy the packet data into the device packet buffer and send it. * Copy the packet data into the device packet buffer and send it.

View File

@ -109,6 +109,13 @@ static uint16_t icmpv6_neighbor_eventhandler(FAR struct net_driver_s *dev,
return flags; return flags;
} }
/* Prepare device buffer */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
return flags;
}
/* It looks like we are good to send the data. /* It looks like we are good to send the data.
* *
* Copy the packet data into the device packet buffer and send it. * Copy the packet data into the device packet buffer and send it.

View File

@ -67,9 +67,8 @@ void icmpv6_poll(FAR struct net_driver_s *dev,
/* Setup for the application callback */ /* Setup for the application callback */
dev->d_appdata = IPBUF(IPICMPv6_HDRLEN); dev->d_len = 0;
dev->d_len = 0; dev->d_sndlen = 0;
dev->d_sndlen = 0;
/* Perform the application callback */ /* Perform the application callback */

View File

@ -151,15 +151,11 @@ static inline void igmp_sched_send(FAR struct net_driver_s *dev,
void igmp_poll(FAR struct net_driver_s *dev) void igmp_poll(FAR struct net_driver_s *dev)
{ {
FAR struct igmp_group_s *group; FAR struct igmp_group_s *group;
uint16_t iphdrlen;
/* Setup the poll operation */ /* Setup the poll operation */
iphdrlen = IPv4_HDRLEN + RASIZE; dev->d_len = 0;
dev->d_sndlen = 0;
dev->d_appdata = IPBUF(iphdrlen + IGMP_HDRLEN);
dev->d_len = 0;
dev->d_sndlen = 0;
/* Check each member of the group */ /* Check each member of the group */

View File

@ -109,6 +109,13 @@ void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
ninfo("msgid: %02x destipaddr: %08x\n", msgid, (int)*destipaddr); ninfo("msgid: %02x destipaddr: %08x\n", msgid, (int)*destipaddr);
/* Prepare device buffer */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
return;
}
/* The IGMP header immediately follows the IP header */ /* The IGMP header immediately follows the IP header */
iphdrlen = IPv4_HDRLEN + RASIZE; iphdrlen = IPv4_HDRLEN + RASIZE;

View File

@ -161,6 +161,11 @@ static uint16_t ipfwd_eventhandler(FAR struct net_driver_s *dev,
else else
{ {
/* Copy the user data into d_appdata and send it. */
devif_forward(fwd);
flags &= ~DEVPOLL_MASK;
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) #if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
/* If both IPv4 and IPv6 support are enabled, then we will need to /* If both IPv4 and IPv6 support are enabled, then we will need to
* select which one to use when generating the outgoing packet. * select which one to use when generating the outgoing packet.
@ -170,10 +175,6 @@ static uint16_t ipfwd_eventhandler(FAR struct net_driver_s *dev,
forward_ipselect(fwd); forward_ipselect(fwd);
#endif #endif
/* Copy the user data into d_appdata and send it. */
devif_forward(fwd);
flags &= ~DEVPOLL_MASK;
} }
/* Free the allocated callback structure */ /* Free the allocated callback structure */

View File

@ -60,9 +60,8 @@ void mld_poll(FAR struct net_driver_s *dev)
/* Setup the poll operation */ /* Setup the poll operation */
dev->d_appdata = IPBUF(IPv6_HDRLEN); dev->d_len = 0;
dev->d_len = 0; dev->d_sndlen = 0;
dev->d_sndlen = 0;
/* Check if a general query is pending */ /* Check if a general query is pending */

View File

@ -96,6 +96,13 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
DEBUGASSERT(dev != NULL); DEBUGASSERT(dev != NULL);
DEBUGASSERT(msgtype == MLD_SEND_GENQUERY || group != NULL); DEBUGASSERT(msgtype == MLD_SEND_GENQUERY || group != NULL);
/* Prepare device buffer */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
return;
}
/* Select IPv6 */ /* Select IPv6 */
IFF_SET_IPv6(dev->d_flags); IFF_SET_IPv6(dev->d_flags);

View File

@ -69,6 +69,7 @@ int netdev_iob_prepare(FAR struct net_driver_s *dev, bool throttled,
if (dev->d_iob == NULL) if (dev->d_iob == NULL)
{ {
nwarn("WARNING: IOB Prepare failed for dev %s!\n", dev->d_ifname);
return -ENOMEM; return -ENOMEM;
} }

View File

@ -65,9 +65,8 @@ void pkt_poll(FAR struct net_driver_s *dev, FAR struct pkt_conn_s *conn)
{ {
/* Setup for the application callback */ /* Setup for the application callback */
dev->d_appdata = IPBUF(0); dev->d_len = 0;
dev->d_len = 0; dev->d_sndlen = 0;
dev->d_sndlen = 0;
/* Perform the application callback */ /* Perform the application callback */

View File

@ -87,6 +87,13 @@ void tcp_poll(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
DEBUGASSERT(dev != NULL && conn != NULL && dev == conn->dev); DEBUGASSERT(dev != NULL && conn != NULL && dev == conn->dev);
/* Prepare device buffer */
if (netdev_iob_prepare(dev, false, 0) != OK)
{
return;
}
/* Discard any currently buffered data */ /* Discard any currently buffered data */
if (conn->timeout) if (conn->timeout)

View File

@ -93,19 +93,8 @@ void udp_poll(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
if (conn->lport != 0) if (conn->lport != 0)
{ {
/* Set up for the callback. We can't know in advance if the dev->d_len = 0;
* application is going to send a IPv4 or an IPv6 packet, so this setup dev->d_sndlen = 0;
* may not actually be used.
*/
#if defined(CONFIG_NET_IPv4)
udp_ipv4_select(dev);
#else /* if defined(CONFIG_NET_IPv6) */
udp_ipv6_select(dev);
#endif
dev->d_len = 0;
dev->d_sndlen = 0;
/* Perform the application callback */ /* Perform the application callback */

View File

@ -406,7 +406,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
{ {
uint16_t udpiplen = udpip_hdrsize(conn); uint16_t udpiplen = udpip_hdrsize(conn);
FAR struct udp_wrbuffer_s *wrb; FAR struct udp_wrbuffer_s *wrb;
size_t sndlen;
/* Peek at the head of the write queue (but don't remove anything /* Peek at the head of the write queue (but don't remove anything
* from the write queue yet). We know from the above test that * from the write queue yet). We know from the above test that
@ -424,14 +423,20 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
udp_connect(conn, (FAR const struct sockaddr *)&wrb->wb_dest); udp_connect(conn, (FAR const struct sockaddr *)&wrb->wb_dest);
/* Then set-up to send that amount of data with the offset
* corresponding to the size of the IP-dependent address structure.
*/
netdev_iob_replace(dev, wrb->wb_iob);
/* Get the amount of data that we can send in the next packet. /* Get the amount of data that we can send in the next packet.
* We will send either the remaining data in the buffer I/O * We will send either the remaining data in the buffer I/O
* buffer chain, or as much as will fit given the MSS and current * buffer chain, or as much as will fit given the MSS and current
* window size. * window size.
*/ */
sndlen = wrb->wb_iob->io_pktlen - udpiplen; dev->d_sndlen = wrb->wb_iob->io_pktlen - udpiplen;
ninfo("wrb=%p sndlen=%zu\n", wrb, sndlen); ninfo("wrb=%p sndlen=%d\n", wrb, dev->d_sndlen);
#ifdef NEED_IPDOMAIN_SUPPORT #ifdef NEED_IPDOMAIN_SUPPORT
/* If both IPv4 and IPv6 support are enabled, then we will need to /* If both IPv4 and IPv6 support are enabled, then we will need to
@ -443,16 +448,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
sendto_ipselect(dev, conn); sendto_ipselect(dev, conn);
#endif #endif
/* Release current device buffer and bypass the iob to l2 driver */
netdev_iob_release(dev);
/* Then set-up to send that amount of data with the offset
* corresponding to the size of the IP-dependent address structure.
*/
devif_iob_send(dev, wrb->wb_iob, sndlen, 0, udpiplen);
/* Free the write buffer at the head of the queue and attempt to /* Free the write buffer at the head of the queue and attempt to
* setup the next transfer. * setup the next transfer.
*/ */

View File

@ -192,6 +192,15 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
else else
{ {
/* Copy the user data into d_appdata and send it */
devif_send(dev, pstate->st_buffer,
pstate->st_buflen, udpip_hdrsize(pstate->st_conn));
if (dev->d_sndlen == 0)
{
return flags;
}
#ifdef NEED_IPDOMAIN_SUPPORT #ifdef NEED_IPDOMAIN_SUPPORT
/* If both IPv4 and IPv6 support are enabled, then we will need to /* If both IPv4 and IPv6 support are enabled, then we will need to
* select which one to use when generating the outgoing packet. * select which one to use when generating the outgoing packet.
@ -202,23 +211,14 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
sendto_ipselect(dev, pstate); sendto_ipselect(dev, pstate);
#endif #endif
/* Copy the user data into d_appdata and send it */
devif_send(dev, pstate->st_buffer,
pstate->st_buflen, udpip_hdrsize(pstate->st_conn));
if (dev->d_sndlen == 0)
{
return flags;
}
pstate->st_sndlen = pstate->st_buflen; pstate->st_sndlen = pstate->st_buflen;
} }
/* Don't allow any further call backs. */ /* Don't allow any further call backs. */
pstate->st_cb->flags = 0; pstate->st_cb->flags = 0;
pstate->st_cb->priv = NULL; pstate->st_cb->priv = NULL;
pstate->st_cb->event = NULL; pstate->st_cb->event = NULL;
/* Wake up the waiting thread */ /* Wake up the waiting thread */