diff options
Diffstat (limited to 'net/tipc/link.c')
| -rw-r--r-- | net/tipc/link.c | 29 | 
1 files changed, 18 insertions, 11 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 6cc75ffd9e2c..999eab592de8 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -160,6 +160,7 @@ struct tipc_link {  	struct {  		u16 len;  		u16 limit; +		struct sk_buff *target_bskb;  	} backlog[5];  	u16 snd_nxt;  	u16 window; @@ -880,6 +881,7 @@ static void link_prepare_wakeup(struct tipc_link *l)  void tipc_link_reset(struct tipc_link *l)  {  	struct sk_buff_head list; +	u32 imp;  	__skb_queue_head_init(&list); @@ -901,11 +903,10 @@ void tipc_link_reset(struct tipc_link *l)  	__skb_queue_purge(&l->deferdq);  	__skb_queue_purge(&l->backlogq);  	__skb_queue_purge(&l->failover_deferdq); -	l->backlog[TIPC_LOW_IMPORTANCE].len = 0; -	l->backlog[TIPC_MEDIUM_IMPORTANCE].len = 0; -	l->backlog[TIPC_HIGH_IMPORTANCE].len = 0; -	l->backlog[TIPC_CRITICAL_IMPORTANCE].len = 0; -	l->backlog[TIPC_SYSTEM_IMPORTANCE].len = 0; +	for (imp = 0; imp <= TIPC_SYSTEM_IMPORTANCE; imp++) { +		l->backlog[imp].len = 0; +		l->backlog[imp].target_bskb = NULL; +	}  	kfree_skb(l->reasm_buf);  	kfree_skb(l->reasm_tnlmsg);  	kfree_skb(l->failover_reasm_skb); @@ -947,7 +948,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,  	u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;  	struct sk_buff_head *transmq = &l->transmq;  	struct sk_buff_head *backlogq = &l->backlogq; -	struct sk_buff *skb, *_skb, *bskb; +	struct sk_buff *skb, *_skb, **tskb;  	int pkt_cnt = skb_queue_len(list);  	int rc = 0; @@ -999,19 +1000,21 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,  			seqno++;  			continue;  		} -		if (tipc_msg_bundle(skb_peek_tail(backlogq), hdr, mtu)) { +		tskb = &l->backlog[imp].target_bskb; +		if (tipc_msg_bundle(*tskb, hdr, mtu)) {  			kfree_skb(__skb_dequeue(list));  			l->stats.sent_bundled++;  			continue;  		} -		if (tipc_msg_make_bundle(&bskb, hdr, mtu, l->addr)) { +		if (tipc_msg_make_bundle(tskb, hdr, mtu, l->addr)) {  			kfree_skb(__skb_dequeue(list)); -			__skb_queue_tail(backlogq, bskb); -			l->backlog[msg_importance(buf_msg(bskb))].len++; +			__skb_queue_tail(backlogq, *tskb); +			l->backlog[imp].len++;  			l->stats.sent_bundled++;  			l->stats.sent_bundles++;  			continue;  		} +		l->backlog[imp].target_bskb = NULL;  		l->backlog[imp].len += skb_queue_len(list);  		skb_queue_splice_tail_init(list, backlogq);  	} @@ -1027,6 +1030,7 @@ static void tipc_link_advance_backlog(struct tipc_link *l,  	u16 seqno = l->snd_nxt;  	u16 ack = l->rcv_nxt - 1;  	u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1; +	u32 imp;  	while (skb_queue_len(&l->transmq) < l->window) {  		skb = skb_peek(&l->backlogq); @@ -1037,7 +1041,10 @@ static void tipc_link_advance_backlog(struct tipc_link *l,  			break;  		__skb_dequeue(&l->backlogq);  		hdr = buf_msg(skb); -		l->backlog[msg_importance(hdr)].len--; +		imp = msg_importance(hdr); +		l->backlog[imp].len--; +		if (unlikely(skb == l->backlog[imp].target_bskb)) +			l->backlog[imp].target_bskb = NULL;  		__skb_queue_tail(&l->transmq, skb);  		/* next retransmit attempt */  		if (link_is_bc_sndlink(l))  | 
