You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ma...@apache.org on 2023/08/22 07:34:32 UTC

[nuttx] 02/04: mm/iob: Add support for increasing length in iob_update_pktlen

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

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

commit d44e19d115b3b5f03789cfe3be0464d836ada72d
Author: Zhe Weng <we...@xiaomi.com>
AuthorDate: Wed May 17 16:11:21 2023 +0800

    mm/iob: Add support for increasing length in iob_update_pktlen
    
    Signed-off-by: Zhe Weng <we...@xiaomi.com>
---
 drivers/net/netdev_upperhalf.c       | 11 ++++++++---
 include/nuttx/mm/iob.h               | 12 +++++++-----
 include/nuttx/net/netdev_lowerhalf.h |  7 +++++--
 mm/iob/iob_update_pktlen.c           | 38 +++++++++++++++++++++++++++++-------
 net/arp/arp_format.c                 |  2 +-
 net/devif/devif_filesend.c           |  4 ++--
 net/devif/devif_poll.c               |  2 +-
 net/devif/devif_send.c               |  2 +-
 net/devif/ipv4_input.c               |  2 +-
 net/devif/ipv6_input.c               |  2 +-
 net/icmp/icmp_reply.c                |  7 ++++---
 net/icmpv6/icmpv6_advertise.c        |  2 +-
 net/icmpv6/icmpv6_radvertise.c       |  2 +-
 net/icmpv6/icmpv6_reply.c            |  7 ++++---
 net/icmpv6/icmpv6_rsolicit.c         |  2 +-
 net/icmpv6/icmpv6_solicit.c          |  2 +-
 net/igmp/igmp_send.c                 |  2 +-
 net/mld/mld_send.c                   |  2 +-
 net/tcp/tcp_send.c                   |  4 ++--
 net/udp/udp_send.c                   |  2 +-
 net/udp/udp_sendto_buffered.c        |  2 +-
 21 files changed, 76 insertions(+), 40 deletions(-)

diff --git a/drivers/net/netdev_upperhalf.c b/drivers/net/netdev_upperhalf.c
index a9f32cd93a..e2cede4d47 100644
--- a/drivers/net/netdev_upperhalf.c
+++ b/drivers/net/netdev_upperhalf.c
@@ -1290,12 +1290,17 @@ FAR uint8_t *netpkt_getbase(FAR netpkt_t *pkt)
  *   pkt    - The net packet
  *   len    - The length of data in netpkt
  *
+ * Returned Value:
+ *   The new effective data length, or a negated errno value on error.
+ *
  ****************************************************************************/
 
-void netpkt_setdatalen(FAR struct netdev_lowerhalf_s *dev,
-                       FAR netpkt_t *pkt, unsigned int len)
+int netpkt_setdatalen(FAR struct netdev_lowerhalf_s *dev,
+                      FAR netpkt_t *pkt, unsigned int len)
 {
-  iob_update_pktlen(pkt, len - NET_LL_HDRLEN(&dev->netdev));
+  uint8_t llhdrlen = NET_LL_HDRLEN(&dev->netdev);
+  int ret = iob_update_pktlen(pkt, len - llhdrlen, false);
+  return ret >= 0 ? ret + llhdrlen : ret;
 }
 
 /****************************************************************************
diff --git a/include/nuttx/mm/iob.h b/include/nuttx/mm/iob.h
index 326597753c..704d9d7bc2 100644
--- a/include/nuttx/mm/iob.h
+++ b/include/nuttx/mm/iob.h
@@ -571,14 +571,16 @@ void iob_reserve(FAR struct iob_s *iob, unsigned int reserved);
  *
  * Description:
  *   This function will update packet length of the iob, it will be
- *   trimmed if the length of the iob chain is greater than the current
- *   length.
- *   This function will not grow the iob link, any grow operation should
- *   be implemented through iob_copyin()/iob_trycopyin().
+ *   trimmed if the current length of the iob chain is greater than the
+ *   new length, and will be grown if less than new length.
+ *
+ * Returned Value:
+ *   The new effective iob packet length, or a negated errno value on error.
  *
  ****************************************************************************/
 
-void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen);
+int iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen,
+                      bool throttled);
 
 /****************************************************************************
  * Name: iob_count
diff --git a/include/nuttx/net/netdev_lowerhalf.h b/include/nuttx/net/netdev_lowerhalf.h
index 737da56a69..d47f324739 100644
--- a/include/nuttx/net/netdev_lowerhalf.h
+++ b/include/nuttx/net/netdev_lowerhalf.h
@@ -422,10 +422,13 @@ FAR uint8_t *netpkt_getbase(FAR netpkt_t *pkt);
  *   pkt    - The net packet
  *   len    - The length of data in netpkt
  *
+ * Returned Value:
+ *   The new effective data length, or a negated errno value on error.
+ *
  ****************************************************************************/
 
-void netpkt_setdatalen(FAR struct netdev_lowerhalf_s *dev,
-                       FAR netpkt_t *pkt, unsigned int len);
+int netpkt_setdatalen(FAR struct netdev_lowerhalf_s *dev,
+                      FAR netpkt_t *pkt, unsigned int len);
 
 /****************************************************************************
  * Name: netpkt_getdatalen
diff --git a/mm/iob/iob_update_pktlen.c b/mm/iob/iob_update_pktlen.c
index 3d1e9eafa9..e6e1fd46e3 100644
--- a/mm/iob/iob_update_pktlen.c
+++ b/mm/iob/iob_update_pktlen.c
@@ -36,14 +36,16 @@
  *
  * Description:
  *   This function will update packet length of the iob, it will be
- *   trimmed if the length of the iob chain is greater than the current
- *   length.
- *   This function will not grow the iob link, any grow operation should
- *   be implemented through iob_copyin()/iob_trycopyin().
+ *   trimmed if the current length of the iob chain is greater than the
+ *   new length, and will be grown if less than new length.
+ *
+ * Returned Value:
+ *   The new effective iob packet length, or a negated errno value on error.
  *
  ****************************************************************************/
 
-void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
+int iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen,
+                      bool throttled)
 {
   FAR struct iob_s *penultimate;
   FAR struct iob_s *next;
@@ -56,7 +58,7 @@ void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
 
   if (iob == NULL)
     {
-      return;
+      return -EINVAL;
     }
 
   /* Calculate the total entries of the data in the I/O buffer chain */
@@ -66,7 +68,8 @@ void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
     {
       ninqueue++;
       offset += next->io_offset;
-      next    = next->io_flink;
+      penultimate = next;
+      next = next->io_flink;
     }
 
   /* Trim inqueue entries if needed */
@@ -104,6 +107,21 @@ void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
             }
         }
     }
+  else if (nrequire > ninqueue)
+    {
+      /* Start from the last IOB */
+
+      next = penultimate;
+
+      /* Loop to extend the link */
+
+      while (next != NULL && nrequire > ninqueue)
+        {
+          next->io_flink = iob_tryalloc(throttled);
+          next = next->io_flink;
+          ninqueue++;
+        }
+    }
 
   iob->io_pktlen = pktlen;
 
@@ -125,4 +143,10 @@ void iob_update_pktlen(FAR struct iob_s *iob, unsigned int pktlen)
       pktlen      -= len;
       next         = next->io_flink;
     }
+
+  /* Adjust final pktlen if it's not fully increased (e.g. alloc fail) */
+
+  iob->io_pktlen -= pktlen;
+
+  return iob->io_pktlen;
 }
diff --git a/net/arp/arp_format.c b/net/arp/arp_format.c
index 2b5db120bb..6623b033d8 100644
--- a/net/arp/arp_format.c
+++ b/net/arp/arp_format.c
@@ -109,7 +109,7 @@ void arp_format(FAR struct net_driver_s *dev, in_addr_t ipaddr)
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, sizeof(struct arp_hdr_s));
+  iob_update_pktlen(dev->d_iob, sizeof(struct arp_hdr_s), false);
 }
 
 #endif /* CONFIG_NET_ARP */
diff --git a/net/devif/devif_filesend.c b/net/devif/devif_filesend.c
index a3245794c0..b6b4198df0 100644
--- a/net/devif/devif_filesend.c
+++ b/net/devif/devif_filesend.c
@@ -92,7 +92,7 @@ int devif_file_send(FAR struct net_driver_s *dev, FAR struct file *file,
       goto errout;
     }
 
-  iob_update_pktlen(dev->d_iob, target_offset);
+  iob_update_pktlen(dev->d_iob, target_offset, false);
 
   ret = file_seek(file, offset, SEEK_SET);
   if (ret < 0)
@@ -142,7 +142,7 @@ int devif_file_send(FAR struct net_driver_s *dev, FAR struct file *file,
         }
     }
 
-  iob_update_pktlen(dev->d_iob, target_offset + len);
+  iob_update_pktlen(dev->d_iob, target_offset + len, false);
 
   dev->d_sndlen = len;
   return len;
diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c
index 45b989add0..8be17bce97 100644
--- a/net/devif/devif_poll.c
+++ b/net/devif/devif_poll.c
@@ -704,7 +704,7 @@ static int devif_poll_ipfrag(FAR struct net_driver_s *dev,
 
   if (!bstop && reused)
     {
-      iob_update_pktlen(dev->d_iob, 0);
+      iob_update_pktlen(dev->d_iob, 0, false);
       netdev_iob_prepare(dev, true, 0);
     }
 
diff --git a/net/devif/devif_send.c b/net/devif/devif_send.c
index 7ba5fd114b..943b737bbd 100644
--- a/net/devif/devif_send.c
+++ b/net/devif/devif_send.c
@@ -102,7 +102,7 @@ int devif_send(FAR struct net_driver_s *dev, FAR const void *buf,
 
   /* Prepare device buffer before poll callback */
 
-  iob_update_pktlen(dev->d_iob, offset);
+  iob_update_pktlen(dev->d_iob, offset, false);
 
   ret = iob_trycopyin(dev->d_iob, buf, len, offset, false);
   if (ret != len)
diff --git a/net/devif/ipv4_input.c b/net/devif/ipv4_input.c
index 7a04d96dc2..5b8f9fc7fc 100644
--- a/net/devif/ipv4_input.c
+++ b/net/devif/ipv4_input.c
@@ -207,7 +207,7 @@ static int ipv4_in(FAR struct net_driver_s *dev)
   totlen = (ipv4->len[0] << 8) + ipv4->len[1];
   if (totlen < dev->d_len)
     {
-      iob_update_pktlen(dev->d_iob, totlen);
+      iob_update_pktlen(dev->d_iob, totlen, false);
       dev->d_len = totlen;
     }
   else if (totlen > dev->d_len)
diff --git a/net/devif/ipv6_input.c b/net/devif/ipv6_input.c
index 943bbc5cb4..4565261c5d 100644
--- a/net/devif/ipv6_input.c
+++ b/net/devif/ipv6_input.c
@@ -256,7 +256,7 @@ static int ipv6_in(FAR struct net_driver_s *dev)
 
   if (paylen < dev->d_len)
     {
-      iob_update_pktlen(dev->d_iob, paylen);
+      iob_update_pktlen(dev->d_iob, paylen, false);
       dev->d_len = paylen;
     }
   else if (paylen > dev->d_len)
diff --git a/net/icmp/icmp_reply.c b/net/icmp/icmp_reply.c
index a19f556497..5a6ca57520 100644
--- a/net/icmp/icmp_reply.c
+++ b/net/icmp/icmp_reply.c
@@ -133,7 +133,7 @@ void icmp_reply(FAR struct net_driver_s *dev, int type, int code)
 
       /* Skip icmp header from iob */
 
-      iob_update_pktlen(dev->d_iob, datalen + ipicmplen);
+      iob_update_pktlen(dev->d_iob, datalen + ipicmplen, false);
     }
   else
     {
@@ -167,8 +167,9 @@ void icmp_reply(FAR struct net_driver_s *dev, int type, int code)
 
       /* Skip icmp header from iob */
 
-      iob_update_pktlen(dev->d_iob, dev->d_iob->io_pktlen +
-                                    sizeof(struct icmp_hdr_s));
+      iob_update_pktlen(dev->d_iob,
+                        dev->d_iob->io_pktlen + sizeof(struct icmp_hdr_s),
+                        false);
 
       /* Concat new icmp packet before original datagram */
 
diff --git a/net/icmpv6/icmpv6_advertise.c b/net/icmpv6/icmpv6_advertise.c
index 0bc2c4c5f9..583522ac1b 100644
--- a/net/icmpv6/icmpv6_advertise.c
+++ b/net/icmpv6/icmpv6_advertise.c
@@ -105,7 +105,7 @@ void icmpv6_advertise(FAR struct net_driver_s *dev,
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);
+  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size, false);
 
   /* Calculate the checksum over both the ICMP header and payload */
 
diff --git a/net/icmpv6/icmpv6_radvertise.c b/net/icmpv6/icmpv6_radvertise.c
index c9a882a973..5b83530f53 100644
--- a/net/icmpv6/icmpv6_radvertise.c
+++ b/net/icmpv6/icmpv6_radvertise.c
@@ -282,7 +282,7 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev)
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);
+  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size, false);
 
   /* Calculate the checksum over both the ICMP header and payload */
 
diff --git a/net/icmpv6/icmpv6_reply.c b/net/icmpv6/icmpv6_reply.c
index 4f20d3b263..9aa0745983 100644
--- a/net/icmpv6/icmpv6_reply.c
+++ b/net/icmpv6/icmpv6_reply.c
@@ -122,7 +122,7 @@ void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data)
 
       /* Skip icmp header from iob */
 
-      iob_update_pktlen(dev->d_iob, datalen + ipicmplen);
+      iob_update_pktlen(dev->d_iob, datalen + ipicmplen, false);
     }
   else
     {
@@ -156,8 +156,9 @@ void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data)
 
       /* Skip icmp header from iob */
 
-      iob_update_pktlen(dev->d_iob, dev->d_iob->io_pktlen +
-                                    sizeof(struct icmpv6_hdr_s));
+      iob_update_pktlen(dev->d_iob,
+                        dev->d_iob->io_pktlen + sizeof(struct icmpv6_hdr_s),
+                        false);
 
       /* Concat new icmp packet before original datagram */
 
diff --git a/net/icmpv6/icmpv6_rsolicit.c b/net/icmpv6/icmpv6_rsolicit.c
index efce18ef20..40f7f024b5 100644
--- a/net/icmpv6/icmpv6_rsolicit.c
+++ b/net/icmpv6/icmpv6_rsolicit.c
@@ -99,7 +99,7 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev)
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);
+  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size, false);
 
   /* Calculate the checksum over both the ICMP header and payload */
 
diff --git a/net/icmpv6/icmpv6_solicit.c b/net/icmpv6/icmpv6_solicit.c
index 07421c9cba..8519abd933 100644
--- a/net/icmpv6/icmpv6_solicit.c
+++ b/net/icmpv6/icmpv6_solicit.c
@@ -122,7 +122,7 @@ void icmpv6_solicit(FAR struct net_driver_s *dev,
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size);
+  iob_update_pktlen(dev->d_iob, IPv6_HDRLEN + l3size, false);
 
   /* Calculate the checksum over both the ICMP header and payload */
 
diff --git a/net/igmp/igmp_send.c b/net/igmp/igmp_send.c
index 9f770909c2..378f3fbc44 100644
--- a/net/igmp/igmp_send.c
+++ b/net/igmp/igmp_send.c
@@ -129,7 +129,7 @@ void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, dev->d_len);
+  iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
   /* The total size of the data is the size of the IGMP header */
 
diff --git a/net/mld/mld_send.c b/net/mld/mld_send.c
index 09d676f075..07e8b76ed7 100644
--- a/net/mld/mld_send.c
+++ b/net/mld/mld_send.c
@@ -168,7 +168,7 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group,
 
   /* Update device buffer length */
 
-  iob_update_pktlen(dev->d_iob, dev->d_len);
+  iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
   /* Select the IPv6 destination address.
    * This varies with the type of message being sent:
diff --git a/net/tcp/tcp_send.c b/net/tcp/tcp_send.c
index 6c328c4c0d..68cd1830fc 100644
--- a/net/tcp/tcp_send.c
+++ b/net/tcp/tcp_send.c
@@ -170,7 +170,7 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev,
 
   /* Update device buffer length before setup the IP header */
 
-  iob_update_pktlen(dev->d_iob, dev->d_len);
+  iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
   /* Calculate chk & build L3 header */
 
@@ -464,7 +464,7 @@ void tcp_reset(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
 
   /* Update device buffer length before setup the IP header */
 
-  iob_update_pktlen(dev->d_iob, dev->d_len);
+  iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
   /* Calculate chk & build L3 header */
 
diff --git a/net/udp/udp_send.c b/net/udp/udp_send.c
index f6377a59f5..39e0ffe665 100644
--- a/net/udp/udp_send.c
+++ b/net/udp/udp_send.c
@@ -174,7 +174,7 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn)
 
       /* Update the device buffer length */
 
-      iob_update_pktlen(dev->d_iob, dev->d_len);
+      iob_update_pktlen(dev->d_iob, dev->d_len, false);
 
 #ifdef CONFIG_NET_UDP_CHECKSUMS
       /* Calculate UDP checksum. */
diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c
index 5e944b05cb..1eff0e8a24 100644
--- a/net/udp/udp_sendto_buffered.c
+++ b/net/udp/udp_sendto_buffered.c
@@ -790,7 +790,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
       udpiplen = udpip_hdrsize(conn);
 
       iob_reserve(wrb->wb_iob, CONFIG_NET_LL_GUARDSIZE);
-      iob_update_pktlen(wrb->wb_iob, udpiplen);
+      iob_update_pktlen(wrb->wb_iob, udpiplen, false);
 
       /* Copy the user data into the write buffer.  We cannot wait for
        * buffer space if the socket was opened non-blocking.