summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-06-04 09:03:11 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-06-04 09:03:11 -0600
commitf1eceaa766fe62c27bbbd455359238077eb970de (patch)
tree6b2a2ba892875297705ef6504dd89c258b2af4ee
parentc6f0f268d5062fa0d40f64dbcdfa8a0103629d12 (diff)
downloadpx4-nuttx-f1eceaa766fe62c27bbbd455359238077eb970de.tar.gz
px4-nuttx-f1eceaa766fe62c27bbbd455359238077eb970de.tar.bz2
px4-nuttx-f1eceaa766fe62c27bbbd455359238077eb970de.zip
NET: Improvied I/O buffer logic
-rw-r--r--nuttx/include/nuttx/net/iob.h31
-rw-r--r--nuttx/net/iob/iob_alloc.c3
-rw-r--r--nuttx/net/iob/iob_concat.c78
-rw-r--r--nuttx/net/iob/iob_copyin.c26
-rw-r--r--nuttx/net/iob/iob_copyout.c2
-rw-r--r--nuttx/net/iob/iob_trimhead.c63
-rw-r--r--nuttx/net/iob/iob_trimtail.c29
7 files changed, 124 insertions, 108 deletions
diff --git a/nuttx/include/nuttx/net/iob.h b/nuttx/include/nuttx/net/iob.h
index 714b4fd80..29457aa3e 100644
--- a/nuttx/include/nuttx/net/iob.h
+++ b/nuttx/include/nuttx/net/iob.h
@@ -41,6 +41,10 @@
****************************************************************************/
#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <queue.h>
+
#include <nuttx/net/iob.h>
/****************************************************************************
@@ -57,7 +61,8 @@
****************************************************************************/
/* Represents one I/O buffer. A packet is contained by one or more I/O
- * buffers in a chain.
+ * buffers in a chain. The io_flags, io_pktlen, io_vtag and io_priv
+ * fields are only valid for the I/O buffer at the head of the chain.
*/
struct iob_s
@@ -65,6 +70,7 @@ struct iob_s
sq_entry_t io_link; /* Link to the next I/O buffer in the chain */
uint8_t io_flags; /* Flags associated with the I/O buffer */
uint16_t io_len; /* Length of the data in the entry */
+ uint16_t io_offset; /* Data begins at this offset */
uint16_t io_pktlen; /* Total length of the packet */
uint16_t io_vtag; /* VLAN tag */
void *io_priv; /* User private data attached to the I/O buffer */
@@ -146,20 +152,35 @@ void iob_concat(FAR struct iob_s *iob1, FAR struct iob_s *iob2);
* Name: iob_trimhead
*
* Description:
- * Remove bytes from the beginning of an I/O chain
+ * Remove bytes from the beginning of an I/O chain. Emptied I/O buffers
+ * are freed and, hence, the beginning of the chain may change.
*
****************************************************************************/
-void iob_trimhead(FAR struct iob_s *iob, unsigned int trimlen);
+FAR struct iob_s *iob_trimhead(FAR struct iob_s *iob, unsigned int trimlen);
/****************************************************************************
* Name: iob_trimtail
*
* Description:
- * Remove bytes from the end of an I/O chain
+ * Remove bytes from the end of an I/O chain. Emptied I/O buffers are
+ * freed NULL will be returned in the special case where the entry I/O
+ * buffer chain is freed.
+ *
+ ****************************************************************************/
+
+FAR struct iob_s *iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen);
+
+/****************************************************************************
+ * Name: iob_pack
+ *
+ * Description:
+ * Pack all data in the I/O buffer chain so that the data offset is zero
+ * and all but the final buffer in the chain are filled. Any emptied
+ * buffers at the end of the chain are freed.
*
****************************************************************************/
-void iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen);
+FAR struct iob_s *iob_pack(FAR struct iob_s *iob);
#endif /* _INCLUDE_NUTTX_NET_IOB_H */
diff --git a/nuttx/net/iob/iob_alloc.c b/nuttx/net/iob/iob_alloc.c
index 390883c83..91106d4d5 100644
--- a/nuttx/net/iob/iob_alloc.c
+++ b/nuttx/net/iob/iob_alloc.c
@@ -80,9 +80,10 @@ FAR struct iob_s *iob_alloc(void)
iob = (FAR struct iob_s *)sq_remfirst(&g_iob_freelist);
if (iob)
{
- iob->io_link.flink = NULL; /* Not in a list */
+ iob->io_link.flink = NULL; /* Not in a chain */
iob->io_flags = 0; /* Flags associated with the I/O buffer */
iob->io_len = 0; /* Length of the data in the entry */
+ iob->io_offset = 0; /* Offset to the beginning of data */
iob->io_pktlen = 0; /* Total length of the packet */
iob->io_vtag = 0; /* VLAN tag */
iob->io_priv = NULL; /* User private data attached to the I/O buffer */
diff --git a/nuttx/net/iob/iob_concat.c b/nuttx/net/iob/iob_concat.c
index d7b03e1fc..a18d0e35e 100644
--- a/nuttx/net/iob/iob_concat.c
+++ b/nuttx/net/iob/iob_concat.c
@@ -76,10 +76,6 @@
void iob_concat(FAR struct iob_s *iob1, FAR struct iob_s *iob2)
{
- unsigned int offset2;
- unsigned int ncopy;
- unsigned int navail;
-
/* Find the last buffer in the iob1 buffer chain */
while (iob1->io_link.flink)
@@ -87,72 +83,16 @@ void iob_concat(FAR struct iob_s *iob1, FAR struct iob_s *iob2)
iob1 = (FAR struct iob_s *)iob1->io_link.flink;
}
- /* Then add data to the end of iob1 */
-
- offset2 = 0;
- while (iob2)
- {
- /* Is the iob1 tail buffer full? */
-
- if (iob1->io_len >= CONFIG_IOB_BUFSIZE)
- {
- /* Yes.. Just connect the chains */
-
- iob1->io_link.flink = iob2->io_link.flink;
-
- /* Has the data offset in iob2? */
-
- if (offset2 > 0)
- {
- /* Yes, move the data down and adjust the size */
-
- iob2->io_len -= offset2;
- memcpy(iob2->io_data, &iob2->io_data[offset2], iob2->io_len);
-
- /* Set up to continue packing, but now into iob2 */
-
- iob1 = iob2;
- iob2 = (FAR struct iob_s *)iob2->io_link.flink;
+ /* Then connect iob2 buffer chain to the end of the iob1 chain */
- iob1->io_link.flink = NULL;
- offset2 = 0;
- }
- else
- {
- /* Otherwise, we are done */
+ iob1->io_link.flink = iob2->io_link.flink;
- return;
- }
- }
+ /* Combine the total packet size. flags, VLAN, tags, and private
+ * data from iob2 are lost.
+ */
- /* How many bytes can we copy from the source (iob2) */
-
- ncopy = iob2->io_len - offset2;
-
- /* Limit the size of the copy to the amount of free space in iob1 */
-
- navail = CONFIG_IOB_BUFSIZE - iob1->io_len;
- if (ncopy > navail)
- {
- ncopy = navail;
- }
-
- /* Copy the data from iob2 into iob1 */
-
- memcpy(iob1->io_data + iob1->io_len, iob2->io_data, ncopy);
- iob1->io_len += ncopy;
- offset2 += ncopy;
-
- /* Have we consumed all of the data in the iob2 entry? */
-
- if (offset2 >= iob2->io_len)
- {
- /* Yes.. free the iob2 entry and start processing the next I/O
- * buffer in the iob2 chain.
- */
-
- iob2 = iob_free(iob2);
- offset2 = 0;
- }
- }
+ iob1->io_pktlen += iob2->io_pktlen;
+ iob2->io_flags = 0;
+ iob2->io_vtag = 0;
+ iob2->io_priv = NULL;
}
diff --git a/nuttx/net/iob/iob_copyin.c b/nuttx/net/iob/iob_copyin.c
index d48518679..34c76bc69 100644
--- a/nuttx/net/iob/iob_copyin.c
+++ b/nuttx/net/iob/iob_copyin.c
@@ -85,11 +85,12 @@
int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
unsigned int len, unsigned int offset)
{
+ FAR struct iob_s *head = iob;
FAR uint8_t *dest;
unsigned int ncopy;
unsigned int avail;
- /* Skip to the I/O buffer containing the offset */
+ /* Skip to the I/O buffer containing the data offset */
while (offset >= iob->io_len)
{
@@ -101,16 +102,18 @@ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
while (len > 0)
{
- /* Get the source I/O buffer offset address and the amount of data
- * available from that address.
+ /* Get the destination I/O buffer address and the amount of data
+ * available from that address. We don't want to extend the length
+ * an I/O buffer here.
*/
- dest = &iob->io_data[offset];
- avail = CONFIG_IOB_BUFSIZE - offset;
+ dest = &iob->io_data[iob->io_offset + offset];
+ avail = iob->io_len - offset;
- /* Copy from the user buffer to the I/O buffer */
+ /* Copy from the user buffer to the I/O buffer
+ */
- ncopy = MIN(avail, len);
+ ncopy = MIN(len, avail);
memcpy(dest, src, ncopy);
/* Adjust the total length of the copy and the destination address in
@@ -127,6 +130,7 @@ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
if (iob->io_link.flink == NULL)
{
struct iob_s *newiob;
+ unsigned int newlen;
/* Yes.. allocate a new buffer */
@@ -140,7 +144,13 @@ int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
/* Add the new I/O buffer to the end of the buffer chain. */
iob->io_link.flink = &newiob->io_link;
- iob = newiob;
+ iob = newiob;
+
+ /* The additional bytes extend the length of the packet */
+
+ newlen = MIN(len, CONFIG_IOB_BUFSIZE);
+ iob->io_len = newlen;
+ head->io_pktlen += newlen;
}
else
{
diff --git a/nuttx/net/iob/iob_copyout.c b/nuttx/net/iob/iob_copyout.c
index 81512c38b..d10356150 100644
--- a/nuttx/net/iob/iob_copyout.c
+++ b/nuttx/net/iob/iob_copyout.c
@@ -106,7 +106,7 @@ void iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob,
* available from that address.
*/
- src = &iob->io_data[offset];
+ src = &iob->io_data[iob->io_offset + offset];
avail = iob->io_len - offset;
/* Copy the from the I/O buffer in to the user buffer */
diff --git a/nuttx/net/iob/iob_trimhead.c b/nuttx/net/iob/iob_trimhead.c
index ef6e1c2f6..a4e47ac2e 100644
--- a/nuttx/net/iob/iob_trimhead.c
+++ b/nuttx/net/iob/iob_trimhead.c
@@ -39,9 +39,6 @@
#include <nuttx/config.h>
-#include <string.h>
-#include <queue.h>
-
#include <nuttx/net/iob.h>
#include "iob.h"
@@ -70,33 +67,55 @@
* Name: iob_trimhead
*
* Description:
- * Remove bytes from the beginning of an I/O chain
+ * Remove bytes from the beginning of an I/O chain. Emptied I/O buffers
+ * are freed and, hence, the beginning of the chain may change.
*
****************************************************************************/
-void iob_trimhead(FAR struct iob_s *iob, unsigned int trimlen)
+FAR struct iob_s *iob_trimhead(FAR struct iob_s *iob, unsigned int trimlen)
{
FAR struct iob_s *entry;
+ uint8_t flags;
+ uint16_t pktlen;
+ uint16_t vtag;
+ void *priv;
unsigned int len;
if (iob && trimlen > 0)
{
- entry = iob;
- len = trimlen;
+ /* Save information from the head of the chain (in case the
+ * head is removed).
+ */
+
+ flags = iob->io_flags;
+ pktlen = iob->io_pktlen;
+ vtag = iob->io_vtag;
+ priv = iob->io_priv;
/* Trim from the head of the I/IO buffer chain */
- while (entry != NULL && len > 0)
+ entry = iob;
+ len = trimlen;
+
+ while (entry != NULL)
{
/* Do we trim this entire I/O buffer away? */
if (entry->io_len <= len)
{
- /* Yes.. just set is length to zero and skip to the next */
+ /* Decrement the trim length by the full data size */
+
+ pktlen -= entry->io_len;
+ len -= entry->io_len;
+
+ /* Free this one and set the next I/O buffer as the head */
- len -= entry->io_len;
- entry->io_len = 0;
- entry = (FAR struct iob_s *)entry->io_link.flink;
+ iob = (FAR struct iob_s *)entry->io_link.flink;
+ iob_free(entry);
+
+ /* Continue with the new buffer head */
+
+ entry = iob;
}
else
{
@@ -104,10 +123,26 @@ void iob_trimhead(FAR struct iob_s *iob, unsigned int trimlen)
* stop the trim.
*/
- entry->io_len -= len;
- memcpy(entry->io_data, &entry->io_data[len], entry->io_len);
+ pktlen -= len;
+ entry->io_len -= len;
+ entry->io_offset += len;
len = 0;
}
}
+
+ /* Restore the state to the head of the chain (which may not be
+ * the same I/O buffer chain head that we started with).
+ *
+ * Adjust the pktlen by the number of bytes removed from the head
+ * of the I/O buffer chain. A special case is where we delete the
+ * entire chain: len > 0 and iob == NULL.
+ */
+
+ iob->io_flags = flags;
+ iob->io_pktlen = pktlen;
+ iob->io_vtag = vtag;
+ iob->io_priv = priv;
}
+
+ return iob;
}
diff --git a/nuttx/net/iob/iob_trimtail.c b/nuttx/net/iob/iob_trimtail.c
index 030042be9..6c8901847 100644
--- a/nuttx/net/iob/iob_trimtail.c
+++ b/nuttx/net/iob/iob_trimtail.c
@@ -74,8 +74,9 @@
*
****************************************************************************/
-void iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen)
+FAR struct iob_s *iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen)
{
+ FAR struct iob_s *head = iob;
FAR struct iob_s *entry;
FAR struct iob_s *penultimate;
FAR struct iob_s *last;
@@ -118,21 +119,27 @@ void iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen)
if (last->io_len <= len)
{
- /* Yes.. just set is length to zero and skip to the next */
+ /* Yes.. Consume the entire buffer */
- len -= last->io_len;
- last->io_len = 0;
+ head->io_pktlen -= last->io_len;
+ len -= last->io_len;
+ last->io_len = 0;
+
+ /* Free the last, empty buffer in the list */
+
+ iob_free(last);
/* There should be a buffer before this one */
if (!penultimate)
{
- return;
+ /* No.. we just freed the head of the chain */
+
+ return NULL;
}
- /* Free the last, empty buffer in the list */
+ /* Unlink the penultimate from the freed buffer */
- iob_free(last);
penultimate->io_link.flink = NULL;
}
@@ -142,10 +149,12 @@ void iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen)
* stop the trim.
*/
- last->io_len -= len;
- memcpy(last->io_data, &last->io_data[len], last->io_len);
- len = 0;
+ head->io_pktlen -= last->io_len;
+ last->io_len -= len;
+ len = 0;
}
}
}
+
+ return iob;
}