From 8a63d29c6edb3056bb2ab89e0eb16896bcf2d57c Mon Sep 17 00:00:00 2001 From: chao an Date: Wed, 11 Jan 2023 16:09:20 +0800 Subject: [PATCH] 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 --- net/arp/arp_format.c | 14 ++++++++++++-- net/can/can_poll.c | 5 ++--- net/devif/devif_poll.c | 16 ---------------- net/devif/devif_send.c | 11 +++++++++-- net/icmp/icmp_poll.c | 5 ++--- net/icmpv6/icmpv6_autoconfig.c | 7 +++++++ net/icmpv6/icmpv6_neighbor.c | 7 +++++++ net/icmpv6/icmpv6_poll.c | 5 ++--- net/igmp/igmp_poll.c | 8 ++------ net/igmp/igmp_send.c | 7 +++++++ net/ipforward/ipfwd_forward.c | 9 +++++---- net/mld/mld_poll.c | 5 ++--- net/mld/mld_send.c | 7 +++++++ net/netdev/netdev_iob.c | 1 + net/pkt/pkt_poll.c | 5 ++--- net/tcp/tcp_devpoll.c | 7 +++++++ net/udp/udp_devpoll.c | 15 ++------------- net/udp/udp_sendto_buffered.c | 21 ++++++++------------- net/udp/udp_sendto_unbuffered.c | 24 ++++++++++++------------ 19 files changed, 96 insertions(+), 83 deletions(-) diff --git a/net/arp/arp_format.c b/net/arp/arp_format.c index 6cca53a7f99..2b5db120bb3 100644 --- a/net/arp/arp_format.c +++ b/net/arp/arp_format.c @@ -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 */ diff --git a/net/can/can_poll.c b/net/can/can_poll.c index 1c7b95019da..2def213a5d6 100644 --- a/net/can/can_poll.c +++ b/net/can/can_poll.c @@ -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 */ diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c index 4b77fbe2187..2fdf462acb8 100644 --- a/net/devif/devif_poll.c +++ b/net/devif/devif_poll.c @@ -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); diff --git a/net/devif/devif_send.c b/net/devif/devif_send.c index 5e076d0ff8e..ea2d5cad416 100644 --- a/net/devif/devif_send.c +++ b/net/devif/devif_send.c @@ -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 diff --git a/net/icmp/icmp_poll.c b/net/icmp/icmp_poll.c index 290c129cd47..09d80d570f1 100644 --- a/net/icmp/icmp_poll.c +++ b/net/icmp/icmp_poll.c @@ -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 */ diff --git a/net/icmpv6/icmpv6_autoconfig.c b/net/icmpv6/icmpv6_autoconfig.c index 0d899ad4e1f..a8021bd2246 100644 --- a/net/icmpv6/icmpv6_autoconfig.c +++ b/net/icmpv6/icmpv6_autoconfig.c @@ -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. diff --git a/net/icmpv6/icmpv6_neighbor.c b/net/icmpv6/icmpv6_neighbor.c index 9b2e4f18b4b..1612865bad9 100644 --- a/net/icmpv6/icmpv6_neighbor.c +++ b/net/icmpv6/icmpv6_neighbor.c @@ -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. diff --git a/net/icmpv6/icmpv6_poll.c b/net/icmpv6/icmpv6_poll.c index 7da0cd005e7..278c3f48b70 100644 --- a/net/icmpv6/icmpv6_poll.c +++ b/net/icmpv6/icmpv6_poll.c @@ -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 */ diff --git a/net/igmp/igmp_poll.c b/net/igmp/igmp_poll.c index 47ef3d34d64..b7f71f2fbeb 100644 --- a/net/igmp/igmp_poll.c +++ b/net/igmp/igmp_poll.c @@ -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 */ diff --git a/net/igmp/igmp_send.c b/net/igmp/igmp_send.c index c15a695f77b..d60a49a21fc 100644 --- a/net/igmp/igmp_send.c +++ b/net/igmp/igmp_send.c @@ -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; diff --git a/net/ipforward/ipfwd_forward.c b/net/ipforward/ipfwd_forward.c index 00d70340307..94a933c38a8 100644 --- a/net/ipforward/ipfwd_forward.c +++ b/net/ipforward/ipfwd_forward.c @@ -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 */ diff --git a/net/mld/mld_poll.c b/net/mld/mld_poll.c index d0cd9264195..d706ffb29a3 100644 --- a/net/mld/mld_poll.c +++ b/net/mld/mld_poll.c @@ -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 */ diff --git a/net/mld/mld_send.c b/net/mld/mld_send.c index f3fab001d86..8364808f7c6 100644 --- a/net/mld/mld_send.c +++ b/net/mld/mld_send.c @@ -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); diff --git a/net/netdev/netdev_iob.c b/net/netdev/netdev_iob.c index d6ebbd87ded..f6159c4f54a 100644 --- a/net/netdev/netdev_iob.c +++ b/net/netdev/netdev_iob.c @@ -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; } diff --git a/net/pkt/pkt_poll.c b/net/pkt/pkt_poll.c index 7d6978fe844..6901ee324b2 100644 --- a/net/pkt/pkt_poll.c +++ b/net/pkt/pkt_poll.c @@ -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 */ diff --git a/net/tcp/tcp_devpoll.c b/net/tcp/tcp_devpoll.c index 51e022aa30f..3d7206c9b43 100644 --- a/net/tcp/tcp_devpoll.c +++ b/net/tcp/tcp_devpoll.c @@ -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) diff --git a/net/udp/udp_devpoll.c b/net/udp/udp_devpoll.c index 7796f8f5e17..d317147f9ec 100644 --- a/net/udp/udp_devpoll.c +++ b/net/udp/udp_devpoll.c @@ -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 */ diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c index e5c36898fcb..7263edb1c07 100644 --- a/net/udp/udp_sendto_buffered.c +++ b/net/udp/udp_sendto_buffered.c @@ -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. */ diff --git a/net/udp/udp_sendto_unbuffered.c b/net/udp/udp_sendto_unbuffered.c index ae629bc91de..db1d6ad0309 100644 --- a/net/udp/udp_sendto_unbuffered.c +++ b/net/udp/udp_sendto_unbuffered.c @@ -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 */