|
@@ -161,6 +161,7 @@ struct tipc_link {
|
|
|
struct {
|
|
struct {
|
|
|
u16 len;
|
|
u16 len;
|
|
|
u16 limit;
|
|
u16 limit;
|
|
|
|
|
+ struct sk_buff *target_bskb;
|
|
|
} backlog[5];
|
|
} backlog[5];
|
|
|
u16 snd_nxt;
|
|
u16 snd_nxt;
|
|
|
u16 last_retransm;
|
|
u16 last_retransm;
|
|
@@ -846,6 +847,7 @@ static void link_prepare_wakeup(struct tipc_link *l)
|
|
|
void tipc_link_reset(struct tipc_link *l)
|
|
void tipc_link_reset(struct tipc_link *l)
|
|
|
{
|
|
{
|
|
|
struct sk_buff_head list;
|
|
struct sk_buff_head list;
|
|
|
|
|
+ u32 imp;
|
|
|
|
|
|
|
|
__skb_queue_head_init(&list);
|
|
__skb_queue_head_init(&list);
|
|
|
|
|
|
|
@@ -864,11 +866,10 @@ void tipc_link_reset(struct tipc_link *l)
|
|
|
__skb_queue_purge(&l->transmq);
|
|
__skb_queue_purge(&l->transmq);
|
|
|
__skb_queue_purge(&l->deferdq);
|
|
__skb_queue_purge(&l->deferdq);
|
|
|
__skb_queue_purge(&l->backlogq);
|
|
__skb_queue_purge(&l->backlogq);
|
|
|
- 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_buf);
|
|
|
kfree_skb(l->failover_reasm_skb);
|
|
kfree_skb(l->failover_reasm_skb);
|
|
|
l->reasm_buf = NULL;
|
|
l->reasm_buf = NULL;
|
|
@@ -909,7 +910,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
|
|
|
u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
|
|
u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
|
|
|
struct sk_buff_head *transmq = &l->transmq;
|
|
struct sk_buff_head *transmq = &l->transmq;
|
|
|
struct sk_buff_head *backlogq = &l->backlogq;
|
|
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 pkt_cnt = skb_queue_len(list);
|
|
|
int rc = 0;
|
|
int rc = 0;
|
|
|
|
|
|
|
@@ -955,19 +956,21 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
|
|
|
seqno++;
|
|
seqno++;
|
|
|
continue;
|
|
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));
|
|
kfree_skb(__skb_dequeue(list));
|
|
|
l->stats.sent_bundled++;
|
|
l->stats.sent_bundled++;
|
|
|
continue;
|
|
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));
|
|
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_bundled++;
|
|
|
l->stats.sent_bundles++;
|
|
l->stats.sent_bundles++;
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ l->backlog[imp].target_bskb = NULL;
|
|
|
l->backlog[imp].len += skb_queue_len(list);
|
|
l->backlog[imp].len += skb_queue_len(list);
|
|
|
skb_queue_splice_tail_init(list, backlogq);
|
|
skb_queue_splice_tail_init(list, backlogq);
|
|
|
}
|
|
}
|
|
@@ -983,6 +986,7 @@ static void tipc_link_advance_backlog(struct tipc_link *l,
|
|
|
u16 seqno = l->snd_nxt;
|
|
u16 seqno = l->snd_nxt;
|
|
|
u16 ack = l->rcv_nxt - 1;
|
|
u16 ack = l->rcv_nxt - 1;
|
|
|
u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
|
|
u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1;
|
|
|
|
|
+ u32 imp;
|
|
|
|
|
|
|
|
while (skb_queue_len(&l->transmq) < l->window) {
|
|
while (skb_queue_len(&l->transmq) < l->window) {
|
|
|
skb = skb_peek(&l->backlogq);
|
|
skb = skb_peek(&l->backlogq);
|
|
@@ -993,7 +997,10 @@ static void tipc_link_advance_backlog(struct tipc_link *l,
|
|
|
break;
|
|
break;
|
|
|
__skb_dequeue(&l->backlogq);
|
|
__skb_dequeue(&l->backlogq);
|
|
|
hdr = buf_msg(skb);
|
|
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);
|
|
__skb_queue_tail(&l->transmq, skb);
|
|
|
__skb_queue_tail(xmitq, _skb);
|
|
__skb_queue_tail(xmitq, _skb);
|
|
|
TIPC_SKB_CB(skb)->ackers = l->ackers;
|
|
TIPC_SKB_CB(skb)->ackers = l->ackers;
|