aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index ad356df12d1e..02b083e5c219 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -2406,6 +2406,8 @@ void tipc_link_recv_bundle(struct sk_buff *buf)
2406 */ 2406 */
2407static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) 2407static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
2408{ 2408{
2409 struct sk_buff *buf_chain = NULL;
2410 struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain;
2409 struct tipc_msg *inmsg = buf_msg(buf); 2411 struct tipc_msg *inmsg = buf_msg(buf);
2410 struct tipc_msg fragm_hdr; 2412 struct tipc_msg fragm_hdr;
2411 u32 insize = msg_size(inmsg); 2413 u32 insize = msg_size(inmsg);
@@ -2414,7 +2416,7 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
2414 u32 rest = insize; 2416 u32 rest = insize;
2415 u32 pack_sz = l_ptr->max_pkt; 2417 u32 pack_sz = l_ptr->max_pkt;
2416 u32 fragm_sz = pack_sz - INT_H_SIZE; 2418 u32 fragm_sz = pack_sz - INT_H_SIZE;
2417 u32 fragm_no = 1; 2419 u32 fragm_no = 0;
2418 u32 destaddr; 2420 u32 destaddr;
2419 2421
2420 if (msg_short(inmsg)) 2422 if (msg_short(inmsg))
@@ -2426,9 +2428,6 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
2426 2428
2427 tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, 2429 tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
2428 INT_H_SIZE, destaddr); 2430 INT_H_SIZE, destaddr);
2429 msg_set_long_msgno(&fragm_hdr, l_ptr->long_msg_seq_no++);
2430 msg_set_fragm_no(&fragm_hdr, fragm_no);
2431 l_ptr->stats.sent_fragmented++;
2432 2431
2433 /* Chop up message: */ 2432 /* Chop up message: */
2434 2433
@@ -2441,27 +2440,37 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
2441 } 2440 }
2442 fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); 2441 fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE);
2443 if (fragm == NULL) { 2442 if (fragm == NULL) {
2444 warn("Link unable to fragment message\n"); 2443 buf_discard(buf);
2445 dsz = -ENOMEM; 2444 while (buf_chain) {
2446 goto exit; 2445 buf = buf_chain;
2446 buf_chain = buf_chain->next;
2447 buf_discard(buf);
2448 }
2449 return -ENOMEM;
2447 } 2450 }
2448 msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); 2451 msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE);
2452 fragm_no++;
2453 msg_set_fragm_no(&fragm_hdr, fragm_no);
2449 skb_copy_to_linear_data(fragm, &fragm_hdr, INT_H_SIZE); 2454 skb_copy_to_linear_data(fragm, &fragm_hdr, INT_H_SIZE);
2450 skb_copy_to_linear_data_offset(fragm, INT_H_SIZE, crs, 2455 skb_copy_to_linear_data_offset(fragm, INT_H_SIZE, crs,
2451 fragm_sz); 2456 fragm_sz);
2452 /* Send queued messages first, if any: */ 2457 buf_chain_tail->next = fragm;
2458 buf_chain_tail = fragm;
2453 2459
2454 l_ptr->stats.sent_fragments++;
2455 tipc_link_send_buf(l_ptr, fragm);
2456 if (!tipc_link_is_up(l_ptr))
2457 return dsz;
2458 msg_set_fragm_no(&fragm_hdr, ++fragm_no);
2459 rest -= fragm_sz; 2460 rest -= fragm_sz;
2460 crs += fragm_sz; 2461 crs += fragm_sz;
2461 msg_set_type(&fragm_hdr, FRAGMENT); 2462 msg_set_type(&fragm_hdr, FRAGMENT);
2462 } 2463 }
2463exit:
2464 buf_discard(buf); 2464 buf_discard(buf);
2465
2466 /* Append chain of fragments to send queue & send them */
2467
2468 l_ptr->long_msg_seq_no++;
2469 link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no);
2470 l_ptr->stats.sent_fragments += fragm_no;
2471 l_ptr->stats.sent_fragmented++;
2472 tipc_link_push_queue(l_ptr);
2473
2465 return dsz; 2474 return dsz;
2466} 2475}
2467 2476