Commit c1336ee472f83a90ede01fdae095ed5d0a2934c9

Authored by Jon Paul Maloy
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

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 }
... ... @@ -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 }