Commit c1336ee472f83a90ede01fdae095ed5d0a2934c9
Committed by
David S. Miller
1 parent
1149557d64
tipc: extract bundled buffers by cloning instead of copying
When we currently extract a bundled buffer from a message bundle in the function tipc_msg_extract(), we allocate a new buffer and explicitly copy the linear data area. This is unnecessary, since we can just clone the buffer and do skb_pull() on the clone to move the data pointer to the correct position. This is what we do in this commit. Reviewed-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 2 changed files with 28 additions and 47 deletions Side-by-side Diff
net/tipc/link.c
1 | 1 | /* |
2 | 2 | * net/tipc/link.c: TIPC link code |
3 | 3 | * |
4 | - * Copyright (c) 1996-2007, 2012-2014, Ericsson AB | |
4 | + * Copyright (c) 1996-2007, 2012-2015, Ericsson AB | |
5 | 5 | * Copyright (c) 2004-2007, 2010-2013, Wind River Systems |
6 | 6 | * All rights reserved. |
7 | 7 | * |
... | ... | @@ -1117,7 +1117,7 @@ |
1117 | 1117 | ackd = msg_ack(msg); |
1118 | 1118 | |
1119 | 1119 | /* Release acked messages */ |
1120 | - if (n_ptr->bclink.recv_permitted) | |
1120 | + if (likely(n_ptr->bclink.recv_permitted)) | |
1121 | 1121 | tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); |
1122 | 1122 | |
1123 | 1123 | released = 0; |
1124 | 1124 | |
1125 | 1125 | |
1126 | 1126 | |
1127 | 1127 | |
1128 | 1128 | |
... | ... | @@ -1712,45 +1712,24 @@ |
1712 | 1712 | } |
1713 | 1713 | } |
1714 | 1714 | |
1715 | -/** | |
1716 | - * buf_extract - extracts embedded TIPC message from another message | |
1717 | - * @skb: encapsulating message buffer | |
1718 | - * @from_pos: offset to extract from | |
1719 | - * | |
1720 | - * Returns a new message buffer containing an embedded message. The | |
1721 | - * encapsulating buffer is left unchanged. | |
1722 | - */ | |
1723 | -static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos) | |
1724 | -{ | |
1725 | - struct tipc_msg *msg = (struct tipc_msg *)(skb->data + from_pos); | |
1726 | - u32 size = msg_size(msg); | |
1727 | - struct sk_buff *eb; | |
1728 | - | |
1729 | - eb = tipc_buf_acquire(size); | |
1730 | - if (eb) | |
1731 | - skb_copy_to_linear_data(eb, msg, size); | |
1732 | - return eb; | |
1733 | -} | |
1734 | - | |
1735 | 1715 | /* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet. |
1736 | 1716 | * Owner node is locked. |
1737 | 1717 | */ |
1738 | -static void tipc_link_dup_rcv(struct tipc_link *l_ptr, | |
1739 | - struct sk_buff *t_buf) | |
1718 | +static void tipc_link_dup_rcv(struct tipc_link *link, | |
1719 | + struct sk_buff *skb) | |
1740 | 1720 | { |
1741 | - struct sk_buff *buf; | |
1721 | + struct sk_buff *iskb; | |
1722 | + int pos = 0; | |
1742 | 1723 | |
1743 | - if (!tipc_link_is_up(l_ptr)) | |
1724 | + if (!tipc_link_is_up(link)) | |
1744 | 1725 | return; |
1745 | 1726 | |
1746 | - buf = buf_extract(t_buf, INT_H_SIZE); | |
1747 | - if (buf == NULL) { | |
1727 | + if (!tipc_msg_extract(skb, &iskb, &pos)) { | |
1748 | 1728 | pr_warn("%sfailed to extract inner dup pkt\n", link_co_err); |
1749 | 1729 | return; |
1750 | 1730 | } |
1751 | - | |
1752 | - /* Add buffer to deferred queue, if applicable: */ | |
1753 | - link_handle_out_of_seq_msg(l_ptr, buf); | |
1731 | + /* Append buffer to deferred queue, if applicable: */ | |
1732 | + link_handle_out_of_seq_msg(link, iskb); | |
1754 | 1733 | } |
1755 | 1734 | |
1756 | 1735 | /* tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet |
... | ... | @@ -1762,6 +1741,7 @@ |
1762 | 1741 | struct tipc_msg *t_msg = buf_msg(t_buf); |
1763 | 1742 | struct sk_buff *buf = NULL; |
1764 | 1743 | struct tipc_msg *msg; |
1744 | + int pos = 0; | |
1765 | 1745 | |
1766 | 1746 | if (tipc_link_is_up(l_ptr)) |
1767 | 1747 | tipc_link_reset(l_ptr); |
... | ... | @@ -1773,8 +1753,7 @@ |
1773 | 1753 | /* Should there be an inner packet? */ |
1774 | 1754 | if (l_ptr->exp_msg_count) { |
1775 | 1755 | l_ptr->exp_msg_count--; |
1776 | - buf = buf_extract(t_buf, INT_H_SIZE); | |
1777 | - if (buf == NULL) { | |
1756 | + if (!tipc_msg_extract(t_buf, &buf, &pos)) { | |
1778 | 1757 | pr_warn("%sno inner failover pkt\n", link_co_err); |
1779 | 1758 | goto exit; |
1780 | 1759 | } |
net/tipc/msg.c
... | ... | @@ -372,38 +372,40 @@ |
372 | 372 | |
373 | 373 | /** |
374 | 374 | * tipc_msg_extract(): extract bundled inner packet from buffer |
375 | - * @skb: linear outer buffer, to be extracted from. | |
375 | + * @skb: buffer to be extracted from. | |
376 | 376 | * @iskb: extracted inner buffer, to be returned |
377 | - * @pos: position of msg to be extracted. Returns with pointer of next msg | |
377 | + * @pos: position in outer message of msg to be extracted. | |
378 | + * Returns position of next msg | |
378 | 379 | * Consumes outer buffer when last packet extracted |
379 | 380 | * Returns true when when there is an extracted buffer, otherwise false |
380 | 381 | */ |
381 | 382 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) |
382 | 383 | { |
383 | 384 | struct tipc_msg *msg; |
384 | - int imsz; | |
385 | - struct tipc_msg *imsg; | |
385 | + int imsz, offset; | |
386 | 386 | |
387 | + *iskb = NULL; | |
387 | 388 | if (unlikely(skb_linearize(skb))) |
388 | - return false; | |
389 | + goto none; | |
390 | + | |
389 | 391 | msg = buf_msg(skb); |
390 | - imsg = (struct tipc_msg *)(msg_data(msg) + *pos); | |
391 | - /* Is there space left for shortest possible message? */ | |
392 | - if (*pos > (msg_data_sz(msg) - SHORT_H_SIZE)) | |
392 | + offset = msg_hdr_sz(msg) + *pos; | |
393 | + if (unlikely(offset > (msg_size(msg) - MIN_H_SIZE))) | |
393 | 394 | goto none; |
394 | - imsz = msg_size(imsg); | |
395 | 395 | |
396 | - /* Is there space left for current message ? */ | |
397 | - if ((*pos + imsz) > msg_data_sz(msg)) | |
396 | + *iskb = skb_clone(skb, GFP_ATOMIC); | |
397 | + if (unlikely(!*iskb)) | |
398 | 398 | goto none; |
399 | - *iskb = tipc_buf_acquire(imsz); | |
400 | - if (!*iskb) | |
399 | + skb_pull(*iskb, offset); | |
400 | + imsz = msg_size(buf_msg(*iskb)); | |
401 | + skb_trim(*iskb, imsz); | |
402 | + if (unlikely(!tipc_msg_validate(*iskb))) | |
401 | 403 | goto none; |
402 | - skb_copy_to_linear_data(*iskb, imsg, imsz); | |
403 | 404 | *pos += align(imsz); |
404 | 405 | return true; |
405 | 406 | none: |
406 | 407 | kfree_skb(skb); |
408 | + kfree_skb(*iskb); | |
407 | 409 | *iskb = NULL; |
408 | 410 | return false; |
409 | 411 | } |