lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] Missing ACKs using LWIP 1.3.2


From: John Hoffman
Subject: [lwip-users] Missing ACKs using LWIP 1.3.2
Date: Wed, 6 May 2015 13:50:22 +0000

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)

 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]