aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-03-13 16:08:08 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-14 14:38:32 -0400
commitc1336ee472f83a90ede01fdae095ed5d0a2934c9 (patch)
tree4178d007c524fe51262b3698150c63d38591b521 /net
parent1149557d64c97dc9adf3103347a1c0e8c06d3b89 (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.c45
-rw-r--r--net/tipc/msg.c30
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 */
1723static 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 */
1738static void tipc_link_dup_rcv(struct tipc_link *l_ptr, 1718static 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 */
381bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) 382bool 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;
405none: 406none:
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}