Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

l2tp: fix reorder timeout recovery

When L2TP data packet reordering is enabled, packets are held in a
queue while waiting for out-of-sequence packets. If a packet gets
lost, packets will be held until the reorder timeout expires, when we
are supposed to then advance to the sequence number of the next packet
but we don't currently do so. As a result, the data channel is stuck
because we are waiting for a packet that will never arrive - all
packets age out and none are passed.

The fix is to add a flag to the session context, which is set when the
reorder timeout expires and tells the receive code to reset the next
expected sequence number to that of the next packet in the queue.

Tested in a production L2TP network with Starent and Nortel L2TP gear.

Signed-off-by: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

James Chapman and committed by
David S. Miller
38d40b3f 1070b1b8

+10
+9
net/l2tp/l2tp_core.c
··· 428 428 session->name, L2TP_SKB_CB(skb)->ns, 429 429 L2TP_SKB_CB(skb)->length, session->nr, 430 430 skb_queue_len(&session->reorder_q)); 431 + session->reorder_skip = 1; 431 432 __skb_unlink(skb, &session->reorder_q); 432 433 kfree_skb(skb); 433 434 if (session->deref) ··· 437 436 } 438 437 439 438 if (L2TP_SKB_CB(skb)->has_seq) { 439 + if (session->reorder_skip) { 440 + PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, 441 + "%s: advancing nr to next pkt: %u -> %u", 442 + session->name, session->nr, 443 + L2TP_SKB_CB(skb)->ns); 444 + session->reorder_skip = 0; 445 + session->nr = L2TP_SKB_CB(skb)->ns; 446 + } 440 447 if (L2TP_SKB_CB(skb)->ns != session->nr) { 441 448 PRINTK(session->debug, L2TP_MSG_SEQ, KERN_DEBUG, 442 449 "%s: holding oos pkt %u len %d, "
+1
net/l2tp/l2tp_core.h
··· 123 123 * categories */ 124 124 int reorder_timeout; /* configured reorder timeout 125 125 * (in jiffies) */ 126 + int reorder_skip; /* set if skip to next nr */ 126 127 int mtu; 127 128 int mru; 128 129 enum l2tp_pwtype pwtype;