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.c159
1 files changed, 44 insertions, 115 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index ada8cadf5af8..a63646e6c2cf 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -404,15 +404,9 @@ static void link_release_outqueue(struct tipc_link *l_ptr)
404 */ 404 */
405void tipc_link_reset_fragments(struct tipc_link *l_ptr) 405void tipc_link_reset_fragments(struct tipc_link *l_ptr)
406{ 406{
407 struct sk_buff *buf = l_ptr->defragm_buf; 407 kfree_skb(l_ptr->reasm_head);
408 struct sk_buff *next; 408 l_ptr->reasm_head = NULL;
409 409 l_ptr->reasm_tail = NULL;
410 while (buf) {
411 next = buf->next;
412 kfree_skb(buf);
413 buf = next;
414 }
415 l_ptr->defragm_buf = NULL;
416} 410}
417 411
418/** 412/**
@@ -1649,13 +1643,15 @@ deliver:
1649 continue; 1643 continue;
1650 case MSG_FRAGMENTER: 1644 case MSG_FRAGMENTER:
1651 l_ptr->stats.recv_fragments++; 1645 l_ptr->stats.recv_fragments++;
1652 ret = tipc_link_recv_fragment(&l_ptr->defragm_buf, 1646 ret = tipc_link_recv_fragment(&l_ptr->reasm_head,
1653 &buf, &msg); 1647 &l_ptr->reasm_tail,
1654 if (ret == 1) { 1648 &buf);
1649 if (ret == LINK_REASM_COMPLETE) {
1655 l_ptr->stats.recv_fragmented++; 1650 l_ptr->stats.recv_fragmented++;
1651 msg = buf_msg(buf);
1656 goto deliver; 1652 goto deliver;
1657 } 1653 }
1658 if (ret == -1) 1654 if (ret == LINK_REASM_ERROR)
1659 l_ptr->next_in_no--; 1655 l_ptr->next_in_no--;
1660 tipc_node_unlock(n_ptr); 1656 tipc_node_unlock(n_ptr);
1661 continue; 1657 continue;
@@ -2343,114 +2339,47 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
2343} 2339}
2344 2340
2345/* 2341/*
2346 * A pending message being re-assembled must store certain values
2347 * to handle subsequent fragments correctly. The following functions
2348 * help storing these values in unused, available fields in the
2349 * pending message. This makes dynamic memory allocation unnecessary.
2350 */
2351static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno)
2352{
2353 msg_set_seqno(buf_msg(buf), seqno);
2354}
2355
2356static u32 get_fragm_size(struct sk_buff *buf)
2357{
2358 return msg_ack(buf_msg(buf));
2359}
2360
2361static void set_fragm_size(struct sk_buff *buf, u32 sz)
2362{
2363 msg_set_ack(buf_msg(buf), sz);
2364}
2365
2366static u32 get_expected_frags(struct sk_buff *buf)
2367{
2368 return msg_bcast_ack(buf_msg(buf));
2369}
2370
2371static void set_expected_frags(struct sk_buff *buf, u32 exp)
2372{
2373 msg_set_bcast_ack(buf_msg(buf), exp);
2374}
2375
2376/*
2377 * tipc_link_recv_fragment(): Called with node lock on. Returns 2342 * tipc_link_recv_fragment(): Called with node lock on. Returns
2378 * the reassembled buffer if message is complete. 2343 * the reassembled buffer if message is complete.
2379 */ 2344 */
2380int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, 2345int tipc_link_recv_fragment(struct sk_buff **head, struct sk_buff **tail,
2381 struct tipc_msg **m) 2346 struct sk_buff **fbuf)
2382{ 2347{
2383 struct sk_buff *prev = NULL; 2348 struct sk_buff *frag = *fbuf;
2384 struct sk_buff *fbuf = *fb; 2349 struct tipc_msg *msg = buf_msg(frag);
2385 struct tipc_msg *fragm = buf_msg(fbuf); 2350 u32 fragid = msg_type(msg);
2386 struct sk_buff *pbuf = *pending; 2351 bool headstolen;
2387 u32 long_msg_seq_no = msg_long_msgno(fragm); 2352 int delta;
2388 2353
2389 *fb = NULL; 2354 skb_pull(frag, msg_hdr_sz(msg));
2390 2355 if (fragid == FIRST_FRAGMENT) {
2391 /* Is there an incomplete message waiting for this fragment? */ 2356 if (*head || skb_unclone(frag, GFP_ATOMIC))
2392 while (pbuf && ((buf_seqno(pbuf) != long_msg_seq_no) || 2357 goto out_free;
2393 (msg_orignode(fragm) != msg_orignode(buf_msg(pbuf))))) { 2358 *head = frag;
2394 prev = pbuf; 2359 skb_frag_list_init(*head);
2395 pbuf = pbuf->next;
2396 }
2397
2398 if (!pbuf && (msg_type(fragm) == FIRST_FRAGMENT)) {
2399 struct tipc_msg *imsg = (struct tipc_msg *)msg_data(fragm);
2400 u32 msg_sz = msg_size(imsg);
2401 u32 fragm_sz = msg_data_sz(fragm);
2402 u32 exp_fragm_cnt;
2403 u32 max = TIPC_MAX_USER_MSG_SIZE + NAMED_H_SIZE;
2404
2405 if (msg_type(imsg) == TIPC_MCAST_MSG)
2406 max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE;
2407 if (fragm_sz == 0 || msg_size(imsg) > max) {
2408 kfree_skb(fbuf);
2409 return 0;
2410 }
2411 exp_fragm_cnt = msg_sz / fragm_sz + !!(msg_sz % fragm_sz);
2412 pbuf = tipc_buf_acquire(msg_size(imsg));
2413 if (pbuf != NULL) {
2414 pbuf->next = *pending;
2415 *pending = pbuf;
2416 skb_copy_to_linear_data(pbuf, imsg,
2417 msg_data_sz(fragm));
2418 /* Prepare buffer for subsequent fragments. */
2419 set_long_msg_seqno(pbuf, long_msg_seq_no);
2420 set_fragm_size(pbuf, fragm_sz);
2421 set_expected_frags(pbuf, exp_fragm_cnt - 1);
2422 } else {
2423 pr_debug("Link unable to reassemble fragmented message\n");
2424 kfree_skb(fbuf);
2425 return -1;
2426 }
2427 kfree_skb(fbuf);
2428 return 0;
2429 } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) {
2430 u32 dsz = msg_data_sz(fragm);
2431 u32 fsz = get_fragm_size(pbuf);
2432 u32 crs = ((msg_fragm_no(fragm) - 1) * fsz);
2433 u32 exp_frags = get_expected_frags(pbuf) - 1;
2434 skb_copy_to_linear_data_offset(pbuf, crs,
2435 msg_data(fragm), dsz);
2436 kfree_skb(fbuf);
2437
2438 /* Is message complete? */
2439 if (exp_frags == 0) {
2440 if (prev)
2441 prev->next = pbuf->next;
2442 else
2443 *pending = pbuf->next;
2444 msg_reset_reroute_cnt(buf_msg(pbuf));
2445 *fb = pbuf;
2446 *m = buf_msg(pbuf);
2447 return 1;
2448 }
2449 set_expected_frags(pbuf, exp_frags);
2450 return 0; 2360 return 0;
2361 } else if (skb_try_coalesce(*head, frag, &headstolen, &delta)) {
2362 kfree_skb_partial(frag, headstolen);
2363 } else {
2364 if (!*head)
2365 goto out_free;
2366 if (!skb_has_frag_list(*head))
2367 skb_shinfo(*head)->frag_list = frag;
2368 else
2369 (*tail)->next = frag;
2370 *tail = frag;
2371 (*head)->truesize += frag->truesize;
2372 }
2373 if (fragid == LAST_FRAGMENT) {
2374 *fbuf = *head;
2375 *tail = *head = NULL;
2376 return LINK_REASM_COMPLETE;
2451 } 2377 }
2452 kfree_skb(fbuf);
2453 return 0; 2378 return 0;
2379out_free:
2380 pr_warn_ratelimited("Link unable to reassemble fragmented message\n");
2381 kfree_skb(*fbuf);
2382 return LINK_REASM_ERROR;
2454} 2383}
2455 2384
2456static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) 2385static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance)