diff options
author | Jon Paul Maloy <jon.maloy@ericsson.com> | 2015-03-13 16:08:08 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-14 14:38:32 -0400 |
commit | c1336ee472f83a90ede01fdae095ed5d0a2934c9 (patch) | |
tree | 4178d007c524fe51262b3698150c63d38591b521 /net | |
parent | 1149557d64c97dc9adf3103347a1c0e8c06d3b89 (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/tipc/link.c | 45 | ||||
-rw-r--r-- | net/tipc/msg.c | 30 |
2 files changed, 28 insertions, 47 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 8c6639d107fc..56c39b1a53a9 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/link.c: TIPC link code | 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 | * Copyright (c) 2004-2007, 2010-2013, Wind River Systems | 5 | * Copyright (c) 2004-2007, 2010-2013, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -1117,7 +1117,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) | |||
1117 | ackd = msg_ack(msg); | 1117 | ackd = msg_ack(msg); |
1118 | 1118 | ||
1119 | /* Release acked messages */ | 1119 | /* Release acked messages */ |
1120 | if (n_ptr->bclink.recv_permitted) | 1120 | if (likely(n_ptr->bclink.recv_permitted)) |
1121 | tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); | 1121 | tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); |
1122 | 1122 | ||
1123 | released = 0; | 1123 | released = 0; |
@@ -1712,45 +1712,24 @@ void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, | |||
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 | /* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet. | 1715 | /* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet. |
1736 | * Owner node is locked. | 1716 | * Owner node is locked. |
1737 | */ | 1717 | */ |
1738 | static void tipc_link_dup_rcv(struct tipc_link *l_ptr, | 1718 | static void tipc_link_dup_rcv(struct tipc_link *link, |
1739 | struct sk_buff *t_buf) | 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 | return; | 1725 | return; |
1745 | 1726 | ||
1746 | buf = buf_extract(t_buf, INT_H_SIZE); | 1727 | if (!tipc_msg_extract(skb, &iskb, &pos)) { |
1747 | if (buf == NULL) { | ||
1748 | pr_warn("%sfailed to extract inner dup pkt\n", link_co_err); | 1728 | pr_warn("%sfailed to extract inner dup pkt\n", link_co_err); |
1749 | return; | 1729 | return; |
1750 | } | 1730 | } |
1751 | 1731 | /* Append buffer to deferred queue, if applicable: */ | |
1752 | /* Add buffer to deferred queue, if applicable: */ | 1732 | link_handle_out_of_seq_msg(link, iskb); |
1753 | link_handle_out_of_seq_msg(l_ptr, buf); | ||
1754 | } | 1733 | } |
1755 | 1734 | ||
1756 | /* tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet | 1735 | /* tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet |
@@ -1762,6 +1741,7 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr, | |||
1762 | struct tipc_msg *t_msg = buf_msg(t_buf); | 1741 | struct tipc_msg *t_msg = buf_msg(t_buf); |
1763 | struct sk_buff *buf = NULL; | 1742 | struct sk_buff *buf = NULL; |
1764 | struct tipc_msg *msg; | 1743 | struct tipc_msg *msg; |
1744 | int pos = 0; | ||
1765 | 1745 | ||
1766 | if (tipc_link_is_up(l_ptr)) | 1746 | if (tipc_link_is_up(l_ptr)) |
1767 | tipc_link_reset(l_ptr); | 1747 | tipc_link_reset(l_ptr); |
@@ -1773,8 +1753,7 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr, | |||
1773 | /* Should there be an inner packet? */ | 1753 | /* Should there be an inner packet? */ |
1774 | if (l_ptr->exp_msg_count) { | 1754 | if (l_ptr->exp_msg_count) { |
1775 | l_ptr->exp_msg_count--; | 1755 | l_ptr->exp_msg_count--; |
1776 | buf = buf_extract(t_buf, INT_H_SIZE); | 1756 | if (!tipc_msg_extract(t_buf, &buf, &pos)) { |
1777 | if (buf == NULL) { | ||
1778 | pr_warn("%sno inner failover pkt\n", link_co_err); | 1757 | pr_warn("%sno inner failover pkt\n", link_co_err); |
1779 | goto exit; | 1758 | goto exit; |
1780 | } | 1759 | } |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index ff8c64cd1cd9..333d2ae1cf76 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -372,38 +372,40 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu) | |||
372 | 372 | ||
373 | /** | 373 | /** |
374 | * tipc_msg_extract(): extract bundled inner packet from buffer | 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 | * @iskb: extracted inner buffer, to be returned | 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 | * Consumes outer buffer when last packet extracted | 379 | * Consumes outer buffer when last packet extracted |
379 | * Returns true when when there is an extracted buffer, otherwise false | 380 | * Returns true when when there is an extracted buffer, otherwise false |
380 | */ | 381 | */ |
381 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) | 382 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) |
382 | { | 383 | { |
383 | struct tipc_msg *msg; | 384 | struct tipc_msg *msg; |
384 | int imsz; | 385 | int imsz, offset; |
385 | struct tipc_msg *imsg; | ||
386 | 386 | ||
387 | *iskb = NULL; | ||
387 | if (unlikely(skb_linearize(skb))) | 388 | if (unlikely(skb_linearize(skb))) |
388 | return false; | 389 | goto none; |
390 | |||
389 | msg = buf_msg(skb); | 391 | msg = buf_msg(skb); |
390 | imsg = (struct tipc_msg *)(msg_data(msg) + *pos); | 392 | offset = msg_hdr_sz(msg) + *pos; |
391 | /* Is there space left for shortest possible message? */ | 393 | if (unlikely(offset > (msg_size(msg) - MIN_H_SIZE))) |
392 | if (*pos > (msg_data_sz(msg) - SHORT_H_SIZE)) | ||
393 | goto none; | 394 | goto none; |
394 | imsz = msg_size(imsg); | ||
395 | 395 | ||
396 | /* Is there space left for current message ? */ | 396 | *iskb = skb_clone(skb, GFP_ATOMIC); |
397 | if ((*pos + imsz) > msg_data_sz(msg)) | 397 | if (unlikely(!*iskb)) |
398 | goto none; | 398 | goto none; |
399 | *iskb = tipc_buf_acquire(imsz); | 399 | skb_pull(*iskb, offset); |
400 | if (!*iskb) | 400 | imsz = msg_size(buf_msg(*iskb)); |
401 | skb_trim(*iskb, imsz); | ||
402 | if (unlikely(!tipc_msg_validate(*iskb))) | ||
401 | goto none; | 403 | goto none; |
402 | skb_copy_to_linear_data(*iskb, imsg, imsz); | ||
403 | *pos += align(imsz); | 404 | *pos += align(imsz); |
404 | return true; | 405 | return true; |
405 | none: | 406 | none: |
406 | kfree_skb(skb); | 407 | kfree_skb(skb); |
408 | kfree_skb(*iskb); | ||
407 | *iskb = NULL; | 409 | *iskb = NULL; |
408 | return false; | 410 | return false; |
409 | } | 411 | } |