Commit 1149557d64c97dc9adf3103347a1c0e8c06d3b89

Authored by Jon Paul Maloy
Committed by David S. Miller
1 parent cf2157f88a

tipc: eliminate unnecessary linearization of incoming buffers

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 <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 10 additions and 9 deletions Side-by-side Diff

... ... @@ -1075,13 +1075,8 @@
1075 1075 if (unlikely(!tipc_msg_validate(skb)))
1076 1076 goto discard;
1077 1077  
1078   - /* Ensure message data is a single contiguous unit */
1079   - if (unlikely(skb_linearize(skb)))
1080   - goto discard;
1081   -
1082 1078 /* Handle arrival of a non-unicast link message */
1083 1079 msg = buf_msg(skb);
1084   -
1085 1080 if (unlikely(msg_non_seq(msg))) {
1086 1081 if (msg_user(msg) == LINK_CONFIG)
1087 1082 tipc_disc_rcv(net, skb, b_ptr);
... ... @@ -165,6 +165,9 @@
165 165 }
166 166  
167 167 if (fragid == LAST_FRAGMENT) {
  168 + TIPC_SKB_CB(head)->validated = false;
  169 + if (unlikely(!tipc_msg_validate(head)))
  170 + goto err;
168 171 *buf = head;
169 172 TIPC_SKB_CB(head)->tail = NULL;
170 173 *headbuf = NULL;
... ... @@ -172,7 +175,6 @@
172 175 }
173 176 *buf = NULL;
174 177 return 0;
175   -
176 178 err:
177 179 pr_warn_ratelimited("Unable to build fragment list\n");
178 180 kfree_skb(*buf);
179 181  
180 182  
... ... @@ -378,10 +380,14 @@
378 380 */
379 381 bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos)
380 382 {
381   - struct tipc_msg *msg = buf_msg(skb);
  383 + struct tipc_msg *msg;
382 384 int imsz;
383   - struct tipc_msg *imsg = (struct tipc_msg *)(msg_data(msg) + *pos);
  385 + struct tipc_msg *imsg;
384 386  
  387 + if (unlikely(skb_linearize(skb)))
  388 + return false;
  389 + msg = buf_msg(skb);
  390 + imsg = (struct tipc_msg *)(msg_data(msg) + *pos);
385 391 /* Is there space left for shortest possible message? */
386 392 if (*pos > (msg_data_sz(msg) - SHORT_H_SIZE))
387 393 goto none;
388 394  
... ... @@ -463,11 +469,11 @@
463 469  
464 470 if (skb_linearize(buf))
465 471 goto exit;
  472 + msg = buf_msg(buf);
466 473 if (msg_dest_droppable(msg))
467 474 goto exit;
468 475 if (msg_errcode(msg))
469 476 goto exit;
470   -
471 477 memcpy(&ohdr, msg, msg_hdr_sz(msg));
472 478 imp = min_t(uint, imp + 1, TIPC_CRITICAL_IMPORTANCE);
473 479 if (msg_isdata(msg))