diff options
author | Tung Nguyen <tung.q.nguyen@dektech.com.au> | 2018-06-28 16:25:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-06-30 07:48:16 -0400 |
commit | ef9be755697f1b841c2a219a05df1a72ccd6f471 (patch) | |
tree | df97059feff846ba6f30769f9096a90b4c2b29b5 /net/tipc | |
parent | 9ca78674eb6a19acbb1d69e86273ebd1d3edf087 (diff) |
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: Tung Nguyen <tung.q.nguyen@dektech.com.au>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/msg.c | 35 |
1 files changed, 15 insertions, 20 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index b6c45dccba3d..b61891054709 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -416,26 +416,31 @@ bool tipc_msg_bundle(struct sk_buff *skb, struct tipc_msg *msg, u32 mtu) | |||
416 | */ | 416 | */ |
417 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) | 417 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) |
418 | { | 418 | { |
419 | struct tipc_msg *msg; | 419 | struct tipc_msg *hdr, *ihdr; |
420 | int imsz, offset; | 420 | int imsz; |
421 | 421 | ||
422 | *iskb = NULL; | 422 | *iskb = NULL; |
423 | if (unlikely(skb_linearize(skb))) | 423 | if (unlikely(skb_linearize(skb))) |
424 | goto none; | 424 | goto none; |
425 | 425 | ||
426 | msg = buf_msg(skb); | 426 | hdr = buf_msg(skb); |
427 | offset = msg_hdr_sz(msg) + *pos; | 427 | if (unlikely(*pos > (msg_data_sz(hdr) - MIN_H_SIZE))) |
428 | if (unlikely(offset > (msg_size(msg) - MIN_H_SIZE))) | ||
429 | goto none; | 428 | goto none; |
430 | 429 | ||
431 | *iskb = skb_clone(skb, GFP_ATOMIC); | 430 | ihdr = (struct tipc_msg *)(msg_data(hdr) + *pos); |
432 | if (unlikely(!*iskb)) | 431 | imsz = msg_size(ihdr); |
432 | |||
433 | if ((*pos + imsz) > msg_data_sz(hdr)) | ||
433 | goto none; | 434 | goto none; |
434 | skb_pull(*iskb, offset); | 435 | |
435 | imsz = msg_size(buf_msg(*iskb)); | 436 | *iskb = tipc_buf_acquire(imsz, GFP_ATOMIC); |
436 | skb_trim(*iskb, imsz); | 437 | if (!*iskb) |
438 | goto none; | ||
439 | |||
440 | skb_copy_to_linear_data(*iskb, ihdr, imsz); | ||
437 | if (unlikely(!tipc_msg_validate(iskb))) | 441 | if (unlikely(!tipc_msg_validate(iskb))) |
438 | goto none; | 442 | goto none; |
443 | |||
439 | *pos += align(imsz); | 444 | *pos += align(imsz); |
440 | return true; | 445 | return true; |
441 | none: | 446 | none: |
@@ -531,12 +536,6 @@ bool tipc_msg_reverse(u32 own_node, struct sk_buff **skb, int err) | |||
531 | msg_set_hdr_sz(hdr, BASIC_H_SIZE); | 536 | msg_set_hdr_sz(hdr, BASIC_H_SIZE); |
532 | } | 537 | } |
533 | 538 | ||
534 | if (skb_cloned(_skb) && | ||
535 | pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC)) | ||
536 | goto exit; | ||
537 | |||
538 | /* reassign after skb header modifications */ | ||
539 | hdr = buf_msg(_skb); | ||
540 | /* Now reverse the concerned fields */ | 539 | /* Now reverse the concerned fields */ |
541 | msg_set_errcode(hdr, err); | 540 | msg_set_errcode(hdr, err); |
542 | msg_set_non_seq(hdr, 0); | 541 | 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 | if (!skb_cloned(skb)) | 594 | if (!skb_cloned(skb)) |
596 | return true; | 595 | return true; |
597 | 596 | ||
598 | /* Unclone buffer in case it was bundled */ | ||
599 | if (pskb_expand_head(skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC)) | ||
600 | return false; | ||
601 | |||
602 | return true; | 597 | return true; |
603 | } | 598 | } |
604 | 599 | ||