lwip-users
[Top][All Lists]
Advanced

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

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


From: Iordan Neshev
Subject: [lwip-users] pcb->acked no longer updated in RC1?
Date: Tue, 22 Jan 2008 16:03:10 +0100
User-agent: Thunderbird 1.5.0.12 (Windows/20070509)

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="" 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="" 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="" 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


reply via email to

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