Fix probably where packets dropped because there was no recv() in place were being ACKed
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@381 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
9b0f9f10d6
commit
5ea5c4cf09
@ -218,5 +218,11 @@
|
||||
* Basic client functionality verified: socket(), bind(), connect(), recv(), send().
|
||||
|
||||
0.3.1 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Separated net/uip/uip.c into several functions in several files.
|
||||
|
||||
* Separated net/uip/uip.c into several functions in several files.
|
||||
* Corrected a TCP problem where packets were dropped because there was no
|
||||
recv() in place but the packet was being ACKed. There are still TCP
|
||||
recv buffering issues, but this is part of a larger buffering issue.
|
||||
|
||||
|
||||
|
||||
|
@ -676,6 +676,9 @@ Other memory:
|
||||
0.3.1 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
|
||||
* Separated net/uip/uip.c into several functions in several files.
|
||||
* Corrected a TCP problem where packets were dropped because there was no
|
||||
recv() in place but the packet was being ACKed. There are still TCP
|
||||
recv buffering issues, but this is part of a larger buffering issue.
|
||||
</pre></ul>
|
||||
|
||||
<table width ="100%">
|
||||
|
7
TODO
7
TODO
@ -43,6 +43,9 @@ o Network
|
||||
nececcesary
|
||||
(2) Copy buffer structure into uip_driver_structure when driver requests write
|
||||
data
|
||||
(3) Extra read buffers will be necessary to buffer TCP data when there is no recv
|
||||
in place to accept the data. At present, received data is not ACKed, but is
|
||||
eventually lost in this case.
|
||||
- Improve performance by stimulating the driver to accept new TX data before the
|
||||
next polling interval.
|
||||
|
||||
@ -55,10 +58,6 @@ o Network
|
||||
polling should respond with TX data only if the UDP packet is intended for the
|
||||
the network supported by the driver.
|
||||
(2) If there were multiple drivers, polling would occur at double the rate.
|
||||
- TCP Bug:
|
||||
When TCP data is received with no read in place, it appears that uIP ACKs the data
|
||||
even though it was not taken accepted. We must either (1) buffer incoming data, or
|
||||
(2) not ACK it so that it will be re-sent.
|
||||
|
||||
o USB
|
||||
- Implement USB device support
|
||||
|
@ -95,8 +95,6 @@ void up_block_task(_TCB *tcb, tstate_t task_state)
|
||||
_TCB *rtcb = (_TCB*)g_readytorun.head;
|
||||
boolean switch_needed;
|
||||
|
||||
lldbg("Blocking TCB=%p\n", tcb);
|
||||
|
||||
/* Remove the tcb task from the ready-to-run list. If we
|
||||
* are blocking the task at the head of the task list (the
|
||||
* most likely case), then a context switch to the next
|
||||
@ -138,7 +136,6 @@ void up_block_task(_TCB *tcb, tstate_t task_state)
|
||||
*/
|
||||
|
||||
rtcb = (_TCB*)g_readytorun.head;
|
||||
lldbg("New Active Task TCB=%p\n", rtcb);
|
||||
|
||||
/* Then switch contexts */
|
||||
|
||||
@ -157,7 +154,6 @@ void up_block_task(_TCB *tcb, tstate_t task_state)
|
||||
*/
|
||||
|
||||
rtcb = (_TCB*)g_readytorun.head;
|
||||
lldbg("New Active Task TCB=%p\n", rtcb);
|
||||
|
||||
/* Then switch contexts */
|
||||
|
||||
|
@ -91,8 +91,6 @@ void up_unblock_task(_TCB *tcb)
|
||||
{
|
||||
_TCB *rtcb = (_TCB*)g_readytorun.head;
|
||||
|
||||
lldbg("Unblocking TCB=%p\n", tcb);
|
||||
|
||||
/* Remove the task from the blocked task list */
|
||||
|
||||
sched_removeblocked(tcb);
|
||||
@ -130,7 +128,6 @@ void up_unblock_task(_TCB *tcb)
|
||||
*/
|
||||
|
||||
rtcb = (_TCB*)g_readytorun.head;
|
||||
lldbg("New Active Task TCB=%p\n", rtcb);
|
||||
|
||||
/* Then switch contexts */
|
||||
|
||||
@ -151,7 +148,6 @@ void up_unblock_task(_TCB *tcb)
|
||||
*/
|
||||
|
||||
rtcb = (_TCB*)g_readytorun.head;
|
||||
lldbg("New Active Task TCB=%p\n", rtcb);
|
||||
|
||||
/* Then switch contexts */
|
||||
|
||||
|
@ -260,10 +260,10 @@
|
||||
# define CONFIG_DM9X_MODE DM9X_MODE_AUTO
|
||||
#endif
|
||||
|
||||
/* TX poll deley = 5 seconds. CLK_TCK is the number of clock ticks per second */
|
||||
/* TX poll deley = 1 seconds. CLK_TCK is the number of clock ticks per second */
|
||||
|
||||
#define DM6X_WDDELAY (5*CLK_TCK)
|
||||
#define DM6X_POLLHSEC (5*2)
|
||||
#define DM6X_WDDELAY (1*CLK_TCK)
|
||||
#define DM6X_POLLHSEC (1*2)
|
||||
|
||||
/* TX timeout = 1 minute */
|
||||
|
||||
|
@ -158,7 +158,7 @@ void send_client(void)
|
||||
}
|
||||
else if (nbytesrecvd != SENDSIZE)
|
||||
{
|
||||
message("client: Bad recv length=%d: %d\n", nbytessent);
|
||||
message("client: Bad recv length=%d: %d\n", nbytesrecvd);
|
||||
close(sockfd);
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -185,10 +185,18 @@ struct uip_conn
|
||||
/* Higher level logic can retain application specific information
|
||||
* in the following:
|
||||
*
|
||||
* data_event() is called on all events. May return one of the following:
|
||||
* UIP_CLOSE - Gracefully close the current connection
|
||||
* UIP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents UIP_CLOSE from working.
|
||||
* data_event() is called on all events. Normally, the input flags are
|
||||
* returned, however, the implemenation may set one of the following:
|
||||
*
|
||||
* UIP_CLOSE - Gracefully close the current connection
|
||||
* UIP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents UIP_CLOSE from working.
|
||||
*
|
||||
* Or clear the following:
|
||||
*
|
||||
* UIP_NEWDATA - May be cleared to suppress returning the ACK response.
|
||||
* (dev->d_len should also be set to zero in this case).
|
||||
*
|
||||
* accept() is called when the TCP logic has created a connection
|
||||
* connection_event() is called on any of the subset of connection-related events
|
||||
*/
|
||||
@ -255,18 +263,17 @@ struct uip_stats
|
||||
} icmp; /* ICMP statistics. */
|
||||
|
||||
struct
|
||||
|
||||
{
|
||||
uip_stats_t drop; /* Number of dropped TCP segments. */
|
||||
uip_stats_t recv; /* Number of recived TCP segments. */
|
||||
uip_stats_t recv; /* Number of received TCP segments. */
|
||||
uip_stats_t sent; /* Number of sent TCP segments. */
|
||||
uip_stats_t chkerr; /* Number of TCP segments with a bad checksum. */
|
||||
uip_stats_t ackerr; /* Number of TCP segments with a bad ACK number. */
|
||||
uip_stats_t rst; /* Number of recevied TCP RST (reset) segments. */
|
||||
uip_stats_t rexmit; /* Number of retransmitted TCP segments. */
|
||||
uip_stats_t syndrop; /* Number of dropped SYNs due to too few
|
||||
connections was avaliable. */
|
||||
uip_stats_t synrst; /* Number of SYNs for closed ports, triggering a RST. */
|
||||
available connections. */
|
||||
uip_stats_t synrst; /* Number of SYNs for closed ports triggering a RST. */
|
||||
} tcp; /* TCP statistics. */
|
||||
|
||||
#ifdef CONFIG_NET_UDP
|
||||
|
@ -259,7 +259,8 @@ static uint8 tcp_connect_interrupt(struct uip_driver_s *dev,
|
||||
|
||||
sem_post(&pstate->tc_sem);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -123,6 +123,10 @@ static void recvfrom_newdata(struct uip_driver_s *dev, struct recvfrom_s *pstate
|
||||
pstate->rf_recvlen += recvlen;
|
||||
pstate->rf_buffer += recvlen;
|
||||
pstate->rf_buflen -= recvlen;
|
||||
|
||||
/* Indicate no data in the buffer */
|
||||
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -313,7 +317,7 @@ static uint8 recvfrom_tcpinterrupt(struct uip_driver_s *dev,
|
||||
}
|
||||
#endif /* CONFIG_NET_SOCKOPTS && !CONFIG_DISABLE_CLOCK */
|
||||
}
|
||||
return 0;
|
||||
return flags;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -180,7 +180,8 @@ static uint8 send_interrupt(struct uip_driver_s *dev, struct uip_conn *conn, uin
|
||||
|
||||
sem_post(&pstate->snd_sem);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -185,7 +185,7 @@ typeerr:
|
||||
ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0;
|
||||
|
||||
uiphdr_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
|
||||
uiphdr_ipaddr_copy(ICMPBUF->srcipaddr, dev->d_ipaddr);
|
||||
uiphdr_ipaddr_copy(ICMPBUF->srcipaddr, &dev->d_ipaddr);
|
||||
ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS;
|
||||
ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */
|
||||
memcpy(&(ICMPBUF->options[2]), &dev->d_mac, IFHWADDRLEN);
|
||||
@ -207,7 +207,7 @@ typeerr:
|
||||
ICMPBUF->type = ICMP6_ECHO_REPLY;
|
||||
|
||||
uiphdr_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr);
|
||||
uiphdr_ipaddr_copy(ICMPBUF->srcipaddr, dev->d_ipaddr);
|
||||
uiphdr_ipaddr_copy(ICMPBUF->srcipaddr, &dev->d_ipaddr);
|
||||
ICMPBUF->icmpchksum = 0;
|
||||
ICMPBUF->icmpchksum = ~uip_icmp6chksum(dev);
|
||||
}
|
||||
|
@ -100,6 +100,8 @@ void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn, uint8 resul
|
||||
|
||||
vdbg("result: %02x\n", result);
|
||||
|
||||
/* Check for connection aborted */
|
||||
|
||||
if (result & UIP_ABORT)
|
||||
{
|
||||
dev->d_sndlen = 0;
|
||||
@ -109,6 +111,8 @@ void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn, uint8 resul
|
||||
uip_tcpsend(dev, conn, TCP_RST | TCP_ACK, UIP_IPTCPH_LEN);
|
||||
}
|
||||
|
||||
/* Check for connection closed */
|
||||
|
||||
else if (result & UIP_CLOSE)
|
||||
{
|
||||
conn->tcpstateflags = UIP_FIN_WAIT_1;
|
||||
@ -120,51 +124,56 @@ void uip_tcpappsend(struct uip_driver_s *dev, struct uip_conn *conn, uint8 resul
|
||||
uip_tcpsend(dev, conn, TCP_FIN | TCP_ACK, UIP_IPTCPH_LEN);
|
||||
}
|
||||
|
||||
/* If d_sndlen > 0, the application has data to be sent. */
|
||||
/* None of the above */
|
||||
|
||||
else if (dev->d_sndlen > 0)
|
||||
else
|
||||
{
|
||||
/* If the connection has acknowledged data, the contents of
|
||||
* the ->len variable should be discarded.
|
||||
*/
|
||||
/* If d_sndlen > 0, the application has data to be sent. */
|
||||
|
||||
if (result & UIP_ACKDATA)
|
||||
if (dev->d_sndlen > 0)
|
||||
{
|
||||
conn->len = 0;
|
||||
}
|
||||
|
||||
/* If the ->len variable is non-zero the connection has
|
||||
* already data in transit and cannot send anymore right
|
||||
* now.
|
||||
*/
|
||||
|
||||
if (conn->len == 0)
|
||||
{
|
||||
/* The application cannot send more than what is
|
||||
* allowed by the mss (the minumum of the MSS and the
|
||||
* available window).
|
||||
/* If the connection has acknowledged data, the contents of
|
||||
* the ->len variable should be discarded.
|
||||
*/
|
||||
|
||||
if (dev->d_sndlen > conn->mss)
|
||||
if (result & UIP_ACKDATA)
|
||||
{
|
||||
dev->d_sndlen = conn->mss;
|
||||
conn->len = 0;
|
||||
}
|
||||
|
||||
/* Remember how much data we send out now so that we
|
||||
* know when everything has been acknowledged.
|
||||
/* If the ->len variable is non-zero the connection has
|
||||
* already data in transit and cannot send anymore right
|
||||
* now.
|
||||
*/
|
||||
|
||||
conn->len = dev->d_sndlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the application already had unacknowledged data,
|
||||
* we make sure that the application does not send
|
||||
* (i.e., retransmit) out more than it previously sent
|
||||
* out.
|
||||
*/
|
||||
if (conn->len == 0)
|
||||
{
|
||||
/* The application cannot send more than what is
|
||||
* allowed by the mss (the minumum of the MSS and the
|
||||
* available window).
|
||||
*/
|
||||
|
||||
dev->d_sndlen = conn->len;
|
||||
if (dev->d_sndlen > conn->mss)
|
||||
{
|
||||
dev->d_sndlen = conn->mss;
|
||||
}
|
||||
|
||||
/* Remember how much data we send out now so that we
|
||||
* know when everything has been acknowledged.
|
||||
*/
|
||||
|
||||
conn->len = dev->d_sndlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the application already had unacknowledged data,
|
||||
* we make sure that the application does not send
|
||||
* (i.e., retransmit) out more than it previously sent
|
||||
* out.
|
||||
*/
|
||||
|
||||
dev->d_sndlen = conn->len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then handle the rest of the operation just as for the rexmit case */
|
||||
|
@ -75,11 +75,13 @@
|
||||
|
||||
uint8 uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
|
||||
{
|
||||
/* Preserve the UIP_ACKDATA & UIP_NEWDATA in the response. These are
|
||||
* needed by uIP to handle ACKing and buffer state.
|
||||
/* Preserve the UIP_ACKDATA, UIP_CLOSE, and UIP_ABORT in the response.
|
||||
* These is needed by uIP to handle responses and buffer state. The
|
||||
* UIP_NEWDATA indication will trigger the ACK response, but must be
|
||||
* explicitly set in the callback.
|
||||
*/
|
||||
|
||||
uint8 ret = flags & (UIP_ACKDATA|UIP_NEWDATA);
|
||||
uint8 ret = flags;
|
||||
|
||||
vdbg("flags: %02x\n", flags);
|
||||
|
||||
@ -87,13 +89,37 @@ uint8 uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, uint8 fla
|
||||
|
||||
if (conn->data_event)
|
||||
{
|
||||
/* Perform the callback. Callback function may return on of:
|
||||
* UIP_CLOSE - Gracefully close the current connection
|
||||
* UIP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents UIP_CLOSE from working.
|
||||
/* Perform the callback. Callback function normally returns the input flags,
|
||||
* however, the implemenation may set one of the following:
|
||||
*
|
||||
* UIP_CLOSE - Gracefully close the current connection
|
||||
* UIP_ABORT - Abort (reset) the current connection on an error that
|
||||
* prevents UIP_CLOSE from working.
|
||||
*
|
||||
* Or clear the following:
|
||||
*
|
||||
* UIP_NEWDATA - May be cleared to suppress returning the ACK response.
|
||||
* (dev->d_len should also be set to zero in this case).
|
||||
*/
|
||||
|
||||
ret |= conn->data_event(dev, conn, flags);
|
||||
ret = conn->data_event(dev, conn, flags);
|
||||
}
|
||||
else if ((flags & UIP_CONN_EVENTS) == 0)
|
||||
{
|
||||
/* There is no handler to receive new data in place and this is not a
|
||||
* connection event (which may also include new data that must be ACKed).
|
||||
* In this case, clear the UIP_NEWDATA bit so that no ACK will be sent
|
||||
* and drop the packet.
|
||||
*/
|
||||
|
||||
dbg("No listener on connection\n");
|
||||
|
||||
#ifdef CONFIG_NET_STATISTICS
|
||||
uip_stat.tcp.drop++;
|
||||
#endif
|
||||
|
||||
ret &= ~UIP_NEWDATA;
|
||||
dev->d_len = 0;
|
||||
}
|
||||
|
||||
/* Check if there is a connection-related event and a connection
|
||||
|
@ -316,7 +316,7 @@ void uip_tcpreset(struct uip_driver_s *dev)
|
||||
/* Swap IP addresses. */
|
||||
|
||||
uiphdr_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr);
|
||||
uiphdr_ipaddr_copy(BUF->srcipaddr, dev->d_ipaddr);
|
||||
uiphdr_ipaddr_copy(BUF->srcipaddr, &dev->d_ipaddr);
|
||||
|
||||
/* And send out the RST packet */
|
||||
|
||||
|
@ -249,7 +249,7 @@ struct uip_udp_conn *uip_udpactive(struct uip_udpip_hdr *buf)
|
||||
(conn->rport == 0 || buf->srcport == conn->rport) &&
|
||||
(uip_ipaddr_cmp(conn->ripaddr, all_zeroes_addr) ||
|
||||
uip_ipaddr_cmp(conn->ripaddr, all_ones_addr) ||
|
||||
uiphdr_ipaddr_cmp(buf->srcipaddr, conn->ripaddr)))
|
||||
uiphdr_ipaddr_cmp(buf->srcipaddr, &conn->ripaddr)))
|
||||
{
|
||||
/* Matching connection found.. return a reference to it */
|
||||
|
||||
|
@ -345,5 +345,6 @@ uint8 uip_interrupt_event(struct uip_driver_s *dev, struct uip_conn *conn, uint8
|
||||
{
|
||||
senddata(dev, conn);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ static uint16 parse_statusline(struct uip_driver_s *dev, uint16 len)
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return = UIP_ABORT;
|
||||
g_return |= UIP_ABORT;
|
||||
webclient_aborted();
|
||||
return 0;
|
||||
}
|
||||
@ -409,7 +409,7 @@ static void newdata(struct uip_driver_s *dev)
|
||||
uint8 uip_interrupt_event(struct uip_driver_s *dev, struct uip_conn *conn, uint8 flags)
|
||||
{
|
||||
#warning OBSOLETE -- needs to be redesigned
|
||||
g_return = 0;
|
||||
g_return = flags;
|
||||
|
||||
if (uip_connected_event(flags))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user