mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 01:05:54 +08:00
net/tcp: cache the drop packet to avoid retransmit
Change-Id: Ia27ed17a7708df8481ac96d9a3a870b6ccef4d24 Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
@@ -203,12 +203,12 @@ Public Function Prototypes
|
||||
Free an entire buffer chain, starting at the
|
||||
beginning of the I/O buffer chain
|
||||
|
||||
.. c:function:: int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq)
|
||||
.. c:function:: int iob_add_queue(FAR struct iob_s *iob, FAR void *priv, FAR struct iob_queue_s *iobq)
|
||||
|
||||
Add one I/O buffer chain to the end of a queue.
|
||||
May fail due to lack of resources.
|
||||
|
||||
.. c:function:: void iob_tryadd_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq)
|
||||
.. c:function:: void iob_tryadd_queue(FAR struct iob_s *iob, FAR void *priv, FAR struct iob_queue_s *iobq)
|
||||
|
||||
Add one I/O buffer chain to the end of a queue
|
||||
without waiting for resources to become free.
|
||||
|
||||
@@ -144,6 +144,7 @@ static FAR const char *g_iob_user_names[] =
|
||||
#endif
|
||||
#if defined(CONFIG_NET_TCP) && !defined(NET_TCP_NO_STACK)
|
||||
"tcp_readahead",
|
||||
"tcp_pendingahead",
|
||||
#endif
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
"tcp_writebuffer",
|
||||
|
||||
@@ -140,6 +140,10 @@ struct iob_qentry_s
|
||||
/* Payload -- Head of the I/O buffer chain */
|
||||
|
||||
FAR struct iob_s *qe_head;
|
||||
|
||||
/* Private data */
|
||||
|
||||
FAR void *qe_priv;
|
||||
};
|
||||
|
||||
/* The I/O buffer queue head structure */
|
||||
@@ -196,6 +200,7 @@ enum iob_user_e
|
||||
#endif
|
||||
#if defined(CONFIG_NET_TCP) && !defined(NET_TCP_NO_STACK)
|
||||
IOBUSER_NET_TCP_READAHEAD,
|
||||
IOBUSER_NET_TCP_PENDINGAHEAD,
|
||||
#endif
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
IOBUSER_NET_TCP_WRITEBUFFER,
|
||||
@@ -377,7 +382,8 @@ void iob_free_chain(FAR struct iob_s *iob, enum iob_user_e producerid);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_IOB_NCHAINS > 0
|
||||
int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq);
|
||||
int iob_add_queue(FAR struct iob_s *iob, FAR void *priv,
|
||||
FAR struct iob_queue_s *iobq);
|
||||
#endif /* CONFIG_IOB_NCHAINS > 0 */
|
||||
|
||||
/****************************************************************************
|
||||
@@ -390,7 +396,8 @@ int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq);
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_IOB_NCHAINS > 0
|
||||
int iob_tryadd_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq);
|
||||
int iob_tryadd_queue(FAR struct iob_s *iob, FAR void *priv,
|
||||
FAR struct iob_queue_s *iobq);
|
||||
#endif /* CONFIG_IOB_NCHAINS > 0 */
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ ifeq ($(CONFIG_MM_IOB),y)
|
||||
CSRCS += iob_add_queue.c iob_alloc.c iob_alloc_qentry.c iob_clone.c
|
||||
CSRCS += iob_concat.c iob_copyin.c iob_copyout.c iob_contig.c iob_free.c
|
||||
CSRCS += iob_free_chain.c iob_free_qentry.c iob_destroy_queue.c
|
||||
CSRCS += iob_get_queue_count.c
|
||||
CSRCS += iob_free_queue.c iob_get_queue_count.c
|
||||
CSRCS += iob_initialize.c iob_pack.c iob_peek_queue.c iob_remove_queue.c
|
||||
CSRCS += iob_statistics.c iob_trimhead.c iob_trimhead_queue.c iob_trimtail.c
|
||||
CSRCS += iob_navail.c
|
||||
|
||||
@@ -72,11 +72,13 @@
|
||||
|
||||
static int iob_add_queue_internal(FAR struct iob_s *iob,
|
||||
FAR struct iob_queue_s *iobq,
|
||||
FAR struct iob_qentry_s *qentry)
|
||||
FAR struct iob_qentry_s *qentry,
|
||||
FAR void *priv)
|
||||
{
|
||||
/* Add the I/O buffer chain to the container */
|
||||
|
||||
qentry->qe_head = iob;
|
||||
qentry->qe_priv = priv;
|
||||
|
||||
/* Add the container to the end of the queue */
|
||||
|
||||
@@ -109,7 +111,8 @@ static int iob_add_queue_internal(FAR struct iob_s *iob,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq)
|
||||
int iob_add_queue(FAR struct iob_s *iob, FAR void *priv,
|
||||
FAR struct iob_queue_s *iobq)
|
||||
{
|
||||
FAR struct iob_qentry_s *qentry;
|
||||
|
||||
@@ -122,7 +125,7 @@ int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return iob_add_queue_internal(iob, iobq, qentry);
|
||||
return iob_add_queue_internal(iob, iobq, qentry, priv);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -134,7 +137,8 @@ int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int iob_tryadd_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq)
|
||||
int iob_tryadd_queue(FAR struct iob_s *iob, FAR void *priv,
|
||||
FAR struct iob_queue_s *iobq)
|
||||
{
|
||||
FAR struct iob_qentry_s *qentry;
|
||||
|
||||
@@ -147,6 +151,6 @@ int iob_tryadd_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return iob_add_queue_internal(iob, iobq, qentry);
|
||||
return iob_add_queue_internal(iob, iobq, qentry, priv);
|
||||
}
|
||||
#endif /* CONFIG_IOB_NCHAINS > 0 */
|
||||
|
||||
@@ -238,6 +238,7 @@ FAR struct iob_qentry_s *iob_tryalloc_qentry(void)
|
||||
/* Put the I/O buffer in a known state */
|
||||
|
||||
iobq->qe_head = NULL; /* Nothing is contained */
|
||||
iobq->qe_priv = NULL;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
@@ -221,7 +221,7 @@ uint16_t can_datahandler(FAR struct can_conn_s *conn, FAR uint8_t *buffer,
|
||||
* without waiting).
|
||||
*/
|
||||
|
||||
ret = iob_tryadd_queue(iob, &conn->readahead);
|
||||
ret = iob_tryadd_queue(iob, NULL, &conn->readahead);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
|
||||
|
||||
@@ -189,7 +189,7 @@ static uint16_t icmp_datahandler(FAR struct net_driver_s *dev,
|
||||
* without waiting).
|
||||
*/
|
||||
|
||||
ret = iob_tryadd_queue(iob, &conn->readahead);
|
||||
ret = iob_tryadd_queue(iob, NULL, &conn->readahead);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
|
||||
|
||||
@@ -192,7 +192,7 @@ static uint16_t icmpv6_datahandler(FAR struct net_driver_s *dev,
|
||||
* without waiting).
|
||||
*/
|
||||
|
||||
ret = iob_tryadd_queue(iob, &conn->readahead);
|
||||
ret = iob_tryadd_queue(iob, NULL, &conn->readahead);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
|
||||
|
||||
+13
-2
@@ -214,7 +214,15 @@ struct tcp_conn_s
|
||||
* where the TCP/IP read-ahead data is retained.
|
||||
*/
|
||||
|
||||
struct iob_queue_s readahead; /* Read-ahead buffering */
|
||||
struct iob_queue_s readahead; /* Read-ahead buffering */
|
||||
|
||||
/* Pending-ahead buffering.
|
||||
*
|
||||
* pendingahead - A singly linked list of type struct iob_qentry_s
|
||||
* where the TCP/IP pending-ahead data is retained.
|
||||
*/
|
||||
|
||||
struct iob_queue_s pendingahead; /* Pending-ahead buffering */
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Write buffering
|
||||
@@ -1120,6 +1128,8 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
|
||||
* buffer - A pointer to the buffer to be copied to the read-ahead
|
||||
* buffers
|
||||
* buflen - The number of bytes to copy to the read-ahead buffer.
|
||||
* priv - Private data.
|
||||
* producerid - id representing who is producing the IOB.
|
||||
*
|
||||
* Returned Value:
|
||||
* The number of bytes actually buffered is returned. This will be either
|
||||
@@ -1133,7 +1143,8 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
|
||||
****************************************************************************/
|
||||
|
||||
uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
|
||||
uint16_t nbytes);
|
||||
uint16_t nbytes, FAR void *priv,
|
||||
enum iob_user_e producerid);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_backlogcreate
|
||||
|
||||
+28
-9
@@ -99,7 +99,8 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
* partial packets will not be buffered.
|
||||
*/
|
||||
|
||||
recvlen = tcp_datahandler(conn, buffer, buflen);
|
||||
recvlen = tcp_datahandler(conn, buffer, buflen, NULL,
|
||||
IOBUSER_NET_TCP_READAHEAD);
|
||||
if (recvlen < buflen)
|
||||
{
|
||||
/* There is no handler to receive new data and there are no free
|
||||
@@ -238,27 +239,45 @@ uint16_t tcp_callback(FAR struct net_driver_s *dev,
|
||||
****************************************************************************/
|
||||
|
||||
uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
|
||||
uint16_t buflen)
|
||||
uint16_t buflen, FAR void *priv,
|
||||
enum iob_user_e producerid)
|
||||
{
|
||||
FAR struct iob_queue_s *queue;
|
||||
FAR struct iob_s *iob;
|
||||
bool throttled = true;
|
||||
int ret;
|
||||
|
||||
/* Get the I/O buffer queue from iob producer id */
|
||||
|
||||
if (producerid == IOBUSER_NET_TCP_READAHEAD)
|
||||
{
|
||||
queue = &conn->readahead;
|
||||
}
|
||||
else if (producerid == IOBUSER_NET_TCP_PENDINGAHEAD)
|
||||
{
|
||||
queue = &conn->pendingahead;
|
||||
}
|
||||
else
|
||||
{
|
||||
nwarn("ERROR: Invalid iob produce id\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try to allocate on I/O buffer to start the chain without waiting (and
|
||||
* throttling as necessary). If we would have to wait, then drop the
|
||||
* packet.
|
||||
*/
|
||||
|
||||
iob = iob_tryalloc(throttled, IOBUSER_NET_TCP_READAHEAD);
|
||||
iob = iob_tryalloc(throttled, producerid);
|
||||
if (iob == NULL)
|
||||
{
|
||||
#if CONFIG_IOB_THROTTLE > 0
|
||||
if (IOB_QEMPTY(&conn->readahead))
|
||||
if (IOB_QEMPTY(queue))
|
||||
{
|
||||
/* Fallback out of the throttled entry */
|
||||
|
||||
throttled = false;
|
||||
iob = iob_tryalloc(throttled, IOBUSER_NET_TCP_READAHEAD);
|
||||
iob = iob_tryalloc(throttled, producerid);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -272,7 +291,7 @@ uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
|
||||
/* Copy the new appdata into the I/O buffer chain (without waiting) */
|
||||
|
||||
ret = iob_trycopyin(iob, buffer, buflen, 0, throttled,
|
||||
IOBUSER_NET_TCP_READAHEAD);
|
||||
producerid);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* On a failure, iob_copyin return a negated error value but does
|
||||
@@ -280,7 +299,7 @@ uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
|
||||
*/
|
||||
|
||||
nerr("ERROR: Failed to add data to the I/O buffer chain: %d\n", ret);
|
||||
iob_free_chain(iob, IOBUSER_NET_TCP_READAHEAD);
|
||||
iob_free_chain(iob, producerid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -288,11 +307,11 @@ uint16_t tcp_datahandler(FAR struct tcp_conn_s *conn, FAR uint8_t *buffer,
|
||||
* without waiting).
|
||||
*/
|
||||
|
||||
ret = iob_tryadd_queue(iob, &conn->readahead);
|
||||
ret = iob_tryadd_queue(iob, priv, queue);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
|
||||
iob_free_chain(iob, IOBUSER_NET_TCP_READAHEAD);
|
||||
iob_free_chain(iob, producerid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -789,6 +789,10 @@ void tcp_free(FAR struct tcp_conn_s *conn)
|
||||
|
||||
iob_destroy_queue(&conn->readahead, IOBUSER_NET_TCP_READAHEAD);
|
||||
|
||||
/* Release any pending-ahead buffers attached to the connection */
|
||||
|
||||
iob_destroy_queue(&conn->pendingahead, IOBUSER_NET_TCP_PENDINGAHEAD);
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Release any write buffers attached to the connection */
|
||||
|
||||
@@ -1032,6 +1036,10 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
||||
|
||||
IOB_QINIT(&conn->readahead);
|
||||
|
||||
/* Initialize the list of TCP pending-ahead buffers */
|
||||
|
||||
IOB_QINIT(&conn->pendingahead);
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Initialize the write buffer lists */
|
||||
|
||||
@@ -1299,6 +1307,10 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
|
||||
IOB_QINIT(&conn->readahead);
|
||||
|
||||
/* Initialize the list of TCP pending-ahead buffers */
|
||||
|
||||
IOB_QINIT(&conn->pendingahead);
|
||||
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
/* Initialize the TCP write buffer lists */
|
||||
|
||||
|
||||
+178
-3
@@ -59,6 +59,8 @@
|
||||
#include <nuttx/net/ip.h>
|
||||
#include <nuttx/net/tcp.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include "devif/devif.h"
|
||||
#include "utils/utils.h"
|
||||
#include "tcp/tcp.h"
|
||||
@@ -73,6 +75,58 @@
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_input_cache
|
||||
****************************************************************************/
|
||||
|
||||
static void tcp_input_cache(FAR struct net_driver_s *dev,
|
||||
FAR struct tcp_conn_s *conn, unsigned int iplen)
|
||||
{
|
||||
uint8_t header[iplen + NET_LL_HDRLEN(dev) + sizeof(struct tcp_hdr_s)];
|
||||
FAR struct iob_qentry_s *qentry;
|
||||
FAR struct tcp_hdr_s *incoming;
|
||||
FAR struct tcp_hdr_s *cached;
|
||||
uint32_t ackseq;
|
||||
uint32_t rcvseq;
|
||||
|
||||
if (dev->d_len < sizeof(header))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get a pointer to the TCP header. The TCP header lies just after the
|
||||
* the link layer header and the IP header.
|
||||
*/
|
||||
|
||||
incoming = (FAR struct tcp_hdr_s *)&dev->d_buf[iplen + NET_LL_HDRLEN(dev)];
|
||||
|
||||
/* Get the sequence number of that has just been acknowledged by this
|
||||
* incoming packet.
|
||||
*/
|
||||
|
||||
ackseq = tcp_getsequence(incoming->seqno);
|
||||
rcvseq = tcp_getsequence(conn->rcvseq);
|
||||
if (ackseq < rcvseq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (qentry = conn->pendingahead.qh_head;
|
||||
qentry != NULL; qentry = qentry->qe_flink)
|
||||
{
|
||||
(void)iob_copyout(header, qentry->qe_head, sizeof(header), 0);
|
||||
cached = (FAR struct tcp_hdr_s *)&header[iplen + NET_LL_HDRLEN(dev)];
|
||||
rcvseq = tcp_getsequence(cached->seqno);
|
||||
if (rcvseq == ackseq)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tcp_datahandler(conn, dev->d_buf, dev->d_len,
|
||||
(void *)iplen, IOBUSER_NET_TCP_PENDINGAHEAD);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_input
|
||||
*
|
||||
@@ -93,7 +147,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
|
||||
unsigned int iplen)
|
||||
unsigned int iplen, FAR struct tcp_conn_s **active)
|
||||
{
|
||||
FAR struct tcp_hdr_s *tcp;
|
||||
FAR struct tcp_conn_s *conn = NULL;
|
||||
@@ -151,6 +205,11 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
|
||||
conn = tcp_active(dev, tcp);
|
||||
if (conn)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
*active = conn;
|
||||
}
|
||||
|
||||
/* We found an active connection.. Check for the subsequent SYN
|
||||
* arriving in TCP_SYN_RCVD state after the SYNACK packet was
|
||||
* lost. To avoid other issues, reset any active connection
|
||||
@@ -200,6 +259,11 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain,
|
||||
conn = tcp_alloc_accept(dev, tcp);
|
||||
if (conn)
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
*active = conn;
|
||||
}
|
||||
|
||||
/* The connection structure was successfully allocated and has
|
||||
* been initialized in the TCP_SYN_RECVD state. The expected
|
||||
* sequence of events is then the rest of the 3-way handshake:
|
||||
@@ -453,6 +517,11 @@ found:
|
||||
if ((dev->d_len > 0 || ((tcp->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
|
||||
memcmp(tcp->seqno, conn->rcvseq, 4) != 0)
|
||||
{
|
||||
/* Restore the data length */
|
||||
|
||||
dev->d_len += hdrlen;
|
||||
tcp_input_cache(dev, conn, iplen);
|
||||
|
||||
tcp_send(dev, conn, TCP_ACK, tcpiplen);
|
||||
return;
|
||||
}
|
||||
@@ -1017,6 +1086,95 @@ drop:
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_process_cache
|
||||
****************************************************************************/
|
||||
|
||||
static void tcp_process_cache(FAR struct net_driver_s *dev, uint8_t domain,
|
||||
FAR struct tcp_conn_s *conn)
|
||||
{
|
||||
FAR struct iob_qentry_s *qentry;
|
||||
FAR uint8_t *reassemble = NULL;
|
||||
FAR struct iob_qentry_s *next;
|
||||
FAR struct tcp_hdr_s tcp;
|
||||
FAR struct iob_s *iob;
|
||||
FAR uint8_t *d_buf;
|
||||
unsigned int iplen;
|
||||
uint32_t ackseq;
|
||||
uint32_t rcvseq;
|
||||
uint16_t d_len;
|
||||
|
||||
if (!conn || !iob_peek_queue(&conn->pendingahead))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
d_len = dev->d_len;
|
||||
d_buf = dev->d_buf;
|
||||
|
||||
for (qentry = conn->pendingahead.qh_head; qentry != NULL; qentry = next)
|
||||
{
|
||||
next = qentry->qe_flink;
|
||||
iob = qentry->qe_head;
|
||||
iplen = (intptr_t)qentry->qe_priv;
|
||||
|
||||
(void)iob_copyout((FAR uint8_t *)&tcp, iob, sizeof(tcp),
|
||||
NET_LL_HDRLEN(dev) + iplen);
|
||||
|
||||
rcvseq = tcp_getsequence(conn->rcvseq);
|
||||
ackseq = tcp_getsequence(tcp.seqno);
|
||||
|
||||
if (rcvseq == ackseq)
|
||||
{
|
||||
if (iob->io_pktlen > iob->io_len)
|
||||
{
|
||||
if (reassemble == NULL)
|
||||
{
|
||||
reassemble = kmm_malloc(CONFIG_NET_ETH_PKTSIZE);
|
||||
if (reassemble == NULL)
|
||||
{
|
||||
iob_destroy_queue(&conn->pendingahead,
|
||||
IOBUSER_NET_TCP_PENDINGAHEAD);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(void)iob_copyout(reassemble, iob, iob->io_pktlen, 0);
|
||||
|
||||
dev->d_buf = reassemble;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev->d_buf = IOB_DATA(iob);
|
||||
}
|
||||
|
||||
dev->d_len = iob->io_pktlen - NET_LL_HDRLEN(dev);
|
||||
|
||||
tcp_input(dev, domain, iplen, NULL);
|
||||
|
||||
iob_free_queue(iob, &conn->pendingahead,
|
||||
IOBUSER_NET_TCP_PENDINGAHEAD);
|
||||
|
||||
/* Re-traverse the pending list */
|
||||
|
||||
qentry = conn->pendingahead.qh_head;
|
||||
}
|
||||
else if (ackseq < rcvseq)
|
||||
{
|
||||
iob_free_queue(iob, &conn->pendingahead,
|
||||
IOBUSER_NET_TCP_PENDINGAHEAD);
|
||||
}
|
||||
}
|
||||
|
||||
dev->d_len = d_len;
|
||||
dev->d_buf = d_buf;
|
||||
|
||||
if (reassemble)
|
||||
{
|
||||
kmm_free(reassemble);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -1042,6 +1200,7 @@ drop:
|
||||
void tcp_ipv4_input(FAR struct net_driver_s *dev)
|
||||
{
|
||||
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||
FAR struct tcp_conn_s *conn = NULL;
|
||||
uint16_t iphdrlen;
|
||||
|
||||
/* Configure to receive an TCP IPv4 packet */
|
||||
@@ -1054,7 +1213,14 @@ void tcp_ipv4_input(FAR struct net_driver_s *dev)
|
||||
|
||||
/* Then process in the TCP IPv4 input */
|
||||
|
||||
tcp_input(dev, PF_INET, iphdrlen);
|
||||
tcp_input(dev, PF_INET, iphdrlen, &conn);
|
||||
|
||||
/* Try the pending cache here */
|
||||
|
||||
if (conn)
|
||||
{
|
||||
tcp_process_cache(dev, PF_INET, conn);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1081,13 +1247,22 @@ void tcp_ipv4_input(FAR struct net_driver_s *dev)
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
void tcp_ipv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn = NULL;
|
||||
|
||||
/* Configure to receive an TCP IPv6 packet */
|
||||
|
||||
tcp_ipv6_select(dev);
|
||||
|
||||
/* Then process in the TCP IPv6 input */
|
||||
|
||||
tcp_input(dev, PF_INET6, iplen);
|
||||
tcp_input(dev, PF_INET6, iplen, &conn);
|
||||
|
||||
/* Try the pending cache here */
|
||||
|
||||
if (conn)
|
||||
{
|
||||
tcp_process_cache(dev, PF_INET6, conn);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -186,9 +186,10 @@ static inline void tcp_newdata(FAR struct net_driver_s *dev,
|
||||
#ifdef CONFIG_DEBUG_NET
|
||||
uint16_t nsaved;
|
||||
|
||||
nsaved = tcp_datahandler(conn, buffer, buflen);
|
||||
nsaved = tcp_datahandler(conn, buffer, buflen, NULL,
|
||||
IOBUSER_NET_TCP_READAHEAD);
|
||||
#else
|
||||
tcp_datahandler(conn, buffer, buflen);
|
||||
tcp_datahandler(conn, buffer, buflen, NULL, IOBUSER_NET_TCP_READAHEAD);
|
||||
#endif
|
||||
|
||||
/* There are complicated buffering issues that are not addressed fully
|
||||
|
||||
@@ -226,7 +226,7 @@ static uint16_t udp_datahandler(FAR struct net_driver_s *dev,
|
||||
|
||||
/* Add the new I/O buffer chain to the tail of the read-ahead queue */
|
||||
|
||||
ret = iob_tryadd_queue(iob, &conn->readahead);
|
||||
ret = iob_tryadd_queue(iob, NULL, &conn->readahead);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
|
||||
|
||||
Reference in New Issue
Block a user