Re: PPP and 1.3.83 - even WORSE!

Linus Torvalds (torvalds@cs.helsinki.fi)
Thu, 4 Apr 1996 07:37:03 +0300 (EET DST)


On Thu, 4 Apr 1996, David Monro wrote:
>
> I just tried upgrading to 1.3.83, and tried a couple of transfers. On a
> 14.4k link I should (and used to) get 1.5 kB/s. With 1.3.82 I get 0.9,
> with 1.3.83 I get 0.23! (This is on a 68Kb file). I think we are going
> to see a storm of complaints about this one ;-(

That's _very_ interesting. Because 83 has only one very minimal patch to
the network code, and that patch shouldn't even trigger under normal
circumstances (it's only triggered when the receive queue allocation
grows beyond the allowed queue length - which shouldn't happen if the
sender sends sane packets within the window).

Even worse, the 83 patch actually has a bug that should probably crash
the machine if the new code is ever triggered ;-)

I'm including the fix for this bug, but I don't think it's responsible: I
really think you would see much worse problems than just bad throughput
if this bug was ever triggered. I'll take a closer look at the TCP dumps
soon, maybe that gives me some idea.

One thing that I'm starting to suspect is simply a timing issue: the new
code since 1.3.73 has been doing the ACK's from within the timer bottom
half handler, asynchronously from the actual network code. Now, if there
is a race within the slhc compression, it would be triggered a lot more
easily thanks to the more asynchronous network behaviour.

Thanks,
Linus

----------
--- v1.3.83/linux/net/ipv4/tcp_input.c Wed Apr 3 16:06:57 1996
+++ linux/net/ipv4/tcp_input.c Wed Apr 3 22:00:35 1996
@@ -1487,6 +1487,7 @@
if (skb->acked)
break;
__skb_unlink(skb, list);
+ kfree_skb(skb, FREE_READ);
}
}

@@ -1501,20 +1502,24 @@
{
struct sk_buff * skb = list->next;

- for (;;) {
- struct sk_buff * next;
+ if (skb != (struct sk_buff *) list) {
+ for (;;) {
+ struct sk_buff * next;

- if (skb == (struct sk_buff *) list)
- break;
- next = skb->next;
- if (next->seq == skb->seq) {
+ next = skb->next;
+ if (next == (struct sk_buff *) list)
+ break;
if (before(next->end_seq, skb->end_seq)) {
__skb_unlink(next, list);
+ kfree_skb(next, FREE_READ);
continue;
}
- __skb_unlink(skb, list);
+ if (next->seq == skb->seq) {
+ __skb_unlink(skb, list);
+ kfree_skb(skb, FREE_READ);
+ }
+ skb = next;
}
- skb = next;
}
}

----------