lwip-users
[Top][All Lists]
Advanced

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

Re: [lwip-users] pcb->acked no longer updated in RC1?


From: address@hidden
Subject: Re: [lwip-users] pcb->acked no longer updated in RC1?
Date: Tue, 22 Jan 2008 20:02:25 +0100
User-agent: Thunderbird 2.0.0.9 (Windows/20071031)

Hi,

What you are seeing might just be a change in timing behaviour: You call tcp_write() with the 'copy' argument set to 0:

err = tcp_write(pcb, src, len, 0);

This tells TCP that the data you want to send ('src' in your case) is static, which means it won't get changed while TCP is using it (e.g. when retransmitting). However, this is not the case since you modify it just after ftp_append() returns. The reason it is working better with 'Delay(100)' is that in 100 ms, the data is likely to be sent and acked by the remote host. Then it doesn't matter if you change the contents of your buffer.

Try calling tcp_write() with TCP_WRITE_FLAG_COPY instead of 0 as the last argument. This copies the data into internal buffers where it is kept for retransmission (until acked). This is the recommended setting, by the way!

As to your second question (the one from the subject): the use of the 'acked' field in struct tcp_pcb is internal, as are all other members of this structure: It is strongly discouraged to use them outside of the lwIP core code. Use the callbacks and functions defined in tcp.h, instead! What you are looking for would be the sent callback in tcp_pcb, which informs you how much bytes where acked by the remote host.

Simon

Iordan Neshev schrieb:
Hello :)

I'm developing a ftp client based on the raw API (with callbacks).
It is almost finished and soon will be available for everybody.

I also made a BSD-like sockets API that does not need OS.

I have no real hardware right now, so I'm using the msvc6 port.
I began my work with the cvs from  * 2007-11-01.*

There is a stripped version of the function that sends a stream of data
over a socket :

int SendData(struct tcp_pcb *pcb, const void* src, unsigned int len_arg, unsigned int *progress)
{
    err_t err;
    u16_t len;
unsigned loop_ack;
    /*unsigned*/ int remaining = len_arg;

    while (remaining != 0)
    {
if (tcp_sndbuf(pcb) < remaining) {// We cannot send more data than space available in the send buffer.
            len = tcp_sndbuf(pcb);
            printf("\n sending data in parts of %d bytes\n", len);
        }
        else {
            len = remaining;
printf("\n sending all %d bytes at once,they fit in tcp_sndbuf==%d :) \n\n", len, tcp_sndbuf(pcb));
        }
// try to send len bytes in this loop
        do
        {
timers_update(); // handle timers (done in tcpip.c when OS present)
            update_adapter();    //  check for packets

            *tcp_output(pcb); *   // prompt the system to send data now

err = tcp_write(pcb, src, len, 0); // to do: if (err != ERR_OK) { ... retry?}

            tcp_output(pcb);// prompt the system to send data now
timers_update(); update_adapter(); if (err == ERR_MEM) {
                len /= 2;
            }
printf("\n Bytes ACKed by peer: %d ", pcb->acked); /// !!!!! } while (err == ERR_MEM && len > 1); // run timers until peer acknowledges all bytes
        loop_ack = LOOPS_ACK_WAIT;    // defined as 100 for example
        *while  (pcb->acked < len)*
        {
timers_update(); update_adapter();
            printf("\nACKed: %d", pcb->acked);
if(pcb->acked == 0) // this happens when remote host closes connection
            {
                // is this indication of a closing connection?
if (((pcb->state) > ESTABLISHED) || ((pcb->state) == CLOSED))// waiting to close connection or already close
                    break;
// no, I have to wait... if (!loop_ack--){ printf("\n exit by timeout\7\n");
                    break;
                }
            }
}
        // now len should be == pcb->acked

        printf("\n sent (maybe in parts)  %d bytes\n\n ", len);
    //...
        remaining -= len;
        // len bytes sent
      ......
    } //while (remaining != 0)
    printf("\n everything is now sent ) -->  [%s]\n\n", src);

    return ERR_OK;
}

Then I made the following test:
{
//... open control connection with server
//... login, open file, open data connection, et..
    for (i = 0; i < 100; i++)    {
        sprintf(databuf, "[%d]", i);
ftp_append(ctrl_s, data_s, databuf, strlen(databuf)); // this uses int SendData()
   }
}

This works fine, peer acknowledges all bytes, the contents of the uploaded file are as expected:
[0][1][2][3][4][5][6][7][8] ..... [99]


Recently I updated the stack to RC1 and observed quite strange results.
First, the data is corrupted, the file now contains something like
[0][2][2][4][5][5][6][8][9][10][10][11][12][14][16][16][17][17][18][20]....

Some packets are dropped, other are dupplicated

I was trying different situations with putting tcp_output(pcb); and running the timers
in different places. Sometimes the file contained just parts of a packet:
[0][2]]4]5][5][6]8][9][1...

When I make a simple delay  between the packets
(with no calls to timers_update(); and update_adapter(); in the Delay loop)

    for (i = 0; i < 100; i++)    {
        sprintf(databuf, "[%d]", i);
ftp_append(ctrl_s, data_s, databuf, strlen(databuf)); // this uses int SendData()
    Delay(100); // 100 milliseconds
   }
things get better
100ms -> results are better
200ms -> almost perfect
>300 ms -> no corruption

I thouht the problem is due to retransmision of packets.

I noticed that the queue gets full, so I inserted another loop that runs the timers until the queue is
empty again, but this did not solve the problem :(

I think that there may be mistmatch of sequence numbers of retransmitted packets (maybe they are incremented
when they should not be?)
I dont know why some of the packets are not received at all.

There is also something else which may be the key to the problem:

with RC1 I do not receive ACKs by the server !!!

this line: printf("\n Bytes ACKed by peer: %d ", pcb->acked);  /// !!!!!
in the older release showed exactly how many bytes are acknowledged
As you can see, I don't call tcp_output(pcb);  before I get
Ack of my "len" bytes.
      while  (pcb->acked < len)
        {
            timers_update();         update_adapter();
            printf("\nACKed: %d", pcb->acked);
            ........
if(pcb->acked == 0) // this happens when remote host closes connection if (!loop_ack--){ printf("\n exit by timeout\7\n");
                    break;
                }
            }
}
I never get ACK and the loop is exited by the timeout.
pcb->acked  stays 0 forever and so does pcb->unacked

This retry-loop_ack-times loop worked well before RC1.

there is a part of the debug messages:

sending [[0]
]tcp_write(pcb=00917CE8, data=00129794, len=4, apiflags=0)
tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0)
tcp_enqueue: queuelen: 0
tcp_enqueue: queueing 6537:6541 (0x0)
tcp_enqueue: 2 (after enqueued)
tcp_output_segment: rtseq 6537
tcp_output_segment: 6537:6541

 Bytes ACKed by peer: 0
SendDataNoPayload():ACKed: 0
 exit by timeout
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 sent (maybe partial)  4 byte

===================================================================
sending this:

[[1]
]tcp_write(pcb=00917CE8, data=00129794, len=4, apiflags=0)
tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0)
tcp_enqueue: queuelen: 2
tcp_enqueue: queueing 6541:6545 (0x0)
tcp_enqueue: 4 (after enqueued)

 Bytes ACKed by peer: 0
SendDataNoPayload():ACKed: 0
 exit by timeout
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 sent (maybe partial)  4 bytes
===================================================================
sending throug socket 1, pcb 0x917CE8 ...
 sending this:

[[2]
]tcp_write(pcb=00917CE8, data=00129794, len=4, apiflags=0)
tcp_enqueue(pcb=00917CE8, arg=00129794, len=4, flags=0, apiflags=0)
tcp_enqueue: queuelen: 4
tcp_enqueue: queueing 6545:6549 (0x0)
tcp_enqueue: chaining segments, new len 8
tcp_enqueue: 6 (after enqueued)
tcp_receive: queuelen 6 ... 4 (after freeing unacked)
tcp_receive: pcb->rttest 13 rtseq 6537 ackno 6541
tcp_receive: experienced rtt 1 ticks (500 msec).
tcp_receive: RTO 6 (3000 milliseconds)

 Data [4] successfully sent over socket 1 CB_active_sent, len = 4
 tcp_output_segment: rtseq 6541
tcp_output_segment: 6541:6549
tcp_receive: pcb->rttest 14 rtseq 6541 ackno 6541

.....



Any suggestions?

Regards
Iordan Neshev
Daisy Technology

------------------------------------------------------------------------

_______________________________________________
lwip-users mailing list
address@hidden
http://lists.nongnu.org/mailman/listinfo/lwip-users
------------------------------------------------------------------------

No virus found in this incoming message.
Checked by AVG Free Edition. Version: 7.5.516 / Virus Database: 269.19.9/1237 - Release Date: 22.01.2008 11:04





reply via email to

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