Skip to content

Commit

Permalink
tipc: eliminate unnecessary linearization of incoming buffers
Browse files Browse the repository at this point in the history
Currently, TIPC linearizes all incoming buffers directly at reception
before passing them upwards in the stack. This is clearly a waste of
CPU resources, and must be avoided.

In this commit, we eliminate this unnecessary linearization. We still
ensure that at least the message header is linear, and that the buffer
is linearized where this is still needed, i.e. when unbundling and when
reversing messages.

In addition, we ensure that fragmented messages are validated after
reassembly before delivering them upwards in the stack.

Reviewed-by: Erik Hugne <[email protected]>
Reviewed-by: Ying Xue <[email protected]>
Signed-off-by: Jon Maloy <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Jon Paul Maloy authored and davem330 committed Mar 14, 2015
1 parent cf2157f commit 1149557
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 9 deletions.
5 changes: 0 additions & 5 deletions net/tipc/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -1075,13 +1075,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
if (unlikely(!tipc_msg_validate(skb)))
goto discard;

/* Ensure message data is a single contiguous unit */
if (unlikely(skb_linearize(skb)))
goto discard;

/* Handle arrival of a non-unicast link message */
msg = buf_msg(skb);

if (unlikely(msg_non_seq(msg))) {
if (msg_user(msg) == LINK_CONFIG)
tipc_disc_rcv(net, skb, b_ptr);
Expand Down
14 changes: 10 additions & 4 deletions net/tipc/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,16 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
}

if (fragid == LAST_FRAGMENT) {
TIPC_SKB_CB(head)->validated = false;
if (unlikely(!tipc_msg_validate(head)))
goto err;
*buf = head;
TIPC_SKB_CB(head)->tail = NULL;
*headbuf = NULL;
return 1;
}
*buf = NULL;
return 0;

err:
pr_warn_ratelimited("Unable to build fragment list\n");
kfree_skb(*buf);
Expand Down Expand Up @@ -378,10 +380,14 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu)
*/
bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos)
{
struct tipc_msg *msg = buf_msg(skb);
struct tipc_msg *msg;
int imsz;
struct tipc_msg *imsg = (struct tipc_msg *)(msg_data(msg) + *pos);
struct tipc_msg *imsg;

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;
Expand Down Expand Up @@ -463,11 +469,11 @@ bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode,

if (skb_linearize(buf))
goto exit;
msg = buf_msg(buf);
if (msg_dest_droppable(msg))
goto exit;
if (msg_errcode(msg))
goto exit;

memcpy(&ohdr, msg, msg_hdr_sz(msg));
imp = min_t(uint, imp + 1, TIPC_CRITICAL_IMPORTANCE);
if (msg_isdata(msg))
Expand Down

0 comments on commit 1149557

Please sign in to comment.