lwip-users
[Top][All Lists]
Advanced

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

Re: [lwip-users] snd_queuelen does not count the number of segments...


From: Kieran Mansley
Subject: Re: [lwip-users] snd_queuelen does not count the number of segments...
Date: Wed, 29 Nov 2006 08:55:32 +0000

On Tue, 2006-11-28 at 13:48 -0500, Tom Hennen wrote:
> I think there's been some miscommunication.  But it's helped me to get
> a better handle on what is going on.
>  
> When I'm queuing packets I'm actually queuing *outgoing* packets (and
> I'm not using any threading).  The problem that I've described pops up
> during tcp retransmissions.
>  
> Imagine this scenario:
>  
> 1. TCP sends segments A B C, incrementing pcb->snd_queuelen by 3
> 2. The link layer queues A B and C, so they all form one long pbuf
> chain
> 3. The link layer sends A B and C, removing them from the queue,
> so A B and C are no longer chained
> 4. No ACK has arrived for A B and C yet and so tcp_rexmit_rto
> moves A B and C from the unacked list to the unsent list
> 5. tcp_output then moves A B and C from the unsent list back to the
> unacked list and then sends the packets via ip_output
> 6. The link layer queues A B and C, forming one long pbuf chain (NOTE:
> the packets have not yet been transmitted)
> 7. An ACK arrives for segment A
> 8. tcp_receive decrements pcb->snd_queuelen by pbuf_clen(A)
> 8a. since A B and C are still queued in the link layer the chain
> length is 3 instead of 1, thus pcb->snd_queuelen is decremented by 3
> instead of the correct value of 1.
> 9. An ACK arrives for segment B
> 10. tcp_receive decrements pcb->snd_queuelen by pbuf_clen(B)
> 10a. since A B and C are still queued in the link layer the chain
> length is 2 instead of 1, thus pcb->snd_queuelen is decremented by 2
> instead of the correct value of 1.  At this point pcb->snd_queuelen is
> -1(or 255) instead of 1.
>  
> So the packet queuing by the link layer combines with a subtle TCP
> timing issue to cause this problem.  If the link layer didn't queue
> packets, or if it could transmit the packets faster, this wouldn't
> occur.
>  
> So, how should this problem be resolved?  Should I be able to use pbuf
> queues for outgoing packets in the link layer?  If so, then I would
> think tcp should use something other than pbuf_clen to determine how
> many pbufs to decrement snd_queuelen by.

Ahh, apologies for misunderstanding you.  I think by using pbuf_queue()
you are essentially corrupting the internal state in lwIP.  pbuf_queue()
modifies the next pointer in the pbuf, but this is already being used
(for the unsent/unacked lists) at the time you are modifying it.  Our
pbuf queues/lists/chains only support the pbuf being in one
queue/list/chain at once, and by adding it to another you're breaking
that assumption.

To resolve it, one solution would be to create yourself a little link-
layer container structure for a pbuf:

struct link_pbuf {
  struct link_pbuf *next;
  struct pbuf *p;
}

Then you can use this next pointer to queue them up however you like
internally to the link layer without risk of corrupting the higher
layers.

Kieran





reply via email to

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