Gavin | 23 Sep 10:13 2014

There is no pbuf to be allocated

Hi,

I got one out of pbuf issue in my application.

I rewrote echo server sample to a tcp client with raw API. My test platform
is TM4C1294XL.

In my test case, I repeated the sequence:
1. connect to server and initialize the necessary parameter.
2. some data transferred between server and client.
3. close the connection and free pbuf allocated.

It was always failed at the 13th trial, so I tried to print the log and
increased memory to verify my assumption. 

1. If I made a bigger "PBUF_POOL_SIZE", and that increased the amount of
trials, but it was still failed eventually.
2. I got the log "tivaif_receive: pbuf_alloc error" that means there is no
pbuf to be allocated.

Based on the above reason, this should be the leakage of pbuf issue.

I also tried to look at the articles in the forum and verify the different
parameter, but it still can't work.

Does anyone get idea how to fix this issue?

thanks
Gavin

(Continue reading)

Michael Steinecke | 23 Sep 10:02 2014
Picon

CRC of each IP Header is not calculated after some point (STM32F4)

Hello Folks,

its me again. I've discovered another strange behavior with the STM32F429ZG
device in conjunction with LwIP 1.4.1 (and FreeRTOS). Everything goes
smoothly for some time, several transfers and so on. But from one point on,
the CRC calculation for all outgoing packets fails or is not executed
entirely. 
In the attached pcap file, I've transferred the same file (~10 MB) from
SD-Card several times. Beginning with packet 452 every outgoing IP Header
has a checksum of zero. Eventually every packet gets discarded by PC. Then
with packet 463, the PC sends another command. The MCU tries to ACK it, but
still no CRC. Conclusion: CRC on receive either works or ist not checked by
MCU.
After the RST from PC, the MCU falls back in auto discovery state. For that,
TCP data port 55557 gets closed and a new accept() socket with the same port
is initiated.
Now we can see a lot of UDP 55555 and DHCP discovery broadcasts. Each of
them with the same problem.
After a reset of the device, everything is working smoothly again.

CRC calculation is done by HW (SW calculation in LwIP turned off), therefore
I would expect another STM bug. Is there something known? Some ideas how to
track down this?

PC: 192.168.111.63
MCU: 192.168.111.200

Turn on checksum calculation in Wireshark. (UDP/TCP settings)
IP-Header_CRC_not_calculated_one_transfer.pcap
<http://lwip.100.n7.nabble.com/file/n23334/IP-Header_CRC_not_calculated_one_transfer.pcap>  
(Continue reading)

Karl Karpfen | 22 Sep 06:55 2014
Picon

poll-function not called

Hi,

I'm using lwIP 1.4.0 implementation that comes with Starterware for AM3358 from Texas Instruments. Thus I do not know that much about its exact implementation for used hardware. Now I found the poll-function is never called in TI's implementation.

To track down the problem: where in lwIP is this this part implemented? Any hints/suggestion hwere to look at are welcome!

Kind regards

Karl


_______________________________________________
lwip-users mailing list
lwip-users@...
https://lists.nongnu.org/mailman/listinfo/lwip-users
Joel Cunningham | 19 Sep 15:27 2014

event_callback() context switch when calling sys_sem_signal()

I'm running LwIP 1.4.1 and have some questions about the event_callback() in sockets.c

In my project, I am experiencing a crash related to synchronization in event_callback() and an application thread calling select().  My project is a uniprocessor system running an RTOS that implements a static priority scheduler.  SYS_ARCH_PROTECT() is implemented by disabling interrupts.  sys_sem_signal() is implemented using a counting semaphore.  TCPIP thread is higher priority than application threads.

The crash happens when the application thread is waiting in select() and the TCPIP thread is calling event_callback() to process an event.  What's happen is in the below loop, calling sys_sem_signal() results in a context switch on my project's RTOS even though application thread is lower priority.  The RTOS's semaphore construct doesn't support priority inheritance/elevation.  The application thread wakes up and finishes the select call, modifying the select_cb_list.  When the context switches back to TCPIP thread, it finishes the loop iteration and crashes because the select_cb_list has been modified.

What I've done to mitigate the context switch is move the line last_select_cb_ctr = select_cb_ctr; to the top of the for loop.  To me the loop already had handling for a context switch per iteration, but it only saved the counter at the end. So now it can handle a switch in the call to sys_sem_signal() as well.

My questions to whether this is a bug depend on:

1) Should SYS_ARCH_PROTECT() do more than just disable interrupts?  Something that would act as a critical section in the case where a context switch happens?
2) Is it assumed that calling sys_sem_signal() will not cause a voluntary context switch?

SYS_ARCH_PROTECT(lev);
...
again:
  for (scb = select_cb_list; scb != NULL; scb = scb->next) {
    if (scb->sem_signalled == 0) {
      /* semaphore not signalled yet */
      int do_signal = 0;
      /* Test this select call for our socket */
      if (sock->rcvevent > 0) {
        if (scb->readset && FD_ISSET(s, scb->readset)) {
          do_signal = 1;
        }
      }
      if (sock->sendevent != 0) {
        if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
          do_signal = 1;
        }
      }
      if (sock->errevent != 0) {
        if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
          do_signal = 1;
        }
      }
      if (do_signal) {
        scb->sem_signalled = 1;
        /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
           lead to the select thread taking itself off the list, invalidagin the semaphore. */
        sys_sem_signal(&scb->sem);
      }
    }
    last_select_cb_ctr = select_cb_ctr;
    /* unlock interrupts with each step */
    SYS_ARCH_UNPROTECT(lev);
    /* this makes sure interrupt protection time is short */
    SYS_ARCH_PROTECT(lev);
    if (last_select_cb_ctr != select_cb_ctr) {
      /* someone has changed select_cb_list, restart at the beginning */
      goto again;
    }

Thanks,

Joel

_______________________________________________
lwip-users mailing list
lwip-users@...
https://lists.nongnu.org/mailman/listinfo/lwip-users
Karl Karpfen | 17 Sep 11:37 2014
Picon

Context of poll and recv?

Hi,

this is a follow-up to "How to check send state?" but I start a new discussion since it is a new question:

I'm trying to enqueue some data into lwIP's send queue that are generated from within my applications main-loop (which is not allowed). Now my solution is to just set a flag and then fetch and enqueue the data out of  lwIPs thread context. This is done once periodically within my poll-function (specified by tcp_poll()) and once immediately from within my recv-function (specified with tcp_recv()).

My question: are both running in same IRQ-context or are they triggered by different ones so that filling the send buffer this way would lead to troubles too? A check if previously enqueued data are fully send of course is implemented.

Thanks for all your kind help :-)

_______________________________________________
lwip-users mailing list
lwip-users@...
https://lists.nongnu.org/mailman/listinfo/lwip-users
Simon Goldschmidt | 17 Sep 11:10 2014
Picon
Picon

Re: How to check send state?

Karl Karpfen wrote:
> Currently I'm doing it as described at http://lwip.wikia.com/wiki/Raw/TCPin section
> "Sending TCP data" which seems to be wrong for my case...

There's nothing wrong with what's described at http://lwip.wikia.com/wiki/Raw/TCP.
What's wrong is that your lwIP calls into lwIP from interrupt context and you call it from your main loop.
This is not allowed, that's all.

Simon

_______________________________________________
lwip-users mailing list
lwip-users <at> nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users
Simon Goldschmidt | 17 Sep 09:08 2014
Picon
Picon

Re: How to check send state?

Karl Karpfen wrote:
> OK, so let me ask this in an different way:
> 
> Currently I do have data to be sent available in main loop only.
> How can I enqueue these data into the lwIP-ISR-context correctly
> so that it can be transmitted without problems?

To do that you'd either need to lock interrupts and then call into lwIP (so that you are absolutely sure your
ethernet interrupt does not call lwIP code while running it from the main loop) or put your data on a list and
soft-trigger an interrupt on the same priority.

However, the "standard" way to handle this is to let the interrupt pull packets off the MAC, put them on a list
and let lwIP run from the main loop, too. This way you only need to make the pbuf and mem(p) functions
thread-safe, which can be achieved by setting SYS_LIGHTWEIGHT_PROT==1 (plus defining the
SYS_ARCH_PROTECT macros correctly) and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT==1 (to allow the
TX-finished interrupt to free PBUF_RAM pbufs from ISR).

> Currently I'm doing it as described at http://lwip.wikia.com/wiki/Raw/TCPin section
> "Sending TCP data" which seems to be wrong for my case...

I only get an empty page with this link: "This page needs content. You can help by adding a sentence or a photo."

Simon

_______________________________________________
lwip-users mailing list
lwip-users <at> nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users
Michael Steinecke | 16 Sep 20:14 2014
Picon

TCP retransmission flooding at end of stream

Hello Folks,

currently I'm struggling while creating an application for a custom
STM32F429ZG based custom board using LwIP.
I need to achieve a throughput of at least 2 MBit/s, according our
requirements. Due to the HW this should be possible.

The application is based on the STMCubeMX V4.3.0 and FW Library 1.3.0.
However I've written a zero-copy EthernetIF driver in RX&TX.

For the application, the MCU based device acts as a TCP/IP server with our
own application protocol, implemented using the RAW TCP API.
The implementation is inspired by the HTTP Server example. Also the
guidelines regarding throughput from the LwIP wiki has been followed.
The FW Library bug in the Ethernet IRQ, eating fast packets is fixed. I'm
using custom memory pools. there is most likely no memory issue.
Also all the priorities are ok.

To achieve maximum throughput, I have done some further, potential dangerous
changes:
- The MSS, TCP_SND_BUF, pbuf len, etc is increased from u16_t to u32_t. The
MTU is still 1500. The problem with u16_t is the limitation the send buffer
to a maximum of 0xFFFE bytes. For some checks in LwIP 0xFFFF is interpreted
as 0x0000, but is need to have segments of 0xFFFF bytes for a fast
processing of SD Card pages.
- I decreased the TCP timer intervals from 250 ms to 10 ms. A even higher
rate tends to produce a lot of retransmissions.

Currently I can achieve almost the desired speed for one file transfer.
However, at the end of the transfer, there is one strange bug. I couldn't
find a similar case in the forums, so far.
Before the last frame of the last segment is sent, LwIP starts to retransmit
a bunch of TCP packets. The actual number is variable, but usually somewhere
between 10 and 25 frames.

Interestingly there is always this pattern:
MCU -> PC Packet 1460 Bytes [ACK]
MCU -> PC Packet 1460 Bytes [ACK]
PC -> MCU ACK on both, 0 Bytes
MCU -> PC Packet 1460 Bytes [ACK]
MCU -> PC Packet 1460 Bytes [ACK]
PC -> MCU ACK on both, 0 Bytes
...
MCU -> PC Packet 1460 Bytes [ACK]
MCU -> PC Packet 1460 Bytes [ACK, PSH]
PC -> MCU ACK on both, 0 Bytes
............

Then the following occurs on the last segment:
(for this example, the Seq is relative to the begin of the segment)
MCU -> PC Packet 1460 Bytes [ACK] [Seq: 0000]
MCU -> PC Packet 1460 Bytes [ACK] [Seq: 1460]
PC -> MCU ACK on both, 0 Bytes [Ack: 2920]
MCU -> PC Packet 1460 Bytes [ACK] [Seq: 2920]
MCU -> PC Packet 1460 Bytes [ACK] [Seq: 4380]
PC -> MCU ACK on both, 0 Bytes [Ack: 4380]
...
MCU -> PC Packet 1460 Bytes [TCP Retransmission] [ACK] [Seq: 0000]
PC -> MCU 0 Bytes [TCP DUP ACK] [Ack: 4380]
MCU -> PC Packet 1460 Bytes [TCP Retransmission] [ACK] [Seq: 2920] (Packet
with Seq 1460 is NOT retransmitted!)
PC -> MCU 0 Bytes [TCP DUP ACK] [Ack: 4380]
MCU -> PC Packet 1460 Bytes [TCP Retransmission] [ACK] [Seq: 4380]
PC -> MCU 0 Bytes [TCP DUP ACK] [Ack: 4380]
...
MCU -> PC Packet 1198 Bytes [ACK, PSH] [Seq: 65700]
PC -> MCU ACK on last one, sending new command, 38 Bytes [ACK, PSH] [Seq:
66898]
MCU -> PC Packet 1198 Bytes [TCP Retransmission] [ACK, PSH] [Seq: 65700]
PC -> MCU 0 Bytes [TCP DUP ACK #1] [ACK, PSH] [Seq: 66898]
MCU -> PC Packet 1198 Bytes [TCP Retransmission] [ACK, PSH] [Seq: 65700]
PC -> MCU0 Bytes [TCP DUP ACK #2] [ACK, PSH] [Seq: 66898]
MCU -> PC Packet 1198 Bytes [TCP Retransmission] [ACK, PSH] [Seq: 65700]
PC -> MCU 0 Bytes [TCP DUP ACK #3] [ACK, PSH] [Seq: 66898]
PC -> MCU ACK on last one, sending new command, 38 Bytes [TCP
Retransmission] [ACK, PSH] [Seq: 66898]
...

Afterwards, nearly every packet is transmitted at least twice in both
directions. Effectively no data transfer possible anymore.
In the pcap file, 192.168.111.200 is MCU and .63 the PC. The interesting
part is starting with frame 2056, the first retransmitted frame. 2057 is not
retransmitted - that means frame 2058 must have been processed by LwIP -
right?

The data is passed to LwIP by tcp_write().
One segment consists of two writes:
tcp_write(pcb, [ptr to 8 bytes of header], 8, TCP_WRITE_FLAG_COPY |
TCP_WRITE_FLAG_MORE)
tcp_write(pcb, [ptr to up to 65535 bytes of data], len, 0) // the data is
stored in elements of the memory pool and freed by the tcp_sent callback

According to lwip_stats there is no memory leak and no packet drop. Has
someone seen something similar? Any clue?
There are some other scenarios, leading to similar behaviors. 

SD_download_breaks.pcap
<http://lwip.100.n7.nabble.com/file/n23275/SD_download_breaks.pcap>  

--
View this message in context: http://lwip.100.n7.nabble.com/TCP-retransmission-flooding-at-end-of-stream-tp23275.html
Sent from the lwip-users mailing list archive at Nabble.com.
Gavin | 16 Sep 04:46 2014

Failed to send TCP data

Hi, 

I have one question about TCP sending.

I refer to tcpecho sample and rewrite to a client application for TCP
sending.

In my case, it only can send data twice successful and always failed at the
third time.

Here is my test code.

void test_package(void)
{
	struct lan_state *ls;
	struct pbuf *cc;
	char *str = "ggg";

	if ((ls = (struct lan_state *)mem_malloc(sizeof(struct lan_state))) ==
NULL)
		return;

	if ((cc = (struct pbuf *)mem_malloc(sizeof(struct pbuf))) == NULL)
		return;
	
	cc->payload = str;
	cc->tot_len = 3;
	cc->len = 3;
	
	ls->state = LS_ACCEPTED;
	ls->pcb = g_pcb;
	ls->retries = 0;
	ls->p = cc;
	
	tcp_sent(g_pcb, LAN_sent);
	LAN_send(g_pcb, ls);
}

void LAN_send(struct tcp_pcb *pcb, struct lan_state *ls)
{
	struct pbuf *ptr;
	err_t wr_err = ERR_OK;

	UARTprintf("LAN_send++\n");
	
	while ((wr_err == ERR_OK) && (ls->p != NULL) && (ls->p->len <=
tcp_sndbuf(pcb)))
	{
		ptr = ls->p;
		
		/* enqueue data for transmission */
		wr_err = tcp_write(pcb, ptr->payload, ptr->len, 1);
		if (wr_err == ERR_OK)
		{
			u16_t plen;
			u8_t freed;
			
			plen = ptr->len;
			/* continue with next pbuf in chain (if any) */
			ls->p = ptr->next;
			if(ls->p != NULL)
			{
				/* new reference! */
				pbuf_ref(ls->p);
			}
			/* chop first pbuf from chain */
			do
			{
				/* try hard to free pbuf */
				freed = pbuf_free(ptr);
			}
			while(freed == 0);
			/* we can read more data now */
			//tcp_recved(pcb, plen);
		}
		else if(wr_err == ERR_MEM)
		{
			/* we are low on memory, try later / harder, defer to poll */
			ls->p = ptr;
		}
		else
		{
		/* other problem ?? */
		}
	}

	UARTprintf("LAN_send--\n");
}

err_t LAN_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
	struct lan_state *ls;

	LWIP_UNUSED_ARG(len);

	UARTprintf("LAN_sent++\n");
	
	ls = (struct lan_state *)arg;
	ls->retries = 0;

	if(ls->p != NULL)
	{
		/* still got pbufs to send */
		tcp_sent(pcb, LAN_sent);
		LAN_send(pcb, ls);
	}
	else
	{
		/* no more pbufs to send */
		if(ls->state == LS_CLOSING)
		{
			LAN_end(pcb, ls);
		}
	}
	
	UARTprintf("LAN_sent--\n");
	
	return ERR_OK;
}

err_t LAN_Init(void)
{
	err_t err;
	struct lan_state *ls;
	struct ip_addr ipaddr;
	struct ip_addr *resolvedIP;

	//connect to server
	IP4_ADDR(&ipaddr, uiServerIP[0], uiServerIP[1], uiServerIP[2],
uiServerIP[3]);

	if ((ls = (struct lan_state *)mem_malloc(sizeof(struct lan_state))) ==
NULL)
		return ERR_MEM;

	if ((g_pcb = tcp_new()) == NULL)
	{
		mem_free(ls);
		return ERR_MEM;
	}
	
	ls->state = LS_ACCEPTED;
	ls->pcb = g_pcb;
	ls->retries = 0;
	ls->p = NULL;
	
	tcp_arg(g_pcb, ls);
	tcp_err(g_pcb, LAN_err);
	tcp_recv(g_pcb, LAN_recv);
	tcp_sent(g_pcb, LAN_sent);
	tcp_poll(g_pcb, LAN_poll, 10);

	err = tcp_connect(g_pcb, &ipaddr, SERVER_PORT, NULL);
	if (err != ERR_OK)
	{
		mem_free(ls);
		tcp_abort(g_pcb);
	}
	
	return err;
}

Is it related with mem allocation or else?

Does anyone have suggestion?

thanks
Gavin

--
View this message in context: http://lwip.100.n7.nabble.com/Failed-to-send-TCP-data-tp23259.html
Sent from the lwip-users mailing list archive at Nabble.com.
Karl Karpfen | 15 Sep 20:59 2014
Picon

How to check send state?

Hi,

within my lwIP application (TCP with permanent connection) I'm sending some data out of main-loop (no interrupt context) and start submission by calling

tcp_output(currentPcb);

Sending of data is done via tcp_write(). Within the send function itself amount of data already sent is stored in a variable sentLength. Now to find out if it is possible to send next bunch of data I check this variable. When its size is equal to the length of the previous data buffer, sending was completed and I start submission of next buffer.

My problem here: sentLength is manipulated out of interrupt context while checking it for completion is done out of main loop. It seems this sometimes causes troubles, at receiver side I can see incomplete frames.

So my question: what is the correct way to find out if currentPcb has finished sending (or better has pushed all data to tcp_write()) and is ready to accept next bunch of data?

Thanks!

_______________________________________________
lwip-users mailing list
lwip-users@...
https://lists.nongnu.org/mailman/listinfo/lwip-users
mobin.seven | 15 Sep 12:11 2014

idle connection timeout

Hi
I want to close idle connections on server side with 15s timeout.
Is  SO_RCVTIMEO what I need?
I use this line:
int timeout = 15000;
lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
it always returns -1.
How can I do this(closing idle connection)?
thanks

--
View this message in context: http://lwip.100.n7.nabble.com/idle-connection-timeout-tp23252.html
Sent from the lwip-users mailing list archive at Nabble.com.

Gmane