mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-02 08:34:20 +08:00
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>
This commit is contained in:
parent
1149557d64
commit
c1336ee472
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* net/tipc/link.c: TIPC link code
|
* net/tipc/link.c: TIPC link code
|
||||||
*
|
*
|
||||||
* Copyright (c) 1996-2007, 2012-2014, Ericsson AB
|
* Copyright (c) 1996-2007, 2012-2015, Ericsson AB
|
||||||
* Copyright (c) 2004-2007, 2010-2013, Wind River Systems
|
* Copyright (c) 2004-2007, 2010-2013, Wind River Systems
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@ -1117,7 +1117,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
|
|||||||
ackd = msg_ack(msg);
|
ackd = msg_ack(msg);
|
||||||
|
|
||||||
/* Release acked messages */
|
/* Release acked messages */
|
||||||
if (n_ptr->bclink.recv_permitted)
|
if (likely(n_ptr->bclink.recv_permitted))
|
||||||
tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
|
tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
|
||||||
|
|
||||||
released = 0;
|
released = 0;
|
||||||
@ -1712,45 +1712,24 @@ void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* buf_extract - extracts embedded TIPC message from another message
|
|
||||||
* @skb: encapsulating message buffer
|
|
||||||
* @from_pos: offset to extract from
|
|
||||||
*
|
|
||||||
* Returns a new message buffer containing an embedded message. The
|
|
||||||
* encapsulating buffer is left unchanged.
|
|
||||||
*/
|
|
||||||
static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos)
|
|
||||||
{
|
|
||||||
struct tipc_msg *msg = (struct tipc_msg *)(skb->data + from_pos);
|
|
||||||
u32 size = msg_size(msg);
|
|
||||||
struct sk_buff *eb;
|
|
||||||
|
|
||||||
eb = tipc_buf_acquire(size);
|
|
||||||
if (eb)
|
|
||||||
skb_copy_to_linear_data(eb, msg, size);
|
|
||||||
return eb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet.
|
/* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet.
|
||||||
* Owner node is locked.
|
* Owner node is locked.
|
||||||
*/
|
*/
|
||||||
static void tipc_link_dup_rcv(struct tipc_link *l_ptr,
|
static void tipc_link_dup_rcv(struct tipc_link *link,
|
||||||
struct sk_buff *t_buf)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct sk_buff *buf;
|
struct sk_buff *iskb;
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
if (!tipc_link_is_up(l_ptr))
|
if (!tipc_link_is_up(link))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
buf = buf_extract(t_buf, INT_H_SIZE);
|
if (!tipc_msg_extract(skb, &iskb, &pos)) {
|
||||||
if (buf == NULL) {
|
|
||||||
pr_warn("%sfailed to extract inner dup pkt\n", link_co_err);
|
pr_warn("%sfailed to extract inner dup pkt\n", link_co_err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/* Append buffer to deferred queue, if applicable: */
|
||||||
/* Add buffer to deferred queue, if applicable: */
|
link_handle_out_of_seq_msg(link, iskb);
|
||||||
link_handle_out_of_seq_msg(l_ptr, buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet
|
/* 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,
|
|||||||
struct tipc_msg *t_msg = buf_msg(t_buf);
|
struct tipc_msg *t_msg = buf_msg(t_buf);
|
||||||
struct sk_buff *buf = NULL;
|
struct sk_buff *buf = NULL;
|
||||||
struct tipc_msg *msg;
|
struct tipc_msg *msg;
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
if (tipc_link_is_up(l_ptr))
|
if (tipc_link_is_up(l_ptr))
|
||||||
tipc_link_reset(l_ptr);
|
tipc_link_reset(l_ptr);
|
||||||
@ -1773,8 +1753,7 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr,
|
|||||||
/* Should there be an inner packet? */
|
/* Should there be an inner packet? */
|
||||||
if (l_ptr->exp_msg_count) {
|
if (l_ptr->exp_msg_count) {
|
||||||
l_ptr->exp_msg_count--;
|
l_ptr->exp_msg_count--;
|
||||||
buf = buf_extract(t_buf, INT_H_SIZE);
|
if (!tipc_msg_extract(t_buf, &buf, &pos)) {
|
||||||
if (buf == NULL) {
|
|
||||||
pr_warn("%sno inner failover pkt\n", link_co_err);
|
pr_warn("%sno inner failover pkt\n", link_co_err);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -372,38 +372,40 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* tipc_msg_extract(): extract bundled inner packet from buffer
|
* tipc_msg_extract(): extract bundled inner packet from buffer
|
||||||
* @skb: linear outer buffer, to be extracted from.
|
* @skb: buffer to be extracted from.
|
||||||
* @iskb: extracted inner buffer, to be returned
|
* @iskb: extracted inner buffer, to be returned
|
||||||
* @pos: position of msg to be extracted. Returns with pointer of next msg
|
* @pos: position in outer message of msg to be extracted.
|
||||||
|
* Returns position of next msg
|
||||||
* Consumes outer buffer when last packet extracted
|
* Consumes outer buffer when last packet extracted
|
||||||
* Returns true when when there is an extracted buffer, otherwise false
|
* Returns true when when there is an extracted buffer, otherwise false
|
||||||
*/
|
*/
|
||||||
bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos)
|
bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos)
|
||||||
{
|
{
|
||||||
struct tipc_msg *msg;
|
struct tipc_msg *msg;
|
||||||
int imsz;
|
int imsz, offset;
|
||||||
struct tipc_msg *imsg;
|
|
||||||
|
|
||||||
|
*iskb = NULL;
|
||||||
if (unlikely(skb_linearize(skb)))
|
if (unlikely(skb_linearize(skb)))
|
||||||
return false;
|
|
||||||
msg = buf_msg(skb);
|
|
||||||
imsg = (struct tipc_msg *)(msg_data(msg) + *pos);
|
|
||||||
/* Is there space left for shortest possible message? */
|
|
||||||
if (*pos > (msg_data_sz(msg) - SHORT_H_SIZE))
|
|
||||||
goto none;
|
goto none;
|
||||||
imsz = msg_size(imsg);
|
|
||||||
|
|
||||||
/* Is there space left for current message ? */
|
msg = buf_msg(skb);
|
||||||
if ((*pos + imsz) > msg_data_sz(msg))
|
offset = msg_hdr_sz(msg) + *pos;
|
||||||
|
if (unlikely(offset > (msg_size(msg) - MIN_H_SIZE)))
|
||||||
goto none;
|
goto none;
|
||||||
*iskb = tipc_buf_acquire(imsz);
|
|
||||||
if (!*iskb)
|
*iskb = skb_clone(skb, GFP_ATOMIC);
|
||||||
|
if (unlikely(!*iskb))
|
||||||
|
goto none;
|
||||||
|
skb_pull(*iskb, offset);
|
||||||
|
imsz = msg_size(buf_msg(*iskb));
|
||||||
|
skb_trim(*iskb, imsz);
|
||||||
|
if (unlikely(!tipc_msg_validate(*iskb)))
|
||||||
goto none;
|
goto none;
|
||||||
skb_copy_to_linear_data(*iskb, imsg, imsz);
|
|
||||||
*pos += align(imsz);
|
*pos += align(imsz);
|
||||||
return true;
|
return true;
|
||||||
none:
|
none:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
|
kfree_skb(*iskb);
|
||||||
*iskb = NULL;
|
*iskb = NULL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user