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.