aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-10-15 14:52:43 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-16 02:55:21 -0400
commit8306f99a517b91ebf8fa94d017c2c84ca62e107c (patch)
treebbcdfbe08e36290dec053b7a155c5a4320987ee0 /net
parent81204c492b05274ade680c54787cd8ba234dcfd7 (diff)
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')
-rw-r--r--net/tipc/link.c2
-rw-r--r--net/tipc/msg.c31
-rw-r--r--net/tipc/msg.h34
3 files changed, 34 insertions, 33 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2b549f653d80..e7c608631276 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1114,7 +1114,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
1114 1114
1115 /* Defer delivery if sequence gap */ 1115 /* Defer delivery if sequence gap */
1116 if (unlikely(seqno != rcv_nxt)) { 1116 if (unlikely(seqno != rcv_nxt)) {
1117 __tipc_skb_queue_sorted(defq, skb); 1117 __tipc_skb_queue_sorted(defq, seqno, skb);
1118 tipc_link_build_nack_msg(l, xmitq); 1118 tipc_link_build_nack_msg(l, xmitq);
1119 break; 1119 break;
1120 } 1120 }
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:
590 kfree_skb(head); 590 kfree_skb(head);
591 return NULL; 591 return NULL;
592} 592}
593
594/* tipc_skb_queue_sorted(); sort pkt into list according to sequence number
595 * @list: list to be appended to
596 * @seqno: sequence number of buffer to add
597 * @skb: buffer to add
598 */
599void __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno,
600 struct sk_buff *skb)
601{
602 struct sk_buff *_skb, *tmp;
603
604 if (skb_queue_empty(list) || less(seqno, buf_seqno(skb_peek(list)))) {
605 __skb_queue_head(list, skb);
606 return;
607 }
608
609 if (more(seqno, buf_seqno(skb_peek_tail(list)))) {
610 __skb_queue_tail(list, skb);
611 return;
612 }
613
614 skb_queue_walk_safe(list, _skb, tmp) {
615 if (more(seqno, buf_seqno(_skb)))
616 continue;
617 if (seqno == buf_seqno(_skb))
618 break;
619 __skb_queue_before(list, _skb, skb);
620 return;
621 }
622 kfree_skb(skb);
623}
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index a82c5848d4bc..c784ba05f2aa 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -790,6 +790,8 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
790 int offset, int dsz, int mtu, struct sk_buff_head *list); 790 int offset, int dsz, int mtu, struct sk_buff_head *list);
791bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err); 791bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err);
792struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); 792struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list);
793void __tipc_skb_queue_sorted(struct sk_buff_head *list, u16 seqno,
794 struct sk_buff *skb);
793 795
794static inline u16 buf_seqno(struct sk_buff *skb) 796static inline u16 buf_seqno(struct sk_buff *skb)
795{ 797{
@@ -862,38 +864,6 @@ static inline struct sk_buff *tipc_skb_dequeue(struct sk_buff_head *list,
862 return skb; 864 return skb;
863} 865}
864 866
865/* tipc_skb_queue_sorted(); sort pkt into list according to sequence number
866 * @list: list to be appended to
867 * @skb: buffer to add
868 * Returns true if queue should treated further, otherwise false
869 */
870static inline bool __tipc_skb_queue_sorted(struct sk_buff_head *list,
871 struct sk_buff *skb)
872{
873 struct sk_buff *_skb, *tmp;
874 struct tipc_msg *hdr = buf_msg(skb);
875 u16 seqno = msg_seqno(hdr);
876
877 if (skb_queue_empty(list) || (msg_user(hdr) == LINK_PROTOCOL)) {
878 __skb_queue_head(list, skb);
879 return true;
880 }
881 if (likely(less(seqno, buf_seqno(skb_peek(list))))) {
882 __skb_queue_head(list, skb);
883 return true;
884 }
885 if (!more(seqno, buf_seqno(skb_peek_tail(list)))) {
886 skb_queue_walk_safe(list, _skb, tmp) {
887 if (likely(less(seqno, buf_seqno(_skb)))) {
888 __skb_queue_before(list, _skb, skb);
889 return true;
890 }
891 }
892 }
893 __skb_queue_tail(list, skb);
894 return false;
895}
896
897/* tipc_skb_queue_splice_tail - append an skb list to lock protected list 867/* tipc_skb_queue_splice_tail - append an skb list to lock protected list
898 * @list: the new list to append. Not lock protected 868 * @list: the new list to append. Not lock protected
899 * @head: target list. Lock protected. 869 * @head: target list. Lock protected.