提交 ef9be755 编写于 作者: T Tung Nguyen 提交者: David S. Miller

tipc: eliminate buffer cloning in function tipc_msg_extract()

The function tipc_msg_extract() is using skb_clone() to clone inner
messages from a message bundle buffer. Although this method is safe,
it has an undesired effect that each buffer clone inherits the
true-size of the bundling buffer. As a result, the buffer clone
almost always ends up with being copied anyway by the message
validation function. This makes the cloning into a sub-optimization.

In this commit we take the consequence of this realization, and copy
each inner message to a separately allocated buffer up front in the
extraction function.

As a bonus we can now eliminate the two cases where we had to copy
re-routed packets that may potentially go out on the wire again.
Signed-off-by: NTung Nguyen <tung.q.nguyen@dektech.com.au>
Signed-off-by: NJon Maloy <jon.maloy@ericsson.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 9ca78674
...@@ -416,26 +416,31 @@ bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu) ...@@ -416,26 +416,31 @@ bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu)
*/ */
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 *hdr, *ihdr;
int imsz, offset; int imsz;
*iskb = NULL; *iskb = NULL;
if (unlikely(skb_linearize(skb))) if (unlikely(skb_linearize(skb)))
goto none; goto none;
msg = buf_msg(skb); hdr = buf_msg(skb);
offset = msg_hdr_sz(msg) + *pos; if (unlikely(*pos > (msg_data_sz(hdr) - MIN_H_SIZE)))
if (unlikely(offset > (msg_size(msg) - MIN_H_SIZE)))
goto none; goto none;
*iskb = skb_clone(skb, GFP_ATOMIC); ihdr = (struct tipc_msg *)(msg_data(hdr) + *pos);
if (unlikely(!*iskb)) imsz = msg_size(ihdr);
if ((*pos + imsz) > msg_data_sz(hdr))
goto none; goto none;
skb_pull(*iskb, offset);
imsz = msg_size(buf_msg(*iskb)); *iskb = tipc_buf_acquire(imsz, GFP_ATOMIC);
skb_trim(*iskb, imsz); if (!*iskb)
goto none;
skb_copy_to_linear_data(*iskb, ihdr, imsz);
if (unlikely(!tipc_msg_validate(iskb))) if (unlikely(!tipc_msg_validate(iskb)))
goto none; goto none;
*pos += align(imsz); *pos += align(imsz);
return true; return true;
none: none:
...@@ -531,12 +536,6 @@ bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err) ...@@ -531,12 +536,6 @@ bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err)
msg_set_hdr_sz(hdr, BASIC_H_SIZE); msg_set_hdr_sz(hdr, BASIC_H_SIZE);
} }
if (skb_cloned(_skb) &&
pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC))
goto exit;
/* reassign after skb header modifications */
hdr = buf_msg(_skb);
/* Now reverse the concerned fields */ /* Now reverse the concerned fields */
msg_set_errcode(hdr, err); msg_set_errcode(hdr, err);
msg_set_non_seq(hdr, 0); msg_set_non_seq(hdr, 0);
...@@ -595,10 +594,6 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err) ...@@ -595,10 +594,6 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
if (!skb_cloned(skb)) if (!skb_cloned(skb))
return true; return true;
/* Unclone buffer in case it was bundled */
if (pskb_expand_head(skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC))
return false;
return true; return true;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册