diff options
author | Jon Paul Maloy <jon.maloy@ericsson.com> | 2015-10-15 21:52:43 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-16 09:55:21 +0300 |
commit | 8306f99a517b91ebf8fa94d017c2c84ca62e107c (patch) | |
tree | bbcdfbe08e36290dec053b7a155c5a4320987ee0 /net/tipc/msg.c | |
parent | 81204c492b05274ade680c54787cd8ba234dcfd7 (diff) | |
download | linux-8306f99a517b91ebf8fa94d017c2c84ca62e107c.tar.xz |
tipc: disallow packet duplicates in link deferred queue
After the previous commits, we are guaranteed that no packets
of type LINK_PROTOCOL or with illegal sequence numbers will be
attempted added to the link deferred queue. This makes it possible to
make some simplifications to the sorting algorithm in the function
tipc_skb_queue_sorted().
We also alter the function so that it will drop packets if one with
the same seqeunce number is already present in the queue. This is
necessary because we have identified weird packet sequences, involving
duplicate packets, where a legitimate in-sequence packet may advance to
the head of the queue without being detected and de-queued.
Finally, we make this function outline, since it will now be called only
in exceptional cases.
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r-- | net/tipc/msg.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index c5ac436235e0..454f5ec275c8 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -590,3 +590,34 @@ error: kfree_skb(head); return NULL; } + +/* tipc_skb_queue_sorted(); sort pkt into list according to sequence number + * @list: list to be appended to + * @seqno: sequence number of buffer to add + * @skb: buffer to add + */ +void __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno, + struct sk_buff *skb) +{ + struct sk_buff *_skb, *tmp; + + if (skb_queue_empty(list) || less(seqno, buf_seqno(skb_peek(list)))) { + __skb_queue_head(list, skb); + return; + } + + if (more(seqno, buf_seqno(skb_peek_tail(list)))) { + __skb_queue_tail(list, skb); + return; + } + + skb_queue_walk_safe(list, _skb, tmp) { + if (more(seqno, buf_seqno(_skb))) + continue; + if (seqno == buf_seqno(_skb)) + break; + __skb_queue_before(list, _skb, skb); + return; + } + kfree_skb(skb); +} |