diff options
-rw-r--r-- | net/tipc/link.c | 26 | ||||
-rw-r--r-- | net/tipc/msg.h | 21 |
2 files changed, 37 insertions, 10 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 5aee1ed23ba9..1f2cde0d025f 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -209,6 +209,7 @@ enum { | |||
209 | }; | 209 | }; |
210 | 210 | ||
211 | #define TIPC_BC_RETR_LIM msecs_to_jiffies(10) /* [ms] */ | 211 | #define TIPC_BC_RETR_LIM msecs_to_jiffies(10) /* [ms] */ |
212 | #define TIPC_UC_RETR_TIME (jiffies + msecs_to_jiffies(1)) | ||
212 | 213 | ||
213 | /* | 214 | /* |
214 | * Interval between NACKs when packets arrive out of order | 215 | * Interval between NACKs when packets arrive out of order |
@@ -1305,6 +1306,10 @@ next_gap_ack: | |||
1305 | kfree_skb(skb); | 1306 | kfree_skb(skb); |
1306 | } else if (less_eq(seqno, acked + gap)) { | 1307 | } else if (less_eq(seqno, acked + gap)) { |
1307 | /* retransmit skb */ | 1308 | /* retransmit skb */ |
1309 | if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr)) | ||
1310 | continue; | ||
1311 | TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME; | ||
1312 | |||
1308 | _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC); | 1313 | _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC); |
1309 | if (!_skb) | 1314 | if (!_skb) |
1310 | continue; | 1315 | continue; |
@@ -1380,6 +1385,7 @@ static int tipc_link_build_nack_msg(struct tipc_link *l, | |||
1380 | struct sk_buff_head *xmitq) | 1385 | struct sk_buff_head *xmitq) |
1381 | { | 1386 | { |
1382 | u32 def_cnt = ++l->stats.deferred_recv; | 1387 | u32 def_cnt = ++l->stats.deferred_recv; |
1388 | u32 defq_len = skb_queue_len(&l->deferdq); | ||
1383 | int match1, match2; | 1389 | int match1, match2; |
1384 | 1390 | ||
1385 | if (link_is_bc_rcvlink(l)) { | 1391 | if (link_is_bc_rcvlink(l)) { |
@@ -1390,7 +1396,7 @@ static int tipc_link_build_nack_msg(struct tipc_link *l, | |||
1390 | return 0; | 1396 | return 0; |
1391 | } | 1397 | } |
1392 | 1398 | ||
1393 | if ((skb_queue_len(&l->deferdq) == 1) || !(def_cnt % TIPC_NACK_INTV)) | 1399 | if (defq_len >= 3 && !((defq_len - 3) % 16)) |
1394 | tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, 0, xmitq); | 1400 | tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, 0, xmitq); |
1395 | return 0; | 1401 | return 0; |
1396 | } | 1402 | } |
@@ -1404,29 +1410,29 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1404 | struct sk_buff_head *xmitq) | 1410 | struct sk_buff_head *xmitq) |
1405 | { | 1411 | { |
1406 | struct sk_buff_head *defq = &l->deferdq; | 1412 | struct sk_buff_head *defq = &l->deferdq; |
1407 | struct tipc_msg *hdr; | 1413 | struct tipc_msg *hdr = buf_msg(skb); |
1408 | u16 seqno, rcv_nxt, win_lim; | 1414 | u16 seqno, rcv_nxt, win_lim; |
1409 | int rc = 0; | 1415 | int rc = 0; |
1410 | 1416 | ||
1417 | /* Verify and update link state */ | ||
1418 | if (unlikely(msg_user(hdr) == LINK_PROTOCOL)) | ||
1419 | return tipc_link_proto_rcv(l, skb, xmitq); | ||
1420 | |||
1421 | /* Don't send probe at next timeout expiration */ | ||
1422 | l->silent_intv_cnt = 0; | ||
1423 | |||
1411 | do { | 1424 | do { |
1412 | hdr = buf_msg(skb); | 1425 | hdr = buf_msg(skb); |
1413 | seqno = msg_seqno(hdr); | 1426 | seqno = msg_seqno(hdr); |
1414 | rcv_nxt = l->rcv_nxt; | 1427 | rcv_nxt = l->rcv_nxt; |
1415 | win_lim = rcv_nxt + TIPC_MAX_LINK_WIN; | 1428 | win_lim = rcv_nxt + TIPC_MAX_LINK_WIN; |
1416 | 1429 | ||
1417 | /* Verify and update link state */ | ||
1418 | if (unlikely(msg_user(hdr) == LINK_PROTOCOL)) | ||
1419 | return tipc_link_proto_rcv(l, skb, xmitq); | ||
1420 | |||
1421 | if (unlikely(!link_is_up(l))) { | 1430 | if (unlikely(!link_is_up(l))) { |
1422 | if (l->state == LINK_ESTABLISHING) | 1431 | if (l->state == LINK_ESTABLISHING) |
1423 | rc = TIPC_LINK_UP_EVT; | 1432 | rc = TIPC_LINK_UP_EVT; |
1424 | goto drop; | 1433 | goto drop; |
1425 | } | 1434 | } |
1426 | 1435 | ||
1427 | /* Don't send probe at next timeout expiration */ | ||
1428 | l->silent_intv_cnt = 0; | ||
1429 | |||
1430 | /* Drop if outside receive window */ | 1436 | /* Drop if outside receive window */ |
1431 | if (unlikely(less(seqno, rcv_nxt) || more(seqno, win_lim))) { | 1437 | if (unlikely(less(seqno, rcv_nxt) || more(seqno, win_lim))) { |
1432 | l->stats.duplicates++; | 1438 | l->stats.duplicates++; |
@@ -1457,7 +1463,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1457 | rc |= tipc_link_build_state_msg(l, xmitq); | 1463 | rc |= tipc_link_build_state_msg(l, xmitq); |
1458 | if (unlikely(rc & ~TIPC_LINK_SND_STATE)) | 1464 | if (unlikely(rc & ~TIPC_LINK_SND_STATE)) |
1459 | break; | 1465 | break; |
1460 | } while ((skb = __skb_dequeue(defq))); | 1466 | } while ((skb = __tipc_skb_dequeue(defq, l->rcv_nxt))); |
1461 | 1467 | ||
1462 | return rc; | 1468 | return rc; |
1463 | drop: | 1469 | drop: |
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index ec5c511a9c9c..8de02ad6e352 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -1151,4 +1151,25 @@ static inline void tipc_skb_queue_splice_tail_init(struct sk_buff_head *list, | |||
1151 | tipc_skb_queue_splice_tail(&tmp, head); | 1151 | tipc_skb_queue_splice_tail(&tmp, head); |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | /* __tipc_skb_dequeue() - dequeue the head skb according to expected seqno | ||
1155 | * @list: list to be dequeued from | ||
1156 | * @seqno: seqno of the expected msg | ||
1157 | * | ||
1158 | * returns skb dequeued from the list if its seqno is less than or equal to | ||
1159 | * the expected one, otherwise the skb is still hold | ||
1160 | * | ||
1161 | * Note: must be used with appropriate locks held only | ||
1162 | */ | ||
1163 | static inline struct sk_buff *__tipc_skb_dequeue(struct sk_buff_head *list, | ||
1164 | u16 seqno) | ||
1165 | { | ||
1166 | struct sk_buff *skb = skb_peek(list); | ||
1167 | |||
1168 | if (skb && less_eq(buf_seqno(skb), seqno)) { | ||
1169 | __skb_unlink(skb, list); | ||
1170 | return skb; | ||
1171 | } | ||
1172 | return NULL; | ||
1173 | } | ||
1174 | |||
1154 | #endif | 1175 | #endif |