Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12745 Discussions

Why is sending tcp so much slower than receiving?

Altera_Forum
Honored Contributor II
1,410 Views

I have some code running under uC-OS that receives a file via TCP and then writes it to flash. This is very quick, a 4MB file is received in 20 seconds or so. I then have another piece of code that dumps the content of flash via TCP. This is extremely slow, it takes at least 20 minutes to send all 16MB. Here's the code: 

 

void send_flash_data(struct tcp_pcb * tpcb, alt_u32 * offset) {  err_t err;  alt_u32 send_data_length = EXT_FLASH_BASE + EXT_FLASH_SIZE - *offset;  INT8U error_code;    //printf("send_data_length: %d\n", send_data_length);    if ( send_data_length > 0 ) //data left to send  {    if ( send_data_length > 1400 )    {      send_data_length = 1400;    }    //printf("Sending %d bytes from %08x\n", send_data_length, EXT_FLASH_BASE + *offset);        err = tcp_write(tpcb, (void *)(EXT_FLASH_BASE + *offset), send_data_length, 0);    *offset += send_data_length;        }  else  {    tcp_arg(tpcb, NULL);    tcp_sent(tpcb, NULL);    tcp_close(tpcb);    error_code = OSQPost(TcpTransmissionDoneQ, 4194304);        alt_SSSErrorHandler(error_code, 0);      } } err_t flash_data_sent(void * arg, struct tcp_pcb * tpcb, alt_u16 len) {  //printf("%d bytes acknowledged\n", len);  send_flash_data(tpcb, arg); } err_t tcp_connected(void * arg, struct tcp_pcb * tpcb, err_t err) {  if ( err == ERR_OK )  {    send_flash_data(tpcb, arg);  }  else  {    printf("tcp_connected called with error value %d\n", err);    tcp_arg(tpcb, NULL);    tcp_sent(tpcb, NULL);    tcp_close(tpcb);  } } void dump_flash(void * arg) {  struct ip_addr ip;  IP4_ADDR(&ip, lwip_config.remote_ip_0, lwip_config.remote_ip_1, lwip_config.remote_ip_2, lwip_config.remote_ip_3);    tcp_snd_pcb = tcp_new();  tcp_arg(tcp_snd_pcb, arg);  tcp_sent(tcp_snd_pcb, flash_data_sent);  tcp_connect(tcp_snd_pcb, &ip, lwip_config.rule_receive_tcp_port, tcp_connected);   }
0 Kudos
6 Replies
Altera_Forum
Honored Contributor II
604 Views

Any ideas?

0 Kudos
Altera_Forum
Honored Contributor II
604 Views

 

--- Quote Start ---  

originally posted by bkucera@Jul 19 2006, 10:28 AM 

any ideas? 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=17019) 

--- quote end ---  

 

--- Quote End ---  

 

 

Have you tried profiling your code? Also, you&#39;re using uC-OSII with the raw LWIP API, right? Any reason you&#39;re not using the sockets-based API? Hopefully, you&#39;re not mixing the two, as I get the feeling that this would be a bad idea :-) 

 

With the drastically longer times you&#39;re seeing, I&#39;d expect that you&#39;re hitting timeouts and resends all over the place. Have you monitored your traffic, with something like ethereal to see what&#39;s happening? 

 

Cheers, 

 

- slacker
0 Kudos
Altera_Forum
Honored Contributor II
604 Views

 

--- Quote Start ---  

originally posted by slacker+jul 19 2006, 05:23 pm--><div class='quotetop'>quote (slacker @ jul 19 2006, 05:23 pm)</div> 

--- quote start ---  

<!--quotebegin-bkucera@Jul 19 2006, 10:28 AM 

any ideas? 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=17019) 

--- quote end ---  

 

--- Quote End ---  

 

 

Have you tried profiling your code? Also, you&#39;re using uC-OSII with the raw LWIP API, right? Any reason you&#39;re not using the sockets-based API? Hopefully, you&#39;re not mixing the two, as I get the feeling that this would be a bad idea :-) 

 

With the drastically longer times you&#39;re seeing, I&#39;d expect that you&#39;re hitting timeouts and resends all over the place. Have you monitored your traffic, with something like ethereal to see what&#39;s happening? 

 

Cheers, 

 

- slacker 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=17020)</div> 

[/b] 

--- Quote End ---  

 

 

I am using uC-OSII, yes. No particular reason to use the raw API, just seemed easiest to do it this way. I haven&#39;t tried profiling it because I don&#39;t know how. I did monitor the traffic with ethereal and didn&#39;t see anything odd, but I&#39;ll look at it again and post back with what I find.
0 Kudos
Altera_Forum
Honored Contributor II
604 Views

 

--- Quote Start ---  

originally posted by bkucera@Jul 26 2006, 03:56 PM 

i am using uc-osii, yes. no particular reason to use the raw api, just seemed easiest to do it this way. i haven&#39;t tried profiling it because i don&#39;t know how. i did monitor the traffic with ethereal and didn&#39;t see anything odd, but i&#39;ll look at it again and post back with what i find. 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=17154) 

--- quote end ---  

 

--- Quote End ---  

 

 

I don&#39;t think that using the raw API is tested in combination with uC-OSII. I&#39;d advise trying the sockets based API, as it is supported. 

 

The raw API is intended for single-threaded systems. 

 

Cheers, 

 

- slacker
0 Kudos
Altera_Forum
Honored Contributor II
604 Views

I think the problem is, that when you call tcp_write with only 1400Bytes of data, the Nagle-algorithm keeps the segment (which is not full) from being sent immediatly. One way of solving the problem is disabling the Nagle-algorithm by setting the TF_NODELAY, the other (better) way is to call tcp_write with the size that tcp_sndbuf returns.  

 

Greetings 

Laplace
0 Kudos
Altera_Forum
Honored Contributor II
604 Views

 

--- Quote Start ---  

originally posted by laplace@Jul 28 2006, 04:22 AM 

i think the problem is, that when you call tcp_write with only 1400bytes of data, the nagle-algorithm keeps the segment (which is not full) from being sent immediatly. one way of solving the problem is disabling the nagle-algorithm by setting the tf_nodelay, the other (better) way is to call tcp_write with the size that tcp_sndbuf returns.  

 

greetings 

laplace 

<div align='right'><{post_snapback}> (index.php?act=findpost&pid=17221) 

--- quote end ---  

 

--- Quote End ---  

 

 

Ha, I think you&#39;re right. The source code mentions that tcp_output should be called after tcp_write to force the data to be sent now. The raw_api.txt file doesn&#39;t mention that. I had been doing 1400 bytes before because tcp_sndbuf returns something like 32768 bytes. I didn&#39;t realize it would break it up for me and send it out.  

 

I&#39;ll look into using the sockets API when I rewrite this whole mess though. Right now it&#39;s a heavily modified version of the simple socket server and it could use a ground-up refactoring. 

 

Thanks!
0 Kudos
Reply