lwIP
(lightweightIP) is a popular free
TCP/IP stack for many embedded processors, including Atmel's AVR32
framework
The version of lwIP in my AVR32 Framework is 1.3.0
When I open a TCP connection, I don't like to use blocking method
to call lwip_recv, for it will not return until it receives something from
the socket, so I always use unblocking option.
Everything seems fine until I try to
send a lot of small packets to it in a short burst. You will not lose any
packets, but the internal counter for incoming packets will be messed up.
When this happens, the next unblocking calls to lwip_recvfrom will lose
sync and turn into a blocking one!
With the help of lwIP's team, the following patch can be applied
to lwIP to fix the bug.
Due to the difference in the lwIP's version controls, You will need to
apply the follow patch manually.
Open the affected
files, use the line number
as reference, which may not be in the exact spot. Remove
the text indicated with - and add
the text with leading + (remove + before adding the text).
Open YourProject->src->SOFTWARE_FRAMEWORK->SERVICES->lwip-1.3.0->src->api->api_msg.c
@@ -108,11 +108,13 @@
buf->addr = &(((struct ip_hdr*)(q->payload))->src);
buf->port = pcb->protocol;
- SYS_ARCH_INC(conn->recv_avail, q->tot_len);
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len);
if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
netbuf_delete(buf);
+ return 0;
+ } else {
+ SYS_ARCH_INC(conn->recv_avail, q->tot_len);
+ /* Register event with callback */
+ API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len);
}
}
}
@@ -166,12 +168,13 @@
buf->port = port;
}
- SYS_ARCH_INC(conn->recv_avail, p->tot_len);
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
netbuf_delete(buf);
return;
+ } else {
+ SYS_ARCH_INC(conn->recv_avail, p->tot_len);
+ /* Register event with callback */
+ API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
}
}
#endif /* LWIP_UDP */
@@ -206,10 +209,12 @@
} else {
len = 0;
}
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
+
if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) {
return ERR_MEM;
+ } else {
+ /* Register event with callback */
+ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
}
return ERR_OK;
@@ -365,8 +370,6 @@
newconn->pcb.tcp = newpcb;
setup_tcp(newconn);
newconn->err = err;
- /* Register event with callback */
- API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) {
/* When returning != ERR_OK, the connection is aborted in tcp_process(),
@@ -374,7 +377,11 @@
newconn->pcb.tcp = NULL;
netconn_free(newconn);
return ERR_MEM;
+ } else {
+ /* Register event with callback */
+ API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
}
+
return ERR_OK;
}
#endif /* LWIP_TCP */
Open YourProject->src->SOFTWARE_FRAMEWORK->SERVICES->lwip-1.3.0->src->api->sockets.c
@@ -66,7 +66,7 @@
u16_t lastoffset;
/** number of times data was received, set by event_callback(),
tested by the receive and select functions */
- u16_t rcvevent;
+ s16_t rcvevent;
/** number of times data was received, set by event_callback(),
tested by select */
u16_t sendevent;
@@ -260,7 +260,7 @@
if (!sock)
return -1;
- if ((sock->flags & O_NONBLOCK) && !sock->rcvevent) {
+ if ((sock->flags & O_NONBLOCK) && (sock->rcvevent <= 0)) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
sock_set_errno(sock, EWOULDBLOCK);
return -1;
@@ -494,7 +494,8 @@
buf = sock->lastdata;
} else {
/* If this is non-blocking call, then check first */
- if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) && !sock->rcvevent) {
+ if (((flags & MSG_DONTWAIT) || (sock->flags & O_NONBLOCK)) &&
+ (sock->rcvevent <= 0)) {
if (off > 0) {
/* already received data, return that */
sock_set_errno(sock, 0);
@@ -545,7 +546,10 @@
if (netconn_type(sock->conn) == NETCONN_TCP) {
LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
len -= copylen;
- if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent || ((flags & MSG_PEEK)!=0)) {
+ if ( (len <= 0) ||
+ (buf->p->flags & PBUF_FLAG_PUSH) ||
+ (sock->rcvevent <= 0) ||
+ ((flags & MSG_PEEK)!=0)) {
done = 1;
}
} else {
@@ -852,7 +856,7 @@
if (FD_ISSET(i, readset)) {
/* See if netconn of this socket is ready for read */
p_sock = get_socket(i);
- if (p_sock && (p_sock->lastdata || p_sock->rcvevent)) {
+ if (p_sock && (p_sock->lastdata || (p_sock->rcvevent > 0))) {
FD_SET(i, &lreadset);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
nready++;
@@ -1100,7 +1104,7 @@
if (scb->sem_signalled == 0) {
/* Test this select call for our socket */
if (scb->readset && FD_ISSET(s, scb->readset))
- if (sock->rcvevent)
+ if (sock->rcvevent > 0)
break;
if (scb->writeset && FD_ISSET(s, scb->writeset))
if (sock->sendevent)
Open YourProject->src->SOFTWARE_FRAMEWORK->SERVICES->lwip-1.3.0->src-> include/lwip/api.h
@@ -137,7 +137,7 @@
/** maximum amount of bytes queued in recvmbox */
int recv_bufsize;
#endif /* LWIP_SO_RCVBUF */
- u16_t recv_avail;
+ s16_t recv_avail;
#if LWIP_TCP
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
this temporarily stores the message. */
Upgrade to the latest lwIP and you won't
need to do the above!
Click here for more lwIP examples
Last update: 04/08/10
|
|
|
| |