This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 948965989 netutils/ping: Optimize stack usage of `icmp_ping`
948965989 is described below

commit 9489659890d05d6e2e526033d4cc2064ce247706
Author: Zhe Weng <weng...@xiaomi.com>
AuthorDate: Tue Nov 14 16:26:48 2023 +0800

    netutils/ping: Optimize stack usage of `icmp_ping`
    
    Can reduce 88~144 Bytes on ARMv7-A depending on optimization level.
    
    Signed-off-by: Zhe Weng <weng...@xiaomi.com>
---
 netutils/ping/icmp_ping.c | 156 +++++++++++++++++++++++++---------------------
 1 file changed, 85 insertions(+), 71 deletions(-)

diff --git a/netutils/ping/icmp_ping.c b/netutils/ping/icmp_ping.c
index b02c6e148..f13ca3aaf 100644
--- a/netutils/ping/icmp_ping.c
+++ b/netutils/ping/icmp_ping.c
@@ -52,6 +52,28 @@
 
 #define ICMP_IOBUFFER_SIZE(x) (sizeof(struct icmp_hdr_s) + (x))
 
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Data needed for ping, reduce stack usage. */
+
+struct ping_priv_s
+{
+  struct sockaddr_in destaddr;
+  struct sockaddr_in fromaddr;
+  struct icmp_hdr_s outhdr;
+  struct pollfd recvfd;
+  socklen_t addrlen;
+  clock_t kickoff;
+  clock_t start;
+  ssize_t nsent;
+  ssize_t nrecvd;
+  long elapsed;
+  bool retry;
+  int sockfd;
+};
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -107,14 +129,14 @@ static int ping_gethostip(FAR const char *hostname, FAR 
struct in_addr *dest)
 #ifdef CONFIG_LIBC_NETDB
   /* Netdb DNS client support is enabled */
 
-  FAR struct addrinfo hint;
   FAR struct addrinfo *info;
   FAR struct sockaddr_in *addr;
+  static const struct addrinfo s_hint =
+  {
+    .ai_family = AF_INET
+  };
 
-  memset(&hint, 0, sizeof(hint));
-  hint.ai_family = AF_INET;
-
-  if (getaddrinfo(hostname, NULL, &hint, &info) != OK)
+  if (getaddrinfo(hostname, NULL, &s_hint, &info) != OK)
     {
       return ERROR;
     }
@@ -166,21 +188,10 @@ static void icmp_callback(FAR struct ping_result_s 
*result,
 void icmp_ping(FAR const struct ping_info_s *info)
 {
   struct ping_result_s result;
-  struct sockaddr_in destaddr;
-  struct sockaddr_in fromaddr;
-  struct icmp_hdr_s outhdr;
+  FAR struct ping_priv_s *priv;
   FAR struct icmp_hdr_s *inhdr;
-  struct pollfd recvfd;
   FAR uint8_t *iobuffer;
   FAR uint8_t *ptr;
-  long elapsed;
-  clock_t kickoff;
-  clock_t start;
-  socklen_t addrlen;
-  ssize_t nsent;
-  ssize_t nrecvd;
-  bool retry;
-  int sockfd;
   int ret;
   int ch;
   int i;
@@ -200,34 +211,36 @@ void icmp_ping(FAR const struct ping_info_s *info)
       return;
     }
 
-  /* Allocate memory to hold ping buffer */
+  /* Allocate memory to hold private data and ping buffer */
 
-  iobuffer = (FAR uint8_t *)malloc(result.outsize);
-  if (iobuffer == NULL)
+  priv = malloc(sizeof(*priv) + result.outsize);
+  if (priv == NULL)
     {
       icmp_callback(&result, ICMP_E_MEMORY, 0);
       return;
     }
 
-  sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
-  if (sockfd < 0)
+  iobuffer = (FAR uint8_t *)(priv + 1);
+
+  priv->sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
+  if (priv->sockfd < 0)
     {
       icmp_callback(&result, ICMP_E_SOCKET, errno);
-      free(iobuffer);
+      free(priv);
       return;
     }
 
-  kickoff = clock();
+  priv->kickoff = clock();
 
-  memset(&destaddr, 0, sizeof(struct sockaddr_in));
-  destaddr.sin_family      = AF_INET;
-  destaddr.sin_port        = 0;
-  destaddr.sin_addr.s_addr = result.dest.s_addr;
+  memset(&priv->destaddr, 0, sizeof(struct sockaddr_in));
+  priv->destaddr.sin_family      = AF_INET;
+  priv->destaddr.sin_port        = 0;
+  priv->destaddr.sin_addr.s_addr = result.dest.s_addr;
 
-  memset(&outhdr, 0, sizeof(struct icmp_hdr_s));
-  outhdr.type              = ICMP_ECHO_REQUEST;
-  outhdr.id                = htons(result.id);
-  outhdr.seqno             = htons(result.seqno);
+  memset(&priv->outhdr, 0, sizeof(struct icmp_hdr_s));
+  priv->outhdr.type              = ICMP_ECHO_REQUEST;
+  priv->outhdr.id                = htons(result.id);
+  priv->outhdr.seqno             = htons(result.seqno);
 
   icmp_callback(&result, ICMP_I_BEGIN, 0);
 
@@ -240,7 +253,7 @@ void icmp_ping(FAR const struct ping_info_s *info)
 
       /* Copy the ICMP header into the I/O buffer */
 
-      memcpy(iobuffer, &outhdr, sizeof(struct icmp_hdr_s));
+      memcpy(iobuffer, &priv->outhdr, sizeof(struct icmp_hdr_s));
 
       /* Add some easily verifiable payload data */
 
@@ -256,33 +269,33 @@ void icmp_ping(FAR const struct ping_info_s *info)
             }
         }
 
-      start = clock();
-      nsent = sendto(sockfd, iobuffer, result.outsize, 0,
-                     (FAR struct sockaddr *)&destaddr,
-                     sizeof(struct sockaddr_in));
-      if (nsent < 0)
+      priv->start = clock();
+      priv->nsent = sendto(priv->sockfd, iobuffer, result.outsize, 0,
+                           (FAR struct sockaddr *)&priv->destaddr,
+                           sizeof(struct sockaddr_in));
+      if (priv->nsent < 0)
         {
           icmp_callback(&result, ICMP_E_SENDTO, errno);
           goto done;
         }
-      else if (nsent != result.outsize)
+      else if (priv->nsent != result.outsize)
         {
-          icmp_callback(&result, ICMP_E_SENDSMALL, nsent);
+          icmp_callback(&result, ICMP_E_SENDSMALL, priv->nsent);
           goto done;
         }
 
       result.nrequests++;
 
-      elapsed = 0;
+      priv->elapsed = 0;
       do
         {
-          retry           = false;
-
-          recvfd.fd       = sockfd;
-          recvfd.events   = POLLIN;
-          recvfd.revents  = 0;
+          priv->retry          = false;
+          priv->recvfd.fd      = priv->sockfd;
+          priv->recvfd.events  = POLLIN;
+          priv->recvfd.revents = 0;
 
-          ret = poll(&recvfd, 1, info->timeout - elapsed / USEC_PER_MSEC);
+          ret = poll(&priv->recvfd, 1,
+                     info->timeout - priv->elapsed / USEC_PER_MSEC);
           if (ret < 0)
             {
               icmp_callback(&result, ICMP_E_POLL, errno);
@@ -296,22 +309,24 @@ void icmp_ping(FAR const struct ping_info_s *info)
 
           /* Get the ICMP response (ignoring the sender) */
 
-          addrlen = sizeof(struct sockaddr_in);
-          nrecvd  = recvfrom(sockfd, iobuffer, result.outsize, 0,
-                             (FAR struct sockaddr *)&fromaddr, &addrlen);
-          if (nrecvd < 0)
+          priv->addrlen = sizeof(struct sockaddr_in);
+          priv->nrecvd  = recvfrom(priv->sockfd, iobuffer,
+                                   result.outsize, 0,
+                                   (FAR struct sockaddr *)&priv->fromaddr,
+                                   &priv->addrlen);
+          if (priv->nrecvd < 0)
             {
               icmp_callback(&result, ICMP_E_RECVFROM, errno);
               goto done;
             }
-          else if (nrecvd < sizeof(struct icmp_hdr_s))
+          else if (priv->nrecvd < sizeof(struct icmp_hdr_s))
             {
-              icmp_callback(&result, ICMP_E_RECVSMALL, nrecvd);
+              icmp_callback(&result, ICMP_E_RECVSMALL, priv->nrecvd);
               goto done;
             }
 
-          elapsed = TICK2USEC(clock() - start);
-          inhdr   = (FAR struct icmp_hdr_s *)iobuffer;
+          priv->elapsed = TICK2USEC(clock() - priv->start);
+          inhdr         = (FAR struct icmp_hdr_s *)iobuffer;
 
           if (inhdr->type == ICMP_ECHO_REPLY)
             {
@@ -319,7 +334,7 @@ void icmp_ping(FAR const struct ping_info_s *info)
               if (ntohs(inhdr->id) != result.id)
                 {
                   icmp_callback(&result, ICMP_W_IDDIFF, ntohs(inhdr->id));
-                  retry = true;
+                  priv->retry = true;
                 }
               else
 #endif
@@ -327,26 +342,25 @@ void icmp_ping(FAR const struct ping_info_s *info)
                 {
                   icmp_callback(&result, ICMP_W_SEQNOBIG,
                                 ntohs(inhdr->seqno));
-                  retry = true;
+                  priv->retry = true;
                 }
               else if (ntohs(inhdr->seqno) < result.seqno)
                 {
                   icmp_callback(&result, ICMP_W_SEQNOSMALL,
                                 ntohs(inhdr->seqno));
-                  retry = true;
+                  priv->retry = true;
                 }
               else
                 {
                   bool verified = true;
-                  long pktdelay = elapsed;
 
-                  icmp_callback(&result, ICMP_I_ROUNDTRIP, pktdelay);
+                  icmp_callback(&result, ICMP_I_ROUNDTRIP, priv->elapsed);
 
                   /* Verify the payload data */
 
-                  if (nrecvd != result.outsize)
+                  if (priv->nrecvd != result.outsize)
                     {
-                      icmp_callback(&result, ICMP_W_RECVBIG, nrecvd);
+                      icmp_callback(&result, ICMP_W_RECVBIG, priv->nrecvd);
                       verified = false;
                     }
                   else
@@ -383,20 +397,20 @@ void icmp_ping(FAR const struct ping_info_s *info)
               icmp_callback(&result, ICMP_W_TYPE, inhdr->type);
             }
         }
-      while (retry && info->delay > elapsed / USEC_PER_MSEC &&
-             info->timeout > elapsed / USEC_PER_MSEC);
+      while (priv->retry && info->delay > priv->elapsed / USEC_PER_MSEC &&
+             info->timeout > priv->elapsed / USEC_PER_MSEC);
 
       /* Wait if necessary to preserved the requested ping rate */
 
-      elapsed = TICK2MSEC(clock() - start);
-      if (elapsed < info->delay)
+      priv->elapsed = TICK2MSEC(clock() - priv->start);
+      if (priv->elapsed < info->delay)
         {
           struct timespec rqt;
           unsigned int remaining;
           unsigned int sec;
           unsigned int frac;  /* In deciseconds */
 
-          remaining   = info->delay - elapsed;
+          remaining   = info->delay - priv->elapsed;
           sec         = remaining / MSEC_PER_SEC;
           frac        = remaining - MSEC_PER_SEC * sec;
 
@@ -406,11 +420,11 @@ void icmp_ping(FAR const struct ping_info_s *info)
           nanosleep(&rqt, NULL);
         }
 
-      outhdr.seqno = htons(++result.seqno);
+      priv->outhdr.seqno = htons(++result.seqno);
     }
 
 done:
-  icmp_callback(&result, ICMP_I_FINISH, TICK2USEC(clock() - kickoff));
-  close(sockfd);
-  free(iobuffer);
+  icmp_callback(&result, ICMP_I_FINISH, TICK2USEC(clock() - priv->kickoff));
+  close(priv->sockfd);
+  free(priv);
 }

Reply via email to