accept does not return and send is slow on uBlaze

rasty1 wrote on Wednesday, November 18, 2015:

Hi,
I got problem similator to what is described in http://sourceforge.net/p/freertos/discussion/382005/thread/31374882/
Accept() does not returm.
Wireshark and netstat show that the connection is established and even data (payload) is acked by FreeRTOS stack.

I digged a bit and found that accepting socket is somehow “forgotten” when a new socked created in accept().

I found a “solution” - “reuse socket” flag and immidiately faced the next problem - Send() sends data very slow, few characters/lines a second.

in addition recieve() always returns “1”, even if more than one bytes is read from the socket.

UDP, ARP, ICMP (ping) work OK. The problem is in TCP.
I believe that the problem is specific to uBlaze.

Does anyone have experiance with FreeRTOS Labs TCP/IP and Xilinx uBlaze?

Best regards
Rasty

rtel wrote on Wednesday, November 18, 2015:

Please post the code for the function that is using FreeRTOS_accept(). Plus the code that is creating and configurating the socket - if it is not in the same function.

Regards.

heinbali01 wrote on Wednesday, November 18, 2015:

…and if you don’t mind, also a copy of your FreeRTOSIPConfig.h and the files in ‘FreeRTOS-Plus-TCP\portable\NetworkInterface\xxx’ that you use?

+TCP has been ported to Xilinx Zynq, not to uBlaze yet, so I’m curious about the portable files that you are using.

A small note about the “reuse socket” option:

If you expect only one client to your server socket, you can save resources by marking a server socket as “reuse”, see socket option ‘FREERTOS_SO_REUSE_LISTEN_SOCKET’.
Reusing the server socket means that the same instance of the listening socket will turn into a connected client socket. When the socket gets a client, the following will happen:

    BaseType_t xTrueValue = pdTRUE;

    FreeRTOS_setsockopt( xServerSocket, 0,
        FREERTOS_SO_REUSE_LISTEN_SOCKET,
        ( void * ) &xTrueValue,
        sizeof( xTrueValue ) );

    Socket_t xClientSocket;

    xClientSocket = FreeRTOS_accept( xServerSocket,
        &xAddress, &xLength );
    if( ( xClientSocket != NULL ) &&
            ( xClientSocket != FREERTOS_INVALID_SOCKET ) )
    {
        /* xServerSocket == xClientSocket if the socket
        was marked as reusable. */
    }       
        

Have you already tried to call FreeRTOS_accept() with a limited blocking time, e.g. only 10 seconds? What happens when you do so?

I believe that the problem is specific to uBlaze
Don’t know, I haven’t seen it happening in a Zynq or other platforms yet.

Regards.

rasty1 wrote on Thursday, November 19, 2015:

Hi,
I attach SimpleTCPEchoServer.c. It is “stock” example, I added variable “client” after accept. It does not increment.

Output from Linux shell
-bash-3.2#telnet 192.168.2.1 7

-bash-3.2# netstat -nat
Active Internet connections (servers and established)
Ptcp 0 0 192.168.2.3:47129 192.168.2.1:7 ESTABLISHED

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eoe0s0, link-type EN10MB (Ethernet), capture size 65535 bytes
17:07:34.120843 IP 192.168.2.3.47128 > 192.168.2.1.echo: Flags [S], seq 56549909
3, win 14600, options [mss 1460,sackOK,TS val 1660343 ecr 0,nop,wscale 4], lengt
h 0
17:07:34.198359 IP 192.168.2.1.echo > 192.168.2.3.47128: Flags [S.], seq 1113537
743, ack 565499094, win 320, options [mss 160,nop,nop,sackOK], length 0
17:07:34.198411 IP 192.168.2.3.47128 > 192.168.2.1.echo: Flags [.], ack 1, win 1
4600, length 0
17:07:40.430556 IP 192.168.2.3.47128 > 192.168.2.1.echo: Flags [P.], seq 1:3, ac
k 1, win 14600, length 2
17:07:40.450031 IP 192.168.2.1.echo > 192.168.2.3.47128: Flags [.], ack 3, win 3
20, length 0
17:07:42.159009 IP 192.168.2.3.47128 > 192.168.2.1.echo: Flags [P.], seq 3:5, ac
k 1, win 14600, length 2
17:07:42.178368 IP 192.168.2.1.echo > 192.168.2.3.47128: Flags [.], ack 5, win 3
20, length 0
17:08:02.193381 IP 192.168.2.3.47128 > 192.168.2.1.echo: Flags [.], ack 1, win 1
4600, length 0
17:08:12.209369 IP 192.168.2.3.47128 > 192.168.2.1.echo: Flags [.], ack 1, win 1
4600, length 0
17:08:22.225372 IP 192.168.2.3.47128 > 192.168.2.1.echo: Flags [.], ack 1, win 1
4600, length 0

rasty1 wrote on Thursday, November 19, 2015:

Zynz is ARM. uBlaze is not. I’m bit concerned about endianess.
I can use “FREERTOS_SO_REUSE_LISTEN_SOCKET” as a workaround, but I immidately face next problem. send() buffers data for a long period of time - few seconds before it actually sends it.

rtel wrote on Thursday, November 19, 2015:

I’m bit concerned about endianess.

Assuming the Microblaze is configured for big endian, that should not be a problem. The TCP code is used a lot on AVR32, which is also big endian.

However, the tiny fragment of the FreeRTOSIPConfig.h file you sent (why have you not provided the whole file?) shows you have configured the TCP stack for little endian. That would lead me to believe your Microblaze is actually configured for little endian (same as Zynq), otherwise other IP functionality would not work either.

Which network controller IP are you using? I only have experience with the EMACLite, but I don’t think that is being used in this case.

Ref NetworkInterface.c: I would consider making:

unsigned char ipAddr[4] = {192,168,2,1};
unsigned char dnsAddr[4] = {0,0,0,0};
unsigned char netMask[4] = {255,255,255,0};
unsigned char gateway[4] = {192,168,2,0}; // must be consistent with IP address and mask
unsigned char macaddr[6] = {0,1,2,3,4,5};

static const, so they don’t consume any stack.

Also, from my reading of the file, I’m assuming ec_eoeReceiveInd() is a callback function executed from the context of the low level driver, and that copies received data to IPBuff[], which is then processed in the deferred interrupt handling task. Is there anything protecting ec_eoeReceiveInd() from being called again, and so overwriting the data in IPBuff[] before the deferred handling task has finished with the previous data?

rasty1 wrote on Thursday, November 19, 2015:

uBlaze implementation puzzles me
It looks like some core registers are bigendian, while variables in memory are littleendian (below)
p /x client
$5 = 0x11223344
x /b &client
0xc006f2c4 : 0x44
x /4b &client
0xc006f2c4 : 0x44 0x33 0x22 0x11
I assume that endianess is OK since ARP, Ping and UDP work OK.

We do not have classic NIC. We interface to EtherCAT, which tunnels Ethernet frame inside another Ethernet frame. So Network interface talks to “NIC” via memory buffers and callbacks.

Your’re right about ec_eoeReceiveInd. No protection currently,except priority of prvEMACDeferredInterruptHandlerTask, which is higher then that of task that calls to ec_eoeReceiveInd()

heinbali01 wrote on Thursday, November 19, 2015:

I assume that endianess is OK since ARP, Ping and UDP work OK.

That sounds very true :slight_smile:
With the wrong endianness, every packet would get dropped because it is invalid.

Regards.

rasty1 wrote on Thursday, November 19, 2015:

I found the problem.
it was:pconfigDRIVER_INCLUDED_TX_IP_CHECKSUM and ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM set to 1
and overrun of TX buffer.
Thank you very much for the hints!!!