FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6355 Discussions

tse transmission get hanged in TCP protocal

Altera_Forum
Honored Contributor II
2,592 Views

Hello,everyone! 

I want to transfer data between my laptop(the OS is windows XP) and my Stratix III 3sl150 board through ethernet wire. I'm using the hardware and software design found here: stratixiii_3sl150_dev_tse_sgmii_v1.zip (http://www.alteraforum.com/forum/attachment.php?attachmentid=1233&d=1246537769), the mode is "10/100/1000mac wtih 1000 base -x/sgmii"(1000Mbps & full Duplex mode). When using this design, the simple socket sever exmaple works well. 

Afterward, I changed the software design to test the stability of the connection, in TCP protocal. I use my Stratix III board as server, and my laptop as client. And made a for loop in both end to send and receive data: stratix iii, receive 1, send 2; laptop, send 1, receive 2. So, if the connection is stable, the loop will never be stop. But practically, the loop get hanged after some time, and I don't know why. 

 

Should it be a hardware problem(timing problem) or I do not write the software code right? 

Can anyone help me please?
0 Kudos
16 Replies
Altera_Forum
Honored Contributor II
661 Views

Here is my changed simple_socket_sever.c 

 

# include <stdio.h> # include <string.h> # include <ctype.h> # include "includes.h" # include "simple_socket_server.h" # include "alt_error_handler.h" # include "ipport.h" # include "tcpport.h" void sss_reset_connection(SSSConn* conn) { memset(conn, 0, sizeof(SSSConn)); conn->fd = -1; conn->state = READY; conn->rx_wr_pos = conn->rx_buffer; conn->rx_rd_pos = conn->rx_buffer; return; } void sss_handle_accept(int listen_socket, SSSConn* conn) { int socket, len; struct sockaddr_in incoming_addr; alt_u8 sendBuf; alt_u8 *send_ptr = sendBuf; len = sizeof(incoming_addr); if ((conn)->fd == -1) { if((socket=accept(listen_socket,(struct sockaddr*)&incoming_addr,&len))<0) { alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE, " accept failed"); } else { (conn)->fd = socket; //sss_send_menu(conn); send_ptr += sprintf(send_ptr,"Connected OK!\n\r"); send_ptr += sprintf(send_ptr,inet_ntoa(incoming_addr.sin_addr)); send_ptr += sprintf(send_ptr,"\n\r"); send(conn->fd, sendBuf, send_ptr-sendBuf, 0); printf(" accepted connection request from %s\n", inet_ntoa(incoming_addr.sin_addr)); } } else { printf(" rejected connection request from %s\n", inet_ntoa(incoming_addr.sin_addr)); } return; } void sss_handle_receive(SSSConn* conn) { char Buf; memset(Buf,0,10); //OSTimeDlyHMSM(0,0,1,0); recv(conn->fd,Buf,2,0); printf("%s\nrecieved OK!\n\n",Buf); //OSTimeDlyHMSM(0,0,1,0); send(conn->fd,"2",2,0); printf("2 sent OK!\n\n"); return; } void SSSSimpleSocketServerTask() { int fd_listen, max_socket; struct sockaddr_in addr; static SSSConn conn; fd_set readfds; if ((fd_listen = socket(AF_INET, SOCK_STREAM, 0)) < 0) { alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE," Socket creation failed"); } addr.sin_family = AF_INET; addr.sin_port = htons(SSS_PORT); //SSS_PORT=30 &#65288;simple_socket_server.h&#65289; addr.sin_addr.s_addr = INADDR_ANY; if ((bind(fd_listen,(struct sockaddr *)&addr,sizeof(addr))) < 0) { alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE," Bind failed"); } if ((listen(fd_listen,1)) < 0) { alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE," Listen failed"); } sss_reset_connection(&conn); printf(" Simple Socket Server listening on port %d\n", SSS_PORT); int cnt=0; sss_handle_accept(fd_listen, &conn); while(1) { sss_handle_receive(&conn); printf("cnt=%d\n\n",++cnt); } /* while(1) */ }
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

The laptop client is written under VC++ 6.0. 

# include <Winsock2.h> # include <stdio.h> void main() { WORD wVersionRequested; WSADATA wsaData; int err; fd_set rfd,wfd; struct timeval timeout; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { return; } if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { WSACleanup( ); return; } char recvBuf; memset(recvBuf,0,100); char sendbuf; memset(recvBuf,0,100); SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=inet_addr("169.254.228.120"); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(30); connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); recv(sockClient,recvBuf,100,0); printf("%s\n\n",recvBuf); int cnt=0; while(1){ cnt++; send(sockClient,"1",2,0); printf("1 sent OK!\n\n"); //Sleep(100); recv(sockClient,recvBuf,2,0); printf("%s\nrecieved OK!\ncnt=%d\n\n",recvBuf,cnt); } closesocket(sockClient); WSACleanup(); }  

 

 

Note: If don't comment the line"Sleep(100);", the loop will not get hanged, but this will cause time loss, and I can't understand why it should be like this.
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

Probably FIFO buffers are filled up... Nios is VERY slow doing ethernet data transmissions, especially when You use InterNiche and RTOS. Don't expect anything more than 10-15Mbps.

0 Kudos
Altera_Forum
Honored Contributor II
661 Views

 

--- Quote Start ---  

Probably FIFO buffers are filled up... Nios is VERY slow doing ethernet data transmissions, especially when You use InterNiche and RTOS. Don't expect anything more than 10-15Mbps. 

--- Quote End ---  

 

 

Thank you for your reply, Socrates. 

For me,10-15Mbps is enough, but the speed is much slower than 1Mbps.(I'm using 1000Mbps & full Duplex mode). 

I ported Benchmark example in AN440 to this hardware design, and found the transmit speed is just 19k/s using TCP. And the transmission can not always get done(sometimes there is send() error).
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

Well... did You turn on optimization for Nios in compile parameters?

0 Kudos
Altera_Forum
Honored Contributor II
661 Views

 

--- Quote Start ---  

Well... did You turn on optimization for Nios in compile parameters? 

--- Quote End ---  

 

 

If you mean "-O3", yes , I turned it on.
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

The best would be -Os, but still, should be fine... Anyway, I see that You're doing TCP connections, when I remembered, that I've tested UDP streams, when reached ~10Mbps. I'd say that it's just too slow to handle such speeds. What's the Nios CPU frequency and how many MIPS does it show?

0 Kudos
Altera_Forum
Honored Contributor II
661 Views

 

--- Quote Start ---  

The best would be -Os, but still, should be fine... Anyway, I see that You're doing TCP connections, when I remembered, that I've tested UDP streams, when reached ~10Mbps. I'd say that it's just too slow to handle such speeds. What's the Nios CPU frequency and how many MIPS does it show? 

--- Quote End ---  

 

 

The Nios CPU frequency is 62.5Mhz; for "many MIPS does it show", I don't know where to check it. 

 

I intend to transmit bmp pictures(about 225kb for each picture), I think it will be cut into smaller packets when transmitting through the net wire, so I choose TCP to guarantee the integrity of the data. 

 

By the way, you mentioned "Probably FIFO buffers are filled up...", in my case, do I need a FIFO buffer larger than 225k(currently, my buffer size is 2048 bytes)?
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

No, because IP packet size is way much smaller, than 225k.The FIFO is inside TSE MAC. Why don't You use UDP? That's a common protocol for image/video streaming.

0 Kudos
Altera_Forum
Honored Contributor II
661 Views

 

--- Quote Start ---  

No, because IP packet size is way much smaller, than 225k.The FIFO is inside TSE MAC. Why don't You use UDP? That's a common protocol for image/video streaming. 

--- Quote End ---  

 

 

Because I think when using UDP, it's not guaranteed that every small packet will be received, and also the data received may not be correct.
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

I use high-definition video transmissions through UDP up to 400Mbps. Even a single packet is not lost on gigabit LAN...

0 Kudos
Altera_Forum
Honored Contributor II
661 Views

Use a tool such as Wireshark on the PC to see what is happening on the Ethernet link. 

One issue I had with TCP connections was that the Nios application couldn't handle the TCP window size it was advertising. The FIFO would get full too fast and some packets would be lost, triggering retransmissions. You see this very well in wireshark, when the connection gets really slow you see lots of red packets with "retransmission" written on them. 

If this is what is happening, then you have two solutions:[list][*]find a way to reduce the TCP window size (probably somewhere in the Interniche TCP/IP stack code)[*]increase the TSE Rx fifo size in SOPC builder/QSys to be at least as big as the TCP window size (32kbytes IIRC).[/list]
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

 

--- Quote Start ---  

Use a tool such as Wireshark on the PC to see what is happening on the Ethernet link. 

One issue I had with TCP connections was that the Nios application couldn't handle the TCP window size it was advertising. The FIFO would get full too fast and some packets would be lost, triggering retransmissions. You see this very well in wireshark, when the connection gets really slow you see lots of red packets with "retransmission" written on them. 

If this is what is happening, then you have two solutions:[list][*]find a way to reduce the TCP window size (probably somewhere in the Interniche TCP/IP stack code)[*]increase the TSE Rx fifo size in SOPC builder/QSys to be at least as big as the TCP window size (32kbytes IIRC).[/list] 

--- Quote End ---  

 

 

In wireshark, I got the red packets as follows: 

 

11 0.218182 169.254.228.129 169.254.228.120 TCP 4858 > 30 Seq=1 Ack=33 Win=65503 Len=0 13 1.814164 169.254.228.129 169.254.228.120 TCP 4858 > 30 Seq=1 Ack=33 Win=65503 Len=2 there are a lot in this kind  

 

I'm sorry, I'm new to wireshark, can you explain me what does these packets mean?
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

yang, 

From your original post I see you are sending 2 byte buffers and wait for the answerback data before the next send. This is really inefficient because: 

- every packet needs to transfer 56bytes for a mere 2 byte data payload, because of Ethernet/IP/TCP protocol headers 

- the tcp protocol overhead will require a complete tcp/ip transaction (3 ethernet packets) for every cycle which only transfers 2 + 2 data bytes 

- you are using the socket connection in a synchronous way, waiting an answer for every request. The dead time between send and recv (due to Nios application, tse MAC and line delays) will prevent the system to achieve the maximum allowed speed 

 

Note that there's no problem with a 2bytes send itself, since the OS can pack bytes coming from multiple calls. The problem is the next receive which blocks until the answer bytes are received. 

You can try this modified code; it should be much more fast: 

 

while(1){  

cnt++; 

 

for (i=0; i<100; i++) { 

send(sockClient,"1",2,0); 

printf("1 sent OK!\n\n"); 

 

 

for (i=0; i<100; i++) { 

recv(sockClient,recvBuf,2,0); 

printf("%s\nrecieved OK!\ncnt=%d\n\n",recvBuf,cnt); 

}
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

 

--- Quote Start ---  

 

while(1){  

cnt++; 

 

for (i=0; i<100; i++) { 

send(sockClient,"1",2,0); 

printf("1 sent OK!\n\n"); 

 

 

for (i=0; i<100; i++) { 

recv(sockClient,recvBuf,2,0); 

printf("%s\nrecieved OK!\ncnt=%d\n\n",recvBuf,cnt); 

--- Quote End ---  

 

 

Thank you for your reply, Cris72 

 

I've tried your code, but it is of no use, the loop stopped when cnt =156. I think it is not a software code efficiency problem.
0 Kudos
Altera_Forum
Honored Contributor II
661 Views

The dup ack and out of order packets seem to indicate that you are indeed loosing packets on the link. 

Do you see any packets with a "window resize" message? If yes try to increase the TSE rx fifo to 32kbytes in SOPC Builder/QSys.
0 Kudos
Reply