We are using LWIP 1.3.2(as ported by TexasInstruments), IAR compiler targeting
a stellaris MCU.
The TI implementation uses a timer tick interrupt 100 times/sec to service the
LWIP stack. No RTOS involved. Our application code also runs on this same
timer tick interrupt so no concurrency issues in play.
We implemented a webservice http client over tcp.
Periodically(about 1-2 times per day), we miss ACKs in the application layer.
Plain and simple, our tcp_sent callback does not get called. We have timers
that expire if the ack is not seen.
I have captured the WireShark trace and the ack is being transmitted. For some
reason the lwip stack does not inform the application layer. I don't know if
the LWIP stack sees the ack or not.
The odd thing is that under normal load conditions the code works and transmits
2-3 large HTTP posts/second. This means that within a 12 hour period it works
2*60*60 *12= 86,400 times without error.
I have adjusted the lwipopts.h settings over and over and nothing seems to
affect the problem.
I have scanned the 1.4.1 changelog and do not see any defects that specifically
address this problem, Further complicating the issue is that TI has not ported
1.4.1. If they had I would have tried it to see if it solves the problem. I am
not sure how much effort it will be to do the port myself. I am willing to do
it if there is a specific defect that address my issue.
Here is how the callbacks are being set up:
if(s_Pcb == NULL)
{
s_Pcb = tcp_new();
err_t bindResult = tcp_bind(s_Pcb, IP_ADDR_ANY, PortNumber);
UpdateCounters(&g_Diagnostics.BindCounters, bindResult);
if(bindResult != ERR_OK)
{
ClosePcb();
// try again next time
return;
}
// Setup the TCP callback functions
tcp_err(s_Pcb, OnError);
tcp_sent(s_Pcb, OnSent);
tcp_recv(s_Pcb, OnReceive);
return;
}
How we send a chunk of the overall HTTP message:
//*****************************************************************************
// Send next chunk of the message.
//*****************************************************************************
void ContinueTransmittingHttpPostMessage()
{
err_t result;
g_BytesAvailable = tcp_sndbuf(s_Pcb);
g_BytesToSend = Message.StopIndex - Message.TransmitIndex;
if(g_BytesToSend > 0)
{
if(g_BytesToSend > TCP_WND)
{
g_BytesToSend = TCP_WND;
}
if(g_BytesAvailable >= g_BytesToSend)
{
result = tcp_write(s_Pcb, &Message.Body[Message.TransmitIndex],
g_BytesToSend, 0);
UpdateCounters(&g_Diagnostics.WriteCounters, result);
if(result == ERR_OK)
{
g_Diagnostics.ulTotalBytesWritten += g_BytesToSend;
Message.TransmitIndex += g_BytesToSend;
Message.State = Sending;
SetTimeout(&Message.StateTimer, 2 Sec);
}
else
{
StopTransmittingHttpPostMessage();
}
}
else
{
g_Diagnostics.ulSendBufferFullErrors++;
}
}
}
The tcp_sent callback that doesn't get call (sometimes).
//*****************************************************************************
// Our TCP sent callback.
// Look at tcp_sent for for information.
//*****************************************************************************
static err_t OnSent(void *arg, struct tcp_pcb *pcb, u16_t numBytesAcknowledged)
{
// Service the watchdog timer
ServiceWatchdogTimer();
// We only get called if the web service received > 0 bytes
g_Diagnostics.ulOnSentCallbacks++;
g_Diagnostics.ulTotalBytesAcknowledged +=numBytesAcknowledged;
if(Message.State == Sending)
{
Message.BytesAcked += numBytesAcknowledged;
if(Message.TransmitIndex >= Message.StopIndex)
{
if(Message.BytesAcked >= Message.StopIndex)
{
Message.State = WaitingForOk;
SetTimeout(&Message.StateTimer, 2 Sec);
}
}
else
{
ContinueTransmittingHttpPostMessage();
}
}
return ERR_OK;
}
John Hoffman
Vice President Software Development
TimeKeeping Systems, Incorporated
30700 Bainbridge Road Unit H
Solon, Ohio 44139
216-595-0890 x108
216-595-0991 (fax)
_______________________________________________
lwip-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/lwip-users