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:
parent
0cbbbb9215
commit
8a63d29c6e
|
@ -75,8 +75,18 @@
|
|||
|
||||
void arp_format(FAR struct net_driver_s *dev, in_addr_t ipaddr)
|
||||
{
|
||||
FAR struct arp_hdr_s *arp = ARPBUF;
|
||||
FAR struct eth_hdr_s *eth = ETHBUF;
|
||||
FAR struct arp_hdr_s *arp;
|
||||
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 */
|
||||
|
||||
|
|
|
@ -66,9 +66,8 @@ void can_poll(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn)
|
|||
|
||||
/* Setup for the application callback */
|
||||
|
||||
dev->d_appdata = IPBUF(0);
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
|
||||
/* Perform the application callback */
|
||||
|
||||
|
|
|
@ -821,13 +821,6 @@ static int devif_iob_poll(FAR struct net_driver_s *dev,
|
|||
{
|
||||
int bstop;
|
||||
|
||||
/* Device polling, prepare iob buffer */
|
||||
|
||||
if (netdev_iob_prepare(dev, false, 0) != OK)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Perform all connections poll */
|
||||
|
||||
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
|
||||
{
|
||||
/* 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 */
|
||||
|
||||
bstop = devif_poll_connections(dev, devif_poll_callback);
|
||||
|
|
|
@ -78,12 +78,19 @@ void devif_send(FAR struct net_driver_s *dev, FAR const void *buf,
|
|||
return;
|
||||
}
|
||||
|
||||
iob_update_pktlen(dev->d_iob, offset);
|
||||
|
||||
/* Copy in iob to target device buffer */
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -66,9 +66,8 @@ void icmp_poll(FAR struct net_driver_s *dev, FAR struct icmp_conn_s *conn)
|
|||
|
||||
/* Setup for the application callback */
|
||||
|
||||
dev->d_appdata = IPBUF(IPICMP_HDRLEN);
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
|
||||
/* Perform the application callback */
|
||||
|
||||
|
|
|
@ -125,6 +125,13 @@ static uint16_t icmpv6_router_eventhandler(FAR struct net_driver_s *dev,
|
|||
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.
|
||||
*
|
||||
* Copy the packet data into the device packet buffer and send it.
|
||||
|
|
|
@ -109,6 +109,13 @@ static uint16_t icmpv6_neighbor_eventhandler(FAR struct net_driver_s *dev,
|
|||
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.
|
||||
*
|
||||
* Copy the packet data into the device packet buffer and send it.
|
||||
|
|
|
@ -67,9 +67,8 @@ void icmpv6_poll(FAR struct net_driver_s *dev,
|
|||
|
||||
/* Setup for the application callback */
|
||||
|
||||
dev->d_appdata = IPBUF(IPICMPv6_HDRLEN);
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
|
||||
/* Perform the application callback */
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
FAR struct igmp_group_s *group;
|
||||
uint16_t iphdrlen;
|
||||
|
||||
/* Setup the poll operation */
|
||||
|
||||
iphdrlen = IPv4_HDRLEN + RASIZE;
|
||||
|
||||
dev->d_appdata = IPBUF(iphdrlen + IGMP_HDRLEN);
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
|
||||
/* Check each member of the group */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* Prepare device buffer */
|
||||
|
||||
if (netdev_iob_prepare(dev, false, 0) != OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* The IGMP header immediately follows the IP header */
|
||||
|
||||
iphdrlen = IPv4_HDRLEN + RASIZE;
|
||||
|
|
|
@ -161,6 +161,11 @@ static uint16_t ipfwd_eventhandler(FAR struct net_driver_s *dev,
|
|||
|
||||
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 both IPv4 and IPv6 support are enabled, then we will need to
|
||||
* 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);
|
||||
#endif
|
||||
/* Copy the user data into d_appdata and send it. */
|
||||
|
||||
devif_forward(fwd);
|
||||
flags &= ~DEVPOLL_MASK;
|
||||
}
|
||||
|
||||
/* Free the allocated callback structure */
|
||||
|
|
|
@ -60,9 +60,8 @@ void mld_poll(FAR struct net_driver_s *dev)
|
|||
|
||||
/* Setup the poll operation */
|
||||
|
||||
dev->d_appdata = IPBUF(IPv6_HDRLEN);
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
|
||||
/* Check if a general query is pending */
|
||||
|
||||
|
|
|
@ -96,6 +96,13 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
|
|||
DEBUGASSERT(dev != NULL);
|
||||
DEBUGASSERT(msgtype == MLD_SEND_GENQUERY || group != NULL);
|
||||
|
||||
/* Prepare device buffer */
|
||||
|
||||
if (netdev_iob_prepare(dev, false, 0) != OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Select IPv6 */
|
||||
|
||||
IFF_SET_IPv6(dev->d_flags);
|
||||
|
|
|
@ -69,6 +69,7 @@ int netdev_iob_prepare(FAR struct net_driver_s *dev, bool throttled,
|
|||
|
||||
if (dev->d_iob == NULL)
|
||||
{
|
||||
nwarn("WARNING: IOB Prepare failed for dev %s!\n", dev->d_ifname);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,9 +65,8 @@ void pkt_poll(FAR struct net_driver_s *dev, FAR struct pkt_conn_s *conn)
|
|||
{
|
||||
/* Setup for the application callback */
|
||||
|
||||
dev->d_appdata = IPBUF(0);
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
|
||||
/* Perform the application callback */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* Prepare device buffer */
|
||||
|
||||
if (netdev_iob_prepare(dev, false, 0) != OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Discard any currently buffered data */
|
||||
|
||||
if (conn->timeout)
|
||||
|
|
|
@ -93,19 +93,8 @@ void udp_poll(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
|
|||
|
||||
if (conn->lport != 0)
|
||||
{
|
||||
/* Set up for the callback. We can't know in advance if the
|
||||
* application is going to send a IPv4 or an IPv6 packet, so this setup
|
||||
* 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;
|
||||
dev->d_len = 0;
|
||||
dev->d_sndlen = 0;
|
||||
|
||||
/* Perform the application callback */
|
||||
|
||||
|
|
|
@ -406,7 +406,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||
{
|
||||
uint16_t udpiplen = udpip_hdrsize(conn);
|
||||
FAR struct udp_wrbuffer_s *wrb;
|
||||
size_t sndlen;
|
||||
|
||||
/* 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
|
||||
|
@ -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);
|
||||
|
||||
/* 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.
|
||||
* 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
|
||||
* window size.
|
||||
*/
|
||||
|
||||
sndlen = wrb->wb_iob->io_pktlen - udpiplen;
|
||||
ninfo("wrb=%p sndlen=%zu\n", wrb, sndlen);
|
||||
dev->d_sndlen = wrb->wb_iob->io_pktlen - udpiplen;
|
||||
ninfo("wrb=%p sndlen=%d\n", wrb, dev->d_sndlen);
|
||||
|
||||
#ifdef NEED_IPDOMAIN_SUPPORT
|
||||
/* 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);
|
||||
#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
|
||||
* setup the next transfer.
|
||||
*/
|
||||
|
|
|
@ -192,6 +192,15 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||
|
||||
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
|
||||
/* If both IPv4 and IPv6 support are enabled, then we will need to
|
||||
* 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);
|
||||
#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;
|
||||
}
|
||||
|
||||
/* Don't allow any further call backs. */
|
||||
|
||||
pstate->st_cb->flags = 0;
|
||||
pstate->st_cb->priv = NULL;
|
||||
pstate->st_cb->event = NULL;
|
||||
pstate->st_cb->flags = 0;
|
||||
pstate->st_cb->priv = NULL;
|
||||
pstate->st_cb->event = NULL;
|
||||
|
||||
/* Wake up the waiting thread */
|
||||
|
||||
|
|
Loading…
Reference in New Issue