mm/iob: Add support for increasing length in iob_update_pktlen

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2023-05-17 16:11:21 +08:00 committed by Masayuki Ishikawa
parent 2fa68fbddd
commit d44e19d115
21 changed files with 76 additions and 40 deletions

View File

@ -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;
}
/****************************************************************************

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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:

View File

@ -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 */

View File

@ -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. */

View File

@ -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.