2019-05-27 06:55:01 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* Routines having to do with the 'struct sk_buff' memory handlers.
|
|
|
|
*
|
2008-10-14 02:01:08 +00:00
|
|
|
* Authors: Alan Cox <alan@lxorguk.ukuu.org.uk>
|
2005-04-16 22:20:36 +00:00
|
|
|
* Florian La Roche <rzsfl@rz.uni-sb.de>
|
|
|
|
*
|
|
|
|
* Fixes:
|
|
|
|
* Alan Cox : Fixed the worst of the load
|
|
|
|
* balancer bugs.
|
|
|
|
* Dave Platt : Interrupt stacking fix.
|
|
|
|
* Richard Kooijman : Timestamp fixes.
|
|
|
|
* Alan Cox : Changed buffer format.
|
|
|
|
* Alan Cox : destructor hook for AF_UNIX etc.
|
|
|
|
* Linus Torvalds : Better skb_clone.
|
|
|
|
* Alan Cox : Added skb_copy.
|
|
|
|
* Alan Cox : Added all the changed routines Linus
|
|
|
|
* only put in the headers
|
|
|
|
* Ray VanTassle : Fixed --skb->lock in free
|
|
|
|
* Alan Cox : skb_copy copy arp field
|
|
|
|
* Andi Kleen : slabified it.
|
|
|
|
* Robert Olsson : Removed skb_head_pool
|
|
|
|
*
|
|
|
|
* NOTE:
|
|
|
|
* The __skb_ routines should be called with interrupts
|
|
|
|
* disabled, or you better be *real* sure that the operation is atomic
|
|
|
|
* with respect to whatever list is being frobbed (e.g. via lock_sock()
|
|
|
|
* or via disabling bottom half handlers, etc).
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The functions in this file will not compile correctly with gcc 2.4.x
|
|
|
|
*/
|
|
|
|
|
2012-05-16 19:58:40 +00:00
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/in.h>
|
|
|
|
#include <linux/inet.h>
|
|
|
|
#include <linux/slab.h>
|
2014-01-26 09:58:16 +00:00
|
|
|
#include <linux/tcp.h>
|
|
|
|
#include <linux/udp.h>
|
2016-06-02 18:05:43 +00:00
|
|
|
#include <linux/sctp.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/netdevice.h>
|
|
|
|
#ifdef CONFIG_NET_CLS_ACT
|
|
|
|
#include <net/pkt_sched.h>
|
|
|
|
#endif
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/skbuff.h>
|
2024-04-10 19:05:01 +00:00
|
|
|
#include <linux/skbuff_ref.h>
|
2007-11-07 07:30:13 +00:00
|
|
|
#include <linux/splice.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/cache.h>
|
|
|
|
#include <linux/rtnetlink.h>
|
|
|
|
#include <linux/init.h>
|
2007-04-03 03:19:53 +00:00
|
|
|
#include <linux/scatterlist.h>
|
2009-02-12 05:03:37 +00:00
|
|
|
#include <linux/errqueue.h>
|
2011-05-20 19:50:29 +00:00
|
|
|
#include <linux/prefetch.h>
|
2023-04-19 12:52:53 +00:00
|
|
|
#include <linux/bitfield.h>
|
net: Always untag vlan-tagged traffic on input.
Currently the functionality to untag traffic on input resides
as part of the vlan module and is build only when VLAN support
is enabled in the kernel. When VLAN is disabled, the function
vlan_untag() turns into a stub and doesn't really untag the
packets. This seems to create an interesting interaction
between VMs supporting checksum offloading and some network drivers.
There are some drivers that do not allow the user to change
tx-vlan-offload feature of the driver. These drivers also seem
to assume that any VLAN-tagged traffic they transmit will
have the vlan information in the vlan_tci and not in the vlan
header already in the skb. When transmitting skbs that already
have tagged data with partial checksum set, the checksum doesn't
appear to be updated correctly by the card thus resulting in a
failure to establish TCP connections.
The following is a packet trace taken on the receiver where a
sender is a VM with a VLAN configued. The host VM is running on
doest not have VLAN support and the outging interface on the
host is tg3:
10:12:43.503055 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27243,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x48d9), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294837885 ecr 0,nop,wscale 7], length 0
10:12:44.505556 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27244,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x44ee), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294838888 ecr 0,nop,wscale 7], length 0
This connection finally times out.
I've only access to the TG3 hardware in this configuration thus have
only tested this with TG3 driver. There are a lot of other drivers
that do not permit user changes to vlan acceleration features, and
I don't know if they all suffere from a similar issue.
The patch attempt to fix this another way. It moves the vlan header
stipping code out of the vlan module and always builds it into the
kernel network core. This way, even if vlan is not supported on
a virtualizatoin host, the virtual machines running on top of such
host will still work with VLANs enabled.
CC: Patrick McHardy <kaber@trash.net>
CC: Nithin Nayak Sujir <nsujir@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
CC: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-08 18:42:13 +00:00
|
|
|
#include <linux/if_vlan.h>
|
2019-07-07 14:01:57 +00:00
|
|
|
#include <linux/mpls.h>
|
2021-02-18 17:31:24 +00:00
|
|
|
#include <linux/kcov.h>
|
2023-09-25 12:03:06 +00:00
|
|
|
#include <linux/iov_iter.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
#include <net/protocol.h>
|
|
|
|
#include <net/dst.h>
|
|
|
|
#include <net/sock.h>
|
|
|
|
#include <net/checksum.h>
|
2023-06-08 19:17:37 +00:00
|
|
|
#include <net/gso.h>
|
2024-03-06 16:00:23 +00:00
|
|
|
#include <net/hotdata.h>
|
2014-01-09 10:02:46 +00:00
|
|
|
#include <net/ip6_checksum.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <net/xfrm.h>
|
2019-07-07 14:01:54 +00:00
|
|
|
#include <net/mpls.h>
|
2020-01-09 15:59:19 +00:00
|
|
|
#include <net/mptcp.h>
|
2021-10-29 03:01:44 +00:00
|
|
|
#include <net/mctp.h>
|
net: skbuff: don't include <net/page_pool/types.h> to <linux/skbuff.h>
Currently, touching <net/page_pool/types.h> triggers a rebuild of more
than half of the kernel. That's because it's included in
<linux/skbuff.h>. And each new include to page_pool/types.h adds more
[useless] data for the toolchain to process per each source file from
that pile.
In commit 6a5bcd84e886 ("page_pool: Allow drivers to hint on SKB
recycling"), Matteo included it to be able to call a couple of functions
defined there. Then, in commit 57f05bc2ab24 ("page_pool: keep pp info as
long as page pool owns the page") one of the calls was removed, so only
one was left. It's the call to page_pool_return_skb_page() in
napi_frag_unref(). The function is external and doesn't have any
dependencies. Having very niche page_pool_types.h included only for that
looks like an overkill.
As %PP_SIGNATURE is not local to page_pool.c (was only in the
early submissions), nothing holds this function there. Teleport
page_pool_return_skb_page() to skbuff.c, just next to the main consumer,
skb_pp_recycle(), and rename it to napi_pp_put_page(), as it doesn't
work with skbs at all and the former name tells nothing. The #if guards
here are only to not compile and have it in the vmlinux when not needed
-- both call sites are already guarded.
Now, touching page_pool_types.h only triggers rebuilding of the drivers
using it and a couple of core networking files.
Suggested-by: Jakub Kicinski <kuba@kernel.org> # make skbuff.h less heavy
Suggested-by: Alexander Duyck <alexanderduyck@fb.com> # move to skbuff.c
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://lore.kernel.org/r/20230804180529.2483231-3-aleksander.lobakin@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-04 18:05:25 +00:00
|
|
|
#include <net/page_pool/helpers.h>
|
2023-04-19 12:52:53 +00:00
|
|
|
#include <net/dropreason.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2016-12-24 19:46:01 +00:00
|
|
|
#include <linux/uaccess.h>
|
2009-04-14 23:39:12 +00:00
|
|
|
#include <trace/events/skb.h>
|
2012-04-05 09:35:15 +00:00
|
|
|
#include <linux/highmem.h>
|
2015-01-30 18:29:32 +00:00
|
|
|
#include <linux/capability.h>
|
|
|
|
#include <linux/user_namespace.h>
|
2019-05-29 15:13:48 +00:00
|
|
|
#include <linux/indirect_call_wrapper.h>
|
2023-01-26 07:14:17 +00:00
|
|
|
#include <linux/textsearch.h>
|
2006-10-19 20:08:53 +00:00
|
|
|
|
2022-05-16 04:24:55 +00:00
|
|
|
#include "dev.h"
|
2021-10-22 10:28:37 +00:00
|
|
|
#include "sock_destructor.h"
|
2019-03-25 16:17:23 +00:00
|
|
|
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
#ifdef CONFIG_SKB_EXTENSIONS
|
|
|
|
static struct kmem_cache *skbuff_ext_cache __ro_after_init;
|
|
|
|
#endif
|
2023-02-06 17:31:03 +00:00
|
|
|
|
|
|
|
#define SKB_SMALL_HEAD_SIZE SKB_HEAD_ALIGN(MAX_TCP_HEADER)
|
|
|
|
|
|
|
|
/* We want SKB_SMALL_HEAD_CACHE_SIZE to not be a power of two.
|
|
|
|
* This should ensure that SKB_SMALL_HEAD_HEADROOM is a unique
|
|
|
|
* size, and we can differentiate heads from skb_small_head_cache
|
|
|
|
* vs system slabs by looking at their size (skb_end_offset()).
|
|
|
|
*/
|
|
|
|
#define SKB_SMALL_HEAD_CACHE_SIZE \
|
|
|
|
(is_power_of_2(SKB_SMALL_HEAD_SIZE) ? \
|
|
|
|
(SKB_SMALL_HEAD_SIZE + L1_CACHE_BYTES) : \
|
|
|
|
SKB_SMALL_HEAD_SIZE)
|
|
|
|
|
|
|
|
#define SKB_SMALL_HEAD_HEADROOM \
|
|
|
|
SKB_WITH_OVERHEAD(SKB_SMALL_HEAD_CACHE_SIZE)
|
|
|
|
|
2024-02-14 22:34:03 +00:00
|
|
|
/* kcm_write_msgs() relies on casting paged frags to bio_vec to use
|
|
|
|
* iov_iter_bvec(). These static asserts ensure the cast is valid is long as the
|
|
|
|
* netmem is a page.
|
|
|
|
*/
|
|
|
|
static_assert(offsetof(struct bio_vec, bv_page) ==
|
|
|
|
offsetof(skb_frag_t, netmem));
|
|
|
|
static_assert(sizeof_field(struct bio_vec, bv_page) ==
|
|
|
|
sizeof_field(skb_frag_t, netmem));
|
|
|
|
|
|
|
|
static_assert(offsetof(struct bio_vec, bv_len) == offsetof(skb_frag_t, len));
|
|
|
|
static_assert(sizeof_field(struct bio_vec, bv_len) ==
|
|
|
|
sizeof_field(skb_frag_t, len));
|
|
|
|
|
|
|
|
static_assert(offsetof(struct bio_vec, bv_offset) ==
|
|
|
|
offsetof(skb_frag_t, offset));
|
|
|
|
static_assert(sizeof_field(struct bio_vec, bv_offset) ==
|
|
|
|
sizeof_field(skb_frag_t, offset));
|
|
|
|
|
net: skb: export skb drop reaons to user by TRACE_DEFINE_ENUM
As Eric reported, the 'reason' field is not presented when trace the
kfree_skb event by perf:
$ perf record -e skb:kfree_skb -a sleep 10
$ perf script
ip_defrag 14605 [021] 221.614303: skb:kfree_skb:
skbaddr=0xffff9d2851242700 protocol=34525 location=0xffffffffa39346b1
reason:
The cause seems to be passing kernel address directly to TP_printk(),
which is not right. As the enum 'skb_drop_reason' is not exported to
user space through TRACE_DEFINE_ENUM(), perf can't get the drop reason
string from the 'reason' field, which is a number.
Therefore, we introduce the macro DEFINE_DROP_REASON(), which is used
to define the trace enum by TRACE_DEFINE_ENUM(). With the help of
DEFINE_DROP_REASON(), now we can remove the auto-generate that we
introduced in the commit ec43908dd556
("net: skb: use auto-generation to convert skb drop reason to string"),
and define the string array 'drop_reasons'.
Hmmmm...now we come back to the situation that have to maintain drop
reasons in both enum skb_drop_reason and DEFINE_DROP_REASON. But they
are both in dropreason.h, which makes it easier.
After this commit, now the format of kfree_skb is like this:
$ cat /tracing/events/skb/kfree_skb/format
name: kfree_skb
ID: 1524
format:
field:unsigned short common_type; offset:0; size:2; signed:0;
field:unsigned char common_flags; offset:2; size:1; signed:0;
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
field:int common_pid; offset:4; size:4; signed:1;
field:void * skbaddr; offset:8; size:8; signed:0;
field:void * location; offset:16; size:8; signed:0;
field:unsigned short protocol; offset:24; size:2; signed:0;
field:enum skb_drop_reason reason; offset:28; size:4; signed:0;
print fmt: "skbaddr=%p protocol=%u location=%p reason: %s", REC->skbaddr, REC->protocol, REC->location, __print_symbolic(REC->reason, { 1, "NOT_SPECIFIED" }, { 2, "NO_SOCKET" } ......
Fixes: ec43908dd556 ("net: skb: use auto-generation to convert skb drop reason to string")
Link: https://lore.kernel.org/netdev/CANn89i+bx0ybvE55iMYf5GJM48WwV1HNpdm9Q6t-HaEstqpCSA@mail.gmail.com/
Reported-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Menglong Dong <imagedong@tencent.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-09-05 03:50:15 +00:00
|
|
|
#undef FN
|
|
|
|
#define FN(reason) [SKB_DROP_REASON_##reason] = #reason,
|
2023-04-19 12:52:53 +00:00
|
|
|
static const char * const drop_reasons[] = {
|
2022-10-29 15:45:16 +00:00
|
|
|
[SKB_CONSUMED] = "CONSUMED",
|
net: skb: export skb drop reaons to user by TRACE_DEFINE_ENUM
As Eric reported, the 'reason' field is not presented when trace the
kfree_skb event by perf:
$ perf record -e skb:kfree_skb -a sleep 10
$ perf script
ip_defrag 14605 [021] 221.614303: skb:kfree_skb:
skbaddr=0xffff9d2851242700 protocol=34525 location=0xffffffffa39346b1
reason:
The cause seems to be passing kernel address directly to TP_printk(),
which is not right. As the enum 'skb_drop_reason' is not exported to
user space through TRACE_DEFINE_ENUM(), perf can't get the drop reason
string from the 'reason' field, which is a number.
Therefore, we introduce the macro DEFINE_DROP_REASON(), which is used
to define the trace enum by TRACE_DEFINE_ENUM(). With the help of
DEFINE_DROP_REASON(), now we can remove the auto-generate that we
introduced in the commit ec43908dd556
("net: skb: use auto-generation to convert skb drop reason to string"),
and define the string array 'drop_reasons'.
Hmmmm...now we come back to the situation that have to maintain drop
reasons in both enum skb_drop_reason and DEFINE_DROP_REASON. But they
are both in dropreason.h, which makes it easier.
After this commit, now the format of kfree_skb is like this:
$ cat /tracing/events/skb/kfree_skb/format
name: kfree_skb
ID: 1524
format:
field:unsigned short common_type; offset:0; size:2; signed:0;
field:unsigned char common_flags; offset:2; size:1; signed:0;
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
field:int common_pid; offset:4; size:4; signed:1;
field:void * skbaddr; offset:8; size:8; signed:0;
field:void * location; offset:16; size:8; signed:0;
field:unsigned short protocol; offset:24; size:2; signed:0;
field:enum skb_drop_reason reason; offset:28; size:4; signed:0;
print fmt: "skbaddr=%p protocol=%u location=%p reason: %s", REC->skbaddr, REC->protocol, REC->location, __print_symbolic(REC->reason, { 1, "NOT_SPECIFIED" }, { 2, "NO_SOCKET" } ......
Fixes: ec43908dd556 ("net: skb: use auto-generation to convert skb drop reason to string")
Link: https://lore.kernel.org/netdev/CANn89i+bx0ybvE55iMYf5GJM48WwV1HNpdm9Q6t-HaEstqpCSA@mail.gmail.com/
Reported-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Menglong Dong <imagedong@tencent.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-09-05 03:50:15 +00:00
|
|
|
DEFINE_DROP_REASON(FN, FN)
|
|
|
|
};
|
2023-04-19 12:52:53 +00:00
|
|
|
|
|
|
|
static const struct drop_reason_list drop_reasons_core = {
|
|
|
|
.reasons = drop_reasons,
|
|
|
|
.n_reasons = ARRAY_SIZE(drop_reasons),
|
|
|
|
};
|
|
|
|
|
|
|
|
const struct drop_reason_list __rcu *
|
|
|
|
drop_reasons_by_subsys[SKB_DROP_REASON_SUBSYS_NUM] = {
|
|
|
|
[SKB_DROP_REASON_SUBSYS_CORE] = RCU_INITIALIZER(&drop_reasons_core),
|
|
|
|
};
|
|
|
|
EXPORT_SYMBOL(drop_reasons_by_subsys);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* drop_reasons_register_subsys - register another drop reason subsystem
|
|
|
|
* @subsys: the subsystem to register, must not be the core
|
|
|
|
* @list: the list of drop reasons within the subsystem, must point to
|
|
|
|
* a statically initialized list
|
|
|
|
*/
|
|
|
|
void drop_reasons_register_subsys(enum skb_drop_reason_subsys subsys,
|
|
|
|
const struct drop_reason_list *list)
|
|
|
|
{
|
|
|
|
if (WARN(subsys <= SKB_DROP_REASON_SUBSYS_CORE ||
|
|
|
|
subsys >= ARRAY_SIZE(drop_reasons_by_subsys),
|
|
|
|
"invalid subsystem %d\n", subsys))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* must point to statically allocated memory, so INIT is OK */
|
|
|
|
RCU_INIT_POINTER(drop_reasons_by_subsys[subsys], list);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(drop_reasons_register_subsys);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* drop_reasons_unregister_subsys - unregister a drop reason subsystem
|
|
|
|
* @subsys: the subsystem to remove, must not be the core
|
|
|
|
*
|
|
|
|
* Note: This will synchronize_rcu() to ensure no users when it returns.
|
|
|
|
*/
|
|
|
|
void drop_reasons_unregister_subsys(enum skb_drop_reason_subsys subsys)
|
|
|
|
{
|
|
|
|
if (WARN(subsys <= SKB_DROP_REASON_SUBSYS_CORE ||
|
|
|
|
subsys >= ARRAY_SIZE(drop_reasons_by_subsys),
|
|
|
|
"invalid subsystem %d\n", subsys))
|
|
|
|
return;
|
|
|
|
|
|
|
|
RCU_INIT_POINTER(drop_reasons_by_subsys[subsys], NULL);
|
|
|
|
|
|
|
|
synchronize_rcu();
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(drop_reasons_unregister_subsys);
|
2022-06-06 02:24:35 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
2013-02-11 13:30:38 +00:00
|
|
|
* skb_panic - private function for out-of-line support
|
|
|
|
* @skb: buffer
|
|
|
|
* @sz: size
|
|
|
|
* @addr: address
|
2013-02-13 11:20:27 +00:00
|
|
|
* @msg: skb_over_panic or skb_under_panic
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
2013-02-11 13:30:38 +00:00
|
|
|
* Out-of-line support for skb_put() and skb_push().
|
|
|
|
* Called via the wrapper skb_over_panic() or skb_under_panic().
|
|
|
|
* Keep out of line to prevent kernel bloat.
|
|
|
|
* __builtin_return_address is not used because it is not always reliable.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2013-02-11 13:30:38 +00:00
|
|
|
static void skb_panic(struct sk_buff *skb, unsigned int sz, void *addr,
|
2013-02-13 11:20:27 +00:00
|
|
|
const char msg[])
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2020-04-27 16:37:43 +00:00
|
|
|
pr_emerg("%s: text:%px len:%d put:%d head:%px data:%px tail:%#lx end:%#lx dev:%s\n",
|
2013-02-13 11:20:27 +00:00
|
|
|
msg, addr, skb->len, sz, skb->head, skb->data,
|
2012-05-16 19:58:40 +00:00
|
|
|
(unsigned long)skb->tail, (unsigned long)skb->end,
|
|
|
|
skb->dev ? skb->dev->name : "<NULL>");
|
2005-04-16 22:20:36 +00:00
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
|
2013-02-11 13:30:38 +00:00
|
|
|
static void skb_over_panic(struct sk_buff *skb, unsigned int sz, void *addr)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2013-02-11 13:30:38 +00:00
|
|
|
skb_panic(skb, sz, addr, __func__);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2013-02-11 13:30:38 +00:00
|
|
|
static void skb_under_panic(struct sk_buff *skb, unsigned int sz, void *addr)
|
|
|
|
{
|
|
|
|
skb_panic(skb, sz, addr, __func__);
|
|
|
|
}
|
2012-07-31 23:44:19 +00:00
|
|
|
|
2021-02-13 14:12:13 +00:00
|
|
|
#define NAPI_SKB_CACHE_SIZE 64
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
#define NAPI_SKB_CACHE_BULK 16
|
|
|
|
#define NAPI_SKB_CACHE_HALF (NAPI_SKB_CACHE_SIZE / 2)
|
2021-02-13 14:12:13 +00:00
|
|
|
|
2022-09-28 08:43:09 +00:00
|
|
|
#if PAGE_SIZE == SZ_4K
|
|
|
|
|
|
|
|
#define NAPI_HAS_SMALL_PAGE_FRAG 1
|
|
|
|
#define NAPI_SMALL_PAGE_PFMEMALLOC(nc) ((nc).pfmemalloc)
|
|
|
|
|
|
|
|
/* specialized page frag allocator using a single order 0 page
|
|
|
|
* and slicing it into 1K sized fragment. Constrained to systems
|
|
|
|
* with a very limited amount of 1K fragments fitting a single
|
|
|
|
* page - to avoid excessive truesize underestimation
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct page_frag_1k {
|
|
|
|
void *va;
|
|
|
|
u16 offset;
|
|
|
|
bool pfmemalloc;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *page_frag_alloc_1k(struct page_frag_1k *nc, gfp_t gfp)
|
|
|
|
{
|
|
|
|
struct page *page;
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
offset = nc->offset - SZ_1K;
|
|
|
|
if (likely(offset >= 0))
|
|
|
|
goto use_frag;
|
|
|
|
|
|
|
|
page = alloc_pages_node(NUMA_NO_NODE, gfp, 0);
|
|
|
|
if (!page)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
nc->va = page_address(page);
|
|
|
|
nc->pfmemalloc = page_is_pfmemalloc(page);
|
|
|
|
offset = PAGE_SIZE - SZ_1K;
|
|
|
|
page_ref_add(page, offset / SZ_1K);
|
|
|
|
|
|
|
|
use_frag:
|
|
|
|
nc->offset = offset;
|
|
|
|
return nc->va + offset;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
|
|
|
|
/* the small page is actually unused in this build; add dummy helpers
|
|
|
|
* to please the compiler and avoid later preprocessor's conditionals
|
|
|
|
*/
|
|
|
|
#define NAPI_HAS_SMALL_PAGE_FRAG 0
|
|
|
|
#define NAPI_SMALL_PAGE_PFMEMALLOC(nc) false
|
|
|
|
|
|
|
|
struct page_frag_1k {
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *page_frag_alloc_1k(struct page_frag_1k *nc, gfp_t gfp_mask)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2021-02-13 14:12:13 +00:00
|
|
|
struct napi_alloc_cache {
|
|
|
|
struct page_frag_cache page;
|
2022-09-28 08:43:09 +00:00
|
|
|
struct page_frag_1k page_small;
|
2021-02-13 14:12:13 +00:00
|
|
|
unsigned int skb_count;
|
|
|
|
void *skb_cache[NAPI_SKB_CACHE_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
static DEFINE_PER_CPU(struct page_frag_cache, netdev_alloc_cache);
|
|
|
|
static DEFINE_PER_CPU(struct napi_alloc_cache, napi_alloc_cache);
|
|
|
|
|
2022-09-28 08:43:09 +00:00
|
|
|
/* Double check that napi_get_frags() allocates skbs with
|
|
|
|
* skb->head being backed by slab, not a page fragment.
|
|
|
|
* This is to make sure bug fixed in 3226b158e67c
|
|
|
|
* ("net: avoid 32 x truesize under-estimation for tiny skbs")
|
|
|
|
* does not accidentally come back.
|
|
|
|
*/
|
|
|
|
void napi_get_frags_check(struct napi_struct *napi)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
local_bh_disable();
|
|
|
|
skb = napi_get_frags(napi);
|
|
|
|
WARN_ON_ONCE(!NAPI_HAS_SMALL_PAGE_FRAG && skb && skb->head_frag);
|
|
|
|
napi_free_frags(napi);
|
|
|
|
local_bh_enable();
|
|
|
|
}
|
|
|
|
|
2021-09-14 03:49:35 +00:00
|
|
|
void *__napi_alloc_frag_align(unsigned int fragsz, unsigned int align_mask)
|
2021-02-13 14:12:13 +00:00
|
|
|
{
|
|
|
|
struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
|
|
|
|
|
|
|
|
fragsz = SKB_DATA_ALIGN(fragsz);
|
|
|
|
|
2024-02-28 09:30:08 +00:00
|
|
|
return __page_frag_alloc_align(&nc->page, fragsz, GFP_ATOMIC,
|
|
|
|
align_mask);
|
2021-02-13 14:12:13 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__napi_alloc_frag_align);
|
|
|
|
|
|
|
|
void *__netdev_alloc_frag_align(unsigned int fragsz, unsigned int align_mask)
|
|
|
|
{
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
fragsz = SKB_DATA_ALIGN(fragsz);
|
2021-08-13 14:57:49 +00:00
|
|
|
if (in_hardirq() || irqs_disabled()) {
|
2021-09-14 03:49:35 +00:00
|
|
|
struct page_frag_cache *nc = this_cpu_ptr(&netdev_alloc_cache);
|
|
|
|
|
2024-02-28 09:30:08 +00:00
|
|
|
data = __page_frag_alloc_align(nc, fragsz, GFP_ATOMIC,
|
|
|
|
align_mask);
|
2021-02-13 14:12:13 +00:00
|
|
|
} else {
|
2021-09-14 03:49:35 +00:00
|
|
|
struct napi_alloc_cache *nc;
|
|
|
|
|
2021-02-13 14:12:13 +00:00
|
|
|
local_bh_disable();
|
2021-09-14 03:49:35 +00:00
|
|
|
nc = this_cpu_ptr(&napi_alloc_cache);
|
2024-02-28 09:30:08 +00:00
|
|
|
data = __page_frag_alloc_align(&nc->page, fragsz, GFP_ATOMIC,
|
|
|
|
align_mask);
|
2021-02-13 14:12:13 +00:00
|
|
|
local_bh_enable();
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__netdev_alloc_frag_align);
|
|
|
|
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
static struct sk_buff *napi_skb_cache_get(void)
|
|
|
|
{
|
|
|
|
struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
2022-06-15 03:24:26 +00:00
|
|
|
if (unlikely(!nc->skb_count)) {
|
2024-03-06 16:00:23 +00:00
|
|
|
nc->skb_count = kmem_cache_alloc_bulk(net_hotdata.skbuff_cache,
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
GFP_ATOMIC,
|
|
|
|
NAPI_SKB_CACHE_BULK,
|
|
|
|
nc->skb_cache);
|
2022-06-15 03:24:26 +00:00
|
|
|
if (unlikely(!nc->skb_count))
|
|
|
|
return NULL;
|
|
|
|
}
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
|
|
|
|
skb = nc->skb_cache[--nc->skb_count];
|
2024-03-06 16:00:23 +00:00
|
|
|
kasan_mempool_unpoison_object(skb, kmem_cache_size(net_hotdata.skbuff_cache));
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
2022-12-08 06:02:59 +00:00
|
|
|
static inline void __finalize_skb_around(struct sk_buff *skb, void *data,
|
|
|
|
unsigned int size)
|
2019-04-12 15:07:37 +00:00
|
|
|
{
|
|
|
|
struct skb_shared_info *shinfo;
|
|
|
|
|
|
|
|
size -= SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
|
|
|
|
|
|
|
|
/* Assumes caller memset cleared SKB */
|
|
|
|
skb->truesize = SKB_TRUESIZE(size);
|
|
|
|
refcount_set(&skb->users, 1);
|
|
|
|
skb->head = data;
|
|
|
|
skb->data = data;
|
|
|
|
skb_reset_tail_pointer(skb);
|
2022-02-22 03:21:12 +00:00
|
|
|
skb_set_end_offset(skb, size);
|
2019-04-12 15:07:37 +00:00
|
|
|
skb->mac_header = (typeof(skb->mac_header))~0U;
|
|
|
|
skb->transport_header = (typeof(skb->transport_header))~0U;
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
skb->alloc_cpu = raw_smp_processor_id();
|
2019-04-12 15:07:37 +00:00
|
|
|
/* make sure we initialize shinfo sequentially */
|
|
|
|
shinfo = skb_shinfo(skb);
|
|
|
|
memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
|
|
|
|
atomic_set(&shinfo->dataref, 1);
|
|
|
|
|
2020-10-29 17:36:19 +00:00
|
|
|
skb_set_kcov_handle(skb, kcov_common_handle());
|
2019-04-12 15:07:37 +00:00
|
|
|
}
|
|
|
|
|
2022-12-08 06:02:59 +00:00
|
|
|
static inline void *__slab_build_skb(struct sk_buff *skb, void *data,
|
|
|
|
unsigned int *size)
|
|
|
|
{
|
|
|
|
void *resized;
|
|
|
|
|
|
|
|
/* Must find the allocation size (and grow it to match). */
|
|
|
|
*size = ksize(data);
|
|
|
|
/* krealloc() will immediately return "data" when
|
|
|
|
* "ksize(data)" is requested: it is the existing upper
|
|
|
|
* bounds. As a result, GFP_ATOMIC will be ignored. Note
|
|
|
|
* that this "new" pointer needs to be passed back to the
|
|
|
|
* caller for use so the __alloc_size hinting will be
|
|
|
|
* tracked correctly.
|
|
|
|
*/
|
|
|
|
resized = krealloc(data, *size, GFP_ATOMIC);
|
|
|
|
WARN_ON_ONCE(resized != data);
|
|
|
|
return resized;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* build_skb() variant which can operate on slab buffers.
|
|
|
|
* Note that this should be used sparingly as slab buffers
|
|
|
|
* cannot be combined efficiently by GRO!
|
|
|
|
*/
|
|
|
|
struct sk_buff *slab_build_skb(void *data)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
unsigned int size;
|
|
|
|
|
2024-03-06 16:00:23 +00:00
|
|
|
skb = kmem_cache_alloc(net_hotdata.skbuff_cache, GFP_ATOMIC);
|
2022-12-08 06:02:59 +00:00
|
|
|
if (unlikely(!skb))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memset(skb, 0, offsetof(struct sk_buff, tail));
|
|
|
|
data = __slab_build_skb(skb, data, &size);
|
|
|
|
__finalize_skb_around(skb, data, size);
|
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(slab_build_skb);
|
|
|
|
|
|
|
|
/* Caller must provide SKB that is memset cleared */
|
|
|
|
static void __build_skb_around(struct sk_buff *skb, void *data,
|
|
|
|
unsigned int frag_size)
|
|
|
|
{
|
|
|
|
unsigned int size = frag_size;
|
|
|
|
|
|
|
|
/* frag_size == 0 is considered deprecated now. Callers
|
|
|
|
* using slab buffer should use slab_build_skb() instead.
|
|
|
|
*/
|
|
|
|
if (WARN_ONCE(size == 0, "Use slab_build_skb() instead"))
|
|
|
|
data = __slab_build_skb(skb, data, &size);
|
|
|
|
|
|
|
|
__finalize_skb_around(skb, data, size);
|
|
|
|
}
|
|
|
|
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
/**
|
2015-04-24 23:05:01 +00:00
|
|
|
* __build_skb - build a network buffer
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
* @data: data buffer provided by caller
|
2022-12-08 06:02:59 +00:00
|
|
|
* @frag_size: size of data (must not be 0)
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
*
|
|
|
|
* Allocate a new &sk_buff. Caller provides space holding head and
|
2022-12-08 06:02:59 +00:00
|
|
|
* skb_shared_info. @data must have been allocated from the page
|
|
|
|
* allocator or vmalloc(). (A @frag_size of 0 to indicate a kmalloc()
|
|
|
|
* allocation is deprecated, and callers should use slab_build_skb()
|
|
|
|
* instead.)
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
* The return is the new skb buffer.
|
|
|
|
* On a failure the return is %NULL, and @data is not freed.
|
|
|
|
* Notes :
|
|
|
|
* Before IO, driver allocates only data buffer where NIC put incoming frame
|
|
|
|
* Driver should add room at head (NET_SKB_PAD) and
|
|
|
|
* MUST add room at tail (SKB_DATA_ALIGN(skb_shared_info))
|
|
|
|
* After IO, driver calls build_skb(), to allocate sk_buff and populate it
|
|
|
|
* before giving packet to stack.
|
|
|
|
* RX rings only contains data buffers, not full skbs.
|
|
|
|
*/
|
2015-04-24 23:05:01 +00:00
|
|
|
struct sk_buff *__build_skb(void *data, unsigned int frag_size)
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
2024-03-06 16:00:23 +00:00
|
|
|
skb = kmem_cache_alloc(net_hotdata.skbuff_cache, GFP_ATOMIC);
|
2019-04-12 15:07:37 +00:00
|
|
|
if (unlikely(!skb))
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memset(skb, 0, offsetof(struct sk_buff, tail));
|
2021-02-13 14:11:26 +00:00
|
|
|
__build_skb_around(skb, data, frag_size);
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
|
2021-02-13 14:11:26 +00:00
|
|
|
return skb;
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
}
|
2015-04-24 23:05:01 +00:00
|
|
|
|
|
|
|
/* build_skb() is wrapper over __build_skb(), that specifically
|
|
|
|
* takes care of skb->head and skb->pfmemalloc
|
|
|
|
*/
|
|
|
|
struct sk_buff *build_skb(void *data, unsigned int frag_size)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb = __build_skb(data, frag_size);
|
|
|
|
|
2023-03-08 13:17:20 +00:00
|
|
|
if (likely(skb && frag_size)) {
|
2015-04-24 23:05:01 +00:00
|
|
|
skb->head_frag = 1;
|
2023-03-08 13:17:19 +00:00
|
|
|
skb_propagate_pfmemalloc(virt_to_head_page(data), skb);
|
2015-04-24 23:05:01 +00:00
|
|
|
}
|
|
|
|
return skb;
|
|
|
|
}
|
net: introduce build_skb()
One of the thing we discussed during netdev 2011 conference was the idea
to change some network drivers to allocate/populate their skb at RX
completion time, right before feeding the skb to network stack.
In old days, we allocated skbs when populating the RX ring.
This means bringing into cpu cache sk_buff and skb_shared_info cache
lines (since we clear/initialize them), then 'queue' skb->data to NIC.
By the time NIC fills a frame in skb->data buffer and host can process
it, cpu probably threw away the cache lines from its caches, because lot
of things happened between the allocation and final use.
So the deal would be to allocate only the data buffer for the NIC to
populate its RX ring buffer. And use build_skb() at RX completion to
attach a data buffer (now filled with an ethernet frame) to a new skb,
initialize the skb_shared_info portion, and give the hot skb to network
stack.
build_skb() is the function to allocate an skb, caller providing the
data buffer that should be attached to it. Drivers are expected to call
skb_reserve() right after build_skb() to adjust skb->data to the
Ethernet frame (usually skipping NET_SKB_PAD and NET_IP_ALIGN, but some
drivers might add a hardware provided alignment)
Data provided to build_skb() MUST have been allocated by a prior
kmalloc() call, with enough room to add SKB_DATA_ALIGN(sizeof(struct
skb_shared_info)) bytes at the end of the data without corrupting
incoming frame.
data = kmalloc(NET_SKB_PAD + NET_IP_ALIGN + 1536 +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
GFP_ATOMIC);
...
skb = build_skb(data);
if (!skb) {
recycle_data(data);
} else {
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
...
}
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Eilon Greenstein <eilong@broadcom.com>
CC: Ben Hutchings <bhutchings@solarflare.com>
CC: Tom Herbert <therbert@google.com>
CC: Jamal Hadi Salim <hadi@mojatatu.com>
CC: Stephen Hemminger <shemminger@vyatta.com>
CC: Thomas Graf <tgraf@infradead.org>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2011-11-14 06:03:34 +00:00
|
|
|
EXPORT_SYMBOL(build_skb);
|
|
|
|
|
2019-04-12 15:07:37 +00:00
|
|
|
/**
|
|
|
|
* build_skb_around - build a network buffer around provided skb
|
|
|
|
* @skb: sk_buff provide by caller, must be memset cleared
|
|
|
|
* @data: data buffer provided by caller
|
2023-01-07 02:29:04 +00:00
|
|
|
* @frag_size: size of data
|
2019-04-12 15:07:37 +00:00
|
|
|
*/
|
|
|
|
struct sk_buff *build_skb_around(struct sk_buff *skb,
|
|
|
|
void *data, unsigned int frag_size)
|
|
|
|
{
|
|
|
|
if (unlikely(!skb))
|
|
|
|
return NULL;
|
|
|
|
|
2021-02-13 14:11:26 +00:00
|
|
|
__build_skb_around(skb, data, frag_size);
|
2019-04-12 15:07:37 +00:00
|
|
|
|
2021-02-13 14:11:26 +00:00
|
|
|
if (frag_size) {
|
2019-04-12 15:07:37 +00:00
|
|
|
skb->head_frag = 1;
|
2023-03-08 13:17:19 +00:00
|
|
|
skb_propagate_pfmemalloc(virt_to_head_page(data), skb);
|
2019-04-12 15:07:37 +00:00
|
|
|
}
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(build_skb_around);
|
|
|
|
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
/**
|
|
|
|
* __napi_build_skb - build a network buffer
|
|
|
|
* @data: data buffer provided by caller
|
2023-01-07 02:29:04 +00:00
|
|
|
* @frag_size: size of data
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
*
|
|
|
|
* Version of __build_skb() that uses NAPI percpu caches to obtain
|
|
|
|
* skbuff_head instead of inplace allocation.
|
|
|
|
*
|
|
|
|
* Returns a new &sk_buff on success, %NULL on allocation failure.
|
|
|
|
*/
|
|
|
|
static struct sk_buff *__napi_build_skb(void *data, unsigned int frag_size)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
skb = napi_skb_cache_get();
|
|
|
|
if (unlikely(!skb))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memset(skb, 0, offsetof(struct sk_buff, tail));
|
|
|
|
__build_skb_around(skb, data, frag_size);
|
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* napi_build_skb - build a network buffer
|
|
|
|
* @data: data buffer provided by caller
|
2023-01-07 02:29:04 +00:00
|
|
|
* @frag_size: size of data
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
*
|
|
|
|
* Version of __napi_build_skb() that takes care of skb->head_frag
|
|
|
|
* and skb->pfmemalloc when the data is a page or page fragment.
|
|
|
|
*
|
|
|
|
* Returns a new &sk_buff on success, %NULL on allocation failure.
|
|
|
|
*/
|
|
|
|
struct sk_buff *napi_build_skb(void *data, unsigned int frag_size)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb = __napi_build_skb(data, frag_size);
|
|
|
|
|
|
|
|
if (likely(skb) && frag_size) {
|
|
|
|
skb->head_frag = 1;
|
|
|
|
skb_propagate_pfmemalloc(virt_to_head_page(data), skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(napi_build_skb);
|
|
|
|
|
2021-02-13 14:11:00 +00:00
|
|
|
/*
|
|
|
|
* kmalloc_reserve is a wrapper around kmalloc_node_track_caller that tells
|
|
|
|
* the caller if emergency pfmemalloc reserves are being used. If it is and
|
|
|
|
* the socket is later found to be SOCK_MEMALLOC then PFMEMALLOC reserves
|
|
|
|
* may be used. Otherwise, the packet data may be discarded until enough
|
|
|
|
* memory is free
|
|
|
|
*/
|
2023-02-06 17:31:02 +00:00
|
|
|
static void *kmalloc_reserve(unsigned int *size, gfp_t flags, int node,
|
2021-02-13 14:11:11 +00:00
|
|
|
bool *pfmemalloc)
|
2021-02-13 14:11:00 +00:00
|
|
|
{
|
|
|
|
bool ret_pfmemalloc = false;
|
2023-08-31 18:37:50 +00:00
|
|
|
size_t obj_size;
|
2023-02-06 17:31:02 +00:00
|
|
|
void *obj;
|
2021-02-13 14:11:00 +00:00
|
|
|
|
2023-02-06 17:31:02 +00:00
|
|
|
obj_size = SKB_HEAD_ALIGN(*size);
|
2023-02-06 17:31:03 +00:00
|
|
|
if (obj_size <= SKB_SMALL_HEAD_CACHE_SIZE &&
|
|
|
|
!(flags & KMALLOC_NOT_NORMAL_BITS)) {
|
2024-03-06 16:00:23 +00:00
|
|
|
obj = kmem_cache_alloc_node(net_hotdata.skb_small_head_cache,
|
2023-02-06 17:31:03 +00:00
|
|
|
flags | __GFP_NOMEMALLOC | __GFP_NOWARN,
|
|
|
|
node);
|
net: avoid skb end_offset change in __skb_unclone_keeptruesize()
Once initial skb->head has been allocated from skb_small_head_cache,
we need to make sure to use the same strategy whenever skb->head
has to be re-allocated, as found by syzbot [1]
This means kmalloc_reserve() can not fallback from using
skb_small_head_cache to generic (power-of-two) kmem caches.
It seems that we probably want to rework things in the future,
to partially revert following patch, because we no longer use
ksize() for skb allocated in TX path.
2b88cba55883 ("net: preserve skb_end_offset() in skb_unclone_keeptruesize()")
Ideally, TCP stack should never put payload in skb->head,
this effort has to be completed.
In the mean time, add a sanity check.
[1]
BUG: KASAN: invalid-free in slab_free mm/slub.c:3787 [inline]
BUG: KASAN: invalid-free in kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
Free of addr ffff88806cdee800 by task syz-executor239/5189
CPU: 0 PID: 5189 Comm: syz-executor239 Not tainted 6.2.0-rc8-syzkaller-02400-gd1fabc68f8e0 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:306 [inline]
print_report+0x15e/0x45d mm/kasan/report.c:417
kasan_report_invalid_free+0x9b/0x1b0 mm/kasan/report.c:482
____kasan_slab_free+0x1a5/0x1c0 mm/kasan/common.c:216
kasan_slab_free include/linux/kasan.h:177 [inline]
slab_free_hook mm/slub.c:1781 [inline]
slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1807
slab_free mm/slub.c:3787 [inline]
kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
skb_kfree_head net/core/skbuff.c:857 [inline]
skb_kfree_head net/core/skbuff.c:853 [inline]
skb_free_head+0x16f/0x1a0 net/core/skbuff.c:872
skb_release_data+0x57a/0x820 net/core/skbuff.c:901
skb_release_all net/core/skbuff.c:966 [inline]
__kfree_skb+0x4f/0x70 net/core/skbuff.c:980
tcp_wmem_free_skb include/net/tcp.h:302 [inline]
tcp_rtx_queue_purge net/ipv4/tcp.c:3061 [inline]
tcp_write_queue_purge+0x617/0xcf0 net/ipv4/tcp.c:3074
tcp_v4_destroy_sock+0x125/0x810 net/ipv4/tcp_ipv4.c:2302
inet_csk_destroy_sock+0x19a/0x440 net/ipv4/inet_connection_sock.c:1195
__tcp_close+0xb96/0xf50 net/ipv4/tcp.c:3021
tcp_close+0x2d/0xc0 net/ipv4/tcp.c:3033
inet_release+0x132/0x270 net/ipv4/af_inet.c:426
__sock_release+0xcd/0x280 net/socket.c:651
sock_close+0x1c/0x20 net/socket.c:1393
__fput+0x27c/0xa90 fs/file_table.c:320
task_work_run+0x16f/0x270 kernel/task_work.c:179
resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
exit_to_user_mode_loop kernel/entry/common.c:171 [inline]
exit_to_user_mode_prepare+0x23c/0x250 kernel/entry/common.c:203
__syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296
do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f2511f546c3
Code: c7 c2 c0 ff ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 64 8b 04 25 18 00 00 00 85 c0 75 14 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 89 7c 24 0c e8
RSP: 002b:00007ffef0103d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
RAX: 0000000000000000 RBX: 0000000000000004 RCX: 00007f2511f546c3
RDX: 0000000000000978 RSI: 00000000200000c0 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000002 R09: 0000000000003434
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffef0103d6c
R13: 00007ffef0103d80 R14: 00007ffef0103dc0 R15: 0000000000000003
</TASK>
Allocated by task 5189:
kasan_save_stack+0x22/0x40 mm/kasan/common.c:45
kasan_set_track+0x25/0x30 mm/kasan/common.c:52
____kasan_kmalloc mm/kasan/common.c:374 [inline]
____kasan_kmalloc mm/kasan/common.c:333 [inline]
__kasan_kmalloc+0xa5/0xb0 mm/kasan/common.c:383
kasan_kmalloc include/linux/kasan.h:211 [inline]
__do_kmalloc_node mm/slab_common.c:968 [inline]
__kmalloc_node_track_caller+0x5b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
pskb_expand_head+0x237/0x1160 net/core/skbuff.c:1995
__skb_unclone_keeptruesize+0x93/0x220 net/core/skbuff.c:2094
skb_unclone_keeptruesize include/linux/skbuff.h:1910 [inline]
skb_prepare_for_shift net/core/skbuff.c:3804 [inline]
skb_shift+0xef8/0x1e20 net/core/skbuff.c:3877
tcp_skb_shift net/ipv4/tcp_input.c:1538 [inline]
tcp_shift_skb_data net/ipv4/tcp_input.c:1646 [inline]
tcp_sacktag_walk+0x93b/0x18a0 net/ipv4/tcp_input.c:1713
tcp_sacktag_write_queue+0x1599/0x31d0 net/ipv4/tcp_input.c:1974
tcp_ack+0x2e9f/0x5a10 net/ipv4/tcp_input.c:3847
tcp_rcv_established+0x667/0x2230 net/ipv4/tcp_input.c:6006
tcp_v4_do_rcv+0x670/0x9b0 net/ipv4/tcp_ipv4.c:1721
sk_backlog_rcv include/net/sock.h:1113 [inline]
__release_sock+0x133/0x3b0 net/core/sock.c:2921
release_sock+0x58/0x1b0 net/core/sock.c:3488
tcp_sendmsg+0x3a/0x50 net/ipv4/tcp.c:1485
inet_sendmsg+0x9d/0xe0 net/ipv4/af_inet.c:825
sock_sendmsg_nosec net/socket.c:722 [inline]
sock_sendmsg+0xde/0x190 net/socket.c:745
sock_write_iter+0x295/0x3d0 net/socket.c:1136
call_write_iter include/linux/fs.h:2189 [inline]
new_sync_write fs/read_write.c:491 [inline]
vfs_write+0x9ed/0xdd0 fs/read_write.c:584
ksys_write+0x1ec/0x250 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
The buggy address belongs to the object at ffff88806cdee800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 0 bytes inside of
1024-byte region [ffff88806cdee800, ffff88806cdeec00)
The buggy address belongs to the physical page:
page:ffffea0001b37a00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x6cde8
head:ffffea0001b37a00 order:3 compound_mapcount:0 subpages_mapcount:0 compound_pincount:0
flags: 0xfff00000010200(slab|head|node=0|zone=1|lastcpupid=0x7ff)
raw: 00fff00000010200 ffff888012441dc0 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask 0x1f2a20(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_MEMALLOC|__GFP_HARDWALL), pid 75, tgid 75 (kworker/u4:4), ts 96369578780, free_ts 26734162530
prep_new_page mm/page_alloc.c:2531 [inline]
get_page_from_freelist+0x119c/0x2ce0 mm/page_alloc.c:4283
__alloc_pages+0x1cb/0x5b0 mm/page_alloc.c:5549
alloc_pages+0x1aa/0x270 mm/mempolicy.c:2287
alloc_slab_page mm/slub.c:1851 [inline]
allocate_slab+0x25f/0x350 mm/slub.c:1998
new_slab mm/slub.c:2051 [inline]
___slab_alloc+0xa91/0x1400 mm/slub.c:3193
__slab_alloc.constprop.0+0x56/0xa0 mm/slub.c:3292
__slab_alloc_node mm/slub.c:3345 [inline]
slab_alloc_node mm/slub.c:3442 [inline]
__kmem_cache_alloc_node+0x1a4/0x430 mm/slub.c:3491
__do_kmalloc_node mm/slab_common.c:967 [inline]
__kmalloc_node_track_caller+0x4b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
__alloc_skb+0x129/0x330 net/core/skbuff.c:608
__netdev_alloc_skb+0x74/0x410 net/core/skbuff.c:672
__netdev_alloc_skb_ip_align include/linux/skbuff.h:3203 [inline]
netdev_alloc_skb_ip_align include/linux/skbuff.h:3213 [inline]
batadv_iv_ogm_aggregate_new+0x106/0x4e0 net/batman-adv/bat_iv_ogm.c:558
batadv_iv_ogm_queue_add net/batman-adv/bat_iv_ogm.c:670 [inline]
batadv_iv_ogm_schedule_buff+0xe6b/0x1450 net/batman-adv/bat_iv_ogm.c:849
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:868 [inline]
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:861 [inline]
batadv_iv_send_outstanding_bat_ogm_packet+0x744/0x910 net/batman-adv/bat_iv_ogm.c:1712
process_one_work+0x9bf/0x1710 kernel/workqueue.c:2289
worker_thread+0x669/0x1090 kernel/workqueue.c:2436
page last free stack trace:
reset_page_owner include/linux/page_owner.h:24 [inline]
free_pages_prepare mm/page_alloc.c:1446 [inline]
free_pcp_prepare+0x66a/0xc20 mm/page_alloc.c:1496
free_unref_page_prepare mm/page_alloc.c:3369 [inline]
free_unref_page+0x1d/0x490 mm/page_alloc.c:3464
free_contig_range+0xb5/0x180 mm/page_alloc.c:9488
destroy_args+0xa8/0x64c mm/debug_vm_pgtable.c:998
debug_vm_pgtable+0x28de/0x296f mm/debug_vm_pgtable.c:1318
do_one_initcall+0x141/0x790 init/main.c:1306
do_initcall_level init/main.c:1379 [inline]
do_initcalls init/main.c:1395 [inline]
do_basic_setup init/main.c:1414 [inline]
kernel_init_freeable+0x6f9/0x782 init/main.c:1634
kernel_init+0x1e/0x1d0 init/main.c:1522
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308
Memory state around the buggy address:
ffff88806cdee700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88806cdee780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88806cdee800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^
ffff88806cdee880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Fixes: bf9f1baa279f ("net: add dedicated kmem_cache for typical/small skb->head")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Christoph Paasch <cpaasch@apple.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-27 14:17:06 +00:00
|
|
|
*size = SKB_SMALL_HEAD_CACHE_SIZE;
|
|
|
|
if (obj || !(gfp_pfmemalloc_allowed(flags)))
|
2023-02-06 17:31:03 +00:00
|
|
|
goto out;
|
net: avoid skb end_offset change in __skb_unclone_keeptruesize()
Once initial skb->head has been allocated from skb_small_head_cache,
we need to make sure to use the same strategy whenever skb->head
has to be re-allocated, as found by syzbot [1]
This means kmalloc_reserve() can not fallback from using
skb_small_head_cache to generic (power-of-two) kmem caches.
It seems that we probably want to rework things in the future,
to partially revert following patch, because we no longer use
ksize() for skb allocated in TX path.
2b88cba55883 ("net: preserve skb_end_offset() in skb_unclone_keeptruesize()")
Ideally, TCP stack should never put payload in skb->head,
this effort has to be completed.
In the mean time, add a sanity check.
[1]
BUG: KASAN: invalid-free in slab_free mm/slub.c:3787 [inline]
BUG: KASAN: invalid-free in kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
Free of addr ffff88806cdee800 by task syz-executor239/5189
CPU: 0 PID: 5189 Comm: syz-executor239 Not tainted 6.2.0-rc8-syzkaller-02400-gd1fabc68f8e0 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:306 [inline]
print_report+0x15e/0x45d mm/kasan/report.c:417
kasan_report_invalid_free+0x9b/0x1b0 mm/kasan/report.c:482
____kasan_slab_free+0x1a5/0x1c0 mm/kasan/common.c:216
kasan_slab_free include/linux/kasan.h:177 [inline]
slab_free_hook mm/slub.c:1781 [inline]
slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1807
slab_free mm/slub.c:3787 [inline]
kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
skb_kfree_head net/core/skbuff.c:857 [inline]
skb_kfree_head net/core/skbuff.c:853 [inline]
skb_free_head+0x16f/0x1a0 net/core/skbuff.c:872
skb_release_data+0x57a/0x820 net/core/skbuff.c:901
skb_release_all net/core/skbuff.c:966 [inline]
__kfree_skb+0x4f/0x70 net/core/skbuff.c:980
tcp_wmem_free_skb include/net/tcp.h:302 [inline]
tcp_rtx_queue_purge net/ipv4/tcp.c:3061 [inline]
tcp_write_queue_purge+0x617/0xcf0 net/ipv4/tcp.c:3074
tcp_v4_destroy_sock+0x125/0x810 net/ipv4/tcp_ipv4.c:2302
inet_csk_destroy_sock+0x19a/0x440 net/ipv4/inet_connection_sock.c:1195
__tcp_close+0xb96/0xf50 net/ipv4/tcp.c:3021
tcp_close+0x2d/0xc0 net/ipv4/tcp.c:3033
inet_release+0x132/0x270 net/ipv4/af_inet.c:426
__sock_release+0xcd/0x280 net/socket.c:651
sock_close+0x1c/0x20 net/socket.c:1393
__fput+0x27c/0xa90 fs/file_table.c:320
task_work_run+0x16f/0x270 kernel/task_work.c:179
resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
exit_to_user_mode_loop kernel/entry/common.c:171 [inline]
exit_to_user_mode_prepare+0x23c/0x250 kernel/entry/common.c:203
__syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296
do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f2511f546c3
Code: c7 c2 c0 ff ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 64 8b 04 25 18 00 00 00 85 c0 75 14 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 89 7c 24 0c e8
RSP: 002b:00007ffef0103d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
RAX: 0000000000000000 RBX: 0000000000000004 RCX: 00007f2511f546c3
RDX: 0000000000000978 RSI: 00000000200000c0 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000002 R09: 0000000000003434
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffef0103d6c
R13: 00007ffef0103d80 R14: 00007ffef0103dc0 R15: 0000000000000003
</TASK>
Allocated by task 5189:
kasan_save_stack+0x22/0x40 mm/kasan/common.c:45
kasan_set_track+0x25/0x30 mm/kasan/common.c:52
____kasan_kmalloc mm/kasan/common.c:374 [inline]
____kasan_kmalloc mm/kasan/common.c:333 [inline]
__kasan_kmalloc+0xa5/0xb0 mm/kasan/common.c:383
kasan_kmalloc include/linux/kasan.h:211 [inline]
__do_kmalloc_node mm/slab_common.c:968 [inline]
__kmalloc_node_track_caller+0x5b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
pskb_expand_head+0x237/0x1160 net/core/skbuff.c:1995
__skb_unclone_keeptruesize+0x93/0x220 net/core/skbuff.c:2094
skb_unclone_keeptruesize include/linux/skbuff.h:1910 [inline]
skb_prepare_for_shift net/core/skbuff.c:3804 [inline]
skb_shift+0xef8/0x1e20 net/core/skbuff.c:3877
tcp_skb_shift net/ipv4/tcp_input.c:1538 [inline]
tcp_shift_skb_data net/ipv4/tcp_input.c:1646 [inline]
tcp_sacktag_walk+0x93b/0x18a0 net/ipv4/tcp_input.c:1713
tcp_sacktag_write_queue+0x1599/0x31d0 net/ipv4/tcp_input.c:1974
tcp_ack+0x2e9f/0x5a10 net/ipv4/tcp_input.c:3847
tcp_rcv_established+0x667/0x2230 net/ipv4/tcp_input.c:6006
tcp_v4_do_rcv+0x670/0x9b0 net/ipv4/tcp_ipv4.c:1721
sk_backlog_rcv include/net/sock.h:1113 [inline]
__release_sock+0x133/0x3b0 net/core/sock.c:2921
release_sock+0x58/0x1b0 net/core/sock.c:3488
tcp_sendmsg+0x3a/0x50 net/ipv4/tcp.c:1485
inet_sendmsg+0x9d/0xe0 net/ipv4/af_inet.c:825
sock_sendmsg_nosec net/socket.c:722 [inline]
sock_sendmsg+0xde/0x190 net/socket.c:745
sock_write_iter+0x295/0x3d0 net/socket.c:1136
call_write_iter include/linux/fs.h:2189 [inline]
new_sync_write fs/read_write.c:491 [inline]
vfs_write+0x9ed/0xdd0 fs/read_write.c:584
ksys_write+0x1ec/0x250 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
The buggy address belongs to the object at ffff88806cdee800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 0 bytes inside of
1024-byte region [ffff88806cdee800, ffff88806cdeec00)
The buggy address belongs to the physical page:
page:ffffea0001b37a00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x6cde8
head:ffffea0001b37a00 order:3 compound_mapcount:0 subpages_mapcount:0 compound_pincount:0
flags: 0xfff00000010200(slab|head|node=0|zone=1|lastcpupid=0x7ff)
raw: 00fff00000010200 ffff888012441dc0 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask 0x1f2a20(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_MEMALLOC|__GFP_HARDWALL), pid 75, tgid 75 (kworker/u4:4), ts 96369578780, free_ts 26734162530
prep_new_page mm/page_alloc.c:2531 [inline]
get_page_from_freelist+0x119c/0x2ce0 mm/page_alloc.c:4283
__alloc_pages+0x1cb/0x5b0 mm/page_alloc.c:5549
alloc_pages+0x1aa/0x270 mm/mempolicy.c:2287
alloc_slab_page mm/slub.c:1851 [inline]
allocate_slab+0x25f/0x350 mm/slub.c:1998
new_slab mm/slub.c:2051 [inline]
___slab_alloc+0xa91/0x1400 mm/slub.c:3193
__slab_alloc.constprop.0+0x56/0xa0 mm/slub.c:3292
__slab_alloc_node mm/slub.c:3345 [inline]
slab_alloc_node mm/slub.c:3442 [inline]
__kmem_cache_alloc_node+0x1a4/0x430 mm/slub.c:3491
__do_kmalloc_node mm/slab_common.c:967 [inline]
__kmalloc_node_track_caller+0x4b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
__alloc_skb+0x129/0x330 net/core/skbuff.c:608
__netdev_alloc_skb+0x74/0x410 net/core/skbuff.c:672
__netdev_alloc_skb_ip_align include/linux/skbuff.h:3203 [inline]
netdev_alloc_skb_ip_align include/linux/skbuff.h:3213 [inline]
batadv_iv_ogm_aggregate_new+0x106/0x4e0 net/batman-adv/bat_iv_ogm.c:558
batadv_iv_ogm_queue_add net/batman-adv/bat_iv_ogm.c:670 [inline]
batadv_iv_ogm_schedule_buff+0xe6b/0x1450 net/batman-adv/bat_iv_ogm.c:849
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:868 [inline]
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:861 [inline]
batadv_iv_send_outstanding_bat_ogm_packet+0x744/0x910 net/batman-adv/bat_iv_ogm.c:1712
process_one_work+0x9bf/0x1710 kernel/workqueue.c:2289
worker_thread+0x669/0x1090 kernel/workqueue.c:2436
page last free stack trace:
reset_page_owner include/linux/page_owner.h:24 [inline]
free_pages_prepare mm/page_alloc.c:1446 [inline]
free_pcp_prepare+0x66a/0xc20 mm/page_alloc.c:1496
free_unref_page_prepare mm/page_alloc.c:3369 [inline]
free_unref_page+0x1d/0x490 mm/page_alloc.c:3464
free_contig_range+0xb5/0x180 mm/page_alloc.c:9488
destroy_args+0xa8/0x64c mm/debug_vm_pgtable.c:998
debug_vm_pgtable+0x28de/0x296f mm/debug_vm_pgtable.c:1318
do_one_initcall+0x141/0x790 init/main.c:1306
do_initcall_level init/main.c:1379 [inline]
do_initcalls init/main.c:1395 [inline]
do_basic_setup init/main.c:1414 [inline]
kernel_init_freeable+0x6f9/0x782 init/main.c:1634
kernel_init+0x1e/0x1d0 init/main.c:1522
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308
Memory state around the buggy address:
ffff88806cdee700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88806cdee780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88806cdee800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^
ffff88806cdee880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Fixes: bf9f1baa279f ("net: add dedicated kmem_cache for typical/small skb->head")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Christoph Paasch <cpaasch@apple.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-27 14:17:06 +00:00
|
|
|
/* Try again but now we are using pfmemalloc reserves */
|
|
|
|
ret_pfmemalloc = true;
|
2024-03-06 16:00:23 +00:00
|
|
|
obj = kmem_cache_alloc_node(net_hotdata.skb_small_head_cache, flags, node);
|
net: avoid skb end_offset change in __skb_unclone_keeptruesize()
Once initial skb->head has been allocated from skb_small_head_cache,
we need to make sure to use the same strategy whenever skb->head
has to be re-allocated, as found by syzbot [1]
This means kmalloc_reserve() can not fallback from using
skb_small_head_cache to generic (power-of-two) kmem caches.
It seems that we probably want to rework things in the future,
to partially revert following patch, because we no longer use
ksize() for skb allocated in TX path.
2b88cba55883 ("net: preserve skb_end_offset() in skb_unclone_keeptruesize()")
Ideally, TCP stack should never put payload in skb->head,
this effort has to be completed.
In the mean time, add a sanity check.
[1]
BUG: KASAN: invalid-free in slab_free mm/slub.c:3787 [inline]
BUG: KASAN: invalid-free in kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
Free of addr ffff88806cdee800 by task syz-executor239/5189
CPU: 0 PID: 5189 Comm: syz-executor239 Not tainted 6.2.0-rc8-syzkaller-02400-gd1fabc68f8e0 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:306 [inline]
print_report+0x15e/0x45d mm/kasan/report.c:417
kasan_report_invalid_free+0x9b/0x1b0 mm/kasan/report.c:482
____kasan_slab_free+0x1a5/0x1c0 mm/kasan/common.c:216
kasan_slab_free include/linux/kasan.h:177 [inline]
slab_free_hook mm/slub.c:1781 [inline]
slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1807
slab_free mm/slub.c:3787 [inline]
kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
skb_kfree_head net/core/skbuff.c:857 [inline]
skb_kfree_head net/core/skbuff.c:853 [inline]
skb_free_head+0x16f/0x1a0 net/core/skbuff.c:872
skb_release_data+0x57a/0x820 net/core/skbuff.c:901
skb_release_all net/core/skbuff.c:966 [inline]
__kfree_skb+0x4f/0x70 net/core/skbuff.c:980
tcp_wmem_free_skb include/net/tcp.h:302 [inline]
tcp_rtx_queue_purge net/ipv4/tcp.c:3061 [inline]
tcp_write_queue_purge+0x617/0xcf0 net/ipv4/tcp.c:3074
tcp_v4_destroy_sock+0x125/0x810 net/ipv4/tcp_ipv4.c:2302
inet_csk_destroy_sock+0x19a/0x440 net/ipv4/inet_connection_sock.c:1195
__tcp_close+0xb96/0xf50 net/ipv4/tcp.c:3021
tcp_close+0x2d/0xc0 net/ipv4/tcp.c:3033
inet_release+0x132/0x270 net/ipv4/af_inet.c:426
__sock_release+0xcd/0x280 net/socket.c:651
sock_close+0x1c/0x20 net/socket.c:1393
__fput+0x27c/0xa90 fs/file_table.c:320
task_work_run+0x16f/0x270 kernel/task_work.c:179
resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
exit_to_user_mode_loop kernel/entry/common.c:171 [inline]
exit_to_user_mode_prepare+0x23c/0x250 kernel/entry/common.c:203
__syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296
do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f2511f546c3
Code: c7 c2 c0 ff ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 64 8b 04 25 18 00 00 00 85 c0 75 14 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 89 7c 24 0c e8
RSP: 002b:00007ffef0103d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
RAX: 0000000000000000 RBX: 0000000000000004 RCX: 00007f2511f546c3
RDX: 0000000000000978 RSI: 00000000200000c0 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000002 R09: 0000000000003434
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffef0103d6c
R13: 00007ffef0103d80 R14: 00007ffef0103dc0 R15: 0000000000000003
</TASK>
Allocated by task 5189:
kasan_save_stack+0x22/0x40 mm/kasan/common.c:45
kasan_set_track+0x25/0x30 mm/kasan/common.c:52
____kasan_kmalloc mm/kasan/common.c:374 [inline]
____kasan_kmalloc mm/kasan/common.c:333 [inline]
__kasan_kmalloc+0xa5/0xb0 mm/kasan/common.c:383
kasan_kmalloc include/linux/kasan.h:211 [inline]
__do_kmalloc_node mm/slab_common.c:968 [inline]
__kmalloc_node_track_caller+0x5b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
pskb_expand_head+0x237/0x1160 net/core/skbuff.c:1995
__skb_unclone_keeptruesize+0x93/0x220 net/core/skbuff.c:2094
skb_unclone_keeptruesize include/linux/skbuff.h:1910 [inline]
skb_prepare_for_shift net/core/skbuff.c:3804 [inline]
skb_shift+0xef8/0x1e20 net/core/skbuff.c:3877
tcp_skb_shift net/ipv4/tcp_input.c:1538 [inline]
tcp_shift_skb_data net/ipv4/tcp_input.c:1646 [inline]
tcp_sacktag_walk+0x93b/0x18a0 net/ipv4/tcp_input.c:1713
tcp_sacktag_write_queue+0x1599/0x31d0 net/ipv4/tcp_input.c:1974
tcp_ack+0x2e9f/0x5a10 net/ipv4/tcp_input.c:3847
tcp_rcv_established+0x667/0x2230 net/ipv4/tcp_input.c:6006
tcp_v4_do_rcv+0x670/0x9b0 net/ipv4/tcp_ipv4.c:1721
sk_backlog_rcv include/net/sock.h:1113 [inline]
__release_sock+0x133/0x3b0 net/core/sock.c:2921
release_sock+0x58/0x1b0 net/core/sock.c:3488
tcp_sendmsg+0x3a/0x50 net/ipv4/tcp.c:1485
inet_sendmsg+0x9d/0xe0 net/ipv4/af_inet.c:825
sock_sendmsg_nosec net/socket.c:722 [inline]
sock_sendmsg+0xde/0x190 net/socket.c:745
sock_write_iter+0x295/0x3d0 net/socket.c:1136
call_write_iter include/linux/fs.h:2189 [inline]
new_sync_write fs/read_write.c:491 [inline]
vfs_write+0x9ed/0xdd0 fs/read_write.c:584
ksys_write+0x1ec/0x250 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
The buggy address belongs to the object at ffff88806cdee800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 0 bytes inside of
1024-byte region [ffff88806cdee800, ffff88806cdeec00)
The buggy address belongs to the physical page:
page:ffffea0001b37a00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x6cde8
head:ffffea0001b37a00 order:3 compound_mapcount:0 subpages_mapcount:0 compound_pincount:0
flags: 0xfff00000010200(slab|head|node=0|zone=1|lastcpupid=0x7ff)
raw: 00fff00000010200 ffff888012441dc0 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask 0x1f2a20(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_MEMALLOC|__GFP_HARDWALL), pid 75, tgid 75 (kworker/u4:4), ts 96369578780, free_ts 26734162530
prep_new_page mm/page_alloc.c:2531 [inline]
get_page_from_freelist+0x119c/0x2ce0 mm/page_alloc.c:4283
__alloc_pages+0x1cb/0x5b0 mm/page_alloc.c:5549
alloc_pages+0x1aa/0x270 mm/mempolicy.c:2287
alloc_slab_page mm/slub.c:1851 [inline]
allocate_slab+0x25f/0x350 mm/slub.c:1998
new_slab mm/slub.c:2051 [inline]
___slab_alloc+0xa91/0x1400 mm/slub.c:3193
__slab_alloc.constprop.0+0x56/0xa0 mm/slub.c:3292
__slab_alloc_node mm/slub.c:3345 [inline]
slab_alloc_node mm/slub.c:3442 [inline]
__kmem_cache_alloc_node+0x1a4/0x430 mm/slub.c:3491
__do_kmalloc_node mm/slab_common.c:967 [inline]
__kmalloc_node_track_caller+0x4b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
__alloc_skb+0x129/0x330 net/core/skbuff.c:608
__netdev_alloc_skb+0x74/0x410 net/core/skbuff.c:672
__netdev_alloc_skb_ip_align include/linux/skbuff.h:3203 [inline]
netdev_alloc_skb_ip_align include/linux/skbuff.h:3213 [inline]
batadv_iv_ogm_aggregate_new+0x106/0x4e0 net/batman-adv/bat_iv_ogm.c:558
batadv_iv_ogm_queue_add net/batman-adv/bat_iv_ogm.c:670 [inline]
batadv_iv_ogm_schedule_buff+0xe6b/0x1450 net/batman-adv/bat_iv_ogm.c:849
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:868 [inline]
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:861 [inline]
batadv_iv_send_outstanding_bat_ogm_packet+0x744/0x910 net/batman-adv/bat_iv_ogm.c:1712
process_one_work+0x9bf/0x1710 kernel/workqueue.c:2289
worker_thread+0x669/0x1090 kernel/workqueue.c:2436
page last free stack trace:
reset_page_owner include/linux/page_owner.h:24 [inline]
free_pages_prepare mm/page_alloc.c:1446 [inline]
free_pcp_prepare+0x66a/0xc20 mm/page_alloc.c:1496
free_unref_page_prepare mm/page_alloc.c:3369 [inline]
free_unref_page+0x1d/0x490 mm/page_alloc.c:3464
free_contig_range+0xb5/0x180 mm/page_alloc.c:9488
destroy_args+0xa8/0x64c mm/debug_vm_pgtable.c:998
debug_vm_pgtable+0x28de/0x296f mm/debug_vm_pgtable.c:1318
do_one_initcall+0x141/0x790 init/main.c:1306
do_initcall_level init/main.c:1379 [inline]
do_initcalls init/main.c:1395 [inline]
do_basic_setup init/main.c:1414 [inline]
kernel_init_freeable+0x6f9/0x782 init/main.c:1634
kernel_init+0x1e/0x1d0 init/main.c:1522
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308
Memory state around the buggy address:
ffff88806cdee700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88806cdee780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88806cdee800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^
ffff88806cdee880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Fixes: bf9f1baa279f ("net: add dedicated kmem_cache for typical/small skb->head")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Christoph Paasch <cpaasch@apple.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-27 14:17:06 +00:00
|
|
|
goto out;
|
2023-02-06 17:31:03 +00:00
|
|
|
}
|
2023-08-31 18:37:50 +00:00
|
|
|
|
|
|
|
obj_size = kmalloc_size_roundup(obj_size);
|
|
|
|
/* The following cast might truncate high-order bits of obj_size, this
|
|
|
|
* is harmless because kmalloc(obj_size >= 2^32) will fail anyway.
|
|
|
|
*/
|
|
|
|
*size = (unsigned int)obj_size;
|
|
|
|
|
2021-02-13 14:11:00 +00:00
|
|
|
/*
|
|
|
|
* Try a regular allocation, when that fails and we're not entitled
|
|
|
|
* to the reserves, fail.
|
|
|
|
*/
|
2023-02-06 17:31:02 +00:00
|
|
|
obj = kmalloc_node_track_caller(obj_size,
|
2021-02-13 14:11:00 +00:00
|
|
|
flags | __GFP_NOMEMALLOC | __GFP_NOWARN,
|
|
|
|
node);
|
|
|
|
if (obj || !(gfp_pfmemalloc_allowed(flags)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Try again but now we are using pfmemalloc reserves */
|
|
|
|
ret_pfmemalloc = true;
|
2023-02-06 17:31:02 +00:00
|
|
|
obj = kmalloc_node_track_caller(obj_size, flags, node);
|
2021-02-13 14:11:00 +00:00
|
|
|
|
|
|
|
out:
|
|
|
|
if (pfmemalloc)
|
|
|
|
*pfmemalloc = ret_pfmemalloc;
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate a new skbuff. We do this ourselves so we can fill in a few
|
|
|
|
* 'private' fields and also do memory statistics to find all the
|
|
|
|
* [BEEP] leaks.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* __alloc_skb - allocate a network buffer
|
|
|
|
* @size: size to allocate
|
|
|
|
* @gfp_mask: allocation mask
|
|
|
|
* @flags: If SKB_ALLOC_FCLONE is set, allocate from fclone cache
|
|
|
|
* instead of head cache and allocate a cloned (child) skb.
|
|
|
|
* If SKB_ALLOC_RX is set, __GFP_MEMALLOC will be used for
|
|
|
|
* allocations in case the data is required for writeback
|
|
|
|
* @node: numa node to allocate memory on
|
|
|
|
*
|
|
|
|
* Allocate a new &sk_buff. The returned buffer has no headroom and a
|
|
|
|
* tail room of at least size bytes. The object has a reference count
|
|
|
|
* of one. The return is the buffer. On a failure the return is %NULL.
|
|
|
|
*
|
|
|
|
* Buffers may only be allocated from interrupts using a @gfp_mask of
|
|
|
|
* %GFP_ATOMIC.
|
|
|
|
*/
|
|
|
|
struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
|
|
|
|
int flags, int node)
|
|
|
|
{
|
|
|
|
struct kmem_cache *cache;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
bool pfmemalloc;
|
2021-09-22 06:17:19 +00:00
|
|
|
u8 *data;
|
2021-02-13 14:11:00 +00:00
|
|
|
|
|
|
|
cache = (flags & SKB_ALLOC_FCLONE)
|
2024-03-06 16:00:23 +00:00
|
|
|
? net_hotdata.skbuff_fclone_cache : net_hotdata.skbuff_cache;
|
2021-02-13 14:11:00 +00:00
|
|
|
|
|
|
|
if (sk_memalloc_socks() && (flags & SKB_ALLOC_RX))
|
|
|
|
gfp_mask |= __GFP_MEMALLOC;
|
|
|
|
|
|
|
|
/* Get the HEAD */
|
2021-02-13 14:12:38 +00:00
|
|
|
if ((flags & (SKB_ALLOC_FCLONE | SKB_ALLOC_NAPI)) == SKB_ALLOC_NAPI &&
|
|
|
|
likely(node == NUMA_NO_NODE || node == numa_mem_id()))
|
|
|
|
skb = napi_skb_cache_get();
|
|
|
|
else
|
|
|
|
skb = kmem_cache_alloc_node(cache, gfp_mask & ~GFP_DMA, node);
|
2021-02-13 14:11:39 +00:00
|
|
|
if (unlikely(!skb))
|
|
|
|
return NULL;
|
2021-02-13 14:11:00 +00:00
|
|
|
prefetchw(skb);
|
|
|
|
|
|
|
|
/* We do our best to align skb_shared_info on a separate cache
|
|
|
|
* line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives
|
|
|
|
* aligned memory blocks, unless SLUB/SLAB debug is enabled.
|
|
|
|
* Both skb->head and skb_shared_info are cache line aligned.
|
|
|
|
*/
|
2023-02-06 17:31:02 +00:00
|
|
|
data = kmalloc_reserve(&size, gfp_mask, node, &pfmemalloc);
|
2021-02-13 14:11:39 +00:00
|
|
|
if (unlikely(!data))
|
2021-02-13 14:11:00 +00:00
|
|
|
goto nodata;
|
2022-10-25 22:39:35 +00:00
|
|
|
/* kmalloc_size_roundup() might give us more room than requested.
|
2021-02-13 14:11:00 +00:00
|
|
|
* Put skb_shared_info exactly at the end of allocated zone,
|
|
|
|
* to allow max possible filling before reallocation.
|
|
|
|
*/
|
2023-02-06 17:31:01 +00:00
|
|
|
prefetchw(data + SKB_WITH_OVERHEAD(size));
|
2021-02-13 14:11:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Only clear those fields we need to clear, not those that we will
|
|
|
|
* actually initialise below. Hence, don't put any more fields after
|
|
|
|
* the tail pointer in struct sk_buff!
|
|
|
|
*/
|
|
|
|
memset(skb, 0, offsetof(struct sk_buff, tail));
|
2023-02-06 17:31:01 +00:00
|
|
|
__build_skb_around(skb, data, size);
|
2021-02-13 14:11:00 +00:00
|
|
|
skb->pfmemalloc = pfmemalloc;
|
|
|
|
|
|
|
|
if (flags & SKB_ALLOC_FCLONE) {
|
|
|
|
struct sk_buff_fclones *fclones;
|
|
|
|
|
|
|
|
fclones = container_of(skb, struct sk_buff_fclones, skb1);
|
|
|
|
|
|
|
|
skb->fclone = SKB_FCLONE_ORIG;
|
|
|
|
refcount_set(&fclones->fclone_ref, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return skb;
|
2021-02-13 14:11:39 +00:00
|
|
|
|
2021-02-13 14:11:00 +00:00
|
|
|
nodata:
|
|
|
|
kmem_cache_free(cache, skb);
|
2021-02-13 14:11:39 +00:00
|
|
|
return NULL;
|
2021-02-13 14:11:00 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__alloc_skb);
|
|
|
|
|
2014-12-10 03:40:49 +00:00
|
|
|
/**
|
|
|
|
* __netdev_alloc_skb - allocate an skbuff for rx on a specific device
|
|
|
|
* @dev: network device to receive on
|
2015-08-24 13:56:54 +00:00
|
|
|
* @len: length to allocate
|
2014-12-10 03:40:49 +00:00
|
|
|
* @gfp_mask: get_free_pages mask, passed to alloc_skb
|
|
|
|
*
|
|
|
|
* Allocate a new &sk_buff and assign it a usage count of one. The
|
|
|
|
* buffer has NET_SKB_PAD headroom built in. Users should allocate
|
|
|
|
* the headroom they think they need without accounting for the
|
|
|
|
* built in space. The built in space is used for optimisations.
|
|
|
|
*
|
|
|
|
* %NULL is returned if there is no free memory.
|
|
|
|
*/
|
2015-05-07 04:11:40 +00:00
|
|
|
struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
|
|
|
|
gfp_t gfp_mask)
|
2014-12-10 03:40:49 +00:00
|
|
|
{
|
2015-05-07 04:11:57 +00:00
|
|
|
struct page_frag_cache *nc;
|
2014-12-10 03:40:49 +00:00
|
|
|
struct sk_buff *skb;
|
2015-05-07 04:11:40 +00:00
|
|
|
bool pfmemalloc;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
len += NET_SKB_PAD;
|
2014-12-10 03:40:49 +00:00
|
|
|
|
2021-01-15 15:04:40 +00:00
|
|
|
/* If requested length is either too small or too big,
|
|
|
|
* we use kmalloc() for skb->head allocation.
|
|
|
|
*/
|
|
|
|
if (len <= SKB_WITH_OVERHEAD(1024) ||
|
|
|
|
len > SKB_WITH_OVERHEAD(PAGE_SIZE) ||
|
2015-11-07 00:28:21 +00:00
|
|
|
(gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) {
|
2015-05-13 20:34:13 +00:00
|
|
|
skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE);
|
|
|
|
if (!skb)
|
|
|
|
goto skb_fail;
|
|
|
|
goto skb_success;
|
|
|
|
}
|
2014-12-10 03:40:49 +00:00
|
|
|
|
2023-02-06 17:31:00 +00:00
|
|
|
len = SKB_HEAD_ALIGN(len);
|
2015-05-07 04:11:40 +00:00
|
|
|
|
|
|
|
if (sk_memalloc_socks())
|
|
|
|
gfp_mask |= __GFP_MEMALLOC;
|
|
|
|
|
2021-08-13 14:57:49 +00:00
|
|
|
if (in_hardirq() || irqs_disabled()) {
|
2019-06-07 19:20:35 +00:00
|
|
|
nc = this_cpu_ptr(&netdev_alloc_cache);
|
|
|
|
data = page_frag_alloc(nc, len, gfp_mask);
|
|
|
|
pfmemalloc = nc->pfmemalloc;
|
|
|
|
} else {
|
|
|
|
local_bh_disable();
|
|
|
|
nc = this_cpu_ptr(&napi_alloc_cache.page);
|
|
|
|
data = page_frag_alloc(nc, len, gfp_mask);
|
|
|
|
pfmemalloc = nc->pfmemalloc;
|
|
|
|
local_bh_enable();
|
|
|
|
}
|
2015-05-07 04:11:40 +00:00
|
|
|
|
|
|
|
if (unlikely(!data))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
skb = __build_skb(data, len);
|
|
|
|
if (unlikely(!skb)) {
|
2015-05-07 04:12:03 +00:00
|
|
|
skb_free_frag(data);
|
2015-05-07 04:11:40 +00:00
|
|
|
return NULL;
|
2006-08-07 23:09:04 +00:00
|
|
|
}
|
2014-12-10 03:40:49 +00:00
|
|
|
|
2015-05-07 04:11:40 +00:00
|
|
|
if (pfmemalloc)
|
|
|
|
skb->pfmemalloc = 1;
|
|
|
|
skb->head_frag = 1;
|
|
|
|
|
2015-05-13 20:34:13 +00:00
|
|
|
skb_success:
|
2015-05-07 04:11:40 +00:00
|
|
|
skb_reserve(skb, NET_SKB_PAD);
|
|
|
|
skb->dev = dev;
|
|
|
|
|
2015-05-13 20:34:13 +00:00
|
|
|
skb_fail:
|
2006-08-01 05:35:23 +00:00
|
|
|
return skb;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(__netdev_alloc_skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2014-12-10 03:40:49 +00:00
|
|
|
/**
|
2024-03-27 04:02:12 +00:00
|
|
|
* napi_alloc_skb - allocate skbuff for rx in a specific NAPI instance
|
2014-12-10 03:40:49 +00:00
|
|
|
* @napi: napi instance this buffer was allocated for
|
2015-08-24 13:56:54 +00:00
|
|
|
* @len: length to allocate
|
2014-12-10 03:40:49 +00:00
|
|
|
*
|
|
|
|
* Allocate a new sk_buff for use in NAPI receive. This buffer will
|
|
|
|
* attempt to allocate the head from a special reserved region used
|
|
|
|
* only for NAPI Rx allocation. By doing this we can save several
|
|
|
|
* CPU cycles by avoiding having to disable and re-enable IRQs.
|
|
|
|
*
|
|
|
|
* %NULL is returned if there is no free memory.
|
|
|
|
*/
|
2024-03-27 04:02:12 +00:00
|
|
|
struct sk_buff *napi_alloc_skb(struct napi_struct *napi, unsigned int len)
|
2014-12-10 03:40:49 +00:00
|
|
|
{
|
2024-03-27 04:02:12 +00:00
|
|
|
gfp_t gfp_mask = GFP_ATOMIC | __GFP_NOWARN;
|
2021-01-13 16:18:19 +00:00
|
|
|
struct napi_alloc_cache *nc;
|
2014-12-10 03:40:49 +00:00
|
|
|
struct sk_buff *skb;
|
2022-09-28 08:43:09 +00:00
|
|
|
bool pfmemalloc;
|
2015-05-07 04:11:40 +00:00
|
|
|
void *data;
|
|
|
|
|
2022-06-08 16:04:37 +00:00
|
|
|
DEBUG_NET_WARN_ON_ONCE(!in_softirq());
|
2015-05-07 04:11:40 +00:00
|
|
|
len += NET_SKB_PAD + NET_IP_ALIGN;
|
2014-12-10 03:40:49 +00:00
|
|
|
|
2021-01-13 16:18:19 +00:00
|
|
|
/* If requested length is either too small or too big,
|
|
|
|
* we use kmalloc() for skb->head allocation.
|
2022-09-28 08:43:09 +00:00
|
|
|
* When the small frag allocator is available, prefer it over kmalloc
|
|
|
|
* for small fragments
|
2021-01-13 16:18:19 +00:00
|
|
|
*/
|
2022-09-28 08:43:09 +00:00
|
|
|
if ((!NAPI_HAS_SMALL_PAGE_FRAG && len <= SKB_WITH_OVERHEAD(1024)) ||
|
2021-01-13 16:18:19 +00:00
|
|
|
len > SKB_WITH_OVERHEAD(PAGE_SIZE) ||
|
2015-11-07 00:28:21 +00:00
|
|
|
(gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) {
|
2021-02-13 14:12:49 +00:00
|
|
|
skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX | SKB_ALLOC_NAPI,
|
|
|
|
NUMA_NO_NODE);
|
2015-05-13 20:34:13 +00:00
|
|
|
if (!skb)
|
|
|
|
goto skb_fail;
|
|
|
|
goto skb_success;
|
|
|
|
}
|
2015-05-07 04:11:40 +00:00
|
|
|
|
2021-01-13 16:18:19 +00:00
|
|
|
nc = this_cpu_ptr(&napi_alloc_cache);
|
2015-05-07 04:11:40 +00:00
|
|
|
|
|
|
|
if (sk_memalloc_socks())
|
|
|
|
gfp_mask |= __GFP_MEMALLOC;
|
2014-12-10 03:40:49 +00:00
|
|
|
|
2022-09-28 08:43:09 +00:00
|
|
|
if (NAPI_HAS_SMALL_PAGE_FRAG && len <= SKB_WITH_OVERHEAD(1024)) {
|
|
|
|
/* we are artificially inflating the allocation size, but
|
|
|
|
* that is not as bad as it may look like, as:
|
|
|
|
* - 'len' less than GRO_MAX_HEAD makes little sense
|
|
|
|
* - On most systems, larger 'len' values lead to fragment
|
|
|
|
* size above 512 bytes
|
|
|
|
* - kmalloc would use the kmalloc-1k slab for such values
|
|
|
|
* - Builds with smaller GRO_MAX_HEAD will very likely do
|
|
|
|
* little networking, as that implies no WiFi and no
|
|
|
|
* tunnels support, and 32 bits arches.
|
|
|
|
*/
|
|
|
|
len = SZ_1K;
|
|
|
|
|
|
|
|
data = page_frag_alloc_1k(&nc->page_small, gfp_mask);
|
|
|
|
pfmemalloc = NAPI_SMALL_PAGE_PFMEMALLOC(nc->page_small);
|
|
|
|
} else {
|
2023-02-06 17:31:00 +00:00
|
|
|
len = SKB_HEAD_ALIGN(len);
|
2022-09-28 08:43:09 +00:00
|
|
|
|
|
|
|
data = page_frag_alloc(&nc->page, len, gfp_mask);
|
|
|
|
pfmemalloc = nc->page.pfmemalloc;
|
|
|
|
}
|
|
|
|
|
2015-05-07 04:11:40 +00:00
|
|
|
if (unlikely(!data))
|
|
|
|
return NULL;
|
|
|
|
|
2021-02-13 14:12:49 +00:00
|
|
|
skb = __napi_build_skb(data, len);
|
2015-05-07 04:11:40 +00:00
|
|
|
if (unlikely(!skb)) {
|
2015-05-07 04:12:03 +00:00
|
|
|
skb_free_frag(data);
|
2015-05-07 04:11:40 +00:00
|
|
|
return NULL;
|
2014-12-10 03:40:49 +00:00
|
|
|
}
|
|
|
|
|
2022-09-28 08:43:09 +00:00
|
|
|
if (pfmemalloc)
|
2015-05-07 04:11:40 +00:00
|
|
|
skb->pfmemalloc = 1;
|
|
|
|
skb->head_frag = 1;
|
|
|
|
|
2015-05-13 20:34:13 +00:00
|
|
|
skb_success:
|
2015-05-07 04:11:40 +00:00
|
|
|
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
|
|
|
|
skb->dev = napi->dev;
|
|
|
|
|
2015-05-13 20:34:13 +00:00
|
|
|
skb_fail:
|
2014-12-10 03:40:49 +00:00
|
|
|
return skb;
|
|
|
|
}
|
2024-03-27 04:02:12 +00:00
|
|
|
EXPORT_SYMBOL(napi_alloc_skb);
|
2014-12-10 03:40:49 +00:00
|
|
|
|
2024-02-14 22:34:03 +00:00
|
|
|
void skb_add_rx_frag_netmem(struct sk_buff *skb, int i, netmem_ref netmem,
|
|
|
|
int off, int size, unsigned int truesize)
|
2008-10-07 21:22:33 +00:00
|
|
|
{
|
2023-09-13 13:48:41 +00:00
|
|
|
DEBUG_NET_WARN_ON_ONCE(size > truesize);
|
|
|
|
|
2024-02-14 22:34:03 +00:00
|
|
|
skb_fill_netmem_desc(skb, i, netmem, off, size);
|
2008-10-07 21:22:33 +00:00
|
|
|
skb->len += size;
|
|
|
|
skb->data_len += size;
|
2012-03-23 23:59:33 +00:00
|
|
|
skb->truesize += truesize;
|
2008-10-07 21:22:33 +00:00
|
|
|
}
|
2024-02-14 22:34:03 +00:00
|
|
|
EXPORT_SYMBOL(skb_add_rx_frag_netmem);
|
2008-10-07 21:22:33 +00:00
|
|
|
|
2013-11-01 06:07:47 +00:00
|
|
|
void skb_coalesce_rx_frag(struct sk_buff *skb, int i, int size,
|
|
|
|
unsigned int truesize)
|
|
|
|
{
|
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
|
|
|
|
2023-09-13 13:48:41 +00:00
|
|
|
DEBUG_NET_WARN_ON_ONCE(size > truesize);
|
|
|
|
|
2013-11-01 06:07:47 +00:00
|
|
|
skb_frag_size_add(frag, size);
|
|
|
|
skb->len += size;
|
|
|
|
skb->data_len += size;
|
|
|
|
skb->truesize += truesize;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_coalesce_rx_frag);
|
|
|
|
|
2006-07-14 02:26:39 +00:00
|
|
|
static void skb_drop_list(struct sk_buff **listp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2013-06-24 13:26:00 +00:00
|
|
|
kfree_skb_list(*listp);
|
2006-07-14 02:26:39 +00:00
|
|
|
*listp = NULL;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-07-14 02:26:39 +00:00
|
|
|
static inline void skb_drop_fraglist(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
skb_drop_list(&skb_shinfo(skb)->frag_list);
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
static void skb_clone_fraglist(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct sk_buff *list;
|
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
skb_walk_frags(skb, list)
|
2005-04-16 22:20:36 +00:00
|
|
|
skb_get(list);
|
|
|
|
}
|
|
|
|
|
2024-05-02 17:54:22 +00:00
|
|
|
static bool is_pp_page(struct page *page)
|
|
|
|
{
|
|
|
|
return (page->pp_magic & ~0x3UL) == PP_SIGNATURE;
|
|
|
|
}
|
|
|
|
|
2024-02-12 09:50:57 +00:00
|
|
|
int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
|
|
|
|
unsigned int headroom)
|
2024-02-12 09:50:56 +00:00
|
|
|
{
|
|
|
|
#if IS_ENABLED(CONFIG_PAGE_POOL)
|
|
|
|
u32 size, truesize, len, max_head_size, off;
|
|
|
|
struct sk_buff *skb = *pskb, *nskb;
|
|
|
|
int err, i, head_off;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
/* XDP does not support fraglist so we need to linearize
|
|
|
|
* the skb.
|
|
|
|
*/
|
|
|
|
if (skb_has_frag_list(skb))
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
max_head_size = SKB_WITH_OVERHEAD(PAGE_SIZE - headroom);
|
|
|
|
if (skb->len > max_head_size + MAX_SKB_FRAGS * PAGE_SIZE)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
size = min_t(u32, skb->len, max_head_size);
|
|
|
|
truesize = SKB_HEAD_ALIGN(size) + headroom;
|
|
|
|
data = page_pool_dev_alloc_va(pool, &truesize);
|
|
|
|
if (!data)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
nskb = napi_build_skb(data, truesize);
|
|
|
|
if (!nskb) {
|
|
|
|
page_pool_free_va(pool, data, true);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb_reserve(nskb, headroom);
|
|
|
|
skb_copy_header(nskb, skb);
|
|
|
|
skb_mark_for_recycle(nskb);
|
|
|
|
|
|
|
|
err = skb_copy_bits(skb, 0, nskb->data, size);
|
|
|
|
if (err) {
|
|
|
|
consume_skb(nskb);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
skb_put(nskb, size);
|
|
|
|
|
|
|
|
head_off = skb_headroom(nskb) - skb_headroom(skb);
|
|
|
|
skb_headers_offset_update(nskb, head_off);
|
|
|
|
|
|
|
|
off = size;
|
|
|
|
len = skb->len - off;
|
|
|
|
for (i = 0; i < MAX_SKB_FRAGS && off < skb->len; i++) {
|
|
|
|
struct page *page;
|
|
|
|
u32 page_off;
|
|
|
|
|
|
|
|
size = min_t(u32, len, PAGE_SIZE);
|
|
|
|
truesize = size;
|
|
|
|
|
|
|
|
page = page_pool_dev_alloc(pool, &page_off, &truesize);
|
2024-02-17 11:12:14 +00:00
|
|
|
if (!page) {
|
2024-02-12 09:50:56 +00:00
|
|
|
consume_skb(nskb);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb_add_rx_frag(nskb, i, page, page_off, size, truesize);
|
|
|
|
err = skb_copy_bits(skb, off, page_address(page) + page_off,
|
|
|
|
size);
|
|
|
|
if (err) {
|
|
|
|
consume_skb(nskb);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
len -= size;
|
|
|
|
off += size;
|
|
|
|
}
|
|
|
|
|
|
|
|
consume_skb(skb);
|
|
|
|
*pskb = nskb;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
#endif
|
|
|
|
}
|
2024-02-12 09:50:57 +00:00
|
|
|
EXPORT_SYMBOL(skb_pp_cow_data);
|
2024-02-12 09:50:56 +00:00
|
|
|
|
|
|
|
int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,
|
|
|
|
struct bpf_prog *prog)
|
|
|
|
{
|
|
|
|
if (!prog->aux->xdp_has_frags)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return skb_pp_cow_data(pool, pskb, XDP_PACKET_HEADROOM);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_cow_data_for_xdp);
|
|
|
|
|
net: skbuff: don't include <net/page_pool/types.h> to <linux/skbuff.h>
Currently, touching <net/page_pool/types.h> triggers a rebuild of more
than half of the kernel. That's because it's included in
<linux/skbuff.h>. And each new include to page_pool/types.h adds more
[useless] data for the toolchain to process per each source file from
that pile.
In commit 6a5bcd84e886 ("page_pool: Allow drivers to hint on SKB
recycling"), Matteo included it to be able to call a couple of functions
defined there. Then, in commit 57f05bc2ab24 ("page_pool: keep pp info as
long as page pool owns the page") one of the calls was removed, so only
one was left. It's the call to page_pool_return_skb_page() in
napi_frag_unref(). The function is external and doesn't have any
dependencies. Having very niche page_pool_types.h included only for that
looks like an overkill.
As %PP_SIGNATURE is not local to page_pool.c (was only in the
early submissions), nothing holds this function there. Teleport
page_pool_return_skb_page() to skbuff.c, just next to the main consumer,
skb_pp_recycle(), and rename it to napi_pp_put_page(), as it doesn't
work with skbs at all and the former name tells nothing. The #if guards
here are only to not compile and have it in the vmlinux when not needed
-- both call sites are already guarded.
Now, touching page_pool_types.h only triggers rebuilding of the drivers
using it and a couple of core networking files.
Suggested-by: Jakub Kicinski <kuba@kernel.org> # make skbuff.h less heavy
Suggested-by: Alexander Duyck <alexanderduyck@fb.com> # move to skbuff.c
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://lore.kernel.org/r/20230804180529.2483231-3-aleksander.lobakin@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-04 18:05:25 +00:00
|
|
|
#if IS_ENABLED(CONFIG_PAGE_POOL)
|
2024-03-29 16:55:06 +00:00
|
|
|
bool napi_pp_put_page(struct page *page)
|
net: skbuff: don't include <net/page_pool/types.h> to <linux/skbuff.h>
Currently, touching <net/page_pool/types.h> triggers a rebuild of more
than half of the kernel. That's because it's included in
<linux/skbuff.h>. And each new include to page_pool/types.h adds more
[useless] data for the toolchain to process per each source file from
that pile.
In commit 6a5bcd84e886 ("page_pool: Allow drivers to hint on SKB
recycling"), Matteo included it to be able to call a couple of functions
defined there. Then, in commit 57f05bc2ab24 ("page_pool: keep pp info as
long as page pool owns the page") one of the calls was removed, so only
one was left. It's the call to page_pool_return_skb_page() in
napi_frag_unref(). The function is external and doesn't have any
dependencies. Having very niche page_pool_types.h included only for that
looks like an overkill.
As %PP_SIGNATURE is not local to page_pool.c (was only in the
early submissions), nothing holds this function there. Teleport
page_pool_return_skb_page() to skbuff.c, just next to the main consumer,
skb_pp_recycle(), and rename it to napi_pp_put_page(), as it doesn't
work with skbs at all and the former name tells nothing. The #if guards
here are only to not compile and have it in the vmlinux when not needed
-- both call sites are already guarded.
Now, touching page_pool_types.h only triggers rebuilding of the drivers
using it and a couple of core networking files.
Suggested-by: Jakub Kicinski <kuba@kernel.org> # make skbuff.h less heavy
Suggested-by: Alexander Duyck <alexanderduyck@fb.com> # move to skbuff.c
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://lore.kernel.org/r/20230804180529.2483231-3-aleksander.lobakin@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-04 18:05:25 +00:00
|
|
|
{
|
|
|
|
page = compound_head(page);
|
|
|
|
|
|
|
|
/* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation
|
|
|
|
* in order to preserve any existing bits, such as bit 0 for the
|
|
|
|
* head page of compound page and bit 1 for pfmemalloc page, so
|
|
|
|
* mask those bits for freeing side when doing below checking,
|
|
|
|
* and page_is_pfmemalloc() is checked in __page_pool_put_page()
|
|
|
|
* to avoid recycling the pfmemalloc page.
|
|
|
|
*/
|
2023-12-15 03:30:10 +00:00
|
|
|
if (unlikely(!is_pp_page(page)))
|
net: skbuff: don't include <net/page_pool/types.h> to <linux/skbuff.h>
Currently, touching <net/page_pool/types.h> triggers a rebuild of more
than half of the kernel. That's because it's included in
<linux/skbuff.h>. And each new include to page_pool/types.h adds more
[useless] data for the toolchain to process per each source file from
that pile.
In commit 6a5bcd84e886 ("page_pool: Allow drivers to hint on SKB
recycling"), Matteo included it to be able to call a couple of functions
defined there. Then, in commit 57f05bc2ab24 ("page_pool: keep pp info as
long as page pool owns the page") one of the calls was removed, so only
one was left. It's the call to page_pool_return_skb_page() in
napi_frag_unref(). The function is external and doesn't have any
dependencies. Having very niche page_pool_types.h included only for that
looks like an overkill.
As %PP_SIGNATURE is not local to page_pool.c (was only in the
early submissions), nothing holds this function there. Teleport
page_pool_return_skb_page() to skbuff.c, just next to the main consumer,
skb_pp_recycle(), and rename it to napi_pp_put_page(), as it doesn't
work with skbs at all and the former name tells nothing. The #if guards
here are only to not compile and have it in the vmlinux when not needed
-- both call sites are already guarded.
Now, touching page_pool_types.h only triggers rebuilding of the drivers
using it and a couple of core networking files.
Suggested-by: Jakub Kicinski <kuba@kernel.org> # make skbuff.h less heavy
Suggested-by: Alexander Duyck <alexanderduyck@fb.com> # move to skbuff.c
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://lore.kernel.org/r/20230804180529.2483231-3-aleksander.lobakin@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-04 18:05:25 +00:00
|
|
|
return false;
|
|
|
|
|
2024-03-29 16:55:06 +00:00
|
|
|
page_pool_put_full_page(page->pp, page, false);
|
net: skbuff: don't include <net/page_pool/types.h> to <linux/skbuff.h>
Currently, touching <net/page_pool/types.h> triggers a rebuild of more
than half of the kernel. That's because it's included in
<linux/skbuff.h>. And each new include to page_pool/types.h adds more
[useless] data for the toolchain to process per each source file from
that pile.
In commit 6a5bcd84e886 ("page_pool: Allow drivers to hint on SKB
recycling"), Matteo included it to be able to call a couple of functions
defined there. Then, in commit 57f05bc2ab24 ("page_pool: keep pp info as
long as page pool owns the page") one of the calls was removed, so only
one was left. It's the call to page_pool_return_skb_page() in
napi_frag_unref(). The function is external and doesn't have any
dependencies. Having very niche page_pool_types.h included only for that
looks like an overkill.
As %PP_SIGNATURE is not local to page_pool.c (was only in the
early submissions), nothing holds this function there. Teleport
page_pool_return_skb_page() to skbuff.c, just next to the main consumer,
skb_pp_recycle(), and rename it to napi_pp_put_page(), as it doesn't
work with skbs at all and the former name tells nothing. The #if guards
here are only to not compile and have it in the vmlinux when not needed
-- both call sites are already guarded.
Now, touching page_pool_types.h only triggers rebuilding of the drivers
using it and a couple of core networking files.
Suggested-by: Jakub Kicinski <kuba@kernel.org> # make skbuff.h less heavy
Suggested-by: Alexander Duyck <alexanderduyck@fb.com> # move to skbuff.c
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://lore.kernel.org/r/20230804180529.2483231-3-aleksander.lobakin@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-04 18:05:25 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(napi_pp_put_page);
|
|
|
|
#endif
|
|
|
|
|
2024-03-29 16:55:06 +00:00
|
|
|
static bool skb_pp_recycle(struct sk_buff *skb, void *data)
|
2022-10-21 02:58:22 +00:00
|
|
|
{
|
|
|
|
if (!IS_ENABLED(CONFIG_PAGE_POOL) || !skb->pp_recycle)
|
|
|
|
return false;
|
2024-03-29 16:55:06 +00:00
|
|
|
return napi_pp_put_page(virt_to_page(data));
|
2022-10-21 02:58:22 +00:00
|
|
|
}
|
|
|
|
|
2024-05-02 17:54:22 +00:00
|
|
|
/**
|
|
|
|
* skb_pp_frag_ref() - Increase fragment references of a page pool aware skb
|
|
|
|
* @skb: page pool aware skb
|
|
|
|
*
|
|
|
|
* Increase the fragment reference count (pp_ref_count) of a skb. This is
|
|
|
|
* intended to gain fragment references only for page pool aware skbs,
|
|
|
|
* i.e. when skb->pp_recycle is true, and not for fragments in a
|
|
|
|
* non-pp-recycling skb. It has a fallback to increase references on normal
|
|
|
|
* pages, as page pool aware skbs may also have normal page fragments.
|
|
|
|
*/
|
|
|
|
static int skb_pp_frag_ref(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct skb_shared_info *shinfo;
|
|
|
|
struct page *head_page;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!skb->pp_recycle)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
shinfo = skb_shinfo(skb);
|
|
|
|
|
|
|
|
for (i = 0; i < shinfo->nr_frags; i++) {
|
|
|
|
head_page = compound_head(skb_frag_page(&shinfo->frags[i]));
|
|
|
|
if (likely(is_pp_page(head_page)))
|
|
|
|
page_pool_ref_page(head_page);
|
|
|
|
else
|
|
|
|
page_ref_inc(head_page);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-02-06 17:31:03 +00:00
|
|
|
static void skb_kfree_head(void *head, unsigned int end_offset)
|
|
|
|
{
|
|
|
|
if (end_offset == SKB_SMALL_HEAD_HEADROOM)
|
2024-03-06 16:00:23 +00:00
|
|
|
kmem_cache_free(net_hotdata.skb_small_head_cache, head);
|
2023-02-06 17:31:03 +00:00
|
|
|
else
|
|
|
|
kfree(head);
|
|
|
|
}
|
|
|
|
|
2024-03-29 16:55:06 +00:00
|
|
|
static void skb_free_head(struct sk_buff *skb)
|
net: allow skb->head to be a page fragment
skb->head is currently allocated from kmalloc(). This is convenient but
has the drawback the data cannot be converted to a page fragment if
needed.
We have three spots were it hurts :
1) GRO aggregation
When a linear skb must be appended to another skb, GRO uses the
frag_list fallback, very inefficient since we keep all struct sk_buff
around. So drivers enabling GRO but delivering linear skbs to network
stack aren't enabling full GRO power.
2) splice(socket -> pipe).
We must copy the linear part to a page fragment.
This kind of defeats splice() purpose (zero copy claim)
3) TCP coalescing.
Recently introduced, this permits to group several contiguous segments
into a single skb. This shortens queue lengths and save kernel memory,
and greatly reduce probabilities of TCP collapses. This coalescing
doesnt work on linear skbs (or we would need to copy data, this would be
too slow)
Given all these issues, the following patch introduces the possibility
of having skb->head be a fragment in itself. We use a new skb flag,
skb->head_frag to carry this information.
build_skb() is changed to accept a frag_size argument. Drivers willing
to provide a page fragment instead of kmalloc() data will set a non zero
value, set to the fragment size.
Then, on situations we need to convert the skb head to a frag in itself,
we can check if skb->head_frag is set and avoid the copies or various
fallbacks we have.
This means drivers currently using frags could be updated to avoid the
current skb->head allocation and reduce their memory footprint (aka skb
truesize). (thats 512 or 1024 bytes saved per skb). This also makes
bpf/netfilter faster since the 'first frag' will be part of skb linear
part, no need to copy data.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Maciej Żenczykowski <maze@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Tom Herbert <therbert@google.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Matt Carlson <mcarlson@broadcom.com>
Cc: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-04-27 00:33:38 +00:00
|
|
|
{
|
2015-05-07 04:12:03 +00:00
|
|
|
unsigned char *head = skb->head;
|
|
|
|
|
2021-06-07 19:02:38 +00:00
|
|
|
if (skb->head_frag) {
|
2024-03-29 16:55:06 +00:00
|
|
|
if (skb_pp_recycle(skb, head))
|
2021-06-07 19:02:38 +00:00
|
|
|
return;
|
2015-05-07 04:12:03 +00:00
|
|
|
skb_free_frag(head);
|
2021-06-07 19:02:38 +00:00
|
|
|
} else {
|
2023-02-06 17:31:03 +00:00
|
|
|
skb_kfree_head(head, skb_end_offset(skb));
|
2021-06-07 19:02:38 +00:00
|
|
|
}
|
net: allow skb->head to be a page fragment
skb->head is currently allocated from kmalloc(). This is convenient but
has the drawback the data cannot be converted to a page fragment if
needed.
We have three spots were it hurts :
1) GRO aggregation
When a linear skb must be appended to another skb, GRO uses the
frag_list fallback, very inefficient since we keep all struct sk_buff
around. So drivers enabling GRO but delivering linear skbs to network
stack aren't enabling full GRO power.
2) splice(socket -> pipe).
We must copy the linear part to a page fragment.
This kind of defeats splice() purpose (zero copy claim)
3) TCP coalescing.
Recently introduced, this permits to group several contiguous segments
into a single skb. This shortens queue lengths and save kernel memory,
and greatly reduce probabilities of TCP collapses. This coalescing
doesnt work on linear skbs (or we would need to copy data, this would be
too slow)
Given all these issues, the following patch introduces the possibility
of having skb->head be a fragment in itself. We use a new skb flag,
skb->head_frag to carry this information.
build_skb() is changed to accept a frag_size argument. Drivers willing
to provide a page fragment instead of kmalloc() data will set a non zero
value, set to the fragment size.
Then, on situations we need to convert the skb head to a frag in itself,
we can check if skb->head_frag is set and avoid the copies or various
fallbacks we have.
This means drivers currently using frags could be updated to avoid the
current skb->head allocation and reduce their memory footprint (aka skb
truesize). (thats 512 or 1024 bytes saved per skb). This also makes
bpf/netfilter faster since the 'first frag' will be part of skb linear
part, no need to copy data.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Maciej Żenczykowski <maze@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Tom Herbert <therbert@google.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Matt Carlson <mcarlson@broadcom.com>
Cc: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-04-27 00:33:38 +00:00
|
|
|
}
|
|
|
|
|
2024-03-29 16:55:06 +00:00
|
|
|
static void skb_release_data(struct sk_buff *skb, enum skb_drop_reason reason)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2014-09-24 01:39:30 +00:00
|
|
|
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
|
|
|
int i;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-03-07 12:34:46 +00:00
|
|
|
if (!skb_data_unref(skb, shinfo))
|
2021-07-16 07:02:18 +00:00
|
|
|
goto exit;
|
2011-07-06 12:22:12 +00:00
|
|
|
|
2022-07-12 20:52:31 +00:00
|
|
|
if (skb_zcopy(skb)) {
|
|
|
|
bool skip_unref = shinfo->flags & SKBFL_MANAGED_FRAG_REFS;
|
|
|
|
|
|
|
|
skb_zcopy_clear(skb, true);
|
|
|
|
if (skip_unref)
|
|
|
|
goto free_head;
|
|
|
|
}
|
2021-01-06 22:18:36 +00:00
|
|
|
|
2014-09-24 01:39:30 +00:00
|
|
|
for (i = 0; i < shinfo->nr_frags; i++)
|
2024-04-08 15:29:58 +00:00
|
|
|
__skb_frag_unref(&shinfo->frags[i], skb->pp_recycle);
|
2011-07-06 12:22:12 +00:00
|
|
|
|
2022-07-12 20:52:31 +00:00
|
|
|
free_head:
|
2014-09-24 01:39:30 +00:00
|
|
|
if (shinfo->frag_list)
|
2022-10-29 15:45:17 +00:00
|
|
|
kfree_skb_list_reason(shinfo->frag_list, reason);
|
2014-09-24 01:39:30 +00:00
|
|
|
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_free_head(skb);
|
2021-07-16 07:02:18 +00:00
|
|
|
exit:
|
|
|
|
/* When we clone an SKB we copy the reycling bit. The pp_recycle
|
|
|
|
* bit is only set on the head though, so in order to avoid races
|
|
|
|
* while trying to recycle fragments on __skb_frag_unref() we need
|
|
|
|
* to make one SKB responsible for triggering the recycle path.
|
|
|
|
* So disable the recycling bit if an SKB is cloned and we have
|
2022-02-09 15:02:42 +00:00
|
|
|
* additional references to the fragmented part of the SKB.
|
2021-07-16 07:02:18 +00:00
|
|
|
* Eventually the last SKB will have the recycling bit set and it's
|
|
|
|
* dataref set to 0, which will trigger the recycling
|
|
|
|
*/
|
|
|
|
skb->pp_recycle = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free an skbuff by memory without cleaning the state.
|
|
|
|
*/
|
2007-11-26 15:11:19 +00:00
|
|
|
static void kfree_skbmem(struct sk_buff *skb)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2014-09-29 20:29:15 +00:00
|
|
|
struct sk_buff_fclones *fclones;
|
2005-08-17 21:57:30 +00:00
|
|
|
|
|
|
|
switch (skb->fclone) {
|
|
|
|
case SKB_FCLONE_UNAVAILABLE:
|
2024-03-06 16:00:23 +00:00
|
|
|
kmem_cache_free(net_hotdata.skbuff_cache, skb);
|
2014-12-04 01:04:39 +00:00
|
|
|
return;
|
2005-08-17 21:57:30 +00:00
|
|
|
|
|
|
|
case SKB_FCLONE_ORIG:
|
2014-09-29 20:29:15 +00:00
|
|
|
fclones = container_of(skb, struct sk_buff_fclones, skb1);
|
2005-08-17 21:57:30 +00:00
|
|
|
|
2014-12-04 01:04:39 +00:00
|
|
|
/* We usually free the clone (TX completion) before original skb
|
|
|
|
* This test would have no chance to be true for the clone,
|
|
|
|
* while here, branch prediction will be good.
|
2005-08-17 21:57:30 +00:00
|
|
|
*/
|
2017-06-30 10:07:59 +00:00
|
|
|
if (refcount_read(&fclones->fclone_ref) == 1)
|
2014-12-04 01:04:39 +00:00
|
|
|
goto fastpath;
|
|
|
|
break;
|
2014-11-21 19:47:16 +00:00
|
|
|
|
2014-12-04 01:04:39 +00:00
|
|
|
default: /* SKB_FCLONE_CLONE */
|
|
|
|
fclones = container_of(skb, struct sk_buff_fclones, skb2);
|
2005-08-17 21:57:30 +00:00
|
|
|
break;
|
2007-04-21 00:09:22 +00:00
|
|
|
}
|
2017-06-30 10:07:59 +00:00
|
|
|
if (!refcount_dec_and_test(&fclones->fclone_ref))
|
2014-12-04 01:04:39 +00:00
|
|
|
return;
|
|
|
|
fastpath:
|
2024-03-06 16:00:23 +00:00
|
|
|
kmem_cache_free(net_hotdata.skbuff_fclone_cache, fclones);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2017-06-12 09:23:42 +00:00
|
|
|
void skb_release_head_state(struct sk_buff *skb)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2009-06-02 05:19:30 +00:00
|
|
|
skb_dst_drop(skb);
|
2005-04-20 05:39:42 +00:00
|
|
|
if (skb->destructor) {
|
2022-06-08 16:04:36 +00:00
|
|
|
DEBUG_NET_WARN_ON_ONCE(in_hardirq());
|
2005-04-16 22:20:36 +00:00
|
|
|
skb->destructor(skb);
|
|
|
|
}
|
2011-12-12 02:58:22 +00:00
|
|
|
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
2017-01-23 17:21:56 +00:00
|
|
|
nf_conntrack_put(skb_nfct(skb));
|
2005-04-16 22:20:36 +00:00
|
|
|
#endif
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
skb_ext_put(skb);
|
2008-10-01 09:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free everything but the sk_buff shell. */
|
2024-03-29 16:55:06 +00:00
|
|
|
static void skb_release_all(struct sk_buff *skb, enum skb_drop_reason reason)
|
2008-10-01 09:33:12 +00:00
|
|
|
{
|
|
|
|
skb_release_head_state(skb);
|
2017-07-23 17:54:47 +00:00
|
|
|
if (likely(skb->head))
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_data(skb, reason);
|
2007-11-26 15:11:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* __kfree_skb - private function
|
|
|
|
* @skb: buffer
|
|
|
|
*
|
|
|
|
* Free an sk_buff. Release anything attached to the buffer.
|
|
|
|
* Clean the state. This is an internal helper function. Users should
|
|
|
|
* always call kfree_skb
|
|
|
|
*/
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-11-26 15:11:19 +00:00
|
|
|
void __kfree_skb(struct sk_buff *skb)
|
|
|
|
{
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_all(skb, SKB_DROP_REASON_NOT_SPECIFIED);
|
2005-04-16 22:20:36 +00:00
|
|
|
kfree_skbmem(skb);
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(__kfree_skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2023-01-13 13:51:59 +00:00
|
|
|
static __always_inline
|
|
|
|
bool __kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
|
|
|
|
{
|
|
|
|
if (unlikely(!skb_unref(skb)))
|
|
|
|
return false;
|
|
|
|
|
2023-04-19 12:52:53 +00:00
|
|
|
DEBUG_NET_WARN_ON_ONCE(reason == SKB_NOT_DROPPED_YET ||
|
|
|
|
u32_get_bits(reason,
|
|
|
|
SKB_DROP_REASON_SUBSYS_MASK) >=
|
|
|
|
SKB_DROP_REASON_SUBSYS_NUM);
|
2023-01-13 13:51:59 +00:00
|
|
|
|
|
|
|
if (reason == SKB_CONSUMED)
|
2023-02-16 15:47:18 +00:00
|
|
|
trace_consume_skb(skb, __builtin_return_address(0));
|
2023-01-13 13:51:59 +00:00
|
|
|
else
|
|
|
|
trace_kfree_skb(skb, __builtin_return_address(0), reason);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-03-21 05:28:35 +00:00
|
|
|
/**
|
2022-01-09 06:36:26 +00:00
|
|
|
* kfree_skb_reason - free an sk_buff with special reason
|
2006-03-21 05:28:35 +00:00
|
|
|
* @skb: buffer to free
|
2022-01-09 06:36:26 +00:00
|
|
|
* @reason: reason why this skb is dropped
|
2006-03-21 05:28:35 +00:00
|
|
|
*
|
|
|
|
* Drop a reference to the buffer and free it if the usage count has
|
2022-01-09 06:36:26 +00:00
|
|
|
* hit zero. Meanwhile, pass the drop reason to 'kfree_skb'
|
|
|
|
* tracepoint.
|
2006-03-21 05:28:35 +00:00
|
|
|
*/
|
2022-08-21 05:18:58 +00:00
|
|
|
void __fix_address
|
|
|
|
kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
|
2006-03-21 05:28:35 +00:00
|
|
|
{
|
2023-01-13 13:51:59 +00:00
|
|
|
if (__kfree_skb_reason(skb, reason))
|
|
|
|
__kfree_skb(skb);
|
2006-03-21 05:28:35 +00:00
|
|
|
}
|
2022-01-09 06:36:26 +00:00
|
|
|
EXPORT_SYMBOL(kfree_skb_reason);
|
2006-03-21 05:28:35 +00:00
|
|
|
|
2023-01-13 13:52:04 +00:00
|
|
|
#define KFREE_SKB_BULK_SIZE 16
|
|
|
|
|
|
|
|
struct skb_free_array {
|
|
|
|
unsigned int skb_count;
|
|
|
|
void *skb_array[KFREE_SKB_BULK_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
static void kfree_skb_add_bulk(struct sk_buff *skb,
|
|
|
|
struct skb_free_array *sa,
|
|
|
|
enum skb_drop_reason reason)
|
|
|
|
{
|
|
|
|
/* if SKB is a clone, don't handle this case */
|
|
|
|
if (unlikely(skb->fclone != SKB_FCLONE_UNAVAILABLE)) {
|
|
|
|
__kfree_skb(skb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_all(skb, reason);
|
2023-01-13 13:52:04 +00:00
|
|
|
sa->skb_array[sa->skb_count++] = skb;
|
|
|
|
|
|
|
|
if (unlikely(sa->skb_count == KFREE_SKB_BULK_SIZE)) {
|
2024-03-06 16:00:23 +00:00
|
|
|
kmem_cache_free_bulk(net_hotdata.skbuff_cache, KFREE_SKB_BULK_SIZE,
|
2023-01-13 13:52:04 +00:00
|
|
|
sa->skb_array);
|
|
|
|
sa->skb_count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-13 13:51:59 +00:00
|
|
|
void __fix_address
|
|
|
|
kfree_skb_list_reason(struct sk_buff *segs, enum skb_drop_reason reason)
|
2013-06-24 13:26:00 +00:00
|
|
|
{
|
2023-01-13 13:52:04 +00:00
|
|
|
struct skb_free_array sa;
|
|
|
|
|
|
|
|
sa.skb_count = 0;
|
|
|
|
|
2013-06-24 13:26:00 +00:00
|
|
|
while (segs) {
|
|
|
|
struct sk_buff *next = segs->next;
|
|
|
|
|
2023-02-03 12:59:29 +00:00
|
|
|
if (__kfree_skb_reason(segs, reason)) {
|
|
|
|
skb_poison_list(segs);
|
2023-01-13 13:52:04 +00:00
|
|
|
kfree_skb_add_bulk(segs, &sa, reason);
|
2023-02-03 12:59:29 +00:00
|
|
|
}
|
2023-01-13 13:52:04 +00:00
|
|
|
|
2013-06-24 13:26:00 +00:00
|
|
|
segs = next;
|
|
|
|
}
|
2023-01-13 13:52:04 +00:00
|
|
|
|
|
|
|
if (sa.skb_count)
|
2024-03-06 16:00:23 +00:00
|
|
|
kmem_cache_free_bulk(net_hotdata.skbuff_cache, sa.skb_count, sa.skb_array);
|
2013-06-24 13:26:00 +00:00
|
|
|
}
|
2022-03-04 06:00:41 +00:00
|
|
|
EXPORT_SYMBOL(kfree_skb_list_reason);
|
2013-06-24 13:26:00 +00:00
|
|
|
|
2019-07-07 09:51:55 +00:00
|
|
|
/* Dump skb information and contents.
|
|
|
|
*
|
|
|
|
* Must only be called from net_ratelimit()-ed paths.
|
|
|
|
*
|
2020-10-05 14:48:38 +00:00
|
|
|
* Dumps whole packets if full_pkt, only headers otherwise.
|
2019-07-07 09:51:55 +00:00
|
|
|
*/
|
|
|
|
void skb_dump(const char *level, const struct sk_buff *skb, bool full_pkt)
|
|
|
|
{
|
|
|
|
struct skb_shared_info *sh = skb_shinfo(skb);
|
|
|
|
struct net_device *dev = skb->dev;
|
|
|
|
struct sock *sk = skb->sk;
|
|
|
|
struct sk_buff *list_skb;
|
|
|
|
bool has_mac, has_trans;
|
|
|
|
int headroom, tailroom;
|
|
|
|
int i, len, seg_len;
|
|
|
|
|
|
|
|
if (full_pkt)
|
|
|
|
len = skb->len;
|
|
|
|
else
|
|
|
|
len = min_t(int, skb->len, MAX_HEADER + 128);
|
|
|
|
|
|
|
|
headroom = skb_headroom(skb);
|
|
|
|
tailroom = skb_tailroom(skb);
|
|
|
|
|
|
|
|
has_mac = skb_mac_header_was_set(skb);
|
|
|
|
has_trans = skb_transport_header_was_set(skb);
|
|
|
|
|
|
|
|
printk("%sskb len=%u headroom=%u headlen=%u tailroom=%u\n"
|
2024-04-07 08:06:06 +00:00
|
|
|
"mac=(%d,%d) mac_len=%u net=(%d,%d) trans=%d\n"
|
2019-07-07 09:51:55 +00:00
|
|
|
"shinfo(txflags=%u nr_frags=%u gso(size=%hu type=%u segs=%hu))\n"
|
2024-04-07 08:06:06 +00:00
|
|
|
"csum(0x%x start=%u offset=%u ip_summed=%u complete_sw=%u valid=%u level=%u)\n"
|
|
|
|
"hash(0x%x sw=%u l4=%u) proto=0x%04x pkttype=%u iif=%d\n"
|
|
|
|
"priority=0x%x mark=0x%x alloc_cpu=%u vlan_all=0x%x\n"
|
|
|
|
"encapsulation=%d inner(proto=0x%04x, mac=%u, net=%u, trans=%u)\n",
|
2019-07-07 09:51:55 +00:00
|
|
|
level, skb->len, headroom, skb_headlen(skb), tailroom,
|
|
|
|
has_mac ? skb->mac_header : -1,
|
|
|
|
has_mac ? skb_mac_header_len(skb) : -1,
|
2024-04-07 08:06:06 +00:00
|
|
|
skb->mac_len,
|
2019-07-07 09:51:55 +00:00
|
|
|
skb->network_header,
|
|
|
|
has_trans ? skb_network_header_len(skb) : -1,
|
|
|
|
has_trans ? skb->transport_header : -1,
|
|
|
|
sh->tx_flags, sh->nr_frags,
|
|
|
|
sh->gso_size, sh->gso_type, sh->gso_segs,
|
2024-04-07 08:06:06 +00:00
|
|
|
skb->csum, skb->csum_start, skb->csum_offset, skb->ip_summed,
|
|
|
|
skb->csum_complete_sw, skb->csum_valid, skb->csum_level,
|
2019-07-07 09:51:55 +00:00
|
|
|
skb->hash, skb->sw_hash, skb->l4_hash,
|
2024-04-07 08:06:06 +00:00
|
|
|
ntohs(skb->protocol), skb->pkt_type, skb->skb_iif,
|
|
|
|
skb->priority, skb->mark, skb->alloc_cpu, skb->vlan_all,
|
|
|
|
skb->encapsulation, skb->inner_protocol, skb->inner_mac_header,
|
|
|
|
skb->inner_network_header, skb->inner_transport_header);
|
2019-07-07 09:51:55 +00:00
|
|
|
|
|
|
|
if (dev)
|
2021-12-16 09:28:25 +00:00
|
|
|
printk("%sdev name=%s feat=%pNF\n",
|
2019-07-07 09:51:55 +00:00
|
|
|
level, dev->name, &dev->features);
|
|
|
|
if (sk)
|
2019-07-16 15:43:05 +00:00
|
|
|
printk("%ssk family=%hu type=%u proto=%u\n",
|
2019-07-07 09:51:55 +00:00
|
|
|
level, sk->sk_family, sk->sk_type, sk->sk_protocol);
|
|
|
|
|
|
|
|
if (full_pkt && headroom)
|
|
|
|
print_hex_dump(level, "skb headroom: ", DUMP_PREFIX_OFFSET,
|
|
|
|
16, 1, skb->head, headroom, false);
|
|
|
|
|
|
|
|
seg_len = min_t(int, skb_headlen(skb), len);
|
|
|
|
if (seg_len)
|
|
|
|
print_hex_dump(level, "skb linear: ", DUMP_PREFIX_OFFSET,
|
|
|
|
16, 1, skb->data, seg_len, false);
|
|
|
|
len -= seg_len;
|
|
|
|
|
|
|
|
if (full_pkt && tailroom)
|
|
|
|
print_hex_dump(level, "skb tailroom: ", DUMP_PREFIX_OFFSET,
|
|
|
|
16, 1, skb_tail_pointer(skb), tailroom, false);
|
|
|
|
|
|
|
|
for (i = 0; len && i < skb_shinfo(skb)->nr_frags; i++) {
|
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
|
|
|
u32 p_off, p_len, copied;
|
|
|
|
struct page *p;
|
|
|
|
u8 *vaddr;
|
|
|
|
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_foreach_page(frag, skb_frag_off(frag),
|
2019-07-07 09:51:55 +00:00
|
|
|
skb_frag_size(frag), p, p_off, p_len,
|
|
|
|
copied) {
|
|
|
|
seg_len = min_t(int, p_len, len);
|
|
|
|
vaddr = kmap_atomic(p);
|
|
|
|
print_hex_dump(level, "skb frag: ",
|
|
|
|
DUMP_PREFIX_OFFSET,
|
|
|
|
16, 1, vaddr + p_off, seg_len, false);
|
|
|
|
kunmap_atomic(vaddr);
|
|
|
|
len -= seg_len;
|
|
|
|
if (!len)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (full_pkt && skb_has_frag_list(skb)) {
|
|
|
|
printk("skb fraglist:\n");
|
|
|
|
skb_walk_frags(skb, list_skb)
|
|
|
|
skb_dump(level, list_skb, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_dump);
|
|
|
|
|
2012-11-01 09:16:28 +00:00
|
|
|
/**
|
|
|
|
* skb_tx_error - report an sk_buff xmit error
|
|
|
|
* @skb: buffer that triggered an error
|
|
|
|
*
|
|
|
|
* Report xmit error if a device callback is tracking this skb.
|
|
|
|
* skb must be freed afterwards.
|
|
|
|
*/
|
|
|
|
void skb_tx_error(struct sk_buff *skb)
|
|
|
|
{
|
2022-07-12 20:52:31 +00:00
|
|
|
if (skb) {
|
|
|
|
skb_zcopy_downgrade_managed(skb);
|
|
|
|
skb_zcopy_clear(skb, true);
|
|
|
|
}
|
2012-11-01 09:16:28 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_tx_error);
|
|
|
|
|
2020-08-21 22:23:29 +00:00
|
|
|
#ifdef CONFIG_TRACEPOINTS
|
2009-03-11 09:49:55 +00:00
|
|
|
/**
|
|
|
|
* consume_skb - free an skbuff
|
|
|
|
* @skb: buffer to free
|
|
|
|
*
|
|
|
|
* Drop a ref to the buffer and free it if the usage count has hit zero
|
|
|
|
* Functions identically to kfree_skb, but kfree_skb assumes that the frame
|
|
|
|
* is being dropped after a failure and notes that
|
|
|
|
*/
|
|
|
|
void consume_skb(struct sk_buff *skb)
|
|
|
|
{
|
2017-06-12 09:23:41 +00:00
|
|
|
if (!skb_unref(skb))
|
2009-03-11 09:49:55 +00:00
|
|
|
return;
|
2017-06-12 09:23:41 +00:00
|
|
|
|
2023-02-16 15:47:18 +00:00
|
|
|
trace_consume_skb(skb, __builtin_return_address(0));
|
2009-03-11 09:49:55 +00:00
|
|
|
__kfree_skb(skb);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(consume_skb);
|
2020-08-21 22:23:29 +00:00
|
|
|
#endif
|
2009-03-11 09:49:55 +00:00
|
|
|
|
2017-06-12 09:23:42 +00:00
|
|
|
/**
|
2020-11-16 10:17:58 +00:00
|
|
|
* __consume_stateless_skb - free an skbuff, assuming it is stateless
|
2017-06-12 09:23:42 +00:00
|
|
|
* @skb: buffer to free
|
|
|
|
*
|
2017-09-06 12:44:36 +00:00
|
|
|
* Alike consume_skb(), but this variant assumes that this is the last
|
|
|
|
* skb reference and all the head states have been already dropped
|
2017-06-12 09:23:42 +00:00
|
|
|
*/
|
2017-09-06 12:44:36 +00:00
|
|
|
void __consume_stateless_skb(struct sk_buff *skb)
|
2017-06-12 09:23:42 +00:00
|
|
|
{
|
2023-02-16 15:47:18 +00:00
|
|
|
trace_consume_skb(skb, __builtin_return_address(0));
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_data(skb, SKB_CONSUMED);
|
2017-06-12 09:23:42 +00:00
|
|
|
kfree_skbmem(skb);
|
|
|
|
}
|
|
|
|
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
static void napi_skb_cache_put(struct sk_buff *skb)
|
2016-02-08 12:14:59 +00:00
|
|
|
{
|
|
|
|
struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
u32 i;
|
2016-02-08 12:14:59 +00:00
|
|
|
|
2023-12-19 22:29:04 +00:00
|
|
|
if (!kasan_mempool_poison_object(skb))
|
|
|
|
return;
|
|
|
|
|
2016-02-08 12:14:59 +00:00
|
|
|
nc->skb_cache[nc->skb_count++] = skb;
|
|
|
|
|
|
|
|
if (unlikely(nc->skb_count == NAPI_SKB_CACHE_SIZE)) {
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
for (i = NAPI_SKB_CACHE_HALF; i < NAPI_SKB_CACHE_SIZE; i++)
|
2023-12-19 22:29:04 +00:00
|
|
|
kasan_mempool_unpoison_object(nc->skb_cache[i],
|
2024-03-06 16:00:23 +00:00
|
|
|
kmem_cache_size(net_hotdata.skbuff_cache));
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
|
2024-03-06 16:00:23 +00:00
|
|
|
kmem_cache_free_bulk(net_hotdata.skbuff_cache, NAPI_SKB_CACHE_HALF,
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
nc->skb_cache + NAPI_SKB_CACHE_HALF);
|
|
|
|
nc->skb_count = NAPI_SKB_CACHE_HALF;
|
2016-02-08 12:14:59 +00:00
|
|
|
}
|
|
|
|
}
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
|
2023-04-20 02:00:05 +00:00
|
|
|
void __napi_kfree_skb(struct sk_buff *skb, enum skb_drop_reason reason)
|
2016-02-08 12:15:04 +00:00
|
|
|
{
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_all(skb, reason);
|
2021-02-13 14:13:09 +00:00
|
|
|
napi_skb_cache_put(skb);
|
|
|
|
}
|
|
|
|
|
|
|
|
void napi_skb_free_stolen_head(struct sk_buff *skb)
|
|
|
|
{
|
2021-07-28 16:24:02 +00:00
|
|
|
if (unlikely(skb->slow_gro)) {
|
|
|
|
nf_reset_ct(skb);
|
|
|
|
skb_dst_drop(skb);
|
|
|
|
skb_ext_put(skb);
|
2021-07-28 16:24:03 +00:00
|
|
|
skb_orphan(skb);
|
2021-07-28 16:24:02 +00:00
|
|
|
skb->slow_gro = 0;
|
|
|
|
}
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
napi_skb_cache_put(skb);
|
2016-02-08 12:15:04 +00:00
|
|
|
}
|
2016-02-08 12:14:59 +00:00
|
|
|
|
|
|
|
void napi_consume_skb(struct sk_buff *skb, int budget)
|
|
|
|
{
|
2016-03-11 08:43:58 +00:00
|
|
|
/* Zero budget indicate non-NAPI context called us, like netpoll */
|
2016-02-08 12:14:59 +00:00
|
|
|
if (unlikely(!budget)) {
|
2016-03-11 08:43:58 +00:00
|
|
|
dev_consume_skb_any(skb);
|
2016-02-08 12:14:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-06-08 16:04:37 +00:00
|
|
|
DEBUG_NET_WARN_ON_ONCE(!in_softirq());
|
2020-11-24 10:49:29 +00:00
|
|
|
|
2017-06-14 09:48:48 +00:00
|
|
|
if (!skb_unref(skb))
|
2016-02-08 12:14:59 +00:00
|
|
|
return;
|
2017-06-14 09:48:48 +00:00
|
|
|
|
2016-02-08 12:14:59 +00:00
|
|
|
/* if reaching here SKB is ready to free */
|
2023-02-16 15:47:18 +00:00
|
|
|
trace_consume_skb(skb, __builtin_return_address(0));
|
2016-02-08 12:14:59 +00:00
|
|
|
|
|
|
|
/* if SKB is a clone, don't handle this case */
|
2016-03-20 18:27:47 +00:00
|
|
|
if (skb->fclone != SKB_FCLONE_UNAVAILABLE) {
|
2016-02-08 12:14:59 +00:00
|
|
|
__kfree_skb(skb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_all(skb, SKB_CONSUMED);
|
skbuff: introduce {,__}napi_build_skb() which reuses NAPI cache heads
Instead of just bulk-flushing skbuff_heads queued up through
napi_consume_skb() or __kfree_skb_defer(), try to reuse them
on allocation path.
If the cache is empty on allocation, bulk-allocate the first
16 elements, which is more efficient than per-skb allocation.
If the cache is full on freeing, bulk-wipe the second half of
the cache (32 elements).
This also includes custom KASAN poisoning/unpoisoning to be
double sure there are no use-after-free cases.
To not change current behaviour, introduce a new function,
napi_build_skb(), to optionally use a new approach later
in drivers.
Note on selected bulk size, 16:
- this equals to XDP_BULK_QUEUE_SIZE, DEV_MAP_BULK_SIZE
and especially VETH_XDP_BATCH, which is also used to
bulk-allocate skbuff_heads and was tested on powerful
setups;
- this also showed the best performance in the actual
test series (from the array of {8, 16, 32}).
Suggested-by: Edward Cree <ecree.xilinx@gmail.com> # Divide on two halves
Suggested-by: Eric Dumazet <edumazet@google.com> # KASAN poisoning
Cc: Dmitry Vyukov <dvyukov@google.com> # Help with KASAN
Cc: Paolo Abeni <pabeni@redhat.com> # Reduced batch size
Signed-off-by: Alexander Lobakin <alobakin@pm.me>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-13 14:12:25 +00:00
|
|
|
napi_skb_cache_put(skb);
|
2016-02-08 12:14:59 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(napi_consume_skb);
|
|
|
|
|
2021-11-21 00:31:49 +00:00
|
|
|
/* Make sure a field is contained by headers group */
|
net: reorganize sk_buff for faster __copy_skb_header()
With proliferation of bit fields in sk_buff, __copy_skb_header() became
quite expensive, showing as the most expensive function in a GSO
workload.
__copy_skb_header() performance is also critical for non GSO TCP
operations, as it is used from skb_clone()
This patch carefully moves all the fields that were not copied in a
separate zone : cloned, nohdr, fclone, peeked, head_frag, xmit_more
Then I moved all other fields and all other copied fields in a section
delimited by headers_start[0]/headers_end[0] section so that we
can use a single memcpy() call, inlined by compiler using long
word load/stores.
I also tried to make all copies in the natural orders of sk_buff,
to help hardware prefetching.
I made sure sk_buff size did not change.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-29 05:18:47 +00:00
|
|
|
#define CHECK_SKB_FIELD(field) \
|
2021-11-21 00:31:49 +00:00
|
|
|
BUILD_BUG_ON(offsetof(struct sk_buff, field) != \
|
|
|
|
offsetof(struct sk_buff, headers.field)); \
|
net: reorganize sk_buff for faster __copy_skb_header()
With proliferation of bit fields in sk_buff, __copy_skb_header() became
quite expensive, showing as the most expensive function in a GSO
workload.
__copy_skb_header() performance is also critical for non GSO TCP
operations, as it is used from skb_clone()
This patch carefully moves all the fields that were not copied in a
separate zone : cloned, nohdr, fclone, peeked, head_frag, xmit_more
Then I moved all other fields and all other copied fields in a section
delimited by headers_start[0]/headers_end[0] section so that we
can use a single memcpy() call, inlined by compiler using long
word load/stores.
I also tried to make all copies in the natural orders of sk_buff,
to help hardware prefetching.
I made sure sk_buff size did not change.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-29 05:18:47 +00:00
|
|
|
|
2007-10-14 07:37:30 +00:00
|
|
|
static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
|
|
|
{
|
|
|
|
new->tstamp = old->tstamp;
|
net: reorganize sk_buff for faster __copy_skb_header()
With proliferation of bit fields in sk_buff, __copy_skb_header() became
quite expensive, showing as the most expensive function in a GSO
workload.
__copy_skb_header() performance is also critical for non GSO TCP
operations, as it is used from skb_clone()
This patch carefully moves all the fields that were not copied in a
separate zone : cloned, nohdr, fclone, peeked, head_frag, xmit_more
Then I moved all other fields and all other copied fields in a section
delimited by headers_start[0]/headers_end[0] section so that we
can use a single memcpy() call, inlined by compiler using long
word load/stores.
I also tried to make all copies in the natural orders of sk_buff,
to help hardware prefetching.
I made sure sk_buff size did not change.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-29 05:18:47 +00:00
|
|
|
/* We do not copy old->sk */
|
2007-10-14 07:37:30 +00:00
|
|
|
new->dev = old->dev;
|
net: reorganize sk_buff for faster __copy_skb_header()
With proliferation of bit fields in sk_buff, __copy_skb_header() became
quite expensive, showing as the most expensive function in a GSO
workload.
__copy_skb_header() performance is also critical for non GSO TCP
operations, as it is used from skb_clone()
This patch carefully moves all the fields that were not copied in a
separate zone : cloned, nohdr, fclone, peeked, head_frag, xmit_more
Then I moved all other fields and all other copied fields in a section
delimited by headers_start[0]/headers_end[0] section so that we
can use a single memcpy() call, inlined by compiler using long
word load/stores.
I also tried to make all copies in the natural orders of sk_buff,
to help hardware prefetching.
I made sure sk_buff size did not change.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-29 05:18:47 +00:00
|
|
|
memcpy(new->cb, old->cb, sizeof(old->cb));
|
2010-05-11 23:19:48 +00:00
|
|
|
skb_dst_copy(new, old);
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
__skb_ext_copy(new, old);
|
net: reorganize sk_buff for faster __copy_skb_header()
With proliferation of bit fields in sk_buff, __copy_skb_header() became
quite expensive, showing as the most expensive function in a GSO
workload.
__copy_skb_header() performance is also critical for non GSO TCP
operations, as it is used from skb_clone()
This patch carefully moves all the fields that were not copied in a
separate zone : cloned, nohdr, fclone, peeked, head_frag, xmit_more
Then I moved all other fields and all other copied fields in a section
delimited by headers_start[0]/headers_end[0] section so that we
can use a single memcpy() call, inlined by compiler using long
word load/stores.
I also tried to make all copies in the natural orders of sk_buff,
to help hardware prefetching.
I made sure sk_buff size did not change.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-29 05:18:47 +00:00
|
|
|
__nf_copy(new, old, false);
|
|
|
|
|
2021-11-21 00:31:49 +00:00
|
|
|
/* Note : this field could be in the headers group.
|
net: reorganize sk_buff for faster __copy_skb_header()
With proliferation of bit fields in sk_buff, __copy_skb_header() became
quite expensive, showing as the most expensive function in a GSO
workload.
__copy_skb_header() performance is also critical for non GSO TCP
operations, as it is used from skb_clone()
This patch carefully moves all the fields that were not copied in a
separate zone : cloned, nohdr, fclone, peeked, head_frag, xmit_more
Then I moved all other fields and all other copied fields in a section
delimited by headers_start[0]/headers_end[0] section so that we
can use a single memcpy() call, inlined by compiler using long
word load/stores.
I also tried to make all copies in the natural orders of sk_buff,
to help hardware prefetching.
I made sure sk_buff size did not change.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-29 05:18:47 +00:00
|
|
|
* It is not yet because we do not want to have a 16 bit hole
|
|
|
|
*/
|
|
|
|
new->queue_mapping = old->queue_mapping;
|
|
|
|
|
2021-11-21 00:31:49 +00:00
|
|
|
memcpy(&new->headers, &old->headers, sizeof(new->headers));
|
net: reorganize sk_buff for faster __copy_skb_header()
With proliferation of bit fields in sk_buff, __copy_skb_header() became
quite expensive, showing as the most expensive function in a GSO
workload.
__copy_skb_header() performance is also critical for non GSO TCP
operations, as it is used from skb_clone()
This patch carefully moves all the fields that were not copied in a
separate zone : cloned, nohdr, fclone, peeked, head_frag, xmit_more
Then I moved all other fields and all other copied fields in a section
delimited by headers_start[0]/headers_end[0] section so that we
can use a single memcpy() call, inlined by compiler using long
word load/stores.
I also tried to make all copies in the natural orders of sk_buff,
to help hardware prefetching.
I made sure sk_buff size did not change.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-29 05:18:47 +00:00
|
|
|
CHECK_SKB_FIELD(protocol);
|
|
|
|
CHECK_SKB_FIELD(csum);
|
|
|
|
CHECK_SKB_FIELD(hash);
|
|
|
|
CHECK_SKB_FIELD(priority);
|
|
|
|
CHECK_SKB_FIELD(skb_iif);
|
|
|
|
CHECK_SKB_FIELD(vlan_proto);
|
|
|
|
CHECK_SKB_FIELD(vlan_tci);
|
|
|
|
CHECK_SKB_FIELD(transport_header);
|
|
|
|
CHECK_SKB_FIELD(network_header);
|
|
|
|
CHECK_SKB_FIELD(mac_header);
|
|
|
|
CHECK_SKB_FIELD(inner_protocol);
|
|
|
|
CHECK_SKB_FIELD(inner_transport_header);
|
|
|
|
CHECK_SKB_FIELD(inner_network_header);
|
|
|
|
CHECK_SKB_FIELD(inner_mac_header);
|
|
|
|
CHECK_SKB_FIELD(mark);
|
|
|
|
#ifdef CONFIG_NETWORK_SECMARK
|
|
|
|
CHECK_SKB_FIELD(secmark);
|
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_NET_RX_BUSY_POLL
|
|
|
|
CHECK_SKB_FIELD(napi_id);
|
2007-10-14 07:37:30 +00:00
|
|
|
#endif
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
CHECK_SKB_FIELD(alloc_cpu);
|
xps: fix xps for stacked devices
A typical qdisc setup is the following :
bond0 : bonding device, using HTB hierarchy
eth1/eth2 : slaves, multiqueue NIC, using MQ + FQ qdisc
XPS allows to spread packets on specific tx queues, based on the cpu
doing the send.
Problem is that dequeues from bond0 qdisc can happen on random cpus,
due to the fact that qdisc_run() can dequeue a batch of packets.
CPUA -> queue packet P1 on bond0 qdisc, P1->ooo_okay=1
CPUA -> queue packet P2 on bond0 qdisc, P2->ooo_okay=0
CPUB -> dequeue packet P1 from bond0
enqueue packet on eth1/eth2
CPUC -> dequeue packet P2 from bond0
enqueue packet on eth1/eth2 using sk cache (ooo_okay is 0)
get_xps_queue() then might select wrong queue for P1, since current cpu
might be different than CPUA.
P2 might be sent on the old queue (stored in sk->sk_tx_queue_mapping),
if CPUC runs a bit faster (or CPUB spins a bit on qdisc lock)
Effect of this bug is TCP reorders, and more generally not optimal
TX queue placement. (A victim bulk flow can be migrated to the wrong TX
queue for a while)
To fix this, we have to record sender cpu number the first time
dev_queue_xmit() is called for one tx skb.
We can union napi_id (used on receive path) and sender_cpu,
granted we clear sender_cpu in skb_scrub_packet() (credit to Willem for
this union idea)
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Nandita Dukkipati <nanditad@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-02-04 07:48:24 +00:00
|
|
|
#ifdef CONFIG_XPS
|
|
|
|
CHECK_SKB_FIELD(sender_cpu);
|
|
|
|
#endif
|
2007-10-14 07:37:30 +00:00
|
|
|
#ifdef CONFIG_NET_SCHED
|
net: reorganize sk_buff for faster __copy_skb_header()
With proliferation of bit fields in sk_buff, __copy_skb_header() became
quite expensive, showing as the most expensive function in a GSO
workload.
__copy_skb_header() performance is also critical for non GSO TCP
operations, as it is used from skb_clone()
This patch carefully moves all the fields that were not copied in a
separate zone : cloned, nohdr, fclone, peeked, head_frag, xmit_more
Then I moved all other fields and all other copied fields in a section
delimited by headers_start[0]/headers_end[0] section so that we
can use a single memcpy() call, inlined by compiler using long
word load/stores.
I also tried to make all copies in the natural orders of sk_buff,
to help hardware prefetching.
I made sure sk_buff size did not change.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-09-29 05:18:47 +00:00
|
|
|
CHECK_SKB_FIELD(tc_index);
|
2007-10-14 07:37:30 +00:00
|
|
|
#endif
|
2013-06-10 08:39:50 +00:00
|
|
|
|
2007-10-14 07:37:30 +00:00
|
|
|
}
|
|
|
|
|
2009-05-22 22:11:37 +00:00
|
|
|
/*
|
|
|
|
* You should not add any new code to this function. Add it to
|
|
|
|
* __copy_skb_header above instead.
|
|
|
|
*/
|
2007-10-14 07:37:52 +00:00
|
|
|
static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
#define C(x) n->x = skb->x
|
|
|
|
|
|
|
|
n->next = n->prev = NULL;
|
|
|
|
n->sk = NULL;
|
2007-10-14 07:37:30 +00:00
|
|
|
__copy_skb_header(n, skb);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
C(len);
|
|
|
|
C(data_len);
|
2007-03-16 22:00:46 +00:00
|
|
|
C(mac_len);
|
[SKBUFF]: Keep track of writable header len of headerless clones
Currently NAT (and others) that want to modify cloned skbs copy them,
even if in the vast majority of cases its not necessary because the
skb is a clone made by TCP and the portion NAT wants to modify is
actually writable because TCP release the header reference before
cloning.
The problem is that there is no clean way for NAT to find out how
long the writable header area is, so this patch introduces skb->hdr_len
to hold this length. When a headerless skb is cloned skb->hdr_len
is set to the current headroom, for regular clones it is copied from
the original. A new function skb_clone_writable(skb, len) returns
whether the skb is writable up to len bytes from skb->data. To avoid
enlarging the skb the mac_len field is reduced to 16 bit and the
new hdr_len field is put in the remaining 16 bit.
I've done a few rough benchmarks of NAT (not with this exact patch,
but a very similar one). As expected it saves huge amounts of system
time in case of sendfile, bringing it down to basically the same
amount as without NAT, with sendmsg it only helps on loopback,
probably because of the large MTU.
Transmit a 1GB file using sendfile/sendmsg over eth0/lo with and
without NAT:
- sendfile eth0, no NAT: sys 0m0.388s
- sendfile eth0, NAT: sys 0m1.835s
- sendfile eth0: NAT + path: sys 0m0.370s (~ -80%)
- sendfile lo, no NAT: sys 0m0.258s
- sendfile lo, NAT: sys 0m2.609s
- sendfile lo, NAT + patch: sys 0m0.260s (~ -90%)
- sendmsg eth0, no NAT: sys 0m2.508s
- sendmsg eth0, NAT: sys 0m2.539s
- sendmsg eth0, NAT + patch: sys 0m2.445s (no change)
- sendmsg lo, no NAT: sys 0m2.151s
- sendmsg lo, NAT: sys 0m3.557s
- sendmsg lo, NAT + patch: sys 0m2.159s (~ -40%)
I expect other users can see a similar performance improvement,
packet mangling iptables targets, ipip and ip_gre come to mind ..
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2007-06-25 11:35:20 +00:00
|
|
|
n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
|
2008-01-08 05:56:41 +00:00
|
|
|
n->cloned = 1;
|
2005-04-16 22:20:36 +00:00
|
|
|
n->nohdr = 0;
|
2018-04-07 20:42:39 +00:00
|
|
|
n->peeked = 0;
|
2018-07-13 11:21:07 +00:00
|
|
|
C(pfmemalloc);
|
2021-06-07 19:02:38 +00:00
|
|
|
C(pp_recycle);
|
2005-04-16 22:20:36 +00:00
|
|
|
n->destructor = NULL;
|
|
|
|
C(tail);
|
|
|
|
C(end);
|
2008-01-08 05:56:41 +00:00
|
|
|
C(head);
|
net: allow skb->head to be a page fragment
skb->head is currently allocated from kmalloc(). This is convenient but
has the drawback the data cannot be converted to a page fragment if
needed.
We have three spots were it hurts :
1) GRO aggregation
When a linear skb must be appended to another skb, GRO uses the
frag_list fallback, very inefficient since we keep all struct sk_buff
around. So drivers enabling GRO but delivering linear skbs to network
stack aren't enabling full GRO power.
2) splice(socket -> pipe).
We must copy the linear part to a page fragment.
This kind of defeats splice() purpose (zero copy claim)
3) TCP coalescing.
Recently introduced, this permits to group several contiguous segments
into a single skb. This shortens queue lengths and save kernel memory,
and greatly reduce probabilities of TCP collapses. This coalescing
doesnt work on linear skbs (or we would need to copy data, this would be
too slow)
Given all these issues, the following patch introduces the possibility
of having skb->head be a fragment in itself. We use a new skb flag,
skb->head_frag to carry this information.
build_skb() is changed to accept a frag_size argument. Drivers willing
to provide a page fragment instead of kmalloc() data will set a non zero
value, set to the fragment size.
Then, on situations we need to convert the skb head to a frag in itself,
we can check if skb->head_frag is set and avoid the copies or various
fallbacks we have.
This means drivers currently using frags could be updated to avoid the
current skb->head allocation and reduce their memory footprint (aka skb
truesize). (thats 512 or 1024 bytes saved per skb). This also makes
bpf/netfilter faster since the 'first frag' will be part of skb linear
part, no need to copy data.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Maciej Żenczykowski <maze@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Tom Herbert <therbert@google.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Matt Carlson <mcarlson@broadcom.com>
Cc: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-04-27 00:33:38 +00:00
|
|
|
C(head_frag);
|
2008-01-08 05:56:41 +00:00
|
|
|
C(data);
|
|
|
|
C(truesize);
|
2017-06-30 10:07:58 +00:00
|
|
|
refcount_set(&n->users, 1);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
atomic_inc(&(skb_shinfo(skb)->dataref));
|
|
|
|
skb->cloned = 1;
|
|
|
|
|
|
|
|
return n;
|
2007-10-14 07:37:52 +00:00
|
|
|
#undef C
|
|
|
|
}
|
|
|
|
|
2019-06-03 22:16:58 +00:00
|
|
|
/**
|
|
|
|
* alloc_skb_for_msg() - allocate sk_buff to wrap frag list forming a msg
|
|
|
|
* @first: first sk_buff of the msg
|
|
|
|
*/
|
|
|
|
struct sk_buff *alloc_skb_for_msg(struct sk_buff *first)
|
|
|
|
{
|
|
|
|
struct sk_buff *n;
|
|
|
|
|
|
|
|
n = alloc_skb(0, GFP_ATOMIC);
|
|
|
|
if (!n)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
n->len = first->len;
|
|
|
|
n->data_len = first->len;
|
|
|
|
n->truesize = first->truesize;
|
|
|
|
|
|
|
|
skb_shinfo(n)->frag_list = first;
|
|
|
|
|
|
|
|
__copy_skb_header(n, first);
|
|
|
|
n->destructor = NULL;
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(alloc_skb_for_msg);
|
|
|
|
|
2007-10-14 07:37:52 +00:00
|
|
|
/**
|
|
|
|
* skb_morph - morph one skb into another
|
|
|
|
* @dst: the skb to receive the contents
|
|
|
|
* @src: the skb to supply the contents
|
|
|
|
*
|
|
|
|
* This is identical to skb_clone except that the target skb is
|
|
|
|
* supplied by the user.
|
|
|
|
*
|
|
|
|
* The target skb is returned upon exit.
|
|
|
|
*/
|
|
|
|
struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
|
|
|
|
{
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_all(dst, SKB_CONSUMED);
|
2007-10-14 07:37:52 +00:00
|
|
|
return __skb_clone(dst, src);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_morph);
|
|
|
|
|
2018-02-15 18:49:32 +00:00
|
|
|
int mm_account_pinned_pages(struct mmpin *mmp, size_t size)
|
2017-08-03 20:29:43 +00:00
|
|
|
{
|
2023-02-14 15:57:40 +00:00
|
|
|
unsigned long max_pg, num_pg, new_pg, old_pg, rlim;
|
2017-08-03 20:29:43 +00:00
|
|
|
struct user_struct *user;
|
|
|
|
|
|
|
|
if (capable(CAP_IPC_LOCK) || !size)
|
|
|
|
return 0;
|
|
|
|
|
2023-02-14 15:57:40 +00:00
|
|
|
rlim = rlimit(RLIMIT_MEMLOCK);
|
|
|
|
if (rlim == RLIM_INFINITY)
|
|
|
|
return 0;
|
|
|
|
|
2017-08-03 20:29:43 +00:00
|
|
|
num_pg = (size >> PAGE_SHIFT) + 2; /* worst case */
|
2023-02-14 15:57:40 +00:00
|
|
|
max_pg = rlim >> PAGE_SHIFT;
|
2017-08-03 20:29:43 +00:00
|
|
|
user = mmp->user ? : current_user();
|
|
|
|
|
2022-11-15 09:10:56 +00:00
|
|
|
old_pg = atomic_long_read(&user->locked_vm);
|
2017-08-03 20:29:43 +00:00
|
|
|
do {
|
|
|
|
new_pg = old_pg + num_pg;
|
|
|
|
if (new_pg > max_pg)
|
|
|
|
return -ENOBUFS;
|
2022-11-15 09:10:56 +00:00
|
|
|
} while (!atomic_long_try_cmpxchg(&user->locked_vm, &old_pg, new_pg));
|
2017-08-03 20:29:43 +00:00
|
|
|
|
|
|
|
if (!mmp->user) {
|
|
|
|
mmp->user = get_uid(user);
|
|
|
|
mmp->num_pg = num_pg;
|
|
|
|
} else {
|
|
|
|
mmp->num_pg += num_pg;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2018-02-15 18:49:32 +00:00
|
|
|
EXPORT_SYMBOL_GPL(mm_account_pinned_pages);
|
2017-08-03 20:29:43 +00:00
|
|
|
|
2018-02-15 18:49:32 +00:00
|
|
|
void mm_unaccount_pinned_pages(struct mmpin *mmp)
|
2017-08-03 20:29:43 +00:00
|
|
|
{
|
|
|
|
if (mmp->user) {
|
|
|
|
atomic_long_sub(mmp->num_pg, &mmp->user->locked_vm);
|
|
|
|
free_uid(mmp->user);
|
|
|
|
}
|
|
|
|
}
|
2018-02-15 18:49:32 +00:00
|
|
|
EXPORT_SYMBOL_GPL(mm_unaccount_pinned_pages);
|
2017-08-03 20:29:43 +00:00
|
|
|
|
2022-05-04 17:09:47 +00:00
|
|
|
static struct ubuf_info *msg_zerocopy_alloc(struct sock *sk, size_t size)
|
2017-08-03 20:29:39 +00:00
|
|
|
{
|
2022-09-23 16:39:04 +00:00
|
|
|
struct ubuf_info_msgzc *uarg;
|
2017-08-03 20:29:39 +00:00
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
WARN_ON_ONCE(!in_task());
|
|
|
|
|
|
|
|
skb = sock_omalloc(sk, 0, GFP_KERNEL);
|
|
|
|
if (!skb)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
BUILD_BUG_ON(sizeof(*uarg) > sizeof(skb->cb));
|
|
|
|
uarg = (void *)skb->cb;
|
2017-08-03 20:29:43 +00:00
|
|
|
uarg->mmp.user = NULL;
|
|
|
|
|
|
|
|
if (mm_account_pinned_pages(&uarg->mmp, size)) {
|
|
|
|
kfree_skb(skb);
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-08-03 20:29:39 +00:00
|
|
|
|
2024-04-19 11:08:39 +00:00
|
|
|
uarg->ubuf.ops = &msg_zerocopy_ubuf_ops;
|
2017-08-03 20:29:42 +00:00
|
|
|
uarg->id = ((u32)atomic_inc_return(&sk->sk_zckey)) - 1;
|
|
|
|
uarg->len = 1;
|
|
|
|
uarg->bytelen = size;
|
2017-08-03 20:29:39 +00:00
|
|
|
uarg->zerocopy = 1;
|
2022-09-23 16:39:04 +00:00
|
|
|
uarg->ubuf.flags = SKBFL_ZEROCOPY_FRAG | SKBFL_DONT_ORPHAN;
|
|
|
|
refcount_set(&uarg->ubuf.refcnt, 1);
|
2017-08-03 20:29:39 +00:00
|
|
|
sock_hold(sk);
|
|
|
|
|
2022-09-23 16:39:04 +00:00
|
|
|
return &uarg->ubuf;
|
2017-08-03 20:29:39 +00:00
|
|
|
}
|
|
|
|
|
2022-09-23 16:39:04 +00:00
|
|
|
static inline struct sk_buff *skb_from_uarg(struct ubuf_info_msgzc *uarg)
|
2017-08-03 20:29:39 +00:00
|
|
|
{
|
|
|
|
return container_of((void *)uarg, struct sk_buff, cb);
|
|
|
|
}
|
|
|
|
|
2021-01-06 22:18:37 +00:00
|
|
|
struct ubuf_info *msg_zerocopy_realloc(struct sock *sk, size_t size,
|
|
|
|
struct ubuf_info *uarg)
|
2017-08-03 20:29:42 +00:00
|
|
|
{
|
|
|
|
if (uarg) {
|
2022-09-23 16:39:04 +00:00
|
|
|
struct ubuf_info_msgzc *uarg_zc;
|
2017-08-03 20:29:42 +00:00
|
|
|
const u32 byte_limit = 1 << 19; /* limit to a few TSO */
|
|
|
|
u32 bytelen, next;
|
|
|
|
|
2022-07-12 20:52:27 +00:00
|
|
|
/* there might be non MSG_ZEROCOPY users */
|
2024-04-19 11:08:39 +00:00
|
|
|
if (uarg->ops != &msg_zerocopy_ubuf_ops)
|
2022-07-12 20:52:27 +00:00
|
|
|
return NULL;
|
|
|
|
|
2017-08-03 20:29:42 +00:00
|
|
|
/* realloc only when socket is locked (TCP, UDP cork),
|
|
|
|
* so uarg->len and sk_zckey access is serialized
|
|
|
|
*/
|
|
|
|
if (!sock_owned_by_user(sk)) {
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-09-23 16:39:04 +00:00
|
|
|
uarg_zc = uarg_to_msgzc(uarg);
|
|
|
|
bytelen = uarg_zc->bytelen + size;
|
|
|
|
if (uarg_zc->len == USHRT_MAX - 1 || bytelen > byte_limit) {
|
2017-08-03 20:29:42 +00:00
|
|
|
/* TCP can create new skb to attach new uarg */
|
|
|
|
if (sk->sk_type == SOCK_STREAM)
|
|
|
|
goto new_alloc;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
next = (u32)atomic_read(&sk->sk_zckey);
|
2022-09-23 16:39:04 +00:00
|
|
|
if ((u32)(uarg_zc->id + uarg_zc->len) == next) {
|
|
|
|
if (mm_account_pinned_pages(&uarg_zc->mmp, size))
|
2017-08-03 20:29:43 +00:00
|
|
|
return NULL;
|
2022-09-23 16:39:04 +00:00
|
|
|
uarg_zc->len++;
|
|
|
|
uarg_zc->bytelen = bytelen;
|
2017-08-03 20:29:42 +00:00
|
|
|
atomic_set(&sk->sk_zckey, ++next);
|
2019-05-30 22:01:21 +00:00
|
|
|
|
|
|
|
/* no extra ref when appending to datagram (MSG_MORE) */
|
|
|
|
if (sk->sk_type == SOCK_STREAM)
|
2021-01-06 22:18:41 +00:00
|
|
|
net_zcopy_get(uarg);
|
2019-05-30 22:01:21 +00:00
|
|
|
|
2017-08-03 20:29:42 +00:00
|
|
|
return uarg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
new_alloc:
|
2021-01-06 22:18:37 +00:00
|
|
|
return msg_zerocopy_alloc(sk, size);
|
2017-08-03 20:29:42 +00:00
|
|
|
}
|
2021-01-06 22:18:37 +00:00
|
|
|
EXPORT_SYMBOL_GPL(msg_zerocopy_realloc);
|
2017-08-03 20:29:42 +00:00
|
|
|
|
|
|
|
static bool skb_zerocopy_notify_extend(struct sk_buff *skb, u32 lo, u16 len)
|
|
|
|
{
|
|
|
|
struct sock_exterr_skb *serr = SKB_EXT_ERR(skb);
|
|
|
|
u32 old_lo, old_hi;
|
|
|
|
u64 sum_len;
|
|
|
|
|
|
|
|
old_lo = serr->ee.ee_info;
|
|
|
|
old_hi = serr->ee.ee_data;
|
|
|
|
sum_len = old_hi - old_lo + 1ULL + len;
|
|
|
|
|
|
|
|
if (sum_len >= (1ULL << 32))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (lo != old_hi + 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
serr->ee.ee_data += len;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-09-23 16:39:04 +00:00
|
|
|
static void __msg_zerocopy_callback(struct ubuf_info_msgzc *uarg)
|
2017-08-03 20:29:39 +00:00
|
|
|
{
|
2017-08-03 20:29:42 +00:00
|
|
|
struct sk_buff *tail, *skb = skb_from_uarg(uarg);
|
2017-08-03 20:29:39 +00:00
|
|
|
struct sock_exterr_skb *serr;
|
|
|
|
struct sock *sk = skb->sk;
|
2017-08-03 20:29:42 +00:00
|
|
|
struct sk_buff_head *q;
|
|
|
|
unsigned long flags;
|
2021-06-09 22:41:57 +00:00
|
|
|
bool is_zerocopy;
|
2017-08-03 20:29:42 +00:00
|
|
|
u32 lo, hi;
|
|
|
|
u16 len;
|
2017-08-03 20:29:39 +00:00
|
|
|
|
2017-08-09 23:09:43 +00:00
|
|
|
mm_unaccount_pinned_pages(&uarg->mmp);
|
|
|
|
|
2017-08-03 20:29:42 +00:00
|
|
|
/* if !len, there was only 1 call, and it was aborted
|
|
|
|
* so do not queue a completion notification
|
|
|
|
*/
|
|
|
|
if (!uarg->len || sock_flag(sk, SOCK_DEAD))
|
2017-08-03 20:29:39 +00:00
|
|
|
goto release;
|
|
|
|
|
2017-08-03 20:29:42 +00:00
|
|
|
len = uarg->len;
|
|
|
|
lo = uarg->id;
|
|
|
|
hi = uarg->id + len - 1;
|
2021-06-09 22:41:57 +00:00
|
|
|
is_zerocopy = uarg->zerocopy;
|
2017-08-03 20:29:42 +00:00
|
|
|
|
2017-08-03 20:29:39 +00:00
|
|
|
serr = SKB_EXT_ERR(skb);
|
|
|
|
memset(serr, 0, sizeof(*serr));
|
|
|
|
serr->ee.ee_errno = 0;
|
|
|
|
serr->ee.ee_origin = SO_EE_ORIGIN_ZEROCOPY;
|
2017-08-03 20:29:42 +00:00
|
|
|
serr->ee.ee_data = hi;
|
|
|
|
serr->ee.ee_info = lo;
|
2021-06-09 22:41:57 +00:00
|
|
|
if (!is_zerocopy)
|
2017-08-03 20:29:39 +00:00
|
|
|
serr->ee.ee_code |= SO_EE_CODE_ZEROCOPY_COPIED;
|
|
|
|
|
2017-08-03 20:29:42 +00:00
|
|
|
q = &sk->sk_error_queue;
|
|
|
|
spin_lock_irqsave(&q->lock, flags);
|
|
|
|
tail = skb_peek_tail(q);
|
|
|
|
if (!tail || SKB_EXT_ERR(tail)->ee.ee_origin != SO_EE_ORIGIN_ZEROCOPY ||
|
|
|
|
!skb_zerocopy_notify_extend(tail, lo, len)) {
|
|
|
|
__skb_queue_tail(q, skb);
|
|
|
|
skb = NULL;
|
|
|
|
}
|
|
|
|
spin_unlock_irqrestore(&q->lock, flags);
|
2017-08-03 20:29:39 +00:00
|
|
|
|
2021-06-27 22:48:21 +00:00
|
|
|
sk_error_report(sk);
|
2017-08-03 20:29:39 +00:00
|
|
|
|
|
|
|
release:
|
|
|
|
consume_skb(skb);
|
|
|
|
sock_put(sk);
|
|
|
|
}
|
2021-01-06 22:18:31 +00:00
|
|
|
|
2024-04-19 11:08:39 +00:00
|
|
|
static void msg_zerocopy_complete(struct sk_buff *skb, struct ubuf_info *uarg,
|
|
|
|
bool success)
|
2021-01-06 22:18:31 +00:00
|
|
|
{
|
2022-09-23 16:39:04 +00:00
|
|
|
struct ubuf_info_msgzc *uarg_zc = uarg_to_msgzc(uarg);
|
|
|
|
|
|
|
|
uarg_zc->zerocopy = uarg_zc->zerocopy & success;
|
2021-01-06 22:18:31 +00:00
|
|
|
|
|
|
|
if (refcount_dec_and_test(&uarg->refcnt))
|
2022-09-23 16:39:04 +00:00
|
|
|
__msg_zerocopy_callback(uarg_zc);
|
2021-01-06 22:18:31 +00:00
|
|
|
}
|
2017-08-03 20:29:39 +00:00
|
|
|
|
2021-01-06 22:18:37 +00:00
|
|
|
void msg_zerocopy_put_abort(struct ubuf_info *uarg, bool have_uref)
|
2017-08-03 20:29:39 +00:00
|
|
|
{
|
2022-09-23 16:39:04 +00:00
|
|
|
struct sock *sk = skb_from_uarg(uarg_to_msgzc(uarg))->sk;
|
2017-08-03 20:29:39 +00:00
|
|
|
|
2021-01-06 22:18:35 +00:00
|
|
|
atomic_dec(&sk->sk_zckey);
|
2022-09-23 16:39:04 +00:00
|
|
|
uarg_to_msgzc(uarg)->len--;
|
2017-08-03 20:29:39 +00:00
|
|
|
|
2021-01-06 22:18:35 +00:00
|
|
|
if (have_uref)
|
2024-04-19 11:08:39 +00:00
|
|
|
msg_zerocopy_complete(NULL, uarg, true);
|
2017-08-03 20:29:39 +00:00
|
|
|
}
|
2021-01-06 22:18:37 +00:00
|
|
|
EXPORT_SYMBOL_GPL(msg_zerocopy_put_abort);
|
2017-08-03 20:29:39 +00:00
|
|
|
|
2024-04-19 11:08:39 +00:00
|
|
|
const struct ubuf_info_ops msg_zerocopy_ubuf_ops = {
|
|
|
|
.complete = msg_zerocopy_complete,
|
|
|
|
};
|
|
|
|
EXPORT_SYMBOL_GPL(msg_zerocopy_ubuf_ops);
|
|
|
|
|
2017-08-03 20:29:39 +00:00
|
|
|
int skb_zerocopy_iter_stream(struct sock *sk, struct sk_buff *skb,
|
|
|
|
struct msghdr *msg, int len,
|
|
|
|
struct ubuf_info *uarg)
|
|
|
|
{
|
2017-08-03 20:29:42 +00:00
|
|
|
struct ubuf_info *orig_uarg = skb_zcopy(skb);
|
2017-08-03 20:29:39 +00:00
|
|
|
int err, orig_len = skb->len;
|
|
|
|
|
2024-04-19 11:08:40 +00:00
|
|
|
if (uarg->ops->link_skb) {
|
|
|
|
err = uarg->ops->link_skb(skb, uarg);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
} else {
|
|
|
|
/* An skb can only point to one uarg. This edge case happens
|
|
|
|
* when TCP appends to an skb, but zerocopy_realloc triggered
|
|
|
|
* a new alloc.
|
|
|
|
*/
|
|
|
|
if (orig_uarg && uarg != orig_uarg)
|
|
|
|
return -EEXIST;
|
|
|
|
}
|
2017-08-03 20:29:42 +00:00
|
|
|
|
2022-07-12 20:52:30 +00:00
|
|
|
err = __zerocopy_sg_from_iter(msg, sk, skb, &msg->msg_iter, len);
|
2017-08-03 20:29:39 +00:00
|
|
|
if (err == -EFAULT || (err == -EMSGSIZE && skb->len == orig_len)) {
|
2017-10-19 16:40:39 +00:00
|
|
|
struct sock *save_sk = skb->sk;
|
|
|
|
|
2017-08-03 20:29:39 +00:00
|
|
|
/* Streams do not free skb on error. Reset to prev state. */
|
2022-04-28 10:57:46 +00:00
|
|
|
iov_iter_revert(&msg->msg_iter, skb->len - orig_len);
|
2017-10-19 16:40:39 +00:00
|
|
|
skb->sk = sk;
|
2017-08-03 20:29:39 +00:00
|
|
|
___pskb_trim(skb, orig_len);
|
2017-10-19 16:40:39 +00:00
|
|
|
skb->sk = save_sk;
|
2017-08-03 20:29:39 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2024-04-19 11:08:40 +00:00
|
|
|
if (!uarg->ops->link_skb)
|
|
|
|
skb_zcopy_set(skb, uarg, NULL);
|
2017-08-03 20:29:39 +00:00
|
|
|
return skb->len - orig_len;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_zerocopy_iter_stream);
|
|
|
|
|
2022-07-12 20:52:31 +00:00
|
|
|
void __skb_zcopy_downgrade_managed(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
skb_shinfo(skb)->flags &= ~SKBFL_MANAGED_FRAG_REFS;
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
|
|
|
|
skb_frag_ref(skb, i);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(__skb_zcopy_downgrade_managed);
|
|
|
|
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
static int skb_zerocopy_clone(struct sk_buff *nskb, struct sk_buff *orig,
|
2017-08-03 20:29:39 +00:00
|
|
|
gfp_t gfp_mask)
|
|
|
|
{
|
|
|
|
if (skb_zcopy(orig)) {
|
|
|
|
if (skb_zcopy(nskb)) {
|
|
|
|
/* !gfp_mask callers are verified to !skb_zcopy(nskb) */
|
|
|
|
if (!gfp_mask) {
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
if (skb_uarg(nskb) == skb_uarg(orig))
|
|
|
|
return 0;
|
|
|
|
if (skb_copy_ubufs(nskb, GFP_ATOMIC))
|
|
|
|
return -EIO;
|
|
|
|
}
|
2018-11-30 20:32:40 +00:00
|
|
|
skb_zcopy_set(nskb, skb_uarg(orig), NULL);
|
2017-08-03 20:29:39 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-10 10:55:09 +00:00
|
|
|
/**
|
|
|
|
* skb_copy_ubufs - copy userspace skb frags buffers to kernel
|
2011-08-31 08:03:29 +00:00
|
|
|
* @skb: the skb to modify
|
|
|
|
* @gfp_mask: allocation priority
|
|
|
|
*
|
2021-01-06 22:18:38 +00:00
|
|
|
* This must be called on skb with SKBFL_ZEROCOPY_ENABLE.
|
2011-08-31 08:03:29 +00:00
|
|
|
* It will copy all frags into kernel and drop the reference
|
|
|
|
* to userspace pages.
|
|
|
|
*
|
|
|
|
* If this function is called from an interrupt gfp_mask() must be
|
|
|
|
* %GFP_ATOMIC.
|
|
|
|
*
|
|
|
|
* Returns 0 on success or a negative error code on failure
|
|
|
|
* to allocate kernel memory to copy to.
|
|
|
|
*/
|
|
|
|
int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
|
2011-07-06 12:22:12 +00:00
|
|
|
{
|
|
|
|
int num_frags = skb_shinfo(skb)->nr_frags;
|
|
|
|
struct page *page, *head = NULL;
|
2023-04-28 04:32:31 +00:00
|
|
|
int i, order, psize, new_frags;
|
2017-08-03 20:29:38 +00:00
|
|
|
u32 d_off;
|
2011-07-06 12:22:12 +00:00
|
|
|
|
2017-08-03 20:29:38 +00:00
|
|
|
if (skb_shared(skb) || skb_unclone(skb, gfp_mask))
|
|
|
|
return -EINVAL;
|
2011-07-06 12:22:12 +00:00
|
|
|
|
2017-12-28 17:38:13 +00:00
|
|
|
if (!num_frags)
|
|
|
|
goto release;
|
|
|
|
|
2023-04-28 04:32:31 +00:00
|
|
|
/* We might have to allocate high order pages, so compute what minimum
|
|
|
|
* page order is needed.
|
|
|
|
*/
|
|
|
|
order = 0;
|
|
|
|
while ((PAGE_SIZE << order) * MAX_SKB_FRAGS < __skb_pagelen(skb))
|
|
|
|
order++;
|
|
|
|
psize = (PAGE_SIZE << order);
|
|
|
|
|
|
|
|
new_frags = (__skb_pagelen(skb) + psize - 1) >> (PAGE_SHIFT + order);
|
2017-08-03 20:29:38 +00:00
|
|
|
for (i = 0; i < new_frags; i++) {
|
2023-04-28 04:32:31 +00:00
|
|
|
page = alloc_pages(gfp_mask | __GFP_COMP, order);
|
2011-07-06 12:22:12 +00:00
|
|
|
if (!page) {
|
|
|
|
while (head) {
|
2013-07-12 07:17:23 +00:00
|
|
|
struct page *next = (struct page *)page_private(head);
|
2011-07-06 12:22:12 +00:00
|
|
|
put_page(head);
|
|
|
|
head = next;
|
|
|
|
}
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2017-08-03 20:29:38 +00:00
|
|
|
set_page_private(page, (unsigned long)head);
|
|
|
|
head = page;
|
|
|
|
}
|
|
|
|
|
|
|
|
page = head;
|
|
|
|
d_off = 0;
|
|
|
|
for (i = 0; i < num_frags; i++) {
|
|
|
|
skb_frag_t *f = &skb_shinfo(skb)->frags[i];
|
|
|
|
u32 p_off, p_len, copied;
|
|
|
|
struct page *p;
|
|
|
|
u8 *vaddr;
|
2017-07-31 12:15:47 +00:00
|
|
|
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_foreach_page(f, skb_frag_off(f), skb_frag_size(f),
|
2017-07-31 12:15:47 +00:00
|
|
|
p, p_off, p_len, copied) {
|
2017-08-03 20:29:38 +00:00
|
|
|
u32 copy, done = 0;
|
2017-07-31 12:15:47 +00:00
|
|
|
vaddr = kmap_atomic(p);
|
2017-08-03 20:29:38 +00:00
|
|
|
|
|
|
|
while (done < p_len) {
|
2023-04-28 04:32:31 +00:00
|
|
|
if (d_off == psize) {
|
2017-08-03 20:29:38 +00:00
|
|
|
d_off = 0;
|
|
|
|
page = (struct page *)page_private(page);
|
|
|
|
}
|
2023-04-28 04:32:31 +00:00
|
|
|
copy = min_t(u32, psize - d_off, p_len - done);
|
2017-08-03 20:29:38 +00:00
|
|
|
memcpy(page_address(page) + d_off,
|
|
|
|
vaddr + p_off + done, copy);
|
|
|
|
done += copy;
|
|
|
|
d_off += copy;
|
|
|
|
}
|
2017-07-31 12:15:47 +00:00
|
|
|
kunmap_atomic(vaddr);
|
|
|
|
}
|
2011-07-06 12:22:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* skb frags release userspace buffers */
|
2012-07-17 02:05:29 +00:00
|
|
|
for (i = 0; i < num_frags; i++)
|
2011-10-19 23:01:49 +00:00
|
|
|
skb_frag_unref(skb, i);
|
2011-07-06 12:22:12 +00:00
|
|
|
|
|
|
|
/* skb frags point to kernel buffers */
|
2017-08-03 20:29:38 +00:00
|
|
|
for (i = 0; i < new_frags - 1; i++) {
|
2024-02-14 22:34:03 +00:00
|
|
|
__skb_fill_netmem_desc(skb, i, page_to_netmem(head), 0, psize);
|
2013-07-12 07:17:23 +00:00
|
|
|
head = (struct page *)page_private(head);
|
2011-07-06 12:22:12 +00:00
|
|
|
}
|
2024-02-14 22:34:03 +00:00
|
|
|
__skb_fill_netmem_desc(skb, new_frags - 1, page_to_netmem(head), 0,
|
|
|
|
d_off);
|
2017-08-03 20:29:38 +00:00
|
|
|
skb_shinfo(skb)->nr_frags = new_frags;
|
2011-08-31 08:03:29 +00:00
|
|
|
|
2017-12-20 22:37:50 +00:00
|
|
|
release:
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
skb_zcopy_clear(skb, false);
|
2011-07-06 12:22:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2012-07-20 09:23:20 +00:00
|
|
|
EXPORT_SYMBOL_GPL(skb_copy_ubufs);
|
2011-07-06 12:22:12 +00:00
|
|
|
|
2007-10-14 07:37:52 +00:00
|
|
|
/**
|
|
|
|
* skb_clone - duplicate an sk_buff
|
|
|
|
* @skb: buffer to clone
|
|
|
|
* @gfp_mask: allocation priority
|
|
|
|
*
|
|
|
|
* Duplicate an &sk_buff. The new one is not owned by a socket. Both
|
|
|
|
* copies share the same packet data but not structure. The new
|
|
|
|
* buffer has a reference count of 1. If the allocation fails the
|
|
|
|
* function returns %NULL otherwise the new buffer is returned.
|
|
|
|
*
|
|
|
|
* If this function is called from an interrupt gfp_mask() must be
|
|
|
|
* %GFP_ATOMIC.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
|
|
|
|
{
|
2014-09-29 20:29:15 +00:00
|
|
|
struct sk_buff_fclones *fclones = container_of(skb,
|
|
|
|
struct sk_buff_fclones,
|
|
|
|
skb1);
|
2014-12-04 01:04:39 +00:00
|
|
|
struct sk_buff *n;
|
2007-10-14 07:37:52 +00:00
|
|
|
|
2012-07-20 09:23:10 +00:00
|
|
|
if (skb_orphan_frags(skb, gfp_mask))
|
|
|
|
return NULL;
|
2011-07-06 12:22:12 +00:00
|
|
|
|
2007-10-14 07:37:52 +00:00
|
|
|
if (skb->fclone == SKB_FCLONE_ORIG &&
|
2017-06-30 10:07:59 +00:00
|
|
|
refcount_read(&fclones->fclone_ref) == 1) {
|
2014-12-04 01:04:39 +00:00
|
|
|
n = &fclones->skb2;
|
2017-06-30 10:07:59 +00:00
|
|
|
refcount_set(&fclones->fclone_ref, 2);
|
2022-07-07 19:18:46 +00:00
|
|
|
n->fclone = SKB_FCLONE_CLONE;
|
2007-10-14 07:37:52 +00:00
|
|
|
} else {
|
2012-07-31 23:44:19 +00:00
|
|
|
if (skb_pfmemalloc(skb))
|
|
|
|
gfp_mask |= __GFP_MEMALLOC;
|
|
|
|
|
2024-03-06 16:00:23 +00:00
|
|
|
n = kmem_cache_alloc(net_hotdata.skbuff_cache, gfp_mask);
|
2007-10-14 07:37:52 +00:00
|
|
|
if (!n)
|
|
|
|
return NULL;
|
2008-08-30 10:16:35 +00:00
|
|
|
|
2007-10-14 07:37:52 +00:00
|
|
|
n->fclone = SKB_FCLONE_UNAVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return __skb_clone(n, skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_clone);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-08-03 07:58:09 +00:00
|
|
|
void skb_headers_offset_update(struct sk_buff *skb, int off)
|
2013-03-07 13:21:40 +00:00
|
|
|
{
|
2013-10-19 18:42:54 +00:00
|
|
|
/* Only adjust this if it actually is csum_start rather than csum */
|
|
|
|
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
|
|
|
skb->csum_start += off;
|
2013-03-07 13:21:40 +00:00
|
|
|
/* {transport,network,mac}_header and tail are relative to skb->head */
|
|
|
|
skb->transport_header += off;
|
|
|
|
skb->network_header += off;
|
|
|
|
if (skb_mac_header_was_set(skb))
|
|
|
|
skb->mac_header += off;
|
|
|
|
skb->inner_transport_header += off;
|
|
|
|
skb->inner_network_header += off;
|
2013-03-07 13:21:46 +00:00
|
|
|
skb->inner_mac_header += off;
|
2013-03-07 13:21:40 +00:00
|
|
|
}
|
2018-08-03 07:58:09 +00:00
|
|
|
EXPORT_SYMBOL(skb_headers_offset_update);
|
2013-03-07 13:21:40 +00:00
|
|
|
|
2018-04-30 07:16:11 +00:00
|
|
|
void skb_copy_header(struct sk_buff *new, const struct sk_buff *old)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2007-10-14 07:37:30 +00:00
|
|
|
__copy_skb_header(new, old);
|
|
|
|
|
2006-06-22 09:40:14 +00:00
|
|
|
skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
|
|
|
|
skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
|
|
|
|
skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2018-04-30 07:16:11 +00:00
|
|
|
EXPORT_SYMBOL(skb_copy_header);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-07-31 23:44:19 +00:00
|
|
|
static inline int skb_alloc_rx_flag(const struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
if (skb_pfmemalloc(skb))
|
|
|
|
return SKB_ALLOC_RX;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* skb_copy - create private copy of an sk_buff
|
|
|
|
* @skb: buffer to copy
|
|
|
|
* @gfp_mask: allocation priority
|
|
|
|
*
|
|
|
|
* Make a copy of both an &sk_buff and its data. This is used when the
|
|
|
|
* caller wishes to modify the data and needs a private copy of the
|
|
|
|
* data to alter. Returns %NULL on failure or the pointer to the buffer
|
|
|
|
* on success. The returned buffer has a reference count of 1.
|
|
|
|
*
|
|
|
|
* As by-product this function converts non-linear &sk_buff to linear
|
|
|
|
* one, so that &sk_buff becomes completely private and caller is allowed
|
|
|
|
* to modify all the data of returned buffer. This means that this
|
|
|
|
* function is not recommended for use in circumstances when only
|
|
|
|
* header is going to be modified. Use pskb_copy() instead.
|
|
|
|
*/
|
|
|
|
|
2005-10-07 06:46:04 +00:00
|
|
|
struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2024-04-27 18:24:19 +00:00
|
|
|
struct sk_buff *n;
|
|
|
|
unsigned int size;
|
|
|
|
int headerlen;
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
|
|
|
|
return NULL;
|
2010-09-01 05:25:10 +00:00
|
|
|
|
2024-04-27 18:24:19 +00:00
|
|
|
headerlen = skb_headroom(skb);
|
|
|
|
size = skb_end_offset(skb) + skb->data_len;
|
|
|
|
n = __alloc_skb(size, gfp_mask,
|
|
|
|
skb_alloc_rx_flag(skb), NUMA_NO_NODE);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!n)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Set the data pointer */
|
|
|
|
skb_reserve(n, headerlen);
|
|
|
|
/* Set the tail pointer and length */
|
|
|
|
skb_put(n, skb->len);
|
|
|
|
|
2017-10-09 15:37:59 +00:00
|
|
|
BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len));
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-04-30 07:16:11 +00:00
|
|
|
skb_copy_header(n, skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
return n;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_copy);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
2014-06-11 22:36:26 +00:00
|
|
|
* __pskb_copy_fclone - create copy of an sk_buff with private head.
|
2005-04-16 22:20:36 +00:00
|
|
|
* @skb: buffer to copy
|
2011-12-03 21:39:53 +00:00
|
|
|
* @headroom: headroom of new skb
|
2005-04-16 22:20:36 +00:00
|
|
|
* @gfp_mask: allocation priority
|
2014-06-11 22:36:26 +00:00
|
|
|
* @fclone: if true allocate the copy of the skb from the fclone
|
|
|
|
* cache instead of the head cache; it is recommended to set this
|
|
|
|
* to true for the cases where the copy will likely be cloned
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* Make a copy of both an &sk_buff and part of its data, located
|
|
|
|
* in header. Fragmented data remain shared. This is used when
|
|
|
|
* the caller wishes to modify only header of &sk_buff and needs
|
|
|
|
* private copy of the header to alter. Returns %NULL on failure
|
|
|
|
* or the pointer to the buffer on success.
|
|
|
|
* The returned buffer has a reference count of 1.
|
|
|
|
*/
|
|
|
|
|
2014-06-11 22:36:26 +00:00
|
|
|
struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom,
|
|
|
|
gfp_t gfp_mask, bool fclone)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2011-12-03 21:39:53 +00:00
|
|
|
unsigned int size = skb_headlen(skb) + headroom;
|
2014-06-11 22:36:26 +00:00
|
|
|
int flags = skb_alloc_rx_flag(skb) | (fclone ? SKB_ALLOC_FCLONE : 0);
|
|
|
|
struct sk_buff *n = __alloc_skb(size, gfp_mask, flags, NUMA_NO_NODE);
|
2010-09-01 05:25:10 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!n)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Set the data pointer */
|
2011-12-03 21:39:53 +00:00
|
|
|
skb_reserve(n, headroom);
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Set the tail pointer and length */
|
|
|
|
skb_put(n, skb_headlen(skb));
|
|
|
|
/* Copy the bytes */
|
2007-03-27 21:55:52 +00:00
|
|
|
skb_copy_from_linear_data(skb, n->data, n->len);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-11-07 22:57:15 +00:00
|
|
|
n->truesize += skb->data_len;
|
2005-04-16 22:20:36 +00:00
|
|
|
n->data_len = skb->data_len;
|
|
|
|
n->len = skb->len;
|
|
|
|
|
|
|
|
if (skb_shinfo(skb)->nr_frags) {
|
|
|
|
int i;
|
|
|
|
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
if (skb_orphan_frags(skb, gfp_mask) ||
|
|
|
|
skb_zerocopy_clone(n, skb, gfp_mask)) {
|
2012-07-20 09:23:10 +00:00
|
|
|
kfree_skb(n);
|
|
|
|
n = NULL;
|
|
|
|
goto out;
|
2011-07-06 12:22:12 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
|
|
|
skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
|
2011-08-22 23:44:58 +00:00
|
|
|
skb_frag_ref(skb, i);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
skb_shinfo(n)->nr_frags = i;
|
|
|
|
}
|
|
|
|
|
2010-08-23 07:13:46 +00:00
|
|
|
if (skb_has_frag_list(skb)) {
|
2005-04-16 22:20:36 +00:00
|
|
|
skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list;
|
|
|
|
skb_clone_fraglist(n);
|
|
|
|
}
|
|
|
|
|
2018-04-30 07:16:11 +00:00
|
|
|
skb_copy_header(n, skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
out:
|
|
|
|
return n;
|
|
|
|
}
|
2014-06-11 22:36:26 +00:00
|
|
|
EXPORT_SYMBOL(__pskb_copy_fclone);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* pskb_expand_head - reallocate header of &sk_buff
|
|
|
|
* @skb: buffer to reallocate
|
|
|
|
* @nhead: room to add at head
|
|
|
|
* @ntail: room to add at tail
|
|
|
|
* @gfp_mask: allocation priority
|
|
|
|
*
|
2013-11-07 13:18:26 +00:00
|
|
|
* Expands (or creates identical copy, if @nhead and @ntail are zero)
|
|
|
|
* header of @skb. &sk_buff itself is not changed. &sk_buff MUST have
|
2005-04-16 22:20:36 +00:00
|
|
|
* reference count of 1. Returns zero in the case of success or error,
|
|
|
|
* if expansion failed. In the last case, &sk_buff is not changed.
|
|
|
|
*
|
|
|
|
* All the pointers pointing into skb header may change and must be
|
|
|
|
* reloaded after call to this function.
|
|
|
|
*/
|
|
|
|
|
2005-07-08 21:57:47 +00:00
|
|
|
int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
|
2005-10-07 06:46:04 +00:00
|
|
|
gfp_t gfp_mask)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2022-10-25 22:39:35 +00:00
|
|
|
unsigned int osize = skb_end_offset(skb);
|
|
|
|
unsigned int size = osize + nhead + ntail;
|
2005-04-16 22:20:36 +00:00
|
|
|
long off;
|
2017-01-27 15:11:27 +00:00
|
|
|
u8 *data;
|
2022-10-25 22:39:35 +00:00
|
|
|
int i;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-10-01 14:09:38 +00:00
|
|
|
BUG_ON(nhead < 0);
|
|
|
|
|
2017-10-09 15:37:59 +00:00
|
|
|
BUG_ON(skb_shared(skb));
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2022-07-12 20:52:31 +00:00
|
|
|
skb_zcopy_downgrade_managed(skb);
|
|
|
|
|
2012-07-31 23:44:19 +00:00
|
|
|
if (skb_pfmemalloc(skb))
|
|
|
|
gfp_mask |= __GFP_MEMALLOC;
|
2022-10-25 22:39:35 +00:00
|
|
|
|
2023-02-06 17:31:02 +00:00
|
|
|
data = kmalloc_reserve(&size, gfp_mask, NUMA_NO_NODE, NULL);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!data)
|
|
|
|
goto nodata;
|
2022-10-25 22:39:35 +00:00
|
|
|
size = SKB_WITH_OVERHEAD(size);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Copy only real data... and, alas, header. This should be
|
2010-09-01 05:25:10 +00:00
|
|
|
* optimized for the cases when header is void.
|
|
|
|
*/
|
|
|
|
memcpy(data + nhead, skb->head, skb_tail_pointer(skb) - skb->head);
|
|
|
|
|
|
|
|
memcpy((struct skb_shared_info *)(data + size),
|
|
|
|
skb_shinfo(skb),
|
2010-07-22 19:09:08 +00:00
|
|
|
offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-05-04 14:26:51 +00:00
|
|
|
/*
|
|
|
|
* if shinfo is shared we must drop the old head gracefully, but if it
|
|
|
|
* is not we can just drop the old head and let the existing refcount
|
|
|
|
* be since all we did is relocate the values
|
|
|
|
*/
|
|
|
|
if (skb_cloned(skb)) {
|
2012-07-20 09:23:10 +00:00
|
|
|
if (skb_orphan_frags(skb, gfp_mask))
|
|
|
|
goto nofrags;
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
if (skb_zcopy(skb))
|
2017-08-31 23:48:22 +00:00
|
|
|
refcount_inc(&skb_uarg(skb)->refcnt);
|
2010-09-02 23:09:32 +00:00
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
|
2011-08-22 23:44:58 +00:00
|
|
|
skb_frag_ref(skb, i);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2010-09-02 23:09:32 +00:00
|
|
|
if (skb_has_frag_list(skb))
|
|
|
|
skb_clone_fraglist(skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_data(skb, SKB_CONSUMED);
|
2012-05-04 14:26:51 +00:00
|
|
|
} else {
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_free_head(skb);
|
2010-09-02 23:09:32 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
off = (data + nhead) - skb->head;
|
|
|
|
|
|
|
|
skb->head = data;
|
net: allow skb->head to be a page fragment
skb->head is currently allocated from kmalloc(). This is convenient but
has the drawback the data cannot be converted to a page fragment if
needed.
We have three spots were it hurts :
1) GRO aggregation
When a linear skb must be appended to another skb, GRO uses the
frag_list fallback, very inefficient since we keep all struct sk_buff
around. So drivers enabling GRO but delivering linear skbs to network
stack aren't enabling full GRO power.
2) splice(socket -> pipe).
We must copy the linear part to a page fragment.
This kind of defeats splice() purpose (zero copy claim)
3) TCP coalescing.
Recently introduced, this permits to group several contiguous segments
into a single skb. This shortens queue lengths and save kernel memory,
and greatly reduce probabilities of TCP collapses. This coalescing
doesnt work on linear skbs (or we would need to copy data, this would be
too slow)
Given all these issues, the following patch introduces the possibility
of having skb->head be a fragment in itself. We use a new skb flag,
skb->head_frag to carry this information.
build_skb() is changed to accept a frag_size argument. Drivers willing
to provide a page fragment instead of kmalloc() data will set a non zero
value, set to the fragment size.
Then, on situations we need to convert the skb head to a frag in itself,
we can check if skb->head_frag is set and avoid the copies or various
fallbacks we have.
This means drivers currently using frags could be updated to avoid the
current skb->head allocation and reduce their memory footprint (aka skb
truesize). (thats 512 or 1024 bytes saved per skb). This also makes
bpf/netfilter faster since the 'first frag' will be part of skb linear
part, no need to copy data.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Maciej Żenczykowski <maze@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Tom Herbert <therbert@google.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Matt Carlson <mcarlson@broadcom.com>
Cc: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-04-27 00:33:38 +00:00
|
|
|
skb->head_frag = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
skb->data += off;
|
2022-02-22 03:21:12 +00:00
|
|
|
|
|
|
|
skb_set_end_offset(skb, size);
|
2007-04-20 03:43:29 +00:00
|
|
|
#ifdef NET_SKBUFF_DATA_USES_OFFSET
|
2007-04-09 18:45:04 +00:00
|
|
|
off = nhead;
|
|
|
|
#endif
|
2007-04-20 03:29:13 +00:00
|
|
|
skb->tail += off;
|
2013-06-06 13:27:21 +00:00
|
|
|
skb_headers_offset_update(skb, nhead);
|
2005-04-16 22:20:36 +00:00
|
|
|
skb->cloned = 0;
|
[SKBUFF]: Keep track of writable header len of headerless clones
Currently NAT (and others) that want to modify cloned skbs copy them,
even if in the vast majority of cases its not necessary because the
skb is a clone made by TCP and the portion NAT wants to modify is
actually writable because TCP release the header reference before
cloning.
The problem is that there is no clean way for NAT to find out how
long the writable header area is, so this patch introduces skb->hdr_len
to hold this length. When a headerless skb is cloned skb->hdr_len
is set to the current headroom, for regular clones it is copied from
the original. A new function skb_clone_writable(skb, len) returns
whether the skb is writable up to len bytes from skb->data. To avoid
enlarging the skb the mac_len field is reduced to 16 bit and the
new hdr_len field is put in the remaining 16 bit.
I've done a few rough benchmarks of NAT (not with this exact patch,
but a very similar one). As expected it saves huge amounts of system
time in case of sendfile, bringing it down to basically the same
amount as without NAT, with sendmsg it only helps on loopback,
probably because of the large MTU.
Transmit a 1GB file using sendfile/sendmsg over eth0/lo with and
without NAT:
- sendfile eth0, no NAT: sys 0m0.388s
- sendfile eth0, NAT: sys 0m1.835s
- sendfile eth0: NAT + path: sys 0m0.370s (~ -80%)
- sendfile lo, no NAT: sys 0m0.258s
- sendfile lo, NAT: sys 0m2.609s
- sendfile lo, NAT + patch: sys 0m0.260s (~ -90%)
- sendmsg eth0, no NAT: sys 0m2.508s
- sendmsg eth0, NAT: sys 0m2.539s
- sendmsg eth0, NAT + patch: sys 0m2.445s (no change)
- sendmsg lo, no NAT: sys 0m2.151s
- sendmsg lo, NAT: sys 0m3.557s
- sendmsg lo, NAT + patch: sys 0m2.159s (~ -40%)
I expect other users can see a similar performance improvement,
packet mangling iptables targets, ipip and ip_gre come to mind ..
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
2007-06-25 11:35:20 +00:00
|
|
|
skb->hdr_len = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
skb->nohdr = 0;
|
|
|
|
atomic_set(&skb_shinfo(skb)->dataref, 1);
|
2017-01-27 15:11:27 +00:00
|
|
|
|
bpf: add meta pointer for direct access
This work enables generic transfer of metadata from XDP into skb. The
basic idea is that we can make use of the fact that the resulting skb
must be linear and already comes with a larger headroom for supporting
bpf_xdp_adjust_head(), which mangles xdp->data. Here, we base our work
on a similar principle and introduce a small helper bpf_xdp_adjust_meta()
for adjusting a new pointer called xdp->data_meta. Thus, the packet has
a flexible and programmable room for meta data, followed by the actual
packet data. struct xdp_buff is therefore laid out that we first point
to data_hard_start, then data_meta directly prepended to data followed
by data_end marking the end of packet. bpf_xdp_adjust_head() takes into
account whether we have meta data already prepended and if so, memmove()s
this along with the given offset provided there's enough room.
xdp->data_meta is optional and programs are not required to use it. The
rationale is that when we process the packet in XDP (e.g. as DoS filter),
we can push further meta data along with it for the XDP_PASS case, and
give the guarantee that a clsact ingress BPF program on the same device
can pick this up for further post-processing. Since we work with skb
there, we can also set skb->mark, skb->priority or other skb meta data
out of BPF, thus having this scratch space generic and programmable
allows for more flexibility than defining a direct 1:1 transfer of
potentially new XDP members into skb (it's also more efficient as we
don't need to initialize/handle each of such new members). The facility
also works together with GRO aggregation. The scratch space at the head
of the packet can be multiple of 4 byte up to 32 byte large. Drivers not
yet supporting xdp->data_meta can simply be set up with xdp->data_meta
as xdp->data + 1 as bpf_xdp_adjust_meta() will detect this and bail out,
such that the subsequent match against xdp->data for later access is
guaranteed to fail.
The verifier treats xdp->data_meta/xdp->data the same way as we treat
xdp->data/xdp->data_end pointer comparisons. The requirement for doing
the compare against xdp->data is that it hasn't been modified from it's
original address we got from ctx access. It may have a range marking
already from prior successful xdp->data/xdp->data_end pointer comparisons
though.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-09-25 00:25:51 +00:00
|
|
|
skb_metadata_clear(skb);
|
|
|
|
|
2017-01-27 15:11:27 +00:00
|
|
|
/* It is not generally safe to change skb->truesize.
|
|
|
|
* For the moment, we really care of rx path, or
|
|
|
|
* when skb is orphaned (not attached to a socket).
|
|
|
|
*/
|
|
|
|
if (!skb->sk || skb->destructor == sock_edemux)
|
|
|
|
skb->truesize += size - osize;
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
return 0;
|
|
|
|
|
2011-07-06 12:22:12 +00:00
|
|
|
nofrags:
|
2023-02-06 17:31:03 +00:00
|
|
|
skb_kfree_head(data, size);
|
2005-04-16 22:20:36 +00:00
|
|
|
nodata:
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(pskb_expand_head);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Make private copy of skb with writable head and some headroom */
|
|
|
|
|
|
|
|
struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb2;
|
|
|
|
int delta = headroom - skb_headroom(skb);
|
|
|
|
|
|
|
|
if (delta <= 0)
|
|
|
|
skb2 = pskb_copy(skb, GFP_ATOMIC);
|
|
|
|
else {
|
|
|
|
skb2 = skb_clone(skb, GFP_ATOMIC);
|
|
|
|
if (skb2 && pskb_expand_head(skb2, SKB_DATA_ALIGN(delta), 0,
|
|
|
|
GFP_ATOMIC)) {
|
|
|
|
kfree_skb(skb2);
|
|
|
|
skb2 = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return skb2;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_realloc_headroom);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
net: avoid skb end_offset change in __skb_unclone_keeptruesize()
Once initial skb->head has been allocated from skb_small_head_cache,
we need to make sure to use the same strategy whenever skb->head
has to be re-allocated, as found by syzbot [1]
This means kmalloc_reserve() can not fallback from using
skb_small_head_cache to generic (power-of-two) kmem caches.
It seems that we probably want to rework things in the future,
to partially revert following patch, because we no longer use
ksize() for skb allocated in TX path.
2b88cba55883 ("net: preserve skb_end_offset() in skb_unclone_keeptruesize()")
Ideally, TCP stack should never put payload in skb->head,
this effort has to be completed.
In the mean time, add a sanity check.
[1]
BUG: KASAN: invalid-free in slab_free mm/slub.c:3787 [inline]
BUG: KASAN: invalid-free in kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
Free of addr ffff88806cdee800 by task syz-executor239/5189
CPU: 0 PID: 5189 Comm: syz-executor239 Not tainted 6.2.0-rc8-syzkaller-02400-gd1fabc68f8e0 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:306 [inline]
print_report+0x15e/0x45d mm/kasan/report.c:417
kasan_report_invalid_free+0x9b/0x1b0 mm/kasan/report.c:482
____kasan_slab_free+0x1a5/0x1c0 mm/kasan/common.c:216
kasan_slab_free include/linux/kasan.h:177 [inline]
slab_free_hook mm/slub.c:1781 [inline]
slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1807
slab_free mm/slub.c:3787 [inline]
kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
skb_kfree_head net/core/skbuff.c:857 [inline]
skb_kfree_head net/core/skbuff.c:853 [inline]
skb_free_head+0x16f/0x1a0 net/core/skbuff.c:872
skb_release_data+0x57a/0x820 net/core/skbuff.c:901
skb_release_all net/core/skbuff.c:966 [inline]
__kfree_skb+0x4f/0x70 net/core/skbuff.c:980
tcp_wmem_free_skb include/net/tcp.h:302 [inline]
tcp_rtx_queue_purge net/ipv4/tcp.c:3061 [inline]
tcp_write_queue_purge+0x617/0xcf0 net/ipv4/tcp.c:3074
tcp_v4_destroy_sock+0x125/0x810 net/ipv4/tcp_ipv4.c:2302
inet_csk_destroy_sock+0x19a/0x440 net/ipv4/inet_connection_sock.c:1195
__tcp_close+0xb96/0xf50 net/ipv4/tcp.c:3021
tcp_close+0x2d/0xc0 net/ipv4/tcp.c:3033
inet_release+0x132/0x270 net/ipv4/af_inet.c:426
__sock_release+0xcd/0x280 net/socket.c:651
sock_close+0x1c/0x20 net/socket.c:1393
__fput+0x27c/0xa90 fs/file_table.c:320
task_work_run+0x16f/0x270 kernel/task_work.c:179
resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
exit_to_user_mode_loop kernel/entry/common.c:171 [inline]
exit_to_user_mode_prepare+0x23c/0x250 kernel/entry/common.c:203
__syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296
do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f2511f546c3
Code: c7 c2 c0 ff ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 64 8b 04 25 18 00 00 00 85 c0 75 14 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 89 7c 24 0c e8
RSP: 002b:00007ffef0103d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
RAX: 0000000000000000 RBX: 0000000000000004 RCX: 00007f2511f546c3
RDX: 0000000000000978 RSI: 00000000200000c0 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000002 R09: 0000000000003434
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffef0103d6c
R13: 00007ffef0103d80 R14: 00007ffef0103dc0 R15: 0000000000000003
</TASK>
Allocated by task 5189:
kasan_save_stack+0x22/0x40 mm/kasan/common.c:45
kasan_set_track+0x25/0x30 mm/kasan/common.c:52
____kasan_kmalloc mm/kasan/common.c:374 [inline]
____kasan_kmalloc mm/kasan/common.c:333 [inline]
__kasan_kmalloc+0xa5/0xb0 mm/kasan/common.c:383
kasan_kmalloc include/linux/kasan.h:211 [inline]
__do_kmalloc_node mm/slab_common.c:968 [inline]
__kmalloc_node_track_caller+0x5b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
pskb_expand_head+0x237/0x1160 net/core/skbuff.c:1995
__skb_unclone_keeptruesize+0x93/0x220 net/core/skbuff.c:2094
skb_unclone_keeptruesize include/linux/skbuff.h:1910 [inline]
skb_prepare_for_shift net/core/skbuff.c:3804 [inline]
skb_shift+0xef8/0x1e20 net/core/skbuff.c:3877
tcp_skb_shift net/ipv4/tcp_input.c:1538 [inline]
tcp_shift_skb_data net/ipv4/tcp_input.c:1646 [inline]
tcp_sacktag_walk+0x93b/0x18a0 net/ipv4/tcp_input.c:1713
tcp_sacktag_write_queue+0x1599/0x31d0 net/ipv4/tcp_input.c:1974
tcp_ack+0x2e9f/0x5a10 net/ipv4/tcp_input.c:3847
tcp_rcv_established+0x667/0x2230 net/ipv4/tcp_input.c:6006
tcp_v4_do_rcv+0x670/0x9b0 net/ipv4/tcp_ipv4.c:1721
sk_backlog_rcv include/net/sock.h:1113 [inline]
__release_sock+0x133/0x3b0 net/core/sock.c:2921
release_sock+0x58/0x1b0 net/core/sock.c:3488
tcp_sendmsg+0x3a/0x50 net/ipv4/tcp.c:1485
inet_sendmsg+0x9d/0xe0 net/ipv4/af_inet.c:825
sock_sendmsg_nosec net/socket.c:722 [inline]
sock_sendmsg+0xde/0x190 net/socket.c:745
sock_write_iter+0x295/0x3d0 net/socket.c:1136
call_write_iter include/linux/fs.h:2189 [inline]
new_sync_write fs/read_write.c:491 [inline]
vfs_write+0x9ed/0xdd0 fs/read_write.c:584
ksys_write+0x1ec/0x250 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
The buggy address belongs to the object at ffff88806cdee800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 0 bytes inside of
1024-byte region [ffff88806cdee800, ffff88806cdeec00)
The buggy address belongs to the physical page:
page:ffffea0001b37a00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x6cde8
head:ffffea0001b37a00 order:3 compound_mapcount:0 subpages_mapcount:0 compound_pincount:0
flags: 0xfff00000010200(slab|head|node=0|zone=1|lastcpupid=0x7ff)
raw: 00fff00000010200 ffff888012441dc0 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask 0x1f2a20(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_MEMALLOC|__GFP_HARDWALL), pid 75, tgid 75 (kworker/u4:4), ts 96369578780, free_ts 26734162530
prep_new_page mm/page_alloc.c:2531 [inline]
get_page_from_freelist+0x119c/0x2ce0 mm/page_alloc.c:4283
__alloc_pages+0x1cb/0x5b0 mm/page_alloc.c:5549
alloc_pages+0x1aa/0x270 mm/mempolicy.c:2287
alloc_slab_page mm/slub.c:1851 [inline]
allocate_slab+0x25f/0x350 mm/slub.c:1998
new_slab mm/slub.c:2051 [inline]
___slab_alloc+0xa91/0x1400 mm/slub.c:3193
__slab_alloc.constprop.0+0x56/0xa0 mm/slub.c:3292
__slab_alloc_node mm/slub.c:3345 [inline]
slab_alloc_node mm/slub.c:3442 [inline]
__kmem_cache_alloc_node+0x1a4/0x430 mm/slub.c:3491
__do_kmalloc_node mm/slab_common.c:967 [inline]
__kmalloc_node_track_caller+0x4b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
__alloc_skb+0x129/0x330 net/core/skbuff.c:608
__netdev_alloc_skb+0x74/0x410 net/core/skbuff.c:672
__netdev_alloc_skb_ip_align include/linux/skbuff.h:3203 [inline]
netdev_alloc_skb_ip_align include/linux/skbuff.h:3213 [inline]
batadv_iv_ogm_aggregate_new+0x106/0x4e0 net/batman-adv/bat_iv_ogm.c:558
batadv_iv_ogm_queue_add net/batman-adv/bat_iv_ogm.c:670 [inline]
batadv_iv_ogm_schedule_buff+0xe6b/0x1450 net/batman-adv/bat_iv_ogm.c:849
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:868 [inline]
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:861 [inline]
batadv_iv_send_outstanding_bat_ogm_packet+0x744/0x910 net/batman-adv/bat_iv_ogm.c:1712
process_one_work+0x9bf/0x1710 kernel/workqueue.c:2289
worker_thread+0x669/0x1090 kernel/workqueue.c:2436
page last free stack trace:
reset_page_owner include/linux/page_owner.h:24 [inline]
free_pages_prepare mm/page_alloc.c:1446 [inline]
free_pcp_prepare+0x66a/0xc20 mm/page_alloc.c:1496
free_unref_page_prepare mm/page_alloc.c:3369 [inline]
free_unref_page+0x1d/0x490 mm/page_alloc.c:3464
free_contig_range+0xb5/0x180 mm/page_alloc.c:9488
destroy_args+0xa8/0x64c mm/debug_vm_pgtable.c:998
debug_vm_pgtable+0x28de/0x296f mm/debug_vm_pgtable.c:1318
do_one_initcall+0x141/0x790 init/main.c:1306
do_initcall_level init/main.c:1379 [inline]
do_initcalls init/main.c:1395 [inline]
do_basic_setup init/main.c:1414 [inline]
kernel_init_freeable+0x6f9/0x782 init/main.c:1634
kernel_init+0x1e/0x1d0 init/main.c:1522
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308
Memory state around the buggy address:
ffff88806cdee700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88806cdee780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88806cdee800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^
ffff88806cdee880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Fixes: bf9f1baa279f ("net: add dedicated kmem_cache for typical/small skb->head")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Christoph Paasch <cpaasch@apple.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-27 14:17:06 +00:00
|
|
|
/* Note: We plan to rework this in linux-6.4 */
|
2022-02-22 03:21:13 +00:00
|
|
|
int __skb_unclone_keeptruesize(struct sk_buff *skb, gfp_t pri)
|
|
|
|
{
|
|
|
|
unsigned int saved_end_offset, saved_truesize;
|
|
|
|
struct skb_shared_info *shinfo;
|
|
|
|
int res;
|
|
|
|
|
|
|
|
saved_end_offset = skb_end_offset(skb);
|
|
|
|
saved_truesize = skb->truesize;
|
|
|
|
|
|
|
|
res = pskb_expand_head(skb, 0, 0, pri);
|
|
|
|
if (res)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
skb->truesize = saved_truesize;
|
|
|
|
|
|
|
|
if (likely(skb_end_offset(skb) == saved_end_offset))
|
|
|
|
return 0;
|
|
|
|
|
net: avoid skb end_offset change in __skb_unclone_keeptruesize()
Once initial skb->head has been allocated from skb_small_head_cache,
we need to make sure to use the same strategy whenever skb->head
has to be re-allocated, as found by syzbot [1]
This means kmalloc_reserve() can not fallback from using
skb_small_head_cache to generic (power-of-two) kmem caches.
It seems that we probably want to rework things in the future,
to partially revert following patch, because we no longer use
ksize() for skb allocated in TX path.
2b88cba55883 ("net: preserve skb_end_offset() in skb_unclone_keeptruesize()")
Ideally, TCP stack should never put payload in skb->head,
this effort has to be completed.
In the mean time, add a sanity check.
[1]
BUG: KASAN: invalid-free in slab_free mm/slub.c:3787 [inline]
BUG: KASAN: invalid-free in kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
Free of addr ffff88806cdee800 by task syz-executor239/5189
CPU: 0 PID: 5189 Comm: syz-executor239 Not tainted 6.2.0-rc8-syzkaller-02400-gd1fabc68f8e0 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xd1/0x138 lib/dump_stack.c:106
print_address_description mm/kasan/report.c:306 [inline]
print_report+0x15e/0x45d mm/kasan/report.c:417
kasan_report_invalid_free+0x9b/0x1b0 mm/kasan/report.c:482
____kasan_slab_free+0x1a5/0x1c0 mm/kasan/common.c:216
kasan_slab_free include/linux/kasan.h:177 [inline]
slab_free_hook mm/slub.c:1781 [inline]
slab_free_freelist_hook+0x8b/0x1c0 mm/slub.c:1807
slab_free mm/slub.c:3787 [inline]
kmem_cache_free+0xee/0x5c0 mm/slub.c:3809
skb_kfree_head net/core/skbuff.c:857 [inline]
skb_kfree_head net/core/skbuff.c:853 [inline]
skb_free_head+0x16f/0x1a0 net/core/skbuff.c:872
skb_release_data+0x57a/0x820 net/core/skbuff.c:901
skb_release_all net/core/skbuff.c:966 [inline]
__kfree_skb+0x4f/0x70 net/core/skbuff.c:980
tcp_wmem_free_skb include/net/tcp.h:302 [inline]
tcp_rtx_queue_purge net/ipv4/tcp.c:3061 [inline]
tcp_write_queue_purge+0x617/0xcf0 net/ipv4/tcp.c:3074
tcp_v4_destroy_sock+0x125/0x810 net/ipv4/tcp_ipv4.c:2302
inet_csk_destroy_sock+0x19a/0x440 net/ipv4/inet_connection_sock.c:1195
__tcp_close+0xb96/0xf50 net/ipv4/tcp.c:3021
tcp_close+0x2d/0xc0 net/ipv4/tcp.c:3033
inet_release+0x132/0x270 net/ipv4/af_inet.c:426
__sock_release+0xcd/0x280 net/socket.c:651
sock_close+0x1c/0x20 net/socket.c:1393
__fput+0x27c/0xa90 fs/file_table.c:320
task_work_run+0x16f/0x270 kernel/task_work.c:179
resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
exit_to_user_mode_loop kernel/entry/common.c:171 [inline]
exit_to_user_mode_prepare+0x23c/0x250 kernel/entry/common.c:203
__syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
syscall_exit_to_user_mode+0x1d/0x50 kernel/entry/common.c:296
do_syscall_64+0x46/0xb0 arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f2511f546c3
Code: c7 c2 c0 ff ff ff f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 64 8b 04 25 18 00 00 00 85 c0 75 14 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 89 7c 24 0c e8
RSP: 002b:00007ffef0103d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
RAX: 0000000000000000 RBX: 0000000000000004 RCX: 00007f2511f546c3
RDX: 0000000000000978 RSI: 00000000200000c0 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000002 R09: 0000000000003434
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffef0103d6c
R13: 00007ffef0103d80 R14: 00007ffef0103dc0 R15: 0000000000000003
</TASK>
Allocated by task 5189:
kasan_save_stack+0x22/0x40 mm/kasan/common.c:45
kasan_set_track+0x25/0x30 mm/kasan/common.c:52
____kasan_kmalloc mm/kasan/common.c:374 [inline]
____kasan_kmalloc mm/kasan/common.c:333 [inline]
__kasan_kmalloc+0xa5/0xb0 mm/kasan/common.c:383
kasan_kmalloc include/linux/kasan.h:211 [inline]
__do_kmalloc_node mm/slab_common.c:968 [inline]
__kmalloc_node_track_caller+0x5b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
pskb_expand_head+0x237/0x1160 net/core/skbuff.c:1995
__skb_unclone_keeptruesize+0x93/0x220 net/core/skbuff.c:2094
skb_unclone_keeptruesize include/linux/skbuff.h:1910 [inline]
skb_prepare_for_shift net/core/skbuff.c:3804 [inline]
skb_shift+0xef8/0x1e20 net/core/skbuff.c:3877
tcp_skb_shift net/ipv4/tcp_input.c:1538 [inline]
tcp_shift_skb_data net/ipv4/tcp_input.c:1646 [inline]
tcp_sacktag_walk+0x93b/0x18a0 net/ipv4/tcp_input.c:1713
tcp_sacktag_write_queue+0x1599/0x31d0 net/ipv4/tcp_input.c:1974
tcp_ack+0x2e9f/0x5a10 net/ipv4/tcp_input.c:3847
tcp_rcv_established+0x667/0x2230 net/ipv4/tcp_input.c:6006
tcp_v4_do_rcv+0x670/0x9b0 net/ipv4/tcp_ipv4.c:1721
sk_backlog_rcv include/net/sock.h:1113 [inline]
__release_sock+0x133/0x3b0 net/core/sock.c:2921
release_sock+0x58/0x1b0 net/core/sock.c:3488
tcp_sendmsg+0x3a/0x50 net/ipv4/tcp.c:1485
inet_sendmsg+0x9d/0xe0 net/ipv4/af_inet.c:825
sock_sendmsg_nosec net/socket.c:722 [inline]
sock_sendmsg+0xde/0x190 net/socket.c:745
sock_write_iter+0x295/0x3d0 net/socket.c:1136
call_write_iter include/linux/fs.h:2189 [inline]
new_sync_write fs/read_write.c:491 [inline]
vfs_write+0x9ed/0xdd0 fs/read_write.c:584
ksys_write+0x1ec/0x250 fs/read_write.c:637
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x39/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
The buggy address belongs to the object at ffff88806cdee800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 0 bytes inside of
1024-byte region [ffff88806cdee800, ffff88806cdeec00)
The buggy address belongs to the physical page:
page:ffffea0001b37a00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x6cde8
head:ffffea0001b37a00 order:3 compound_mapcount:0 subpages_mapcount:0 compound_pincount:0
flags: 0xfff00000010200(slab|head|node=0|zone=1|lastcpupid=0x7ff)
raw: 00fff00000010200 ffff888012441dc0 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask 0x1f2a20(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_MEMALLOC|__GFP_HARDWALL), pid 75, tgid 75 (kworker/u4:4), ts 96369578780, free_ts 26734162530
prep_new_page mm/page_alloc.c:2531 [inline]
get_page_from_freelist+0x119c/0x2ce0 mm/page_alloc.c:4283
__alloc_pages+0x1cb/0x5b0 mm/page_alloc.c:5549
alloc_pages+0x1aa/0x270 mm/mempolicy.c:2287
alloc_slab_page mm/slub.c:1851 [inline]
allocate_slab+0x25f/0x350 mm/slub.c:1998
new_slab mm/slub.c:2051 [inline]
___slab_alloc+0xa91/0x1400 mm/slub.c:3193
__slab_alloc.constprop.0+0x56/0xa0 mm/slub.c:3292
__slab_alloc_node mm/slub.c:3345 [inline]
slab_alloc_node mm/slub.c:3442 [inline]
__kmem_cache_alloc_node+0x1a4/0x430 mm/slub.c:3491
__do_kmalloc_node mm/slab_common.c:967 [inline]
__kmalloc_node_track_caller+0x4b/0xc0 mm/slab_common.c:988
kmalloc_reserve+0xf1/0x230 net/core/skbuff.c:539
__alloc_skb+0x129/0x330 net/core/skbuff.c:608
__netdev_alloc_skb+0x74/0x410 net/core/skbuff.c:672
__netdev_alloc_skb_ip_align include/linux/skbuff.h:3203 [inline]
netdev_alloc_skb_ip_align include/linux/skbuff.h:3213 [inline]
batadv_iv_ogm_aggregate_new+0x106/0x4e0 net/batman-adv/bat_iv_ogm.c:558
batadv_iv_ogm_queue_add net/batman-adv/bat_iv_ogm.c:670 [inline]
batadv_iv_ogm_schedule_buff+0xe6b/0x1450 net/batman-adv/bat_iv_ogm.c:849
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:868 [inline]
batadv_iv_ogm_schedule net/batman-adv/bat_iv_ogm.c:861 [inline]
batadv_iv_send_outstanding_bat_ogm_packet+0x744/0x910 net/batman-adv/bat_iv_ogm.c:1712
process_one_work+0x9bf/0x1710 kernel/workqueue.c:2289
worker_thread+0x669/0x1090 kernel/workqueue.c:2436
page last free stack trace:
reset_page_owner include/linux/page_owner.h:24 [inline]
free_pages_prepare mm/page_alloc.c:1446 [inline]
free_pcp_prepare+0x66a/0xc20 mm/page_alloc.c:1496
free_unref_page_prepare mm/page_alloc.c:3369 [inline]
free_unref_page+0x1d/0x490 mm/page_alloc.c:3464
free_contig_range+0xb5/0x180 mm/page_alloc.c:9488
destroy_args+0xa8/0x64c mm/debug_vm_pgtable.c:998
debug_vm_pgtable+0x28de/0x296f mm/debug_vm_pgtable.c:1318
do_one_initcall+0x141/0x790 init/main.c:1306
do_initcall_level init/main.c:1379 [inline]
do_initcalls init/main.c:1395 [inline]
do_basic_setup init/main.c:1414 [inline]
kernel_init_freeable+0x6f9/0x782 init/main.c:1634
kernel_init+0x1e/0x1d0 init/main.c:1522
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308
Memory state around the buggy address:
ffff88806cdee700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff88806cdee780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88806cdee800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^
ffff88806cdee880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Fixes: bf9f1baa279f ("net: add dedicated kmem_cache for typical/small skb->head")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Christoph Paasch <cpaasch@apple.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-02-27 14:17:06 +00:00
|
|
|
/* We can not change skb->end if the original or new value
|
|
|
|
* is SKB_SMALL_HEAD_HEADROOM, as it might break skb_kfree_head().
|
|
|
|
*/
|
|
|
|
if (saved_end_offset == SKB_SMALL_HEAD_HEADROOM ||
|
|
|
|
skb_end_offset(skb) == SKB_SMALL_HEAD_HEADROOM) {
|
|
|
|
/* We think this path should not be taken.
|
|
|
|
* Add a temporary trace to warn us just in case.
|
|
|
|
*/
|
|
|
|
pr_err_once("__skb_unclone_keeptruesize() skb_end_offset() %u -> %u\n",
|
|
|
|
saved_end_offset, skb_end_offset(skb));
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-02-22 03:21:13 +00:00
|
|
|
shinfo = skb_shinfo(skb);
|
|
|
|
|
|
|
|
/* We are about to change back skb->end,
|
|
|
|
* we need to move skb_shinfo() to its new location.
|
|
|
|
*/
|
|
|
|
memmove(skb->head + saved_end_offset,
|
|
|
|
shinfo,
|
|
|
|
offsetof(struct skb_shared_info, frags[shinfo->nr_frags]));
|
|
|
|
|
|
|
|
skb_set_end_offset(skb, saved_end_offset);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-08-02 08:52:15 +00:00
|
|
|
/**
|
|
|
|
* skb_expand_head - reallocate header of &sk_buff
|
|
|
|
* @skb: buffer to reallocate
|
|
|
|
* @headroom: needed headroom
|
|
|
|
*
|
|
|
|
* Unlike skb_realloc_headroom, this one does not allocate a new skb
|
|
|
|
* if possible; copies skb->sk to new skb as needed
|
|
|
|
* and frees original skb in case of failures.
|
|
|
|
*
|
|
|
|
* It expect increased headroom and generates warning otherwise.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct sk_buff *skb_expand_head(struct sk_buff *skb, unsigned int headroom)
|
|
|
|
{
|
|
|
|
int delta = headroom - skb_headroom(skb);
|
2021-10-22 10:28:37 +00:00
|
|
|
int osize = skb_end_offset(skb);
|
|
|
|
struct sock *sk = skb->sk;
|
2021-08-02 08:52:15 +00:00
|
|
|
|
|
|
|
if (WARN_ONCE(delta <= 0,
|
|
|
|
"%s is expecting an increase in the headroom", __func__))
|
|
|
|
return skb;
|
|
|
|
|
2021-10-22 10:28:37 +00:00
|
|
|
delta = SKB_DATA_ALIGN(delta);
|
|
|
|
/* pskb_expand_head() might crash, if skb is shared. */
|
|
|
|
if (skb_shared(skb) || !is_skb_wmem(skb)) {
|
2021-08-02 08:52:15 +00:00
|
|
|
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
|
|
|
|
|
2021-10-22 10:28:37 +00:00
|
|
|
if (unlikely(!nskb))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (sk)
|
|
|
|
skb_set_owner_w(nskb, sk);
|
|
|
|
consume_skb(skb);
|
2021-08-02 08:52:15 +00:00
|
|
|
skb = nskb;
|
|
|
|
}
|
2021-10-22 10:28:37 +00:00
|
|
|
if (pskb_expand_head(skb, delta, 0, GFP_ATOMIC))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (sk && is_skb_wmem(skb)) {
|
|
|
|
delta = skb_end_offset(skb) - osize;
|
|
|
|
refcount_add(delta, &sk->sk_wmem_alloc);
|
|
|
|
skb->truesize += delta;
|
2021-08-02 08:52:15 +00:00
|
|
|
}
|
|
|
|
return skb;
|
2021-10-22 10:28:37 +00:00
|
|
|
|
|
|
|
fail:
|
|
|
|
kfree_skb(skb);
|
|
|
|
return NULL;
|
2021-08-02 08:52:15 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_expand_head);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* skb_copy_expand - copy and expand sk_buff
|
|
|
|
* @skb: buffer to copy
|
|
|
|
* @newheadroom: new free bytes at head
|
|
|
|
* @newtailroom: new free bytes at tail
|
|
|
|
* @gfp_mask: allocation priority
|
|
|
|
*
|
|
|
|
* Make a copy of both an &sk_buff and its data and while doing so
|
|
|
|
* allocate additional space.
|
|
|
|
*
|
|
|
|
* This is used when the caller wishes to modify the data and needs a
|
|
|
|
* private copy of the data to alter as well as more space for new fields.
|
|
|
|
* Returns %NULL on failure or the pointer to the buffer
|
|
|
|
* on success. The returned buffer has a reference count of 1.
|
|
|
|
*
|
|
|
|
* You must pass %GFP_ATOMIC as the allocation priority if this function
|
|
|
|
* is called from an interrupt.
|
|
|
|
*/
|
|
|
|
struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
|
2005-07-08 21:57:47 +00:00
|
|
|
int newheadroom, int newtailroom,
|
2005-10-07 06:46:04 +00:00
|
|
|
gfp_t gfp_mask)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Allocate the copy buffer
|
|
|
|
*/
|
|
|
|
int head_copy_len, head_copy_off;
|
2024-04-27 18:24:19 +00:00
|
|
|
struct sk_buff *n;
|
|
|
|
int oldheadroom;
|
|
|
|
|
|
|
|
if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
|
|
|
|
return NULL;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2024-04-27 18:24:19 +00:00
|
|
|
oldheadroom = skb_headroom(skb);
|
|
|
|
n = __alloc_skb(newheadroom + skb->len + newtailroom,
|
|
|
|
gfp_mask, skb_alloc_rx_flag(skb),
|
|
|
|
NUMA_NO_NODE);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!n)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
skb_reserve(n, newheadroom);
|
|
|
|
|
|
|
|
/* Set the tail pointer and length */
|
|
|
|
skb_put(n, skb->len);
|
|
|
|
|
2007-04-11 01:30:09 +00:00
|
|
|
head_copy_len = oldheadroom;
|
2005-04-16 22:20:36 +00:00
|
|
|
head_copy_off = 0;
|
|
|
|
if (newheadroom <= head_copy_len)
|
|
|
|
head_copy_len = newheadroom;
|
|
|
|
else
|
|
|
|
head_copy_off = newheadroom - head_copy_len;
|
|
|
|
|
|
|
|
/* Copy the linear header and data. */
|
2017-10-09 15:37:59 +00:00
|
|
|
BUG_ON(skb_copy_bits(skb, -head_copy_len, n->head + head_copy_off,
|
|
|
|
skb->len + head_copy_len));
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-04-30 07:16:11 +00:00
|
|
|
skb_copy_header(n, skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2013-10-19 18:42:54 +00:00
|
|
|
skb_headers_offset_update(n, newheadroom - oldheadroom);
|
2007-04-11 01:30:09 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
return n;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_copy_expand);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
2017-08-22 22:12:14 +00:00
|
|
|
* __skb_pad - zero pad the tail of an skb
|
2005-04-16 22:20:36 +00:00
|
|
|
* @skb: buffer to pad
|
|
|
|
* @pad: space to pad
|
2017-08-22 22:12:14 +00:00
|
|
|
* @free_on_error: free buffer on error
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* Ensure that a buffer is followed by a padding area that is zero
|
|
|
|
* filled. Used by network drivers which may DMA or transfer data
|
|
|
|
* beyond the buffer end onto the wire.
|
|
|
|
*
|
2017-08-22 22:12:14 +00:00
|
|
|
* May return error in out of memory cases. The skb is freed on error
|
|
|
|
* if @free_on_error is true.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2007-02-09 14:24:36 +00:00
|
|
|
|
2017-08-22 22:12:14 +00:00
|
|
|
int __skb_pad(struct sk_buff *skb, int pad, bool free_on_error)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-06-23 09:06:41 +00:00
|
|
|
int err;
|
|
|
|
int ntail;
|
2007-02-09 14:24:36 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* If the skbuff is non linear tailroom is always zero.. */
|
2006-06-23 09:06:41 +00:00
|
|
|
if (!skb_cloned(skb) && skb_tailroom(skb) >= pad) {
|
2005-04-16 22:20:36 +00:00
|
|
|
memset(skb->data+skb->len, 0, pad);
|
2006-06-23 09:06:41 +00:00
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2006-06-23 09:06:41 +00:00
|
|
|
|
2007-04-20 03:43:29 +00:00
|
|
|
ntail = skb->data_len + pad - (skb->end - skb->tail);
|
2006-06-23 09:06:41 +00:00
|
|
|
if (likely(skb_cloned(skb) || ntail > 0)) {
|
|
|
|
err = pskb_expand_head(skb, 0, ntail, GFP_ATOMIC);
|
|
|
|
if (unlikely(err))
|
|
|
|
goto free_skb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: The use of this function with non-linear skb's really needs
|
|
|
|
* to be audited.
|
|
|
|
*/
|
|
|
|
err = skb_linearize(skb);
|
|
|
|
if (unlikely(err))
|
|
|
|
goto free_skb;
|
|
|
|
|
|
|
|
memset(skb->data + skb->len, 0, pad);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
free_skb:
|
2017-08-22 22:12:14 +00:00
|
|
|
if (free_on_error)
|
|
|
|
kfree_skb(skb);
|
2006-06-23 09:06:41 +00:00
|
|
|
return err;
|
2007-02-09 14:24:36 +00:00
|
|
|
}
|
2017-08-22 22:12:14 +00:00
|
|
|
EXPORT_SYMBOL(__skb_pad);
|
2007-02-09 14:24:36 +00:00
|
|
|
|
2013-11-07 13:18:24 +00:00
|
|
|
/**
|
|
|
|
* pskb_put - add data to the tail of a potentially fragmented buffer
|
|
|
|
* @skb: start of the buffer to use
|
|
|
|
* @tail: tail fragment of the buffer to use
|
|
|
|
* @len: amount of data to add
|
|
|
|
*
|
|
|
|
* This function extends the used data area of the potentially
|
|
|
|
* fragmented buffer. @tail must be the last fragment of @skb -- or
|
|
|
|
* @skb itself. If this would exceed the total buffer size the kernel
|
|
|
|
* will panic. A pointer to the first byte of the extra data is
|
|
|
|
* returned.
|
|
|
|
*/
|
|
|
|
|
networking: make skb_put & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions (skb_put, __skb_put and pskb_put) return void *
and remove all the casts across the tree, adding a (u8 *) cast only
where the unsigned char pointer was used directly, all done with the
following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_put, __skb_put };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_put, __skb_put };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
which actually doesn't cover pskb_put since there are only three
users overall.
A handful of stragglers were converted manually, notably a macro in
drivers/isdn/i4l/isdn_bsdcomp.c and, oddly enough, one of the many
instances in net/bluetooth/hci_sock.c. In the former file, I also
had to fix one whitespace problem spatch introduced.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 12:29:21 +00:00
|
|
|
void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
|
2013-11-07 13:18:24 +00:00
|
|
|
{
|
|
|
|
if (tail != skb) {
|
|
|
|
skb->data_len += len;
|
|
|
|
skb->len += len;
|
|
|
|
}
|
|
|
|
return skb_put(tail, len);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(pskb_put);
|
|
|
|
|
2008-03-28 00:43:41 +00:00
|
|
|
/**
|
|
|
|
* skb_put - add data to a buffer
|
|
|
|
* @skb: buffer to use
|
|
|
|
* @len: amount of data to add
|
|
|
|
*
|
|
|
|
* This function extends the used data area of the buffer. If this would
|
|
|
|
* exceed the total buffer size the kernel will panic. A pointer to the
|
|
|
|
* first byte of the extra data is returned.
|
|
|
|
*/
|
networking: make skb_put & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions (skb_put, __skb_put and pskb_put) return void *
and remove all the casts across the tree, adding a (u8 *) cast only
where the unsigned char pointer was used directly, all done with the
following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_put, __skb_put };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_put, __skb_put };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
which actually doesn't cover pskb_put since there are only three
users overall.
A handful of stragglers were converted manually, notably a macro in
drivers/isdn/i4l/isdn_bsdcomp.c and, oddly enough, one of the many
instances in net/bluetooth/hci_sock.c. In the former file, I also
had to fix one whitespace problem spatch introduced.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 12:29:21 +00:00
|
|
|
void *skb_put(struct sk_buff *skb, unsigned int len)
|
2008-03-28 00:43:41 +00:00
|
|
|
{
|
networking: make skb_put & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions (skb_put, __skb_put and pskb_put) return void *
and remove all the casts across the tree, adding a (u8 *) cast only
where the unsigned char pointer was used directly, all done with the
following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_put, __skb_put };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_put, __skb_put };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
which actually doesn't cover pskb_put since there are only three
users overall.
A handful of stragglers were converted manually, notably a macro in
drivers/isdn/i4l/isdn_bsdcomp.c and, oddly enough, one of the many
instances in net/bluetooth/hci_sock.c. In the former file, I also
had to fix one whitespace problem spatch introduced.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 12:29:21 +00:00
|
|
|
void *tmp = skb_tail_pointer(skb);
|
2008-03-28 00:43:41 +00:00
|
|
|
SKB_LINEAR_ASSERT(skb);
|
|
|
|
skb->tail += len;
|
|
|
|
skb->len += len;
|
|
|
|
if (unlikely(skb->tail > skb->end))
|
|
|
|
skb_over_panic(skb, len, __builtin_return_address(0));
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_put);
|
|
|
|
|
2008-03-28 00:52:40 +00:00
|
|
|
/**
|
|
|
|
* skb_push - add data to the start of a buffer
|
|
|
|
* @skb: buffer to use
|
|
|
|
* @len: amount of data to add
|
|
|
|
*
|
|
|
|
* This function extends the used data area of the buffer at the buffer
|
|
|
|
* start. If this would exceed the total buffer headroom the kernel will
|
|
|
|
* panic. A pointer to the first byte of the extra data is returned.
|
|
|
|
*/
|
networking: make skb_push & __skb_push return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
@@
expression SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- fn(SKB, LEN)[0]
+ *(u8 *)fn(SKB, LEN)
Note that the last part there converts from push(...)[0] to the
more idiomatic *(u8 *)push(...).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 12:29:23 +00:00
|
|
|
void *skb_push(struct sk_buff *skb, unsigned int len)
|
2008-03-28 00:52:40 +00:00
|
|
|
{
|
|
|
|
skb->data -= len;
|
|
|
|
skb->len += len;
|
2018-08-02 10:04:52 +00:00
|
|
|
if (unlikely(skb->data < skb->head))
|
2008-03-28 00:52:40 +00:00
|
|
|
skb_under_panic(skb, len, __builtin_return_address(0));
|
|
|
|
return skb->data;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_push);
|
|
|
|
|
2008-03-28 00:47:24 +00:00
|
|
|
/**
|
|
|
|
* skb_pull - remove data from the start of a buffer
|
|
|
|
* @skb: buffer to use
|
|
|
|
* @len: amount of data to remove
|
|
|
|
*
|
|
|
|
* This function removes data from the start of a buffer, returning
|
|
|
|
* the memory to the headroom. A pointer to the next data in the buffer
|
|
|
|
* is returned. Once the data has been pulled future pushes will overwrite
|
|
|
|
* the old data.
|
|
|
|
*/
|
networking: make skb_pull & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = {
skb_pull,
__skb_pull,
skb_pull_inline,
__pskb_pull_tail,
__pskb_pull,
pskb_pull
};
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = {
skb_pull,
__skb_pull,
skb_pull_inline,
__pskb_pull_tail,
__pskb_pull,
pskb_pull
};
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 12:29:22 +00:00
|
|
|
void *skb_pull(struct sk_buff *skb, unsigned int len)
|
2008-03-28 00:47:24 +00:00
|
|
|
{
|
2010-05-02 09:21:44 +00:00
|
|
|
return skb_pull_inline(skb, len);
|
2008-03-28 00:47:24 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_pull);
|
|
|
|
|
2021-12-01 18:54:52 +00:00
|
|
|
/**
|
|
|
|
* skb_pull_data - remove data from the start of a buffer returning its
|
|
|
|
* original position.
|
|
|
|
* @skb: buffer to use
|
|
|
|
* @len: amount of data to remove
|
|
|
|
*
|
|
|
|
* This function removes data from the start of a buffer, returning
|
|
|
|
* the memory to the headroom. A pointer to the original data in the buffer
|
|
|
|
* is returned after checking if there is enough data to pull. Once the
|
|
|
|
* data has been pulled future pushes will overwrite the old data.
|
|
|
|
*/
|
|
|
|
void *skb_pull_data(struct sk_buff *skb, size_t len)
|
|
|
|
{
|
|
|
|
void *data = skb->data;
|
|
|
|
|
|
|
|
if (skb->len < len)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
skb_pull(skb, len);
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_pull_data);
|
|
|
|
|
2008-03-28 00:54:01 +00:00
|
|
|
/**
|
|
|
|
* skb_trim - remove end from a buffer
|
|
|
|
* @skb: buffer to alter
|
|
|
|
* @len: new length
|
|
|
|
*
|
|
|
|
* Cut the length of a buffer down by removing data from the tail. If
|
|
|
|
* the buffer is already under the length specified it is not modified.
|
|
|
|
* The skb must be linear.
|
|
|
|
*/
|
|
|
|
void skb_trim(struct sk_buff *skb, unsigned int len)
|
|
|
|
{
|
|
|
|
if (skb->len > len)
|
|
|
|
__skb_trim(skb, len);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_trim);
|
|
|
|
|
2006-06-09 23:13:38 +00:00
|
|
|
/* Trims skb to length len. It can change skb pointers.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
|
2006-06-09 23:13:38 +00:00
|
|
|
int ___pskb_trim(struct sk_buff *skb, unsigned int len)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2006-07-14 02:26:39 +00:00
|
|
|
struct sk_buff **fragp;
|
|
|
|
struct sk_buff *frag;
|
2005-04-16 22:20:36 +00:00
|
|
|
int offset = skb_headlen(skb);
|
|
|
|
int nfrags = skb_shinfo(skb)->nr_frags;
|
|
|
|
int i;
|
2006-07-14 02:26:39 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (skb_cloned(skb) &&
|
|
|
|
unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
|
|
|
|
return err;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-07-31 03:20:28 +00:00
|
|
|
i = 0;
|
|
|
|
if (offset >= len)
|
|
|
|
goto drop_pages;
|
|
|
|
|
|
|
|
for (; i < nfrags; i++) {
|
2011-10-18 21:00:24 +00:00
|
|
|
int end = offset + skb_frag_size(&skb_shinfo(skb)->frags[i]);
|
2006-07-14 02:26:39 +00:00
|
|
|
|
|
|
|
if (end < len) {
|
|
|
|
offset = end;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-10-18 21:00:24 +00:00
|
|
|
skb_frag_size_set(&skb_shinfo(skb)->frags[i++], len - offset);
|
2006-07-14 02:26:39 +00:00
|
|
|
|
2006-07-31 03:20:28 +00:00
|
|
|
drop_pages:
|
2006-07-14 02:26:39 +00:00
|
|
|
skb_shinfo(skb)->nr_frags = i;
|
|
|
|
|
|
|
|
for (; i < nfrags; i++)
|
2011-08-22 23:44:58 +00:00
|
|
|
skb_frag_unref(skb, i);
|
2006-07-14 02:26:39 +00:00
|
|
|
|
2010-08-23 07:13:46 +00:00
|
|
|
if (skb_has_frag_list(skb))
|
2006-07-14 02:26:39 +00:00
|
|
|
skb_drop_fraglist(skb);
|
2006-07-31 03:20:28 +00:00
|
|
|
goto done;
|
2006-07-14 02:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
|
|
|
|
fragp = &frag->next) {
|
|
|
|
int end = offset + frag->len;
|
|
|
|
|
|
|
|
if (skb_shared(frag)) {
|
|
|
|
struct sk_buff *nfrag;
|
|
|
|
|
|
|
|
nfrag = skb_clone(frag, GFP_ATOMIC);
|
|
|
|
if (unlikely(!nfrag))
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
nfrag->next = frag->next;
|
2012-04-19 02:24:53 +00:00
|
|
|
consume_skb(frag);
|
2006-07-14 02:26:39 +00:00
|
|
|
frag = nfrag;
|
|
|
|
*fragp = frag;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2006-07-14 02:26:39 +00:00
|
|
|
|
|
|
|
if (end < len) {
|
|
|
|
offset = end;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (end > len &&
|
|
|
|
unlikely((err = pskb_trim(frag, len - offset))))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (frag->next)
|
|
|
|
skb_drop_list(&frag->next);
|
|
|
|
break;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2006-07-31 03:20:28 +00:00
|
|
|
done:
|
2006-07-14 02:26:39 +00:00
|
|
|
if (len > skb_headlen(skb)) {
|
2005-04-16 22:20:36 +00:00
|
|
|
skb->data_len -= skb->len - len;
|
|
|
|
skb->len = len;
|
|
|
|
} else {
|
2006-07-14 02:26:39 +00:00
|
|
|
skb->len = len;
|
|
|
|
skb->data_len = 0;
|
2007-04-20 03:29:13 +00:00
|
|
|
skb_set_tail_pointer(skb, len);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2017-04-26 16:07:46 +00:00
|
|
|
if (!skb->sk || skb->destructor == sock_edemux)
|
|
|
|
skb_condense(skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(___pskb_trim);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-04-18 18:43:15 +00:00
|
|
|
/* Note : use pskb_trim_rcsum() instead of calling this directly
|
|
|
|
*/
|
|
|
|
int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len)
|
|
|
|
{
|
|
|
|
if (skb->ip_summed == CHECKSUM_COMPLETE) {
|
|
|
|
int delta = skb->len - len;
|
|
|
|
|
2018-10-20 00:07:13 +00:00
|
|
|
skb->csum = csum_block_sub(skb->csum,
|
|
|
|
skb_checksum(skb, len, delta, 0),
|
|
|
|
len);
|
2020-12-14 19:07:39 +00:00
|
|
|
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
|
|
|
int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len;
|
|
|
|
int offset = skb_checksum_start_offset(skb) + skb->csum_offset;
|
|
|
|
|
|
|
|
if (offset + sizeof(__sum16) > hdlen)
|
|
|
|
return -EINVAL;
|
2018-04-18 18:43:15 +00:00
|
|
|
}
|
|
|
|
return __pskb_trim(skb, len);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(pskb_trim_rcsum_slow);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* __pskb_pull_tail - advance tail of skb header
|
|
|
|
* @skb: buffer to reallocate
|
|
|
|
* @delta: number of bytes to advance tail
|
|
|
|
*
|
|
|
|
* The function makes a sense only on a fragmented &sk_buff,
|
|
|
|
* it expands header moving its tail forward and copying necessary
|
|
|
|
* data from fragmented part.
|
|
|
|
*
|
|
|
|
* &sk_buff MUST have reference count of 1.
|
|
|
|
*
|
|
|
|
* Returns %NULL (and &sk_buff does not change) if pull failed
|
|
|
|
* or value of new tail of skb in the case of success.
|
|
|
|
*
|
|
|
|
* All the pointers pointing into skb header may change and must be
|
|
|
|
* reloaded after call to this function.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Moves tail of skb head forward, copying data from fragmented part,
|
|
|
|
* when it is necessary.
|
|
|
|
* 1. It may fail due to malloc failure.
|
|
|
|
* 2. It may change skb pointers.
|
|
|
|
*
|
|
|
|
* It is pretty complicated. Luckily, it is called only in exceptional cases.
|
|
|
|
*/
|
networking: make skb_pull & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = {
skb_pull,
__skb_pull,
skb_pull_inline,
__pskb_pull_tail,
__pskb_pull,
pskb_pull
};
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = {
skb_pull,
__skb_pull,
skb_pull_inline,
__pskb_pull_tail,
__pskb_pull,
pskb_pull
};
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 12:29:22 +00:00
|
|
|
void *__pskb_pull_tail(struct sk_buff *skb, int delta)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
/* If skb has not enough free space at tail, get new one
|
|
|
|
* plus 128 bytes for future expansions. If we have enough
|
|
|
|
* room at tail, reallocate without expansion only if skb is cloned.
|
|
|
|
*/
|
2007-04-20 03:43:29 +00:00
|
|
|
int i, k, eat = (skb->tail + delta) - skb->end;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (eat > 0 || skb_cloned(skb)) {
|
|
|
|
if (pskb_expand_head(skb, 0, eat > 0 ? eat + 128 : 0,
|
|
|
|
GFP_ATOMIC))
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-10-09 15:37:59 +00:00
|
|
|
BUG_ON(skb_copy_bits(skb, skb_headlen(skb),
|
|
|
|
skb_tail_pointer(skb), delta));
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Optimization: no fragments, no reasons to preestimate
|
|
|
|
* size of pulled pages. Superb.
|
|
|
|
*/
|
2010-08-23 07:13:46 +00:00
|
|
|
if (!skb_has_frag_list(skb))
|
2005-04-16 22:20:36 +00:00
|
|
|
goto pull_pages;
|
|
|
|
|
|
|
|
/* Estimate size of pulled pages. */
|
|
|
|
eat = delta;
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
2011-10-18 21:00:24 +00:00
|
|
|
int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
|
|
|
|
|
|
|
|
if (size >= eat)
|
2005-04-16 22:20:36 +00:00
|
|
|
goto pull_pages;
|
2011-10-18 21:00:24 +00:00
|
|
|
eat -= size;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If we need update frag list, we are in troubles.
|
2017-10-14 16:51:36 +00:00
|
|
|
* Certainly, it is possible to add an offset to skb data,
|
2005-04-16 22:20:36 +00:00
|
|
|
* but taking into account that pulling is expected to
|
|
|
|
* be very rare operation, it is worth to fight against
|
|
|
|
* further bloating skb head and crucify ourselves here instead.
|
|
|
|
* Pure masohism, indeed. 8)8)
|
|
|
|
*/
|
|
|
|
if (eat) {
|
|
|
|
struct sk_buff *list = skb_shinfo(skb)->frag_list;
|
|
|
|
struct sk_buff *clone = NULL;
|
|
|
|
struct sk_buff *insp = NULL;
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (list->len <= eat) {
|
|
|
|
/* Eaten as whole. */
|
|
|
|
eat -= list->len;
|
|
|
|
list = list->next;
|
|
|
|
insp = list;
|
|
|
|
} else {
|
|
|
|
/* Eaten partially. */
|
2022-12-15 06:11:58 +00:00
|
|
|
if (skb_is_gso(skb) && !list->head_frag &&
|
|
|
|
skb_headlen(list))
|
|
|
|
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (skb_shared(list)) {
|
|
|
|
/* Sucks! We need to fork list. :-( */
|
|
|
|
clone = skb_clone(list, GFP_ATOMIC);
|
|
|
|
if (!clone)
|
|
|
|
return NULL;
|
|
|
|
insp = list->next;
|
|
|
|
list = clone;
|
|
|
|
} else {
|
|
|
|
/* This may be pulled without
|
|
|
|
* problems. */
|
|
|
|
insp = list;
|
|
|
|
}
|
|
|
|
if (!pskb_pull(list, eat)) {
|
2009-02-25 00:37:32 +00:00
|
|
|
kfree_skb(clone);
|
2005-04-16 22:20:36 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (eat);
|
|
|
|
|
|
|
|
/* Free pulled out fragments. */
|
|
|
|
while ((list = skb_shinfo(skb)->frag_list) != insp) {
|
|
|
|
skb_shinfo(skb)->frag_list = list->next;
|
2022-02-20 15:40:52 +00:00
|
|
|
consume_skb(list);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
/* And insert new clone at head. */
|
|
|
|
if (clone) {
|
|
|
|
clone->next = list;
|
|
|
|
skb_shinfo(skb)->frag_list = clone;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Success! Now we may commit changes to skb data. */
|
|
|
|
|
|
|
|
pull_pages:
|
|
|
|
eat = delta;
|
|
|
|
k = 0;
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
2011-10-18 21:00:24 +00:00
|
|
|
int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
|
|
|
|
|
|
|
|
if (size <= eat) {
|
2011-08-22 23:44:58 +00:00
|
|
|
skb_frag_unref(skb, i);
|
2011-10-18 21:00:24 +00:00
|
|
|
eat -= size;
|
2005-04-16 22:20:36 +00:00
|
|
|
} else {
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[k];
|
|
|
|
|
|
|
|
*frag = skb_shinfo(skb)->frags[i];
|
2005-04-16 22:20:36 +00:00
|
|
|
if (eat) {
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off_add(frag, eat);
|
|
|
|
skb_frag_size_sub(frag, eat);
|
2017-07-17 09:25:02 +00:00
|
|
|
if (!i)
|
|
|
|
goto end;
|
2005-04-16 22:20:36 +00:00
|
|
|
eat = 0;
|
|
|
|
}
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
skb_shinfo(skb)->nr_frags = k;
|
|
|
|
|
2017-07-17 09:25:02 +00:00
|
|
|
end:
|
2005-04-16 22:20:36 +00:00
|
|
|
skb->tail += delta;
|
|
|
|
skb->data_len -= delta;
|
|
|
|
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
if (!skb->data_len)
|
|
|
|
skb_zcopy_clear(skb, false);
|
|
|
|
|
2007-04-20 03:29:13 +00:00
|
|
|
return skb_tail_pointer(skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(__pskb_pull_tail);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-07-29 18:37:31 +00:00
|
|
|
/**
|
|
|
|
* skb_copy_bits - copy bits from skb to kernel buffer
|
|
|
|
* @skb: source skb
|
|
|
|
* @offset: offset in source
|
|
|
|
* @to: destination buffer
|
|
|
|
* @len: number of bytes to copy
|
|
|
|
*
|
|
|
|
* Copy the specified number of bytes from the source skb to the
|
|
|
|
* destination buffer.
|
|
|
|
*
|
|
|
|
* CAUTION ! :
|
|
|
|
* If its prototype is ever changed,
|
|
|
|
* check arch/{*}/net/{*}.S files,
|
|
|
|
* since it is called from BPF assembly code.
|
|
|
|
*/
|
2005-04-16 22:20:36 +00:00
|
|
|
int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
|
|
|
|
{
|
2007-04-27 22:21:23 +00:00
|
|
|
int start = skb_headlen(skb);
|
2009-06-09 07:18:59 +00:00
|
|
|
struct sk_buff *frag_iter;
|
|
|
|
int i, copy;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (offset > (int)skb->len - len)
|
|
|
|
goto fault;
|
|
|
|
|
|
|
|
/* Copy header. */
|
2007-04-27 22:21:23 +00:00
|
|
|
if ((copy = start - offset) > 0) {
|
2005-04-16 22:20:36 +00:00
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
2007-03-27 21:55:52 +00:00
|
|
|
skb_copy_from_linear_data_offset(skb, offset, to, copy);
|
2005-04-16 22:20:36 +00:00
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return 0;
|
|
|
|
offset += copy;
|
|
|
|
to += copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
2007-04-27 22:21:23 +00:00
|
|
|
int end;
|
2012-04-05 09:35:15 +00:00
|
|
|
skb_frag_t *f = &skb_shinfo(skb)->frags[i];
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-07-26 04:43:18 +00:00
|
|
|
WARN_ON(start > offset + len);
|
2007-04-27 22:21:23 +00:00
|
|
|
|
2012-04-05 09:35:15 +00:00
|
|
|
end = start + skb_frag_size(f);
|
2005-04-16 22:20:36 +00:00
|
|
|
if ((copy = end - offset) > 0) {
|
2017-07-31 12:15:47 +00:00
|
|
|
u32 p_off, p_len, copied;
|
|
|
|
struct page *p;
|
2005-04-16 22:20:36 +00:00
|
|
|
u8 *vaddr;
|
|
|
|
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
|
|
|
|
2017-07-31 12:15:47 +00:00
|
|
|
skb_frag_foreach_page(f,
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off(f) + offset - start,
|
2017-07-31 12:15:47 +00:00
|
|
|
copy, p, p_off, p_len, copied) {
|
|
|
|
vaddr = kmap_atomic(p);
|
|
|
|
memcpy(to + copied, vaddr + p_off, p_len);
|
|
|
|
kunmap_atomic(vaddr);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return 0;
|
|
|
|
offset += copy;
|
|
|
|
to += copy;
|
|
|
|
}
|
2007-04-27 22:21:23 +00:00
|
|
|
start = end;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
skb_walk_frags(skb, frag_iter) {
|
|
|
|
int end;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
WARN_ON(start > offset + len);
|
|
|
|
|
|
|
|
end = start + frag_iter->len;
|
|
|
|
if ((copy = end - offset) > 0) {
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
|
|
|
if (skb_copy_bits(frag_iter, offset - start, to, copy))
|
|
|
|
goto fault;
|
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return 0;
|
|
|
|
offset += copy;
|
|
|
|
to += copy;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-06-09 07:18:59 +00:00
|
|
|
start = end;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2011-07-06 12:22:12 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!len)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fault:
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_copy_bits);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-11-07 07:30:13 +00:00
|
|
|
/*
|
|
|
|
* Callback from splice_to_pipe(), if we need to release some pages
|
|
|
|
* at the end of the spd in case we error'ed out in filling the pipe.
|
|
|
|
*/
|
|
|
|
static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
|
|
|
|
{
|
2009-01-20 01:03:56 +00:00
|
|
|
put_page(spd->pages[i]);
|
|
|
|
}
|
2007-11-07 07:30:13 +00:00
|
|
|
|
2012-04-24 03:06:11 +00:00
|
|
|
static struct page *linear_to_page(struct page *page, unsigned int *len,
|
|
|
|
unsigned int *offset,
|
2013-01-11 14:46:37 +00:00
|
|
|
struct sock *sk)
|
2009-01-20 01:03:56 +00:00
|
|
|
{
|
net: use a per task frag allocator
We currently use a per socket order-0 page cache for tcp_sendmsg()
operations.
This page is used to build fragments for skbs.
Its done to increase probability of coalescing small write() into
single segments in skbs still in write queue (not yet sent)
But it wastes a lot of memory for applications handling many mostly
idle sockets, since each socket holds one page in sk->sk_sndmsg_page
Its also quite inefficient to build TSO 64KB packets, because we need
about 16 pages per skb on arches where PAGE_SIZE = 4096, so we hit
page allocator more than wanted.
This patch adds a per task frag allocator and uses bigger pages,
if available. An automatic fallback is done in case of memory pressure.
(up to 32768 bytes per frag, thats order-3 pages on x86)
This increases TCP stream performance by 20% on loopback device,
but also benefits on other network devices, since 8x less frags are
mapped on transmit and unmapped on tx completion. Alexander Duyck
mentioned a probable performance win on systems with IOMMU enabled.
Its possible some SG enabled hardware cant cope with bigger fragments,
but their ndo_start_xmit() should already handle this, splitting a
fragment in sub fragments, since some arches have PAGE_SIZE=65536
Successfully tested on various ethernet devices.
(ixgbe, igb, bnx2x, tg3, mellanox mlx4)
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Vijay Subramanian <subramanian.vijay@gmail.com>
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Vijay Subramanian <subramanian.vijay@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-09-23 23:04:42 +00:00
|
|
|
struct page_frag *pfrag = sk_page_frag(sk);
|
2009-02-01 08:41:42 +00:00
|
|
|
|
net: use a per task frag allocator
We currently use a per socket order-0 page cache for tcp_sendmsg()
operations.
This page is used to build fragments for skbs.
Its done to increase probability of coalescing small write() into
single segments in skbs still in write queue (not yet sent)
But it wastes a lot of memory for applications handling many mostly
idle sockets, since each socket holds one page in sk->sk_sndmsg_page
Its also quite inefficient to build TSO 64KB packets, because we need
about 16 pages per skb on arches where PAGE_SIZE = 4096, so we hit
page allocator more than wanted.
This patch adds a per task frag allocator and uses bigger pages,
if available. An automatic fallback is done in case of memory pressure.
(up to 32768 bytes per frag, thats order-3 pages on x86)
This increases TCP stream performance by 20% on loopback device,
but also benefits on other network devices, since 8x less frags are
mapped on transmit and unmapped on tx completion. Alexander Duyck
mentioned a probable performance win on systems with IOMMU enabled.
Its possible some SG enabled hardware cant cope with bigger fragments,
but their ndo_start_xmit() should already handle this, splitting a
fragment in sub fragments, since some arches have PAGE_SIZE=65536
Successfully tested on various ethernet devices.
(ixgbe, igb, bnx2x, tg3, mellanox mlx4)
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Vijay Subramanian <subramanian.vijay@gmail.com>
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Vijay Subramanian <subramanian.vijay@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-09-23 23:04:42 +00:00
|
|
|
if (!sk_page_frag_refill(sk, pfrag))
|
|
|
|
return NULL;
|
2009-02-01 08:41:42 +00:00
|
|
|
|
net: use a per task frag allocator
We currently use a per socket order-0 page cache for tcp_sendmsg()
operations.
This page is used to build fragments for skbs.
Its done to increase probability of coalescing small write() into
single segments in skbs still in write queue (not yet sent)
But it wastes a lot of memory for applications handling many mostly
idle sockets, since each socket holds one page in sk->sk_sndmsg_page
Its also quite inefficient to build TSO 64KB packets, because we need
about 16 pages per skb on arches where PAGE_SIZE = 4096, so we hit
page allocator more than wanted.
This patch adds a per task frag allocator and uses bigger pages,
if available. An automatic fallback is done in case of memory pressure.
(up to 32768 bytes per frag, thats order-3 pages on x86)
This increases TCP stream performance by 20% on loopback device,
but also benefits on other network devices, since 8x less frags are
mapped on transmit and unmapped on tx completion. Alexander Duyck
mentioned a probable performance win on systems with IOMMU enabled.
Its possible some SG enabled hardware cant cope with bigger fragments,
but their ndo_start_xmit() should already handle this, splitting a
fragment in sub fragments, since some arches have PAGE_SIZE=65536
Successfully tested on various ethernet devices.
(ixgbe, igb, bnx2x, tg3, mellanox mlx4)
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Vijay Subramanian <subramanian.vijay@gmail.com>
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Vijay Subramanian <subramanian.vijay@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-09-23 23:04:42 +00:00
|
|
|
*len = min_t(unsigned int, *len, pfrag->size - pfrag->offset);
|
2009-02-01 08:41:42 +00:00
|
|
|
|
net: use a per task frag allocator
We currently use a per socket order-0 page cache for tcp_sendmsg()
operations.
This page is used to build fragments for skbs.
Its done to increase probability of coalescing small write() into
single segments in skbs still in write queue (not yet sent)
But it wastes a lot of memory for applications handling many mostly
idle sockets, since each socket holds one page in sk->sk_sndmsg_page
Its also quite inefficient to build TSO 64KB packets, because we need
about 16 pages per skb on arches where PAGE_SIZE = 4096, so we hit
page allocator more than wanted.
This patch adds a per task frag allocator and uses bigger pages,
if available. An automatic fallback is done in case of memory pressure.
(up to 32768 bytes per frag, thats order-3 pages on x86)
This increases TCP stream performance by 20% on loopback device,
but also benefits on other network devices, since 8x less frags are
mapped on transmit and unmapped on tx completion. Alexander Duyck
mentioned a probable performance win on systems with IOMMU enabled.
Its possible some SG enabled hardware cant cope with bigger fragments,
but their ndo_start_xmit() should already handle this, splitting a
fragment in sub fragments, since some arches have PAGE_SIZE=65536
Successfully tested on various ethernet devices.
(ixgbe, igb, bnx2x, tg3, mellanox mlx4)
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Vijay Subramanian <subramanian.vijay@gmail.com>
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Vijay Subramanian <subramanian.vijay@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-09-23 23:04:42 +00:00
|
|
|
memcpy(page_address(pfrag->page) + pfrag->offset,
|
|
|
|
page_address(page) + *offset, *len);
|
|
|
|
*offset = pfrag->offset;
|
|
|
|
pfrag->offset += *len;
|
2009-01-20 01:03:56 +00:00
|
|
|
|
net: use a per task frag allocator
We currently use a per socket order-0 page cache for tcp_sendmsg()
operations.
This page is used to build fragments for skbs.
Its done to increase probability of coalescing small write() into
single segments in skbs still in write queue (not yet sent)
But it wastes a lot of memory for applications handling many mostly
idle sockets, since each socket holds one page in sk->sk_sndmsg_page
Its also quite inefficient to build TSO 64KB packets, because we need
about 16 pages per skb on arches where PAGE_SIZE = 4096, so we hit
page allocator more than wanted.
This patch adds a per task frag allocator and uses bigger pages,
if available. An automatic fallback is done in case of memory pressure.
(up to 32768 bytes per frag, thats order-3 pages on x86)
This increases TCP stream performance by 20% on loopback device,
but also benefits on other network devices, since 8x less frags are
mapped on transmit and unmapped on tx completion. Alexander Duyck
mentioned a probable performance win on systems with IOMMU enabled.
Its possible some SG enabled hardware cant cope with bigger fragments,
but their ndo_start_xmit() should already handle this, splitting a
fragment in sub fragments, since some arches have PAGE_SIZE=65536
Successfully tested on various ethernet devices.
(ixgbe, igb, bnx2x, tg3, mellanox mlx4)
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Vijay Subramanian <subramanian.vijay@gmail.com>
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Vijay Subramanian <subramanian.vijay@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2012-09-23 23:04:42 +00:00
|
|
|
return pfrag->page;
|
2007-11-07 07:30:13 +00:00
|
|
|
}
|
|
|
|
|
2012-04-22 12:26:16 +00:00
|
|
|
static bool spd_can_coalesce(const struct splice_pipe_desc *spd,
|
|
|
|
struct page *page,
|
|
|
|
unsigned int offset)
|
|
|
|
{
|
|
|
|
return spd->nr_pages &&
|
|
|
|
spd->pages[spd->nr_pages - 1] == page &&
|
|
|
|
(spd->partial[spd->nr_pages - 1].offset +
|
|
|
|
spd->partial[spd->nr_pages - 1].len == offset);
|
|
|
|
}
|
|
|
|
|
2007-11-07 07:30:13 +00:00
|
|
|
/*
|
|
|
|
* Fill page/offset/length into spd, if it can hold more pages.
|
|
|
|
*/
|
2012-04-24 03:06:11 +00:00
|
|
|
static bool spd_fill_page(struct splice_pipe_desc *spd,
|
|
|
|
struct pipe_inode_info *pipe, struct page *page,
|
|
|
|
unsigned int *len, unsigned int offset,
|
2013-01-11 14:46:37 +00:00
|
|
|
bool linear,
|
2012-04-24 03:06:11 +00:00
|
|
|
struct sock *sk)
|
2007-11-07 07:30:13 +00:00
|
|
|
{
|
2012-04-22 12:26:16 +00:00
|
|
|
if (unlikely(spd->nr_pages == MAX_SKB_FRAGS))
|
2012-04-24 03:06:11 +00:00
|
|
|
return true;
|
2007-11-07 07:30:13 +00:00
|
|
|
|
2009-01-20 01:03:56 +00:00
|
|
|
if (linear) {
|
2013-01-11 14:46:37 +00:00
|
|
|
page = linear_to_page(page, len, &offset, sk);
|
2009-01-20 01:03:56 +00:00
|
|
|
if (!page)
|
2012-04-24 03:06:11 +00:00
|
|
|
return true;
|
2012-04-22 12:26:16 +00:00
|
|
|
}
|
|
|
|
if (spd_can_coalesce(spd, page, offset)) {
|
|
|
|
spd->partial[spd->nr_pages - 1].len += *len;
|
2012-04-24 03:06:11 +00:00
|
|
|
return false;
|
2012-04-22 12:26:16 +00:00
|
|
|
}
|
|
|
|
get_page(page);
|
2007-11-07 07:30:13 +00:00
|
|
|
spd->pages[spd->nr_pages] = page;
|
2009-02-01 08:41:42 +00:00
|
|
|
spd->partial[spd->nr_pages].len = *len;
|
2007-11-07 07:30:13 +00:00
|
|
|
spd->partial[spd->nr_pages].offset = offset;
|
|
|
|
spd->nr_pages++;
|
2009-01-20 01:03:56 +00:00
|
|
|
|
2012-04-24 03:06:11 +00:00
|
|
|
return false;
|
2007-11-07 07:30:13 +00:00
|
|
|
}
|
|
|
|
|
2012-04-24 03:06:11 +00:00
|
|
|
static bool __splice_segment(struct page *page, unsigned int poff,
|
|
|
|
unsigned int plen, unsigned int *off,
|
2013-01-11 14:46:37 +00:00
|
|
|
unsigned int *len,
|
2012-04-24 03:35:04 +00:00
|
|
|
struct splice_pipe_desc *spd, bool linear,
|
2012-04-24 03:06:11 +00:00
|
|
|
struct sock *sk,
|
|
|
|
struct pipe_inode_info *pipe)
|
2007-11-07 07:30:13 +00:00
|
|
|
{
|
2008-07-15 07:49:11 +00:00
|
|
|
if (!*len)
|
2012-04-24 03:06:11 +00:00
|
|
|
return true;
|
2008-07-15 07:49:11 +00:00
|
|
|
|
|
|
|
/* skip this segment if already processed */
|
|
|
|
if (*off >= plen) {
|
|
|
|
*off -= plen;
|
2012-04-24 03:06:11 +00:00
|
|
|
return false;
|
2008-06-28 00:27:21 +00:00
|
|
|
}
|
2007-11-07 07:30:13 +00:00
|
|
|
|
2008-07-15 07:49:11 +00:00
|
|
|
/* ignore any bits we already processed */
|
2013-01-05 21:31:18 +00:00
|
|
|
poff += *off;
|
|
|
|
plen -= *off;
|
|
|
|
*off = 0;
|
2007-11-07 07:30:13 +00:00
|
|
|
|
2013-01-11 14:46:37 +00:00
|
|
|
do {
|
|
|
|
unsigned int flen = min(*len, plen);
|
2008-07-15 07:49:11 +00:00
|
|
|
|
2013-01-11 14:46:37 +00:00
|
|
|
if (spd_fill_page(spd, pipe, page, &flen, poff,
|
|
|
|
linear, sk))
|
|
|
|
return true;
|
|
|
|
poff += flen;
|
|
|
|
plen -= flen;
|
|
|
|
*len -= flen;
|
|
|
|
} while (*len && plen);
|
2008-07-15 07:49:11 +00:00
|
|
|
|
2012-04-24 03:06:11 +00:00
|
|
|
return false;
|
2008-07-15 07:49:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2012-04-24 03:06:11 +00:00
|
|
|
* Map linear and fragment data from the skb to spd. It reports true if the
|
2008-07-15 07:49:11 +00:00
|
|
|
* pipe is full or if we already spliced the requested length.
|
|
|
|
*/
|
2012-04-24 03:06:11 +00:00
|
|
|
static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
|
|
|
|
unsigned int *offset, unsigned int *len,
|
|
|
|
struct splice_pipe_desc *spd, struct sock *sk)
|
2008-07-15 07:49:11 +00:00
|
|
|
{
|
|
|
|
int seg;
|
2016-03-07 22:11:04 +00:00
|
|
|
struct sk_buff *iter;
|
2008-07-15 07:49:11 +00:00
|
|
|
|
2012-04-27 02:10:03 +00:00
|
|
|
/* map the linear part :
|
2012-05-02 18:18:42 +00:00
|
|
|
* If skb->head_frag is set, this 'linear' part is backed by a
|
|
|
|
* fragment, and if the head is not shared with any clones then
|
|
|
|
* we can avoid a copy since we own the head portion of this page.
|
2008-07-15 07:49:11 +00:00
|
|
|
*/
|
|
|
|
if (__splice_segment(virt_to_page(skb->data),
|
|
|
|
(unsigned long) skb->data & (PAGE_SIZE - 1),
|
|
|
|
skb_headlen(skb),
|
2013-01-11 14:46:37 +00:00
|
|
|
offset, len, spd,
|
2012-05-03 01:09:42 +00:00
|
|
|
skb_head_is_locked(skb),
|
2012-04-27 02:10:03 +00:00
|
|
|
sk, pipe))
|
2012-04-24 03:06:11 +00:00
|
|
|
return true;
|
2007-11-07 07:30:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* then map the fragments
|
|
|
|
*/
|
|
|
|
for (seg = 0; seg < skb_shinfo(skb)->nr_frags; seg++) {
|
|
|
|
const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
|
|
|
|
|
2011-08-22 23:44:58 +00:00
|
|
|
if (__splice_segment(skb_frag_page(f),
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off(f), skb_frag_size(f),
|
2013-01-11 14:46:37 +00:00
|
|
|
offset, len, spd, false, sk, pipe))
|
2012-04-24 03:06:11 +00:00
|
|
|
return true;
|
2007-11-07 07:30:13 +00:00
|
|
|
}
|
|
|
|
|
2016-03-07 22:11:04 +00:00
|
|
|
skb_walk_frags(skb, iter) {
|
|
|
|
if (*offset >= iter->len) {
|
|
|
|
*offset -= iter->len;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* __skb_splice_bits() only fails if the output has no room
|
|
|
|
* left, so no point in going over the frag_list for the error
|
|
|
|
* case.
|
|
|
|
*/
|
|
|
|
if (__skb_splice_bits(iter, pipe, offset, len, spd, sk))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-04-24 03:06:11 +00:00
|
|
|
return false;
|
2007-11-07 07:30:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Map data from the skb to a pipe. Should handle both the linear part,
|
2016-03-07 22:11:04 +00:00
|
|
|
* the fragments, and the frag list.
|
2007-11-07 07:30:13 +00:00
|
|
|
*/
|
2015-05-21 15:00:00 +00:00
|
|
|
int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset,
|
2007-11-07 07:30:13 +00:00
|
|
|
struct pipe_inode_info *pipe, unsigned int tlen,
|
2016-09-18 01:02:10 +00:00
|
|
|
unsigned int flags)
|
2007-11-07 07:30:13 +00:00
|
|
|
{
|
2012-04-22 12:26:16 +00:00
|
|
|
struct partial_page partial[MAX_SKB_FRAGS];
|
|
|
|
struct page *pages[MAX_SKB_FRAGS];
|
2007-11-07 07:30:13 +00:00
|
|
|
struct splice_pipe_desc spd = {
|
|
|
|
.pages = pages,
|
|
|
|
.partial = partial,
|
2012-06-12 13:24:40 +00:00
|
|
|
.nr_pages_max = MAX_SKB_FRAGS,
|
2014-01-22 18:36:57 +00:00
|
|
|
.ops = &nosteal_pipe_buf_ops,
|
2007-11-07 07:30:13 +00:00
|
|
|
.spd_release = sock_spd_release,
|
|
|
|
};
|
2010-05-20 08:43:18 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
2016-03-07 22:11:04 +00:00
|
|
|
__skb_splice_bits(skb, pipe, &offset, &tlen, &spd, sk);
|
2007-11-07 07:30:13 +00:00
|
|
|
|
2015-05-21 15:00:00 +00:00
|
|
|
if (spd.nr_pages)
|
2016-09-18 01:02:10 +00:00
|
|
|
ret = splice_to_pipe(pipe, &spd);
|
2007-11-07 07:30:13 +00:00
|
|
|
|
2010-05-20 08:43:18 +00:00
|
|
|
return ret;
|
2007-11-07 07:30:13 +00:00
|
|
|
}
|
2015-05-21 15:00:01 +00:00
|
|
|
EXPORT_SYMBOL_GPL(skb_splice_bits);
|
2007-11-07 07:30:13 +00:00
|
|
|
|
2023-06-23 22:54:59 +00:00
|
|
|
static int sendmsg_locked(struct sock *sk, struct msghdr *msg)
|
2021-03-31 02:32:24 +00:00
|
|
|
{
|
|
|
|
struct socket *sock = sk->sk_socket;
|
2023-06-23 22:54:59 +00:00
|
|
|
size_t size = msg_data_left(msg);
|
2021-03-31 02:32:24 +00:00
|
|
|
|
|
|
|
if (!sock)
|
|
|
|
return -EINVAL;
|
2023-06-23 22:54:59 +00:00
|
|
|
|
|
|
|
if (!sock->ops->sendmsg_locked)
|
|
|
|
return sock_no_sendmsg_locked(sk, msg, size);
|
|
|
|
|
|
|
|
return sock->ops->sendmsg_locked(sk, msg, size);
|
2021-03-31 02:32:24 +00:00
|
|
|
}
|
|
|
|
|
2023-06-23 22:54:59 +00:00
|
|
|
static int sendmsg_unlocked(struct sock *sk, struct msghdr *msg)
|
2021-03-31 02:32:24 +00:00
|
|
|
{
|
|
|
|
struct socket *sock = sk->sk_socket;
|
|
|
|
|
|
|
|
if (!sock)
|
|
|
|
return -EINVAL;
|
2023-06-23 22:54:59 +00:00
|
|
|
return sock_sendmsg(sock, msg);
|
2021-03-31 02:32:24 +00:00
|
|
|
}
|
|
|
|
|
2023-06-23 22:54:59 +00:00
|
|
|
typedef int (*sendmsg_func)(struct sock *sk, struct msghdr *msg);
|
2021-03-31 02:32:24 +00:00
|
|
|
static int __skb_send_sock(struct sock *sk, struct sk_buff *skb, int offset,
|
2023-06-23 22:54:59 +00:00
|
|
|
int len, sendmsg_func sendmsg)
|
2017-07-28 23:22:42 +00:00
|
|
|
{
|
|
|
|
unsigned int orig_len = len;
|
|
|
|
struct sk_buff *head = skb;
|
|
|
|
unsigned short fragidx;
|
|
|
|
int slen, ret;
|
|
|
|
|
|
|
|
do_frag_list:
|
|
|
|
|
|
|
|
/* Deal with head data */
|
|
|
|
while (offset < skb_headlen(skb) && len) {
|
|
|
|
struct kvec kv;
|
|
|
|
struct msghdr msg;
|
|
|
|
|
|
|
|
slen = min_t(int, len, skb_headlen(skb) - offset);
|
|
|
|
kv.iov_base = skb->data + offset;
|
2017-08-16 05:31:34 +00:00
|
|
|
kv.iov_len = slen;
|
2017-07-28 23:22:42 +00:00
|
|
|
memset(&msg, 0, sizeof(msg));
|
2019-05-24 15:01:00 +00:00
|
|
|
msg.msg_flags = MSG_DONTWAIT;
|
2017-07-28 23:22:42 +00:00
|
|
|
|
2023-06-23 22:54:59 +00:00
|
|
|
iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &kv, 1, slen);
|
|
|
|
ret = INDIRECT_CALL_2(sendmsg, sendmsg_locked,
|
|
|
|
sendmsg_unlocked, sk, &msg);
|
2017-07-28 23:22:42 +00:00
|
|
|
if (ret <= 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
offset += ret;
|
|
|
|
len -= ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All the data was skb head? */
|
|
|
|
if (!len)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Make offset relative to start of frags */
|
|
|
|
offset -= skb_headlen(skb);
|
|
|
|
|
|
|
|
/* Find where we are in frag list */
|
|
|
|
for (fragidx = 0; fragidx < skb_shinfo(skb)->nr_frags; fragidx++) {
|
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[fragidx];
|
|
|
|
|
2019-07-23 03:08:26 +00:00
|
|
|
if (offset < skb_frag_size(frag))
|
2017-07-28 23:22:42 +00:00
|
|
|
break;
|
|
|
|
|
2019-07-23 03:08:26 +00:00
|
|
|
offset -= skb_frag_size(frag);
|
2017-07-28 23:22:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (; len && fragidx < skb_shinfo(skb)->nr_frags; fragidx++) {
|
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[fragidx];
|
|
|
|
|
2019-07-23 03:08:26 +00:00
|
|
|
slen = min_t(size_t, len, skb_frag_size(frag) - offset);
|
2017-07-28 23:22:42 +00:00
|
|
|
|
|
|
|
while (slen) {
|
2023-06-23 22:54:59 +00:00
|
|
|
struct bio_vec bvec;
|
|
|
|
struct msghdr msg = {
|
|
|
|
.msg_flags = MSG_SPLICE_PAGES | MSG_DONTWAIT,
|
|
|
|
};
|
|
|
|
|
|
|
|
bvec_set_page(&bvec, skb_frag_page(frag), slen,
|
|
|
|
skb_frag_off(frag) + offset);
|
|
|
|
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1,
|
|
|
|
slen);
|
|
|
|
|
|
|
|
ret = INDIRECT_CALL_2(sendmsg, sendmsg_locked,
|
|
|
|
sendmsg_unlocked, sk, &msg);
|
2017-07-28 23:22:42 +00:00
|
|
|
if (ret <= 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
len -= ret;
|
|
|
|
offset += ret;
|
|
|
|
slen -= ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len) {
|
|
|
|
/* Process any frag lists */
|
|
|
|
|
|
|
|
if (skb == head) {
|
|
|
|
if (skb_has_frag_list(skb)) {
|
|
|
|
skb = skb_shinfo(skb)->frag_list;
|
|
|
|
goto do_frag_list;
|
|
|
|
}
|
|
|
|
} else if (skb->next) {
|
|
|
|
skb = skb->next;
|
|
|
|
goto do_frag_list;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
return orig_len - len;
|
|
|
|
|
|
|
|
error:
|
|
|
|
return orig_len == len ? ret : orig_len - len;
|
|
|
|
}
|
2021-03-31 02:32:24 +00:00
|
|
|
|
|
|
|
/* Send skb data on a socket. Socket must be locked. */
|
|
|
|
int skb_send_sock_locked(struct sock *sk, struct sk_buff *skb, int offset,
|
|
|
|
int len)
|
|
|
|
{
|
2023-06-23 22:54:59 +00:00
|
|
|
return __skb_send_sock(sk, skb, offset, len, sendmsg_locked);
|
2021-03-31 02:32:24 +00:00
|
|
|
}
|
2017-07-28 23:22:42 +00:00
|
|
|
EXPORT_SYMBOL_GPL(skb_send_sock_locked);
|
|
|
|
|
2021-03-31 02:32:24 +00:00
|
|
|
/* Send skb data on a socket. Socket must be unlocked. */
|
|
|
|
int skb_send_sock(struct sock *sk, struct sk_buff *skb, int offset, int len)
|
|
|
|
{
|
2023-06-23 22:54:59 +00:00
|
|
|
return __skb_send_sock(sk, skb, offset, len, sendmsg_unlocked);
|
2021-03-31 02:32:24 +00:00
|
|
|
}
|
|
|
|
|
2005-04-20 05:30:14 +00:00
|
|
|
/**
|
|
|
|
* skb_store_bits - store bits from kernel buffer to skb
|
|
|
|
* @skb: destination buffer
|
|
|
|
* @offset: offset in destination
|
|
|
|
* @from: source buffer
|
|
|
|
* @len: number of bytes to copy
|
|
|
|
*
|
|
|
|
* Copy the specified number of bytes from the source buffer to the
|
|
|
|
* destination skb. This function handles all the messy bits of
|
|
|
|
* traversing fragment lists and such.
|
|
|
|
*/
|
|
|
|
|
2007-04-20 23:40:01 +00:00
|
|
|
int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
|
2005-04-20 05:30:14 +00:00
|
|
|
{
|
2007-04-27 22:21:23 +00:00
|
|
|
int start = skb_headlen(skb);
|
2009-06-09 07:18:59 +00:00
|
|
|
struct sk_buff *frag_iter;
|
|
|
|
int i, copy;
|
2005-04-20 05:30:14 +00:00
|
|
|
|
|
|
|
if (offset > (int)skb->len - len)
|
|
|
|
goto fault;
|
|
|
|
|
2007-04-27 22:21:23 +00:00
|
|
|
if ((copy = start - offset) > 0) {
|
2005-04-20 05:30:14 +00:00
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
2007-03-31 14:55:19 +00:00
|
|
|
skb_copy_to_linear_data_offset(skb, offset, from, copy);
|
2005-04-20 05:30:14 +00:00
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return 0;
|
|
|
|
offset += copy;
|
|
|
|
from += copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
2007-04-27 22:21:23 +00:00
|
|
|
int end;
|
|
|
|
|
2008-07-26 04:43:18 +00:00
|
|
|
WARN_ON(start > offset + len);
|
2005-04-20 05:30:14 +00:00
|
|
|
|
2011-10-18 21:00:24 +00:00
|
|
|
end = start + skb_frag_size(frag);
|
2005-04-20 05:30:14 +00:00
|
|
|
if ((copy = end - offset) > 0) {
|
2017-07-31 12:15:47 +00:00
|
|
|
u32 p_off, p_len, copied;
|
|
|
|
struct page *p;
|
2005-04-20 05:30:14 +00:00
|
|
|
u8 *vaddr;
|
|
|
|
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
|
|
|
|
2017-07-31 12:15:47 +00:00
|
|
|
skb_frag_foreach_page(frag,
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off(frag) + offset - start,
|
2017-07-31 12:15:47 +00:00
|
|
|
copy, p, p_off, p_len, copied) {
|
|
|
|
vaddr = kmap_atomic(p);
|
|
|
|
memcpy(vaddr + p_off, from + copied, p_len);
|
|
|
|
kunmap_atomic(vaddr);
|
|
|
|
}
|
2005-04-20 05:30:14 +00:00
|
|
|
|
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return 0;
|
|
|
|
offset += copy;
|
|
|
|
from += copy;
|
|
|
|
}
|
2007-04-27 22:21:23 +00:00
|
|
|
start = end;
|
2005-04-20 05:30:14 +00:00
|
|
|
}
|
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
skb_walk_frags(skb, frag_iter) {
|
|
|
|
int end;
|
2005-04-20 05:30:14 +00:00
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
WARN_ON(start > offset + len);
|
|
|
|
|
|
|
|
end = start + frag_iter->len;
|
|
|
|
if ((copy = end - offset) > 0) {
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
|
|
|
if (skb_store_bits(frag_iter, offset - start,
|
|
|
|
from, copy))
|
|
|
|
goto fault;
|
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return 0;
|
|
|
|
offset += copy;
|
|
|
|
from += copy;
|
2005-04-20 05:30:14 +00:00
|
|
|
}
|
2009-06-09 07:18:59 +00:00
|
|
|
start = end;
|
2005-04-20 05:30:14 +00:00
|
|
|
}
|
|
|
|
if (!len)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fault:
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_store_bits);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* Checksum skb data. */
|
2013-10-30 10:50:51 +00:00
|
|
|
__wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
|
|
|
|
__wsum csum, const struct skb_checksum_ops *ops)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2007-04-27 22:21:23 +00:00
|
|
|
int start = skb_headlen(skb);
|
|
|
|
int i, copy = start - offset;
|
2009-06-09 07:18:59 +00:00
|
|
|
struct sk_buff *frag_iter;
|
2005-04-16 22:20:36 +00:00
|
|
|
int pos = 0;
|
|
|
|
|
|
|
|
/* Checksum header. */
|
|
|
|
if (copy > 0) {
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
2019-05-29 15:13:48 +00:00
|
|
|
csum = INDIRECT_CALL_1(ops->update, csum_partial_ext,
|
|
|
|
skb->data + offset, copy, csum);
|
2005-04-16 22:20:36 +00:00
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return csum;
|
|
|
|
offset += copy;
|
|
|
|
pos = copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
2007-04-27 22:21:23 +00:00
|
|
|
int end;
|
2012-04-05 09:35:15 +00:00
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
2007-04-27 22:21:23 +00:00
|
|
|
|
2008-07-26 04:43:18 +00:00
|
|
|
WARN_ON(start > offset + len);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-04-05 09:35:15 +00:00
|
|
|
end = start + skb_frag_size(frag);
|
2005-04-16 22:20:36 +00:00
|
|
|
if ((copy = end - offset) > 0) {
|
2017-07-31 12:15:47 +00:00
|
|
|
u32 p_off, p_len, copied;
|
|
|
|
struct page *p;
|
2006-11-15 05:36:14 +00:00
|
|
|
__wsum csum2;
|
2005-04-16 22:20:36 +00:00
|
|
|
u8 *vaddr;
|
|
|
|
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
2017-07-31 12:15:47 +00:00
|
|
|
|
|
|
|
skb_frag_foreach_page(frag,
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off(frag) + offset - start,
|
2017-07-31 12:15:47 +00:00
|
|
|
copy, p, p_off, p_len, copied) {
|
|
|
|
vaddr = kmap_atomic(p);
|
2019-05-29 15:13:48 +00:00
|
|
|
csum2 = INDIRECT_CALL_1(ops->update,
|
|
|
|
csum_partial_ext,
|
|
|
|
vaddr + p_off, p_len, 0);
|
2017-07-31 12:15:47 +00:00
|
|
|
kunmap_atomic(vaddr);
|
2019-05-29 15:13:48 +00:00
|
|
|
csum = INDIRECT_CALL_1(ops->combine,
|
|
|
|
csum_block_add_ext, csum,
|
|
|
|
csum2, pos, p_len);
|
2017-07-31 12:15:47 +00:00
|
|
|
pos += p_len;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!(len -= copy))
|
|
|
|
return csum;
|
|
|
|
offset += copy;
|
|
|
|
}
|
2007-04-27 22:21:23 +00:00
|
|
|
start = end;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
skb_walk_frags(skb, frag_iter) {
|
|
|
|
int end;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
WARN_ON(start > offset + len);
|
|
|
|
|
|
|
|
end = start + frag_iter->len;
|
|
|
|
if ((copy = end - offset) > 0) {
|
|
|
|
__wsum csum2;
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
2013-10-30 10:50:51 +00:00
|
|
|
csum2 = __skb_checksum(frag_iter, offset - start,
|
|
|
|
copy, 0, ops);
|
2019-05-29 15:13:48 +00:00
|
|
|
csum = INDIRECT_CALL_1(ops->combine, csum_block_add_ext,
|
|
|
|
csum, csum2, pos, copy);
|
2009-06-09 07:18:59 +00:00
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return csum;
|
|
|
|
offset += copy;
|
|
|
|
pos += copy;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-06-09 07:18:59 +00:00
|
|
|
start = end;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2006-01-09 06:24:28 +00:00
|
|
|
BUG_ON(len);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
return csum;
|
|
|
|
}
|
2013-10-30 10:50:51 +00:00
|
|
|
EXPORT_SYMBOL(__skb_checksum);
|
|
|
|
|
|
|
|
__wsum skb_checksum(const struct sk_buff *skb, int offset,
|
|
|
|
int len, __wsum csum)
|
|
|
|
{
|
|
|
|
const struct skb_checksum_ops ops = {
|
2013-11-04 16:10:25 +00:00
|
|
|
.update = csum_partial_ext,
|
2013-10-30 10:50:51 +00:00
|
|
|
.combine = csum_block_add_ext,
|
|
|
|
};
|
|
|
|
|
|
|
|
return __skb_checksum(skb, offset, len, csum, &ops);
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_checksum);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Both of above in one bottle. */
|
|
|
|
|
2006-11-15 05:37:33 +00:00
|
|
|
__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
|
2020-07-11 00:07:10 +00:00
|
|
|
u8 *to, int len)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2007-04-27 22:21:23 +00:00
|
|
|
int start = skb_headlen(skb);
|
|
|
|
int i, copy = start - offset;
|
2009-06-09 07:18:59 +00:00
|
|
|
struct sk_buff *frag_iter;
|
2005-04-16 22:20:36 +00:00
|
|
|
int pos = 0;
|
2020-07-11 00:07:10 +00:00
|
|
|
__wsum csum = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* Copy header. */
|
|
|
|
if (copy > 0) {
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
|
|
|
csum = csum_partial_copy_nocheck(skb->data + offset, to,
|
2020-07-11 04:12:07 +00:00
|
|
|
copy);
|
2005-04-16 22:20:36 +00:00
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return csum;
|
|
|
|
offset += copy;
|
|
|
|
to += copy;
|
|
|
|
pos = copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
2007-04-27 22:21:23 +00:00
|
|
|
int end;
|
|
|
|
|
2008-07-26 04:43:18 +00:00
|
|
|
WARN_ON(start > offset + len);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-10-18 21:00:24 +00:00
|
|
|
end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]);
|
2005-04-16 22:20:36 +00:00
|
|
|
if ((copy = end - offset) > 0) {
|
2017-07-31 12:15:47 +00:00
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
|
|
|
u32 p_off, p_len, copied;
|
|
|
|
struct page *p;
|
2006-11-15 05:36:34 +00:00
|
|
|
__wsum csum2;
|
2005-04-16 22:20:36 +00:00
|
|
|
u8 *vaddr;
|
|
|
|
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
2017-07-31 12:15:47 +00:00
|
|
|
|
|
|
|
skb_frag_foreach_page(frag,
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off(frag) + offset - start,
|
2017-07-31 12:15:47 +00:00
|
|
|
copy, p, p_off, p_len, copied) {
|
|
|
|
vaddr = kmap_atomic(p);
|
|
|
|
csum2 = csum_partial_copy_nocheck(vaddr + p_off,
|
|
|
|
to + copied,
|
2020-07-11 04:12:07 +00:00
|
|
|
p_len);
|
2017-07-31 12:15:47 +00:00
|
|
|
kunmap_atomic(vaddr);
|
|
|
|
csum = csum_block_add(csum, csum2, pos);
|
|
|
|
pos += p_len;
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!(len -= copy))
|
|
|
|
return csum;
|
|
|
|
offset += copy;
|
|
|
|
to += copy;
|
|
|
|
}
|
2007-04-27 22:21:23 +00:00
|
|
|
start = end;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
skb_walk_frags(skb, frag_iter) {
|
|
|
|
__wsum csum2;
|
|
|
|
int end;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
WARN_ON(start > offset + len);
|
|
|
|
|
|
|
|
end = start + frag_iter->len;
|
|
|
|
if ((copy = end - offset) > 0) {
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
|
|
|
csum2 = skb_copy_and_csum_bits(frag_iter,
|
|
|
|
offset - start,
|
2020-07-11 00:07:10 +00:00
|
|
|
to, copy);
|
2009-06-09 07:18:59 +00:00
|
|
|
csum = csum_block_add(csum, csum2, pos);
|
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return csum;
|
|
|
|
offset += copy;
|
|
|
|
to += copy;
|
|
|
|
pos += copy;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-06-09 07:18:59 +00:00
|
|
|
start = end;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2006-01-09 06:24:28 +00:00
|
|
|
BUG_ON(len);
|
2005-04-16 22:20:36 +00:00
|
|
|
return csum;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_copy_and_csum_bits);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-11-08 22:05:42 +00:00
|
|
|
__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
|
|
|
|
{
|
|
|
|
__sum16 sum;
|
|
|
|
|
|
|
|
sum = csum_fold(skb_checksum(skb, 0, len, skb->csum));
|
2018-11-26 17:31:26 +00:00
|
|
|
/* See comments in __skb_checksum_complete(). */
|
2018-11-08 22:05:42 +00:00
|
|
|
if (likely(!sum)) {
|
|
|
|
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
|
|
|
|
!skb->csum_complete_sw)
|
2018-11-12 22:47:18 +00:00
|
|
|
netdev_rx_csum_fault(skb->dev, skb);
|
2018-11-08 22:05:42 +00:00
|
|
|
}
|
|
|
|
if (!skb_shared(skb))
|
|
|
|
skb->csum_valid = !sum;
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__skb_checksum_complete_head);
|
|
|
|
|
2018-11-26 17:31:26 +00:00
|
|
|
/* This function assumes skb->csum already holds pseudo header's checksum,
|
|
|
|
* which has been changed from the hardware checksum, for example, by
|
|
|
|
* __skb_checksum_validate_complete(). And, the original skb->csum must
|
|
|
|
* have been validated unsuccessfully for CHECKSUM_COMPLETE case.
|
|
|
|
*
|
|
|
|
* It returns non-zero if the recomputed checksum is still invalid, otherwise
|
|
|
|
* zero. The new checksum is stored back into skb->csum unless the skb is
|
|
|
|
* shared.
|
|
|
|
*/
|
2018-11-08 22:05:42 +00:00
|
|
|
__sum16 __skb_checksum_complete(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
__wsum csum;
|
|
|
|
__sum16 sum;
|
|
|
|
|
|
|
|
csum = skb_checksum(skb, 0, skb->len, 0);
|
|
|
|
|
|
|
|
sum = csum_fold(csum_add(skb->csum, csum));
|
2018-11-26 17:31:26 +00:00
|
|
|
/* This check is inverted, because we already knew the hardware
|
|
|
|
* checksum is invalid before calling this function. So, if the
|
|
|
|
* re-computed checksum is valid instead, then we have a mismatch
|
|
|
|
* between the original skb->csum and skb_checksum(). This means either
|
|
|
|
* the original hardware checksum is incorrect or we screw up skb->csum
|
|
|
|
* when moving skb->data around.
|
|
|
|
*/
|
2018-11-08 22:05:42 +00:00
|
|
|
if (likely(!sum)) {
|
|
|
|
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
|
|
|
|
!skb->csum_complete_sw)
|
2018-11-12 22:47:18 +00:00
|
|
|
netdev_rx_csum_fault(skb->dev, skb);
|
2018-11-08 22:05:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!skb_shared(skb)) {
|
|
|
|
/* Save full packet checksum */
|
|
|
|
skb->csum = csum;
|
|
|
|
skb->ip_summed = CHECKSUM_COMPLETE;
|
|
|
|
skb->csum_complete_sw = 1;
|
|
|
|
skb->csum_valid = !sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__skb_checksum_complete);
|
|
|
|
|
2017-05-18 13:44:37 +00:00
|
|
|
static __wsum warn_crc32c_csum_update(const void *buff, int len, __wsum sum)
|
|
|
|
{
|
|
|
|
net_warn_ratelimited(
|
|
|
|
"%s: attempt to compute crc32c without libcrc32c.ko\n",
|
|
|
|
__func__);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __wsum warn_crc32c_csum_combine(__wsum csum, __wsum csum2,
|
|
|
|
int offset, int len)
|
|
|
|
{
|
|
|
|
net_warn_ratelimited(
|
|
|
|
"%s: attempt to compute crc32c without libcrc32c.ko\n",
|
|
|
|
__func__);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct skb_checksum_ops default_crc32c_ops = {
|
|
|
|
.update = warn_crc32c_csum_update,
|
|
|
|
.combine = warn_crc32c_csum_combine,
|
|
|
|
};
|
|
|
|
|
|
|
|
const struct skb_checksum_ops *crc32c_csum_stub __read_mostly =
|
|
|
|
&default_crc32c_ops;
|
|
|
|
EXPORT_SYMBOL(crc32c_csum_stub);
|
|
|
|
|
2013-12-13 14:22:17 +00:00
|
|
|
/**
|
|
|
|
* skb_zerocopy_headlen - Calculate headroom needed for skb_zerocopy()
|
|
|
|
* @from: source buffer
|
|
|
|
*
|
|
|
|
* Calculates the amount of linear headroom needed in the 'to' skb passed
|
|
|
|
* into skb_zerocopy().
|
|
|
|
*/
|
|
|
|
unsigned int
|
|
|
|
skb_zerocopy_headlen(const struct sk_buff *from)
|
|
|
|
{
|
|
|
|
unsigned int hlen = 0;
|
|
|
|
|
|
|
|
if (!from->head_frag ||
|
|
|
|
skb_headlen(from) < L1_CACHE_BYTES ||
|
2021-07-15 23:59:00 +00:00
|
|
|
skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS) {
|
2013-12-13 14:22:17 +00:00
|
|
|
hlen = skb_headlen(from);
|
2021-07-15 23:59:00 +00:00
|
|
|
if (!hlen)
|
|
|
|
hlen = from->len;
|
|
|
|
}
|
2013-12-13 14:22:17 +00:00
|
|
|
|
|
|
|
if (skb_has_frag_list(from))
|
|
|
|
hlen = from->len;
|
|
|
|
|
|
|
|
return hlen;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_zerocopy_headlen);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_zerocopy - Zero copy skb to skb
|
|
|
|
* @to: destination buffer
|
2014-01-28 16:05:28 +00:00
|
|
|
* @from: source buffer
|
2013-12-13 14:22:17 +00:00
|
|
|
* @len: number of bytes to copy from source buffer
|
|
|
|
* @hlen: size of linear headroom in destination buffer
|
|
|
|
*
|
|
|
|
* Copies up to `len` bytes from `from` to `to` by creating references
|
|
|
|
* to the frags in the source buffer.
|
|
|
|
*
|
|
|
|
* The `hlen` as calculated by skb_zerocopy_headlen() specifies the
|
|
|
|
* headroom in the `to` buffer.
|
2014-03-26 22:37:45 +00:00
|
|
|
*
|
|
|
|
* Return value:
|
|
|
|
* 0: everything is OK
|
|
|
|
* -ENOMEM: couldn't orphan frags of @from due to lack of memory
|
|
|
|
* -EFAULT: skb_copy_bits() found some problem with skb geometry
|
2013-12-13 14:22:17 +00:00
|
|
|
*/
|
2014-03-26 22:37:45 +00:00
|
|
|
int
|
|
|
|
skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
|
2013-12-13 14:22:17 +00:00
|
|
|
{
|
|
|
|
int i, j = 0;
|
|
|
|
int plen = 0; /* length of skb->head fragment */
|
2014-03-26 22:37:45 +00:00
|
|
|
int ret;
|
2013-12-13 14:22:17 +00:00
|
|
|
struct page *page;
|
|
|
|
unsigned int offset;
|
|
|
|
|
|
|
|
BUG_ON(!from->head_frag && !hlen);
|
|
|
|
|
|
|
|
/* dont bother with small payloads */
|
2014-03-26 22:37:45 +00:00
|
|
|
if (len <= skb_tailroom(to))
|
|
|
|
return skb_copy_bits(from, 0, skb_put(to, len), len);
|
2013-12-13 14:22:17 +00:00
|
|
|
|
|
|
|
if (hlen) {
|
2014-03-26 22:37:45 +00:00
|
|
|
ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
|
|
|
|
if (unlikely(ret))
|
|
|
|
return ret;
|
2013-12-13 14:22:17 +00:00
|
|
|
len -= hlen;
|
|
|
|
} else {
|
|
|
|
plen = min_t(int, skb_headlen(from), len);
|
|
|
|
if (plen) {
|
|
|
|
page = virt_to_head_page(from->head);
|
|
|
|
offset = from->data - (unsigned char *)page_address(page);
|
2024-02-14 22:34:03 +00:00
|
|
|
__skb_fill_netmem_desc(to, 0, page_to_netmem(page),
|
|
|
|
offset, plen);
|
2013-12-13 14:22:17 +00:00
|
|
|
get_page(page);
|
|
|
|
j = 1;
|
|
|
|
len -= plen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-22 16:09:03 +00:00
|
|
|
skb_len_add(to, len + plen);
|
2013-12-13 14:22:17 +00:00
|
|
|
|
2014-03-26 22:37:45 +00:00
|
|
|
if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) {
|
|
|
|
skb_tx_error(from);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
skb_zerocopy_clone(to, from, GFP_ATOMIC);
|
2014-03-26 22:37:45 +00:00
|
|
|
|
2013-12-13 14:22:17 +00:00
|
|
|
for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
|
2019-07-23 03:08:26 +00:00
|
|
|
int size;
|
|
|
|
|
2013-12-13 14:22:17 +00:00
|
|
|
if (!len)
|
|
|
|
break;
|
|
|
|
skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i];
|
2019-07-23 03:08:26 +00:00
|
|
|
size = min_t(int, skb_frag_size(&skb_shinfo(to)->frags[j]),
|
|
|
|
len);
|
|
|
|
skb_frag_size_set(&skb_shinfo(to)->frags[j], size);
|
|
|
|
len -= size;
|
2013-12-13 14:22:17 +00:00
|
|
|
skb_frag_ref(to, j);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
skb_shinfo(to)->nr_frags = j;
|
2014-03-26 22:37:45 +00:00
|
|
|
|
|
|
|
return 0;
|
2013-12-13 14:22:17 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_zerocopy);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
|
|
|
|
{
|
2006-11-15 05:24:49 +00:00
|
|
|
__wsum csum;
|
2005-04-16 22:20:36 +00:00
|
|
|
long csstart;
|
|
|
|
|
2006-08-29 23:44:56 +00:00
|
|
|
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
2010-12-14 15:24:08 +00:00
|
|
|
csstart = skb_checksum_start_offset(skb);
|
2005-04-16 22:20:36 +00:00
|
|
|
else
|
|
|
|
csstart = skb_headlen(skb);
|
|
|
|
|
2006-01-09 06:24:28 +00:00
|
|
|
BUG_ON(csstart > skb_headlen(skb));
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-03-27 21:55:52 +00:00
|
|
|
skb_copy_from_linear_data(skb, to, csstart);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
csum = 0;
|
|
|
|
if (csstart != skb->len)
|
|
|
|
csum = skb_copy_and_csum_bits(skb, csstart, to + csstart,
|
2020-07-11 00:07:10 +00:00
|
|
|
skb->len - csstart);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-08-29 23:44:56 +00:00
|
|
|
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
2006-11-21 02:07:29 +00:00
|
|
|
long csstuff = csstart + skb->csum_offset;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-11-15 05:24:49 +00:00
|
|
|
*((__sum16 *)(to + csstuff)) = csum_fold(csum);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_copy_and_csum_dev);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_dequeue - remove from the head of the queue
|
|
|
|
* @list: list to dequeue from
|
|
|
|
*
|
|
|
|
* Remove the head of the list. The list lock is taken so the function
|
|
|
|
* may be used safely with other locking list functions. The head item is
|
|
|
|
* returned or %NULL if the list is empty.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct sk_buff *skb_dequeue(struct sk_buff_head *list)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
struct sk_buff *result;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&list->lock, flags);
|
|
|
|
result = __skb_dequeue(list);
|
|
|
|
spin_unlock_irqrestore(&list->lock, flags);
|
|
|
|
return result;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_dequeue);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_dequeue_tail - remove from the tail of the queue
|
|
|
|
* @list: list to dequeue from
|
|
|
|
*
|
|
|
|
* Remove the tail of the list. The list lock is taken so the function
|
|
|
|
* may be used safely with other locking list functions. The tail item is
|
|
|
|
* returned or %NULL if the list is empty.
|
|
|
|
*/
|
|
|
|
struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
struct sk_buff *result;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&list->lock, flags);
|
|
|
|
result = __skb_dequeue_tail(list);
|
|
|
|
spin_unlock_irqrestore(&list->lock, flags);
|
|
|
|
return result;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_dequeue_tail);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
2023-08-18 09:40:39 +00:00
|
|
|
* skb_queue_purge_reason - empty a list
|
2005-04-16 22:20:36 +00:00
|
|
|
* @list: list to empty
|
2023-08-18 09:40:39 +00:00
|
|
|
* @reason: drop reason
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* Delete all buffers on an &sk_buff list. Each buffer is removed from
|
|
|
|
* the list and one reference dropped. This function takes the list
|
|
|
|
* lock and is atomic with respect to other list locking functions.
|
|
|
|
*/
|
2023-08-18 09:40:39 +00:00
|
|
|
void skb_queue_purge_reason(struct sk_buff_head *list,
|
|
|
|
enum skb_drop_reason reason)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2023-10-03 18:19:20 +00:00
|
|
|
struct sk_buff_head tmp;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
if (skb_queue_empty_lockless(list))
|
|
|
|
return;
|
2023-08-18 09:40:39 +00:00
|
|
|
|
2023-10-03 18:19:20 +00:00
|
|
|
__skb_queue_head_init(&tmp);
|
|
|
|
|
|
|
|
spin_lock_irqsave(&list->lock, flags);
|
|
|
|
skb_queue_splice_init(list, &tmp);
|
|
|
|
spin_unlock_irqrestore(&list->lock, flags);
|
2023-08-18 09:40:39 +00:00
|
|
|
|
2023-10-03 18:19:20 +00:00
|
|
|
__skb_queue_purge_reason(&tmp, reason);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2023-08-18 09:40:39 +00:00
|
|
|
EXPORT_SYMBOL(skb_queue_purge_reason);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
tcp: use an RB tree for ooo receive queue
Over the years, TCP BDP has increased by several orders of magnitude,
and some people are considering to reach the 2 Gbytes limit.
Even with current window scale limit of 14, ~1 Gbytes maps to ~740,000
MSS.
In presence of packet losses (or reorders), TCP stores incoming packets
into an out of order queue, and number of skbs sitting there waiting for
the missing packets to be received can be in the 10^5 range.
Most packets are appended to the tail of this queue, and when
packets can finally be transferred to receive queue, we scan the queue
from its head.
However, in presence of heavy losses, we might have to find an arbitrary
point in this queue, involving a linear scan for every incoming packet,
throwing away cpu caches.
This patch converts it to a RB tree, to get bounded latencies.
Yaogong wrote a preliminary patch about 2 years ago.
Eric did the rebase, added ofo_last_skb cache, polishing and tests.
Tested with network dropping between 1 and 10 % packets, with good
success (about 30 % increase of throughput in stress tests)
Next step would be to also use an RB tree for the write queue at sender
side ;)
Signed-off-by: Yaogong Wang <wygivan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Acked-By: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-09-07 21:49:28 +00:00
|
|
|
/**
|
|
|
|
* skb_rbtree_purge - empty a skb rbtree
|
|
|
|
* @root: root of the rbtree to empty
|
2018-08-02 23:34:38 +00:00
|
|
|
* Return value: the sum of truesizes of all purged skbs.
|
tcp: use an RB tree for ooo receive queue
Over the years, TCP BDP has increased by several orders of magnitude,
and some people are considering to reach the 2 Gbytes limit.
Even with current window scale limit of 14, ~1 Gbytes maps to ~740,000
MSS.
In presence of packet losses (or reorders), TCP stores incoming packets
into an out of order queue, and number of skbs sitting there waiting for
the missing packets to be received can be in the 10^5 range.
Most packets are appended to the tail of this queue, and when
packets can finally be transferred to receive queue, we scan the queue
from its head.
However, in presence of heavy losses, we might have to find an arbitrary
point in this queue, involving a linear scan for every incoming packet,
throwing away cpu caches.
This patch converts it to a RB tree, to get bounded latencies.
Yaogong wrote a preliminary patch about 2 years ago.
Eric did the rebase, added ofo_last_skb cache, polishing and tests.
Tested with network dropping between 1 and 10 % packets, with good
success (about 30 % increase of throughput in stress tests)
Next step would be to also use an RB tree for the write queue at sender
side ;)
Signed-off-by: Yaogong Wang <wygivan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Acked-By: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-09-07 21:49:28 +00:00
|
|
|
*
|
|
|
|
* Delete all buffers on an &sk_buff rbtree. Each buffer is removed from
|
|
|
|
* the list and one reference dropped. This function does not take
|
|
|
|
* any lock. Synchronization should be handled by the caller (e.g., TCP
|
|
|
|
* out-of-order queue is protected by the socket lock).
|
|
|
|
*/
|
2018-08-02 23:34:38 +00:00
|
|
|
unsigned int skb_rbtree_purge(struct rb_root *root)
|
tcp: use an RB tree for ooo receive queue
Over the years, TCP BDP has increased by several orders of magnitude,
and some people are considering to reach the 2 Gbytes limit.
Even with current window scale limit of 14, ~1 Gbytes maps to ~740,000
MSS.
In presence of packet losses (or reorders), TCP stores incoming packets
into an out of order queue, and number of skbs sitting there waiting for
the missing packets to be received can be in the 10^5 range.
Most packets are appended to the tail of this queue, and when
packets can finally be transferred to receive queue, we scan the queue
from its head.
However, in presence of heavy losses, we might have to find an arbitrary
point in this queue, involving a linear scan for every incoming packet,
throwing away cpu caches.
This patch converts it to a RB tree, to get bounded latencies.
Yaogong wrote a preliminary patch about 2 years ago.
Eric did the rebase, added ofo_last_skb cache, polishing and tests.
Tested with network dropping between 1 and 10 % packets, with good
success (about 30 % increase of throughput in stress tests)
Next step would be to also use an RB tree for the write queue at sender
side ;)
Signed-off-by: Yaogong Wang <wygivan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Acked-By: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-09-07 21:49:28 +00:00
|
|
|
{
|
2017-09-23 19:39:12 +00:00
|
|
|
struct rb_node *p = rb_first(root);
|
2018-08-02 23:34:38 +00:00
|
|
|
unsigned int sum = 0;
|
tcp: use an RB tree for ooo receive queue
Over the years, TCP BDP has increased by several orders of magnitude,
and some people are considering to reach the 2 Gbytes limit.
Even with current window scale limit of 14, ~1 Gbytes maps to ~740,000
MSS.
In presence of packet losses (or reorders), TCP stores incoming packets
into an out of order queue, and number of skbs sitting there waiting for
the missing packets to be received can be in the 10^5 range.
Most packets are appended to the tail of this queue, and when
packets can finally be transferred to receive queue, we scan the queue
from its head.
However, in presence of heavy losses, we might have to find an arbitrary
point in this queue, involving a linear scan for every incoming packet,
throwing away cpu caches.
This patch converts it to a RB tree, to get bounded latencies.
Yaogong wrote a preliminary patch about 2 years ago.
Eric did the rebase, added ofo_last_skb cache, polishing and tests.
Tested with network dropping between 1 and 10 % packets, with good
success (about 30 % increase of throughput in stress tests)
Next step would be to also use an RB tree for the write queue at sender
side ;)
Signed-off-by: Yaogong Wang <wygivan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Acked-By: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-09-07 21:49:28 +00:00
|
|
|
|
2017-09-23 19:39:12 +00:00
|
|
|
while (p) {
|
|
|
|
struct sk_buff *skb = rb_entry(p, struct sk_buff, rbnode);
|
tcp: use an RB tree for ooo receive queue
Over the years, TCP BDP has increased by several orders of magnitude,
and some people are considering to reach the 2 Gbytes limit.
Even with current window scale limit of 14, ~1 Gbytes maps to ~740,000
MSS.
In presence of packet losses (or reorders), TCP stores incoming packets
into an out of order queue, and number of skbs sitting there waiting for
the missing packets to be received can be in the 10^5 range.
Most packets are appended to the tail of this queue, and when
packets can finally be transferred to receive queue, we scan the queue
from its head.
However, in presence of heavy losses, we might have to find an arbitrary
point in this queue, involving a linear scan for every incoming packet,
throwing away cpu caches.
This patch converts it to a RB tree, to get bounded latencies.
Yaogong wrote a preliminary patch about 2 years ago.
Eric did the rebase, added ofo_last_skb cache, polishing and tests.
Tested with network dropping between 1 and 10 % packets, with good
success (about 30 % increase of throughput in stress tests)
Next step would be to also use an RB tree for the write queue at sender
side ;)
Signed-off-by: Yaogong Wang <wygivan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Acked-By: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-09-07 21:49:28 +00:00
|
|
|
|
2017-09-23 19:39:12 +00:00
|
|
|
p = rb_next(p);
|
|
|
|
rb_erase(&skb->rbnode, root);
|
2018-08-02 23:34:38 +00:00
|
|
|
sum += skb->truesize;
|
2017-09-23 19:39:12 +00:00
|
|
|
kfree_skb(skb);
|
|
|
|
}
|
2018-08-02 23:34:38 +00:00
|
|
|
return sum;
|
tcp: use an RB tree for ooo receive queue
Over the years, TCP BDP has increased by several orders of magnitude,
and some people are considering to reach the 2 Gbytes limit.
Even with current window scale limit of 14, ~1 Gbytes maps to ~740,000
MSS.
In presence of packet losses (or reorders), TCP stores incoming packets
into an out of order queue, and number of skbs sitting there waiting for
the missing packets to be received can be in the 10^5 range.
Most packets are appended to the tail of this queue, and when
packets can finally be transferred to receive queue, we scan the queue
from its head.
However, in presence of heavy losses, we might have to find an arbitrary
point in this queue, involving a linear scan for every incoming packet,
throwing away cpu caches.
This patch converts it to a RB tree, to get bounded latencies.
Yaogong wrote a preliminary patch about 2 years ago.
Eric did the rebase, added ofo_last_skb cache, polishing and tests.
Tested with network dropping between 1 and 10 % packets, with good
success (about 30 % increase of throughput in stress tests)
Next step would be to also use an RB tree for the write queue at sender
side ;)
Signed-off-by: Yaogong Wang <wygivan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Acked-By: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-09-07 21:49:28 +00:00
|
|
|
}
|
|
|
|
|
2023-08-18 17:41:45 +00:00
|
|
|
void skb_errqueue_purge(struct sk_buff_head *list)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb, *next;
|
|
|
|
struct sk_buff_head kill;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
__skb_queue_head_init(&kill);
|
|
|
|
|
|
|
|
spin_lock_irqsave(&list->lock, flags);
|
|
|
|
skb_queue_walk_safe(list, skb, next) {
|
|
|
|
if (SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ZEROCOPY ||
|
|
|
|
SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING)
|
|
|
|
continue;
|
|
|
|
__skb_unlink(skb, list);
|
|
|
|
__skb_queue_tail(&kill, skb);
|
|
|
|
}
|
|
|
|
spin_unlock_irqrestore(&list->lock, flags);
|
|
|
|
__skb_queue_purge(&kill);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_errqueue_purge);
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* skb_queue_head - queue a buffer at the list head
|
|
|
|
* @list: list to use
|
|
|
|
* @newsk: buffer to queue
|
|
|
|
*
|
|
|
|
* Queue a buffer at the start of the list. This function takes the
|
|
|
|
* list lock and can be used safely with other locking &sk_buff functions
|
|
|
|
* safely.
|
|
|
|
*
|
|
|
|
* A buffer cannot be placed on two lists at the same time.
|
|
|
|
*/
|
|
|
|
void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&list->lock, flags);
|
|
|
|
__skb_queue_head(list, newsk);
|
|
|
|
spin_unlock_irqrestore(&list->lock, flags);
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_queue_head);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_queue_tail - queue a buffer at the list tail
|
|
|
|
* @list: list to use
|
|
|
|
* @newsk: buffer to queue
|
|
|
|
*
|
|
|
|
* Queue a buffer at the tail of the list. This function takes the
|
|
|
|
* list lock and can be used safely with other locking &sk_buff functions
|
|
|
|
* safely.
|
|
|
|
*
|
|
|
|
* A buffer cannot be placed on two lists at the same time.
|
|
|
|
*/
|
|
|
|
void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
spin_lock_irqsave(&list->lock, flags);
|
|
|
|
__skb_queue_tail(list, newsk);
|
|
|
|
spin_unlock_irqrestore(&list->lock, flags);
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_queue_tail);
|
2005-08-10 02:25:21 +00:00
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/**
|
|
|
|
* skb_unlink - remove a buffer from a list
|
|
|
|
* @skb: buffer to remove
|
2005-08-10 02:25:21 +00:00
|
|
|
* @list: list to use
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
2005-08-10 02:25:21 +00:00
|
|
|
* Remove a packet from a list. The list locks are taken and this
|
|
|
|
* function is atomic with respect to other list locked calls
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
2005-08-10 02:25:21 +00:00
|
|
|
* You must know what list the SKB is on.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
2005-08-10 02:25:21 +00:00
|
|
|
void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2005-08-10 02:25:21 +00:00
|
|
|
unsigned long flags;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2005-08-10 02:25:21 +00:00
|
|
|
spin_lock_irqsave(&list->lock, flags);
|
|
|
|
__skb_unlink(skb, list);
|
|
|
|
spin_unlock_irqrestore(&list->lock, flags);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_unlink);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_append - append a buffer
|
|
|
|
* @old: buffer to insert after
|
|
|
|
* @newsk: buffer to insert
|
2005-08-10 02:25:21 +00:00
|
|
|
* @list: list to use
|
2005-04-16 22:20:36 +00:00
|
|
|
*
|
|
|
|
* Place a packet after a given packet in a list. The list locks are taken
|
|
|
|
* and this function is atomic with respect to other list locked calls.
|
|
|
|
* A buffer cannot be placed on two lists at the same time.
|
|
|
|
*/
|
2005-08-10 02:25:21 +00:00
|
|
|
void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
2005-08-10 02:25:21 +00:00
|
|
|
spin_lock_irqsave(&list->lock, flags);
|
2008-04-14 07:05:09 +00:00
|
|
|
__skb_queue_after(list, old, newsk);
|
2005-08-10 02:25:21 +00:00
|
|
|
spin_unlock_irqrestore(&list->lock, flags);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_append);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
static inline void skb_split_inside_header(struct sk_buff *skb,
|
|
|
|
struct sk_buff* skb1,
|
|
|
|
const u32 len, const int pos)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2007-03-27 21:55:52 +00:00
|
|
|
skb_copy_from_linear_data_offset(skb, len, skb_put(skb1, pos - len),
|
|
|
|
pos - len);
|
2005-04-16 22:20:36 +00:00
|
|
|
/* And move data appendix as is. */
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
|
|
|
|
skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i];
|
|
|
|
|
|
|
|
skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags;
|
|
|
|
skb_shinfo(skb)->nr_frags = 0;
|
|
|
|
skb1->data_len = skb->data_len;
|
|
|
|
skb1->len += skb1->data_len;
|
|
|
|
skb->data_len = 0;
|
|
|
|
skb->len = len;
|
2007-04-20 03:29:13 +00:00
|
|
|
skb_set_tail_pointer(skb, len);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void skb_split_no_header(struct sk_buff *skb,
|
|
|
|
struct sk_buff* skb1,
|
|
|
|
const u32 len, int pos)
|
|
|
|
{
|
|
|
|
int i, k = 0;
|
|
|
|
const int nfrags = skb_shinfo(skb)->nr_frags;
|
|
|
|
|
|
|
|
skb_shinfo(skb)->nr_frags = 0;
|
|
|
|
skb1->len = skb1->data_len = skb->len - len;
|
|
|
|
skb->len = len;
|
|
|
|
skb->data_len = len - pos;
|
|
|
|
|
|
|
|
for (i = 0; i < nfrags; i++) {
|
2011-10-18 21:00:24 +00:00
|
|
|
int size = skb_frag_size(&skb_shinfo(skb)->frags[i]);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (pos + size > len) {
|
|
|
|
skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i];
|
|
|
|
|
|
|
|
if (pos < len) {
|
|
|
|
/* Split frag.
|
|
|
|
* We have two variants in this case:
|
|
|
|
* 1. Move all the frag to the second
|
|
|
|
* part, if it is possible. F.e.
|
|
|
|
* this approach is mandatory for TUX,
|
|
|
|
* where splitting is expensive.
|
|
|
|
* 2. Split is accurately. We make this.
|
|
|
|
*/
|
2011-08-22 23:44:58 +00:00
|
|
|
skb_frag_ref(skb, i);
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off_add(&skb_shinfo(skb1)->frags[0], len - pos);
|
2011-10-18 21:00:24 +00:00
|
|
|
skb_frag_size_sub(&skb_shinfo(skb1)->frags[0], len - pos);
|
|
|
|
skb_frag_size_set(&skb_shinfo(skb)->frags[i], len - pos);
|
2005-04-16 22:20:36 +00:00
|
|
|
skb_shinfo(skb)->nr_frags++;
|
|
|
|
}
|
|
|
|
k++;
|
|
|
|
} else
|
|
|
|
skb_shinfo(skb)->nr_frags++;
|
|
|
|
pos += size;
|
|
|
|
}
|
|
|
|
skb_shinfo(skb1)->nr_frags = k;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_split - Split fragmented skb to two parts at length len.
|
|
|
|
* @skb: the buffer to split
|
|
|
|
* @skb1: the buffer to receive the second part
|
|
|
|
* @len: new length for skb
|
|
|
|
*/
|
|
|
|
void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
|
|
|
|
{
|
|
|
|
int pos = skb_headlen(skb);
|
2021-11-03 02:58:44 +00:00
|
|
|
const int zc_flags = SKBFL_SHARED_FRAG | SKBFL_PURE_ZEROCOPY;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2022-07-12 20:52:31 +00:00
|
|
|
skb_zcopy_downgrade_managed(skb);
|
|
|
|
|
2021-11-03 02:58:44 +00:00
|
|
|
skb_shinfo(skb1)->flags |= skb_shinfo(skb)->flags & zc_flags;
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
skb_zerocopy_clone(skb1, skb, 0);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (len < pos) /* Split line is inside header. */
|
|
|
|
skb_split_inside_header(skb, skb1, len, pos);
|
|
|
|
else /* Second chunk has no header, nothing to copy. */
|
|
|
|
skb_split_no_header(skb, skb1, len, pos);
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_split);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-11-25 21:57:01 +00:00
|
|
|
/* Shifting from/to a cloned skb is a no-go.
|
|
|
|
*
|
|
|
|
* Caller cannot keep skb_shinfo related pointers past calling here!
|
|
|
|
*/
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
static int skb_prepare_for_shift(struct sk_buff *skb)
|
|
|
|
{
|
2021-11-02 00:45:55 +00:00
|
|
|
return skb_unclone_keeptruesize(skb, GFP_ATOMIC);
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_shift - Shifts paged data partially from skb to another
|
|
|
|
* @tgt: buffer into which tail data gets added
|
|
|
|
* @skb: buffer from which the paged data comes from
|
|
|
|
* @shiftlen: shift up to this many bytes
|
|
|
|
*
|
|
|
|
* Attempts to shift up to shiftlen worth of bytes, which may be less than
|
2011-11-21 01:47:11 +00:00
|
|
|
* the length of the skb, from skb to tgt. Returns number bytes shifted.
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
* It's up to caller to free skb if everything was shifted.
|
|
|
|
*
|
|
|
|
* If @tgt runs out of frags, the whole operation is aborted.
|
|
|
|
*
|
|
|
|
* Skb cannot include anything else but paged data while tgt is allowed
|
|
|
|
* to have non-paged data as well.
|
|
|
|
*
|
|
|
|
* TODO: full sized shift could be optimized but that would need
|
|
|
|
* specialized skb free'er to handle frags without up-to-date nr_frags.
|
|
|
|
*/
|
|
|
|
int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
|
|
|
|
{
|
|
|
|
int from, to, merge, todo;
|
2019-07-23 03:08:26 +00:00
|
|
|
skb_frag_t *fragfrom, *fragto;
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
|
|
|
|
BUG_ON(shiftlen > skb->len);
|
tcp: enhance tcp_collapse_retrans() with skb_shift()
In commit 2331ccc5b323 ("tcp: enhance tcp collapsing"),
we made a first step allowing copying right skb to left skb head.
Since all skbs in socket write queue are headless (but possibly the very
first one), this strategy often does not work.
This patch extends tcp_collapse_retrans() to perform frag shifting,
thanks to skb_shift() helper.
This helper needs to not BUG on non headless skbs, as callers are ok
with that.
Tested:
Following packetdrill test now passes :
0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
+0 < S 0:0(0) win 32792 <mss 1460,sackOK,nop,nop,nop,wscale 8>
+0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+.100 < . 1:1(0) ack 1 win 257
+0 accept(3, ..., ...) = 4
+0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+0 write(4, ..., 200) = 200
+0 > P. 1:201(200) ack 1
+.001 write(4, ..., 200) = 200
+0 > P. 201:401(200) ack 1
+.001 write(4, ..., 200) = 200
+0 > P. 401:601(200) ack 1
+.001 write(4, ..., 200) = 200
+0 > P. 601:801(200) ack 1
+.001 write(4, ..., 200) = 200
+0 > P. 801:1001(200) ack 1
+.001 write(4, ..., 100) = 100
+0 > P. 1001:1101(100) ack 1
+.001 write(4, ..., 100) = 100
+0 > P. 1101:1201(100) ack 1
+.001 write(4, ..., 100) = 100
+0 > P. 1201:1301(100) ack 1
+.001 write(4, ..., 100) = 100
+0 > P. 1301:1401(100) ack 1
+.099 < . 1:1(0) ack 201 win 257
+.001 < . 1:1(0) ack 201 win 257 <nop,nop,sack 1001:1401>
+0 > P. 201:1001(800) ack 1
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Acked-by: Yuchung Cheng <ycheng@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-11-15 20:51:50 +00:00
|
|
|
|
|
|
|
if (skb_headlen(skb))
|
|
|
|
return 0;
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
if (skb_zcopy(tgt) || skb_zcopy(skb))
|
|
|
|
return 0;
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
|
|
|
|
todo = shiftlen;
|
|
|
|
from = 0;
|
|
|
|
to = skb_shinfo(tgt)->nr_frags;
|
|
|
|
fragfrom = &skb_shinfo(skb)->frags[from];
|
|
|
|
|
|
|
|
/* Actual merge is delayed until the point when we know we can
|
|
|
|
* commit all, so that we don't have to undo partial changes
|
|
|
|
*/
|
|
|
|
if (!to ||
|
2011-08-22 23:44:58 +00:00
|
|
|
!skb_can_coalesce(tgt, to, skb_frag_page(fragfrom),
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off(fragfrom))) {
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
merge = -1;
|
|
|
|
} else {
|
|
|
|
merge = to - 1;
|
|
|
|
|
2011-10-18 21:00:24 +00:00
|
|
|
todo -= skb_frag_size(fragfrom);
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
if (todo < 0) {
|
|
|
|
if (skb_prepare_for_shift(skb) ||
|
|
|
|
skb_prepare_for_shift(tgt))
|
|
|
|
return 0;
|
|
|
|
|
2008-11-25 21:57:01 +00:00
|
|
|
/* All previous frag pointers might be stale! */
|
|
|
|
fragfrom = &skb_shinfo(skb)->frags[from];
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
fragto = &skb_shinfo(tgt)->frags[merge];
|
|
|
|
|
2011-10-18 21:00:24 +00:00
|
|
|
skb_frag_size_add(fragto, shiftlen);
|
|
|
|
skb_frag_size_sub(fragfrom, shiftlen);
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off_add(fragfrom, shiftlen);
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
|
|
|
|
goto onlymerged;
|
|
|
|
}
|
|
|
|
|
|
|
|
from++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Skip full, not-fitting skb to avoid expensive operations */
|
|
|
|
if ((shiftlen == skb->len) &&
|
|
|
|
(skb_shinfo(skb)->nr_frags - from) > (MAX_SKB_FRAGS - to))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (skb_prepare_for_shift(skb) || skb_prepare_for_shift(tgt))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while ((todo > 0) && (from < skb_shinfo(skb)->nr_frags)) {
|
|
|
|
if (to == MAX_SKB_FRAGS)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fragfrom = &skb_shinfo(skb)->frags[from];
|
|
|
|
fragto = &skb_shinfo(tgt)->frags[to];
|
|
|
|
|
2011-10-18 21:00:24 +00:00
|
|
|
if (todo >= skb_frag_size(fragfrom)) {
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
*fragto = *fragfrom;
|
2011-10-18 21:00:24 +00:00
|
|
|
todo -= skb_frag_size(fragfrom);
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
from++;
|
|
|
|
to++;
|
|
|
|
|
|
|
|
} else {
|
2024-05-02 17:54:22 +00:00
|
|
|
__skb_frag_ref(fragfrom);
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_page_copy(fragto, fragfrom);
|
|
|
|
skb_frag_off_copy(fragto, fragfrom);
|
2011-10-18 21:00:24 +00:00
|
|
|
skb_frag_size_set(fragto, todo);
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off_add(fragfrom, todo);
|
2011-10-18 21:00:24 +00:00
|
|
|
skb_frag_size_sub(fragfrom, todo);
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
todo = 0;
|
|
|
|
|
|
|
|
to++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ready to "commit" this state change to tgt */
|
|
|
|
skb_shinfo(tgt)->nr_frags = to;
|
|
|
|
|
|
|
|
if (merge >= 0) {
|
|
|
|
fragfrom = &skb_shinfo(skb)->frags[0];
|
|
|
|
fragto = &skb_shinfo(tgt)->frags[merge];
|
|
|
|
|
2011-10-18 21:00:24 +00:00
|
|
|
skb_frag_size_add(fragto, skb_frag_size(fragfrom));
|
2021-06-07 19:02:38 +00:00
|
|
|
__skb_frag_unref(fragfrom, skb->pp_recycle);
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Reposition in the original skb */
|
|
|
|
to = 0;
|
|
|
|
while (from < skb_shinfo(skb)->nr_frags)
|
|
|
|
skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++];
|
|
|
|
skb_shinfo(skb)->nr_frags = to;
|
|
|
|
|
|
|
|
BUG_ON(todo > 0 && !skb_shinfo(skb)->nr_frags);
|
|
|
|
|
|
|
|
onlymerged:
|
|
|
|
/* Most likely the tgt won't ever need its checksum anymore, skb on
|
|
|
|
* the other hand might need it if it needs to be resent
|
|
|
|
*/
|
|
|
|
tgt->ip_summed = CHECKSUM_PARTIAL;
|
|
|
|
skb->ip_summed = CHECKSUM_PARTIAL;
|
|
|
|
|
2022-06-22 16:09:03 +00:00
|
|
|
skb_len_add(skb, -shiftlen);
|
|
|
|
skb_len_add(tgt, shiftlen);
|
tcp: Try to restore large SKBs while SACK processing
During SACK processing, most of the benefits of TSO are eaten by
the SACK blocks that one-by-one fragment SKBs to MSS sized chunks.
Then we're in problems when cleanup work for them has to be done
when a large cumulative ACK comes. Try to return back to pre-split
state already while more and more SACK info gets discovered by
combining newly discovered SACK areas with the previous skb if
that's SACKed as well.
This approach has a number of benefits:
1) The processing overhead is spread more equally over the RTT
2) Write queue has less skbs to process (affect everything
which has to walk in the queue past the sacked areas)
3) Write queue is consistent whole the time, so no other parts
of TCP has to be aware of this (this was not the case with
some other approach that was, well, quite intrusive all
around).
4) Clean_rtx_queue can release most of the pages using single
put_page instead of previous PAGE_SIZE/mss+1 calls
In case a hole is fully filled by the new SACK block, we attempt
to combine the next skb too which allows construction of skbs
that are even larger than what tso split them to and it handles
hole per on every nth patterns that often occur during slow start
overshoot pretty nicely. Though this to be really useful also
a retransmission would have to get lost since cumulative ACKs
advance one hole at a time in the most typical case.
TODO: handle upwards only merging. That should be rather easy
when segment is fully sacked but I'm leaving that as future
work item (it won't make very large difference anyway since
this current approach already covers quite a lot of normal
cases).
I was earlier thinking of some sophisticated way of tracking
timestamps of the first and the last segment but later on
realized that it won't be that necessary at all to store the
timestamp of the last segment. The cases that can occur are
basically either:
1) ambiguous => no sensible measurement can be taken anyway
2) non-ambiguous is due to reordering => having the timestamp
of the last segment there is just skewing things more off
than does some good since the ack got triggered by one of
the holes (besides some substle issues that would make
determining right hole/skb even harder problem). Anyway,
it has nothing to do with this change then.
I choose to route some abnormal looking cases with goto noop,
some could be handled differently (eg., by stopping the
walking at that skb but again). In general, they either
shouldn't happen at all or are rare enough to make no difference
in practice.
In theory this change (as whole) could cause some macroscale
regression (global) because of cache misses that are taken over
the round-trip time but it gets very likely better because of much
less (local) cache misses per other write queue walkers and the
big recovery clearing cumulative ack.
Worth to note that these benefits would be very easy to get also
without TSO/GSO being on as long as the data is in pages so that
we can merge them. Currently I won't let that happen because
DSACK splitting at fragment that would mess up pcounts due to
sk_can_gso in tcp_set_skb_tso_segs. Once DSACKs fragments gets
avoided, we have some conditions that can be made less strict.
TODO: I will probably have to convert the excessive pointer
passing to struct sacktag_state... :-)
My testing revealed that considerable amount of skbs couldn't
be shifted because they were cloned (most likely still awaiting
tx reclaim)...
[The rest is considering future work instead since I got
repeatably EFAULT to tcpdump's recvfrom when I added
pskb_expand_head to deal with clones, so I separated that
into another, later patch]
...To counter that, I gave up on the fifth advantage:
5) When growing previous SACK block, less allocs for new skbs
are done, basically a new alloc is needed only when new hole
is detected and when the previous skb runs out of frags space
...which now only happens of if reclaim is fast enough to dispose
the clone before the SACK block comes in (the window is RTT long),
otherwise we'll have to alloc some.
With clones being handled I got these numbers (will be somewhat
worse without that), taken with fine-grained mibs:
TCPSackShifted 398
TCPSackMerged 877
TCPSackShiftFallback 320
TCPSACKCOLLAPSEFALLBACKGSO 0
TCPSACKCOLLAPSEFALLBACKSKBBITS 0
TCPSACKCOLLAPSEFALLBACKSKBDATA 0
TCPSACKCOLLAPSEFALLBACKBELOW 0
TCPSACKCOLLAPSEFALLBACKFIRST 1
TCPSACKCOLLAPSEFALLBACKPREVBITS 318
TCPSACKCOLLAPSEFALLBACKMSS 1
TCPSACKCOLLAPSEFALLBACKNOHEAD 0
TCPSACKCOLLAPSEFALLBACKSHIFT 0
TCPSACKCOLLAPSENOOPSEQ 0
TCPSACKCOLLAPSENOOPSMALLPCOUNT 0
TCPSACKCOLLAPSENOOPSMALLLEN 0
TCPSACKCOLLAPSEHOLE 12
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-11-25 05:20:15 +00:00
|
|
|
|
|
|
|
return shiftlen;
|
|
|
|
}
|
|
|
|
|
2005-06-24 03:59:51 +00:00
|
|
|
/**
|
|
|
|
* skb_prepare_seq_read - Prepare a sequential read of skb data
|
|
|
|
* @skb: the buffer to read
|
|
|
|
* @from: lower offset of data to be read
|
|
|
|
* @to: upper offset of data to be read
|
|
|
|
* @st: state variable
|
|
|
|
*
|
|
|
|
* Initializes the specified state variable. Must be called before
|
|
|
|
* invoking skb_seq_read() for the first time.
|
|
|
|
*/
|
|
|
|
void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from,
|
|
|
|
unsigned int to, struct skb_seq_state *st)
|
|
|
|
{
|
|
|
|
st->lower_offset = from;
|
|
|
|
st->upper_offset = to;
|
|
|
|
st->root_skb = st->cur_skb = skb;
|
|
|
|
st->frag_idx = st->stepped_offset = 0;
|
|
|
|
st->frag_data = NULL;
|
2021-01-09 22:18:33 +00:00
|
|
|
st->frag_off = 0;
|
2005-06-24 03:59:51 +00:00
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_prepare_seq_read);
|
2005-06-24 03:59:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_seq_read - Sequentially read skb data
|
|
|
|
* @consumed: number of bytes consumed by the caller so far
|
|
|
|
* @data: destination pointer for data to be returned
|
|
|
|
* @st: state variable
|
|
|
|
*
|
2013-11-07 13:18:26 +00:00
|
|
|
* Reads a block of skb data at @consumed relative to the
|
2005-06-24 03:59:51 +00:00
|
|
|
* lower offset specified to skb_prepare_seq_read(). Assigns
|
2013-11-07 13:18:26 +00:00
|
|
|
* the head of the data block to @data and returns the length
|
2005-06-24 03:59:51 +00:00
|
|
|
* of the block or 0 if the end of the skb data or the upper
|
|
|
|
* offset has been reached.
|
|
|
|
*
|
|
|
|
* The caller is not required to consume all of the data
|
2013-11-07 13:18:26 +00:00
|
|
|
* returned, i.e. @consumed is typically set to the number
|
2005-06-24 03:59:51 +00:00
|
|
|
* of bytes already consumed and the next call to
|
|
|
|
* skb_seq_read() will return the remaining part of the block.
|
|
|
|
*
|
2011-03-31 01:57:33 +00:00
|
|
|
* Note 1: The size of each block of data returned can be arbitrary,
|
2014-09-04 14:44:36 +00:00
|
|
|
* this limitation is the cost for zerocopy sequential
|
2005-06-24 03:59:51 +00:00
|
|
|
* reads of potentially non linear data.
|
|
|
|
*
|
2008-02-13 23:03:25 +00:00
|
|
|
* Note 2: Fragment lists within fragments are not implemented
|
2005-06-24 03:59:51 +00:00
|
|
|
* at the moment, state->root_skb could be replaced with
|
|
|
|
* a stack for this purpose.
|
|
|
|
*/
|
|
|
|
unsigned int skb_seq_read(unsigned int consumed, const u8 **data,
|
|
|
|
struct skb_seq_state *st)
|
|
|
|
{
|
|
|
|
unsigned int block_limit, abs_offset = consumed + st->lower_offset;
|
|
|
|
skb_frag_t *frag;
|
|
|
|
|
2013-06-24 06:33:48 +00:00
|
|
|
if (unlikely(abs_offset >= st->upper_offset)) {
|
|
|
|
if (st->frag_data) {
|
|
|
|
kunmap_atomic(st->frag_data);
|
|
|
|
st->frag_data = NULL;
|
|
|
|
}
|
2005-06-24 03:59:51 +00:00
|
|
|
return 0;
|
2013-06-24 06:33:48 +00:00
|
|
|
}
|
2005-06-24 03:59:51 +00:00
|
|
|
|
|
|
|
next_skb:
|
2009-01-30 00:07:52 +00:00
|
|
|
block_limit = skb_headlen(st->cur_skb) + st->stepped_offset;
|
2005-06-24 03:59:51 +00:00
|
|
|
|
2009-05-19 04:43:27 +00:00
|
|
|
if (abs_offset < block_limit && !st->frag_data) {
|
2009-01-30 00:07:52 +00:00
|
|
|
*data = st->cur_skb->data + (abs_offset - st->stepped_offset);
|
2005-06-24 03:59:51 +00:00
|
|
|
return block_limit - abs_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (st->frag_idx == 0 && !st->frag_data)
|
|
|
|
st->stepped_offset += skb_headlen(st->cur_skb);
|
|
|
|
|
|
|
|
while (st->frag_idx < skb_shinfo(st->cur_skb)->nr_frags) {
|
2021-01-09 22:18:33 +00:00
|
|
|
unsigned int pg_idx, pg_off, pg_sz;
|
|
|
|
|
2005-06-24 03:59:51 +00:00
|
|
|
frag = &skb_shinfo(st->cur_skb)->frags[st->frag_idx];
|
|
|
|
|
2021-01-09 22:18:33 +00:00
|
|
|
pg_idx = 0;
|
|
|
|
pg_off = skb_frag_off(frag);
|
|
|
|
pg_sz = skb_frag_size(frag);
|
|
|
|
|
|
|
|
if (skb_frag_must_loop(skb_frag_page(frag))) {
|
|
|
|
pg_idx = (pg_off + st->frag_off) >> PAGE_SHIFT;
|
|
|
|
pg_off = offset_in_page(pg_off + st->frag_off);
|
|
|
|
pg_sz = min_t(unsigned int, pg_sz - st->frag_off,
|
|
|
|
PAGE_SIZE - pg_off);
|
|
|
|
}
|
|
|
|
|
|
|
|
block_limit = pg_sz + st->stepped_offset;
|
2005-06-24 03:59:51 +00:00
|
|
|
if (abs_offset < block_limit) {
|
|
|
|
if (!st->frag_data)
|
2021-01-09 22:18:33 +00:00
|
|
|
st->frag_data = kmap_atomic(skb_frag_page(frag) + pg_idx);
|
2005-06-24 03:59:51 +00:00
|
|
|
|
2021-01-09 22:18:33 +00:00
|
|
|
*data = (u8 *)st->frag_data + pg_off +
|
2005-06-24 03:59:51 +00:00
|
|
|
(abs_offset - st->stepped_offset);
|
|
|
|
|
|
|
|
return block_limit - abs_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (st->frag_data) {
|
2012-04-05 09:35:15 +00:00
|
|
|
kunmap_atomic(st->frag_data);
|
2005-06-24 03:59:51 +00:00
|
|
|
st->frag_data = NULL;
|
|
|
|
}
|
|
|
|
|
2021-01-09 22:18:33 +00:00
|
|
|
st->stepped_offset += pg_sz;
|
|
|
|
st->frag_off += pg_sz;
|
|
|
|
if (st->frag_off == skb_frag_size(frag)) {
|
|
|
|
st->frag_off = 0;
|
|
|
|
st->frag_idx++;
|
|
|
|
}
|
2005-06-24 03:59:51 +00:00
|
|
|
}
|
|
|
|
|
2007-06-24 06:11:52 +00:00
|
|
|
if (st->frag_data) {
|
2012-04-05 09:35:15 +00:00
|
|
|
kunmap_atomic(st->frag_data);
|
2007-06-24 06:11:52 +00:00
|
|
|
st->frag_data = NULL;
|
|
|
|
}
|
|
|
|
|
2010-08-23 07:13:46 +00:00
|
|
|
if (st->root_skb == st->cur_skb && skb_has_frag_list(st->root_skb)) {
|
2009-01-30 00:12:42 +00:00
|
|
|
st->cur_skb = skb_shinfo(st->root_skb)->frag_list;
|
2005-06-24 03:59:51 +00:00
|
|
|
st->frag_idx = 0;
|
|
|
|
goto next_skb;
|
2009-01-30 00:12:42 +00:00
|
|
|
} else if (st->cur_skb->next) {
|
|
|
|
st->cur_skb = st->cur_skb->next;
|
2009-01-30 00:07:52 +00:00
|
|
|
st->frag_idx = 0;
|
2005-06-24 03:59:51 +00:00
|
|
|
goto next_skb;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_seq_read);
|
2005-06-24 03:59:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_abort_seq_read - Abort a sequential read of skb data
|
|
|
|
* @st: state variable
|
|
|
|
*
|
|
|
|
* Must be called if skb_seq_read() was not called until it
|
|
|
|
* returned 0.
|
|
|
|
*/
|
|
|
|
void skb_abort_seq_read(struct skb_seq_state *st)
|
|
|
|
{
|
|
|
|
if (st->frag_data)
|
2012-04-05 09:35:15 +00:00
|
|
|
kunmap_atomic(st->frag_data);
|
2005-06-24 03:59:51 +00:00
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_abort_seq_read);
|
2005-06-24 03:59:51 +00:00
|
|
|
|
2005-06-24 04:00:17 +00:00
|
|
|
#define TS_SKB_CB(state) ((struct skb_seq_state *) &((state)->cb))
|
|
|
|
|
|
|
|
static unsigned int skb_ts_get_next_block(unsigned int offset, const u8 **text,
|
|
|
|
struct ts_config *conf,
|
|
|
|
struct ts_state *state)
|
|
|
|
{
|
|
|
|
return skb_seq_read(offset, text, TS_SKB_CB(state));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void skb_ts_finish(struct ts_config *conf, struct ts_state *state)
|
|
|
|
{
|
|
|
|
skb_abort_seq_read(TS_SKB_CB(state));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_find_text - Find a text pattern in skb data
|
|
|
|
* @skb: the buffer to look in
|
|
|
|
* @from: search offset
|
|
|
|
* @to: search limit
|
|
|
|
* @config: textsearch configuration
|
|
|
|
*
|
|
|
|
* Finds a pattern in the skb data according to the specified
|
|
|
|
* textsearch configuration. Use textsearch_next() to retrieve
|
|
|
|
* subsequent occurrences of the pattern. Returns the offset
|
|
|
|
* to the first occurrence or UINT_MAX if no match was found.
|
|
|
|
*/
|
|
|
|
unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
|
2015-02-22 10:46:35 +00:00
|
|
|
unsigned int to, struct ts_config *config)
|
2005-06-24 04:00:17 +00:00
|
|
|
{
|
2023-10-17 09:39:06 +00:00
|
|
|
unsigned int patlen = config->ops->get_pattern_len(config);
|
2015-02-22 10:46:35 +00:00
|
|
|
struct ts_state state;
|
2006-06-26 07:00:57 +00:00
|
|
|
unsigned int ret;
|
|
|
|
|
2021-03-01 15:09:44 +00:00
|
|
|
BUILD_BUG_ON(sizeof(struct skb_seq_state) > sizeof(state.cb));
|
|
|
|
|
2005-06-24 04:00:17 +00:00
|
|
|
config->get_next_block = skb_ts_get_next_block;
|
|
|
|
config->finish = skb_ts_finish;
|
|
|
|
|
2015-02-22 10:46:35 +00:00
|
|
|
skb_prepare_seq_read(skb, from, to, TS_SKB_CB(&state));
|
2005-06-24 04:00:17 +00:00
|
|
|
|
2015-02-22 10:46:35 +00:00
|
|
|
ret = textsearch_find(config, &state);
|
2023-10-17 09:39:06 +00:00
|
|
|
return (ret + patlen <= to - from ? ret : UINT_MAX);
|
2005-06-24 04:00:17 +00:00
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL(skb_find_text);
|
2005-06-24 04:00:17 +00:00
|
|
|
|
2015-05-21 14:59:58 +00:00
|
|
|
int skb_append_pagefrags(struct sk_buff *skb, struct page *page,
|
2023-05-22 12:11:11 +00:00
|
|
|
int offset, size_t size, size_t max_frags)
|
2015-05-21 14:59:58 +00:00
|
|
|
{
|
|
|
|
int i = skb_shinfo(skb)->nr_frags;
|
|
|
|
|
|
|
|
if (skb_can_coalesce(skb, i, page, offset)) {
|
|
|
|
skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], size);
|
2023-05-22 12:11:11 +00:00
|
|
|
} else if (i < max_frags) {
|
2022-07-12 20:52:31 +00:00
|
|
|
skb_zcopy_downgrade_managed(skb);
|
2015-05-21 14:59:58 +00:00
|
|
|
get_page(page);
|
2022-10-27 04:03:46 +00:00
|
|
|
skb_fill_page_desc_noacc(skb, i, page, offset, size);
|
2015-05-21 14:59:58 +00:00
|
|
|
} else {
|
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_append_pagefrags);
|
|
|
|
|
2006-03-21 06:43:56 +00:00
|
|
|
/**
|
|
|
|
* skb_pull_rcsum - pull skb and update receive checksum
|
|
|
|
* @skb: buffer to update
|
|
|
|
* @len: length of data pulled
|
|
|
|
*
|
|
|
|
* This function performs an skb_pull on the packet and updates
|
2008-02-13 06:03:25 +00:00
|
|
|
* the CHECKSUM_COMPLETE checksum. It should be used on
|
2006-08-29 23:44:56 +00:00
|
|
|
* receive path processing instead of skb_pull unless you know
|
|
|
|
* that the checksum difference is zero (e.g., a valid IP header)
|
|
|
|
* or you are setting ip_summed to CHECKSUM_NONE.
|
2006-03-21 06:43:56 +00:00
|
|
|
*/
|
networking: make skb_pull & friends return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = {
skb_pull,
__skb_pull,
skb_pull_inline,
__pskb_pull_tail,
__pskb_pull,
pskb_pull
};
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = {
skb_pull,
__skb_pull,
skb_pull_inline,
__pskb_pull_tail,
__pskb_pull,
pskb_pull
};
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 12:29:22 +00:00
|
|
|
void *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
|
2006-03-21 06:43:56 +00:00
|
|
|
{
|
2015-09-29 00:24:25 +00:00
|
|
|
unsigned char *data = skb->data;
|
|
|
|
|
2006-03-21 06:43:56 +00:00
|
|
|
BUG_ON(len > skb->len);
|
2015-09-29 00:24:25 +00:00
|
|
|
__skb_pull(skb, len);
|
|
|
|
skb_postpull_rcsum(skb, data, len);
|
|
|
|
return skb->data;
|
2006-03-21 06:43:56 +00:00
|
|
|
}
|
2006-03-21 06:47:55 +00:00
|
|
|
EXPORT_SYMBOL_GPL(skb_pull_rcsum);
|
|
|
|
|
2018-03-21 23:31:03 +00:00
|
|
|
static inline skb_frag_t skb_head_frag_to_page_desc(struct sk_buff *frag_skb)
|
|
|
|
{
|
|
|
|
skb_frag_t head_frag;
|
|
|
|
struct page *page;
|
|
|
|
|
|
|
|
page = virt_to_head_page(frag_skb->head);
|
2023-05-11 01:12:12 +00:00
|
|
|
skb_frag_fill_page_desc(&head_frag, page, frag_skb->data -
|
|
|
|
(unsigned char *)page_address(page),
|
|
|
|
skb_headlen(frag_skb));
|
2018-03-21 23:31:03 +00:00
|
|
|
return head_frag;
|
|
|
|
}
|
|
|
|
|
2020-01-25 10:26:44 +00:00
|
|
|
struct sk_buff *skb_segment_list(struct sk_buff *skb,
|
|
|
|
netdev_features_t features,
|
|
|
|
unsigned int offset)
|
|
|
|
{
|
|
|
|
struct sk_buff *list_skb = skb_shinfo(skb)->frag_list;
|
|
|
|
unsigned int tnl_hlen = skb_tnl_header_len(skb);
|
|
|
|
unsigned int delta_truesize = 0;
|
|
|
|
unsigned int delta_len = 0;
|
|
|
|
struct sk_buff *tail = NULL;
|
2021-01-08 02:28:38 +00:00
|
|
|
struct sk_buff *nskb, *tmp;
|
net: fix wrong network header length
When clatd starts with ebpf offloaing, and NETIF_F_GRO_FRAGLIST is enable,
several skbs are gathered in skb_shinfo(skb)->frag_list. The first skb's
ipv6 header will be changed to ipv4 after bpf_skb_proto_6_to_4,
network_header\transport_header\mac_header have been updated as ipv4 acts,
but other skbs in frag_list didnot update anything, just ipv6 packets.
udp_queue_rcv_skb will call skb_segment_list to traverse other skbs in
frag_list and make sure right udp payload is delivered to user space.
Unfortunately, other skbs in frag_list who are still ipv6 packets are
updated like the first skb and will have wrong transport header length.
e.g.before bpf_skb_proto_6_to_4,the first skb and other skbs in frag_list
has the same network_header(24)& transport_header(64), after
bpf_skb_proto_6_to_4, ipv6 protocol has been changed to ipv4, the first
skb's network_header is 44,transport_header is 64, other skbs in frag_list
didnot change.After skb_segment_list, the other skbs in frag_list has
different network_header(24) and transport_header(44), so there will be 20
bytes different from original,that is difference between ipv6 header and
ipv4 header. Just change transport_header to be the same with original.
Actually, there are two solutions to fix it, one is traversing all skbs
and changing every skb header in bpf_skb_proto_6_to_4, the other is
modifying frag_list skb's header in skb_segment_list. Considering
efficiency, adopt the second one--- when the first skb and other skbs in
frag_list has different network_header length, restore them to make sure
right udp payload is delivered to user space.
Signed-off-by: Lina Wang <lina.wang@mediatek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-05 05:48:49 +00:00
|
|
|
int len_diff, err;
|
2020-01-25 10:26:44 +00:00
|
|
|
|
|
|
|
skb_push(skb, -skb_network_offset(skb) + offset);
|
|
|
|
|
2023-07-07 08:11:10 +00:00
|
|
|
/* Ensure the head is writeable before touching the shared info */
|
|
|
|
err = skb_unclone(skb, GFP_ATOMIC);
|
|
|
|
if (err)
|
|
|
|
goto err_linearize;
|
|
|
|
|
2020-01-25 10:26:44 +00:00
|
|
|
skb_shinfo(skb)->frag_list = NULL;
|
|
|
|
|
2023-01-30 20:51:48 +00:00
|
|
|
while (list_skb) {
|
2020-01-25 10:26:44 +00:00
|
|
|
nskb = list_skb;
|
|
|
|
list_skb = list_skb->next;
|
|
|
|
|
2021-01-08 02:28:38 +00:00
|
|
|
err = 0;
|
2022-03-01 11:17:09 +00:00
|
|
|
delta_truesize += nskb->truesize;
|
2021-01-08 02:28:38 +00:00
|
|
|
if (skb_shared(nskb)) {
|
|
|
|
tmp = skb_clone(nskb, GFP_ATOMIC);
|
|
|
|
if (tmp) {
|
|
|
|
consume_skb(nskb);
|
|
|
|
nskb = tmp;
|
|
|
|
err = skb_unclone(nskb, GFP_ATOMIC);
|
|
|
|
} else {
|
|
|
|
err = -ENOMEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-25 10:26:44 +00:00
|
|
|
if (!tail)
|
|
|
|
skb->next = nskb;
|
|
|
|
else
|
|
|
|
tail->next = nskb;
|
|
|
|
|
2021-01-08 02:28:38 +00:00
|
|
|
if (unlikely(err)) {
|
|
|
|
nskb->next = list_skb;
|
|
|
|
goto err_linearize;
|
|
|
|
}
|
|
|
|
|
2020-01-25 10:26:44 +00:00
|
|
|
tail = nskb;
|
|
|
|
|
|
|
|
delta_len += nskb->len;
|
|
|
|
|
|
|
|
skb_push(nskb, -skb_network_offset(nskb) + offset);
|
|
|
|
|
2020-03-30 16:51:29 +00:00
|
|
|
skb_release_head_state(nskb);
|
net: fix wrong network header length
When clatd starts with ebpf offloaing, and NETIF_F_GRO_FRAGLIST is enable,
several skbs are gathered in skb_shinfo(skb)->frag_list. The first skb's
ipv6 header will be changed to ipv4 after bpf_skb_proto_6_to_4,
network_header\transport_header\mac_header have been updated as ipv4 acts,
but other skbs in frag_list didnot update anything, just ipv6 packets.
udp_queue_rcv_skb will call skb_segment_list to traverse other skbs in
frag_list and make sure right udp payload is delivered to user space.
Unfortunately, other skbs in frag_list who are still ipv6 packets are
updated like the first skb and will have wrong transport header length.
e.g.before bpf_skb_proto_6_to_4,the first skb and other skbs in frag_list
has the same network_header(24)& transport_header(64), after
bpf_skb_proto_6_to_4, ipv6 protocol has been changed to ipv4, the first
skb's network_header is 44,transport_header is 64, other skbs in frag_list
didnot change.After skb_segment_list, the other skbs in frag_list has
different network_header(24) and transport_header(44), so there will be 20
bytes different from original,that is difference between ipv6 header and
ipv4 header. Just change transport_header to be the same with original.
Actually, there are two solutions to fix it, one is traversing all skbs
and changing every skb header in bpf_skb_proto_6_to_4, the other is
modifying frag_list skb's header in skb_segment_list. Considering
efficiency, adopt the second one--- when the first skb and other skbs in
frag_list has different network_header length, restore them to make sure
right udp payload is delivered to user space.
Signed-off-by: Lina Wang <lina.wang@mediatek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-05 05:48:49 +00:00
|
|
|
len_diff = skb_network_header_len(nskb) - skb_network_header_len(skb);
|
2021-09-02 22:56:23 +00:00
|
|
|
__copy_skb_header(nskb, skb);
|
2020-01-25 10:26:44 +00:00
|
|
|
|
|
|
|
skb_headers_offset_update(nskb, skb_headroom(nskb) - skb_headroom(skb));
|
net: fix wrong network header length
When clatd starts with ebpf offloaing, and NETIF_F_GRO_FRAGLIST is enable,
several skbs are gathered in skb_shinfo(skb)->frag_list. The first skb's
ipv6 header will be changed to ipv4 after bpf_skb_proto_6_to_4,
network_header\transport_header\mac_header have been updated as ipv4 acts,
but other skbs in frag_list didnot update anything, just ipv6 packets.
udp_queue_rcv_skb will call skb_segment_list to traverse other skbs in
frag_list and make sure right udp payload is delivered to user space.
Unfortunately, other skbs in frag_list who are still ipv6 packets are
updated like the first skb and will have wrong transport header length.
e.g.before bpf_skb_proto_6_to_4,the first skb and other skbs in frag_list
has the same network_header(24)& transport_header(64), after
bpf_skb_proto_6_to_4, ipv6 protocol has been changed to ipv4, the first
skb's network_header is 44,transport_header is 64, other skbs in frag_list
didnot change.After skb_segment_list, the other skbs in frag_list has
different network_header(24) and transport_header(44), so there will be 20
bytes different from original,that is difference between ipv6 header and
ipv4 header. Just change transport_header to be the same with original.
Actually, there are two solutions to fix it, one is traversing all skbs
and changing every skb header in bpf_skb_proto_6_to_4, the other is
modifying frag_list skb's header in skb_segment_list. Considering
efficiency, adopt the second one--- when the first skb and other skbs in
frag_list has different network_header length, restore them to make sure
right udp payload is delivered to user space.
Signed-off-by: Lina Wang <lina.wang@mediatek.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-05 05:48:49 +00:00
|
|
|
nskb->transport_header += len_diff;
|
2020-01-25 10:26:44 +00:00
|
|
|
skb_copy_from_linear_data_offset(skb, -tnl_hlen,
|
|
|
|
nskb->data - tnl_hlen,
|
|
|
|
offset + tnl_hlen);
|
|
|
|
|
|
|
|
if (skb_needs_linearize(nskb, features) &&
|
|
|
|
__skb_linearize(nskb))
|
|
|
|
goto err_linearize;
|
2023-01-30 20:51:48 +00:00
|
|
|
}
|
2020-01-25 10:26:44 +00:00
|
|
|
|
|
|
|
skb->truesize = skb->truesize - delta_truesize;
|
|
|
|
skb->data_len = skb->data_len - delta_len;
|
|
|
|
skb->len = skb->len - delta_len;
|
|
|
|
|
|
|
|
skb_gso_reset(skb);
|
|
|
|
|
|
|
|
skb->prev = tail;
|
|
|
|
|
|
|
|
if (skb_needs_linearize(skb, features) &&
|
|
|
|
__skb_linearize(skb))
|
|
|
|
goto err_linearize;
|
|
|
|
|
|
|
|
skb_get(skb);
|
|
|
|
|
|
|
|
return skb;
|
|
|
|
|
|
|
|
err_linearize:
|
|
|
|
kfree_skb_list(skb->next);
|
|
|
|
skb->next = NULL;
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_segment_list);
|
|
|
|
|
2006-06-22 10:02:40 +00:00
|
|
|
/**
|
|
|
|
* skb_segment - Perform protocol segmentation on skb.
|
2014-03-10 16:29:19 +00:00
|
|
|
* @head_skb: buffer to segment
|
2006-06-27 20:22:38 +00:00
|
|
|
* @features: features for the output path (see dev->features)
|
2006-06-22 10:02:40 +00:00
|
|
|
*
|
|
|
|
* This function performs segmentation on the given skb. It returns
|
2008-04-14 04:52:48 +00:00
|
|
|
* a pointer to the first in a list of new skbs for the segments.
|
|
|
|
* In case of error it returns ERR_PTR(err).
|
2006-06-22 10:02:40 +00:00
|
|
|
*/
|
2014-03-10 16:29:19 +00:00
|
|
|
struct sk_buff *skb_segment(struct sk_buff *head_skb,
|
|
|
|
netdev_features_t features)
|
2006-06-22 10:02:40 +00:00
|
|
|
{
|
|
|
|
struct sk_buff *segs = NULL;
|
|
|
|
struct sk_buff *tail = NULL;
|
2014-03-10 17:27:59 +00:00
|
|
|
struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list;
|
2014-03-10 16:29:19 +00:00
|
|
|
unsigned int mss = skb_shinfo(head_skb)->gso_size;
|
|
|
|
unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
|
2006-06-22 10:02:40 +00:00
|
|
|
unsigned int offset = doffset;
|
2014-03-10 16:29:19 +00:00
|
|
|
unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
|
2016-04-11 01:45:03 +00:00
|
|
|
unsigned int partial_segs = 0;
|
2006-06-22 10:02:40 +00:00
|
|
|
unsigned int headroom;
|
2016-04-11 01:45:03 +00:00
|
|
|
unsigned int len = head_skb->len;
|
2023-08-31 08:17:02 +00:00
|
|
|
struct sk_buff *frag_skb;
|
|
|
|
skb_frag_t *frag;
|
2013-03-07 09:28:01 +00:00
|
|
|
__be16 proto;
|
2016-05-02 16:38:18 +00:00
|
|
|
bool csum, sg;
|
2006-06-22 10:02:40 +00:00
|
|
|
int err = -ENOMEM;
|
|
|
|
int i = 0;
|
2023-08-31 08:17:02 +00:00
|
|
|
int nfrags, pos;
|
2006-06-22 10:02:40 +00:00
|
|
|
|
net: gso: fix panic on frag_list with mixed head alloc types
Since commit 3dcbdb134f32 ("net: gso: Fix skb_segment splat when
splitting gso_size mangled skb having linear-headed frag_list"), it is
allowed to change gso_size of a GRO packet. However, that commit assumes
that "checking the first list_skb member suffices; i.e if either of the
list_skb members have non head_frag head, then the first one has too".
It turns out this assumption does not hold. We've seen BUG_ON being hit
in skb_segment when skbs on the frag_list had differing head_frag with
the vmxnet3 driver. This happens because __netdev_alloc_skb and
__napi_alloc_skb can return a skb that is page backed or kmalloced
depending on the requested size. As the result, the last small skb in
the GRO packet can be kmalloced.
There are three different locations where this can be fixed:
(1) We could check head_frag in GRO and not allow GROing skbs with
different head_frag. However, that would lead to performance
regression on normal forward paths with unmodified gso_size, where
!head_frag in the last packet is not a problem.
(2) Set a flag in bpf_skb_net_grow and bpf_skb_net_shrink indicating
that NETIF_F_SG is undesirable. That would need to eat a bit in
sk_buff. Furthermore, that flag can be unset when all skbs on the
frag_list are page backed. To retain good performance,
bpf_skb_net_grow/shrink would have to walk the frag_list.
(3) Walk the frag_list in skb_segment when determining whether
NETIF_F_SG should be cleared. This of course slows things down.
This patch implements (3). To limit the performance impact in
skb_segment, the list is walked only for skbs with SKB_GSO_DODGY set
that have gso_size changed. Normal paths thus will not hit it.
We could check only the last skb but since we need to walk the whole
list anyway, let's stay on the safe side.
Fixes: 3dcbdb134f32 ("net: gso: Fix skb_segment splat when splitting gso_size mangled skb having linear-headed frag_list")
Signed-off-by: Jiri Benc <jbenc@redhat.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://lore.kernel.org/r/e04426a6a91baf4d1081e1b478c82b5de25fdf21.1667407944.git.jbenc@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-11-02 16:53:25 +00:00
|
|
|
if ((skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY) &&
|
|
|
|
mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb)) {
|
|
|
|
struct sk_buff *check_skb;
|
|
|
|
|
|
|
|
for (check_skb = list_skb; check_skb; check_skb = check_skb->next) {
|
|
|
|
if (skb_headlen(check_skb) && !check_skb->head_frag) {
|
|
|
|
/* gso_size is untrusted, and we have a frag_list with
|
|
|
|
* a linear non head_frag item.
|
|
|
|
*
|
|
|
|
* If head_skb's headlen does not fit requested gso_size,
|
|
|
|
* it means that the frag_list members do NOT terminate
|
|
|
|
* on exact gso_size boundaries. Hence we cannot perform
|
|
|
|
* skb_frag_t page sharing. Therefore we must fallback to
|
|
|
|
* copying the frag_list skbs; we do so by disabling SG.
|
|
|
|
*/
|
|
|
|
features &= ~NETIF_F_SG;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
net: gso: Fix skb_segment splat when splitting gso_size mangled skb having linear-headed frag_list
Historically, support for frag_list packets entering skb_segment() was
limited to frag_list members terminating on exact same gso_size
boundaries. This is verified with a BUG_ON since commit 89319d3801d1
("net: Add frag_list support to skb_segment"), quote:
As such we require all frag_list members terminate on exact MSS
boundaries. This is checked using BUG_ON.
As there should only be one producer in the kernel of such packets,
namely GRO, this requirement should not be difficult to maintain.
However, since commit 6578171a7ff0 ("bpf: add bpf_skb_change_proto helper"),
the "exact MSS boundaries" assumption no longer holds:
An eBPF program using bpf_skb_change_proto() DOES modify 'gso_size', but
leaves the frag_list members as originally merged by GRO with the
original 'gso_size'. Example of such programs are bpf-based NAT46 or
NAT64.
This lead to a kernel BUG_ON for flows involving:
- GRO generating a frag_list skb
- bpf program performing bpf_skb_change_proto() or bpf_skb_adjust_room()
- skb_segment() of the skb
See example BUG_ON reports in [0].
In commit 13acc94eff12 ("net: permit skb_segment on head_frag frag_list skb"),
skb_segment() was modified to support the "gso_size mangling" case of
a frag_list GRO'ed skb, but *only* for frag_list members having
head_frag==true (having a page-fragment head).
Alas, GRO packets having frag_list members with a linear kmalloced head
(head_frag==false) still hit the BUG_ON.
This commit adds support to skb_segment() for a 'head_skb' packet having
a frag_list whose members are *non* head_frag, with gso_size mangled, by
disabling SG and thus falling-back to copying the data from the given
'head_skb' into the generated segmented skbs - as suggested by Willem de
Bruijn [1].
Since this approach involves the penalty of skb_copy_and_csum_bits()
when building the segments, care was taken in order to enable this
solution only when required:
- untrusted gso_size, by testing SKB_GSO_DODGY is set
(SKB_GSO_DODGY is set by any gso_size mangling functions in
net/core/filter.c)
- the frag_list is non empty, its item is a non head_frag, *and* the
headlen of the given 'head_skb' does not match the gso_size.
[0]
https://lore.kernel.org/netdev/20190826170724.25ff616f@pixies/
https://lore.kernel.org/netdev/9265b93f-253d-6b8c-f2b8-4b54eff1835c@fb.com/
[1]
https://lore.kernel.org/netdev/CA+FuTSfVsgNDi7c=GUU8nMg2hWxF2SjCNLXetHeVPdnxAW5K-w@mail.gmail.com/
Fixes: 6578171a7ff0 ("bpf: add bpf_skb_change_proto helper")
Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Alexander Duyck <alexander.duyck@gmail.com>
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Alexander Duyck <alexander.h.duyck@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-09-06 09:23:50 +00:00
|
|
|
}
|
|
|
|
|
2014-06-09 06:48:54 +00:00
|
|
|
__skb_push(head_skb, doffset);
|
2020-08-01 09:36:05 +00:00
|
|
|
proto = skb_network_protocol(head_skb, NULL);
|
2013-03-07 09:28:01 +00:00
|
|
|
if (unlikely(!proto))
|
|
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
2016-05-02 16:38:18 +00:00
|
|
|
sg = !!(features & NETIF_F_SG);
|
2016-02-05 23:28:26 +00:00
|
|
|
csum = !!can_checksum_protocol(features, proto);
|
2014-06-05 00:20:02 +00:00
|
|
|
|
2016-09-19 10:58:47 +00:00
|
|
|
if (sg && csum && (mss != GSO_BY_FRAGS)) {
|
|
|
|
if (!(features & NETIF_F_GSO_PARTIAL)) {
|
|
|
|
struct sk_buff *iter;
|
2017-04-19 18:26:07 +00:00
|
|
|
unsigned int frag_len;
|
2016-09-19 10:58:47 +00:00
|
|
|
|
|
|
|
if (!list_skb ||
|
|
|
|
!net_gso_ok(features, skb_shinfo(head_skb)->gso_type))
|
|
|
|
goto normal;
|
|
|
|
|
2017-04-19 18:26:07 +00:00
|
|
|
/* If we get here then all the required
|
|
|
|
* GSO features except frag_list are supported.
|
|
|
|
* Try to split the SKB to multiple GSO SKBs
|
|
|
|
* with no frag_list.
|
|
|
|
* Currently we can do that only when the buffers don't
|
|
|
|
* have a linear part and all the buffers except
|
|
|
|
* the last are of the same length.
|
2016-09-19 10:58:47 +00:00
|
|
|
*/
|
2017-04-19 18:26:07 +00:00
|
|
|
frag_len = list_skb->len;
|
2016-09-19 10:58:47 +00:00
|
|
|
skb_walk_frags(head_skb, iter) {
|
2017-04-19 18:26:07 +00:00
|
|
|
if (frag_len != iter->len && iter->next)
|
|
|
|
goto normal;
|
2017-04-07 23:07:08 +00:00
|
|
|
if (skb_headlen(iter) && !iter->head_frag)
|
2016-09-19 10:58:47 +00:00
|
|
|
goto normal;
|
|
|
|
|
|
|
|
len -= iter->len;
|
|
|
|
}
|
2017-04-19 18:26:07 +00:00
|
|
|
|
|
|
|
if (len != frag_len)
|
|
|
|
goto normal;
|
2016-09-19 10:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* GSO partial only requires that we trim off any excess that
|
|
|
|
* doesn't fit into an MSS sized block, so take care of that
|
|
|
|
* now.
|
2023-12-12 16:46:21 +00:00
|
|
|
* Cap len to not accidentally hit GSO_BY_FRAGS.
|
2016-09-19 10:58:47 +00:00
|
|
|
*/
|
2023-12-12 16:46:21 +00:00
|
|
|
partial_segs = min(len, GSO_BY_FRAGS - 1) / mss;
|
2016-05-02 16:38:12 +00:00
|
|
|
if (partial_segs > 1)
|
|
|
|
mss *= partial_segs;
|
|
|
|
else
|
|
|
|
partial_segs = 0;
|
2016-04-11 01:45:03 +00:00
|
|
|
}
|
|
|
|
|
2016-09-19 10:58:47 +00:00
|
|
|
normal:
|
2014-03-10 16:29:19 +00:00
|
|
|
headroom = skb_headroom(head_skb);
|
|
|
|
pos = skb_headlen(head_skb);
|
2006-06-22 10:02:40 +00:00
|
|
|
|
2023-08-31 08:17:02 +00:00
|
|
|
if (skb_orphan_frags(head_skb, GFP_ATOMIC))
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
nfrags = skb_shinfo(head_skb)->nr_frags;
|
|
|
|
frag = skb_shinfo(head_skb)->frags;
|
|
|
|
frag_skb = head_skb;
|
|
|
|
|
2006-06-22 10:02:40 +00:00
|
|
|
do {
|
|
|
|
struct sk_buff *nskb;
|
2014-03-10 16:29:04 +00:00
|
|
|
skb_frag_t *nskb_frag;
|
2006-10-29 23:59:41 +00:00
|
|
|
int hsize;
|
2006-06-22 10:02:40 +00:00
|
|
|
int size;
|
|
|
|
|
2016-06-02 18:05:40 +00:00
|
|
|
if (unlikely(mss == GSO_BY_FRAGS)) {
|
|
|
|
len = list_skb->len;
|
|
|
|
} else {
|
|
|
|
len = head_skb->len - offset;
|
|
|
|
if (len > mss)
|
|
|
|
len = mss;
|
|
|
|
}
|
2006-06-22 10:02:40 +00:00
|
|
|
|
2014-03-10 16:29:19 +00:00
|
|
|
hsize = skb_headlen(head_skb) - offset;
|
2006-06-22 10:02:40 +00:00
|
|
|
|
2021-01-15 09:36:38 +00:00
|
|
|
if (hsize <= 0 && i >= nfrags && skb_headlen(list_skb) &&
|
2014-03-10 17:27:59 +00:00
|
|
|
(skb_headlen(list_skb) == len || sg)) {
|
|
|
|
BUG_ON(skb_headlen(list_skb) > len);
|
2013-11-21 19:10:04 +00:00
|
|
|
|
2023-08-31 08:17:02 +00:00
|
|
|
nskb = skb_clone(list_skb, GFP_ATOMIC);
|
|
|
|
if (unlikely(!nskb))
|
|
|
|
goto err;
|
|
|
|
|
2013-11-21 19:10:04 +00:00
|
|
|
i = 0;
|
2014-03-10 17:27:59 +00:00
|
|
|
nfrags = skb_shinfo(list_skb)->nr_frags;
|
|
|
|
frag = skb_shinfo(list_skb)->frags;
|
2014-03-10 17:28:08 +00:00
|
|
|
frag_skb = list_skb;
|
2014-03-10 17:27:59 +00:00
|
|
|
pos += skb_headlen(list_skb);
|
2013-11-21 19:10:04 +00:00
|
|
|
|
|
|
|
while (pos < offset + len) {
|
|
|
|
BUG_ON(i >= nfrags);
|
|
|
|
|
2014-03-10 16:29:14 +00:00
|
|
|
size = skb_frag_size(frag);
|
2013-11-21 19:10:04 +00:00
|
|
|
if (pos + size > offset + len)
|
|
|
|
break;
|
|
|
|
|
|
|
|
i++;
|
|
|
|
pos += size;
|
2014-03-10 16:29:14 +00:00
|
|
|
frag++;
|
2013-11-21 19:10:04 +00:00
|
|
|
}
|
2008-12-16 07:26:06 +00:00
|
|
|
|
2014-03-10 17:27:59 +00:00
|
|
|
list_skb = list_skb->next;
|
2008-12-16 07:26:06 +00:00
|
|
|
|
2013-11-21 19:10:04 +00:00
|
|
|
if (unlikely(pskb_trim(nskb, len))) {
|
|
|
|
kfree_skb(nskb);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2012-05-04 14:26:56 +00:00
|
|
|
hsize = skb_end_offset(nskb);
|
2008-12-16 07:26:06 +00:00
|
|
|
if (skb_cow_head(nskb, doffset + headroom)) {
|
|
|
|
kfree_skb(nskb);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2012-05-04 14:26:56 +00:00
|
|
|
nskb->truesize += skb_end_offset(nskb) - hsize;
|
2008-12-16 07:26:06 +00:00
|
|
|
skb_release_head_state(nskb);
|
|
|
|
__skb_push(nskb, doffset);
|
|
|
|
} else {
|
2021-01-19 16:56:56 +00:00
|
|
|
if (hsize < 0)
|
|
|
|
hsize = 0;
|
2021-01-15 09:36:38 +00:00
|
|
|
if (hsize > len || !sg)
|
|
|
|
hsize = len;
|
|
|
|
|
2012-07-31 23:44:19 +00:00
|
|
|
nskb = __alloc_skb(hsize + doffset + headroom,
|
2014-03-10 16:29:19 +00:00
|
|
|
GFP_ATOMIC, skb_alloc_rx_flag(head_skb),
|
2012-07-31 23:44:19 +00:00
|
|
|
NUMA_NO_NODE);
|
2008-12-16 07:26:06 +00:00
|
|
|
|
|
|
|
if (unlikely(!nskb))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
skb_reserve(nskb, headroom);
|
|
|
|
__skb_put(nskb, doffset);
|
|
|
|
}
|
2006-06-22 10:02:40 +00:00
|
|
|
|
|
|
|
if (segs)
|
|
|
|
tail->next = nskb;
|
|
|
|
else
|
|
|
|
segs = nskb;
|
|
|
|
tail = nskb;
|
|
|
|
|
2014-03-10 16:29:19 +00:00
|
|
|
__copy_skb_header(nskb, head_skb);
|
2006-06-22 10:02:40 +00:00
|
|
|
|
2013-10-19 18:42:54 +00:00
|
|
|
skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom);
|
2014-07-31 14:33:06 +00:00
|
|
|
skb_reset_mac_len(nskb);
|
2013-02-14 14:02:41 +00:00
|
|
|
|
2014-03-10 16:29:19 +00:00
|
|
|
skb_copy_from_linear_data_offset(head_skb, -tnl_hlen,
|
2013-02-14 14:02:41 +00:00
|
|
|
nskb->data - tnl_hlen,
|
|
|
|
doffset + tnl_hlen);
|
2008-12-16 07:26:06 +00:00
|
|
|
|
2013-11-21 19:10:04 +00:00
|
|
|
if (nskb->len == len + doffset)
|
2013-05-19 15:46:49 +00:00
|
|
|
goto perform_csum_check;
|
2008-12-16 07:26:06 +00:00
|
|
|
|
2016-02-05 23:27:43 +00:00
|
|
|
if (!sg) {
|
2020-03-17 08:38:38 +00:00
|
|
|
if (!csum) {
|
|
|
|
if (!nskb->remcsum_offload)
|
|
|
|
nskb->ip_summed = CHECKSUM_NONE;
|
|
|
|
SKB_GSO_CB(nskb)->csum =
|
|
|
|
skb_copy_and_csum_bits(head_skb, offset,
|
|
|
|
skb_put(nskb,
|
|
|
|
len),
|
2020-07-11 00:07:10 +00:00
|
|
|
len);
|
2020-03-17 08:38:38 +00:00
|
|
|
SKB_GSO_CB(nskb)->csum_start =
|
|
|
|
skb_headroom(nskb) + doffset;
|
|
|
|
} else {
|
2022-08-23 05:44:11 +00:00
|
|
|
if (skb_copy_bits(head_skb, offset, skb_put(nskb, len), len))
|
|
|
|
goto err;
|
2020-03-17 08:38:38 +00:00
|
|
|
}
|
2006-06-22 10:02:40 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-03-10 16:29:04 +00:00
|
|
|
nskb_frag = skb_shinfo(nskb)->frags;
|
2006-06-22 10:02:40 +00:00
|
|
|
|
2014-03-10 16:29:19 +00:00
|
|
|
skb_copy_from_linear_data_offset(head_skb, offset,
|
2007-03-27 21:55:52 +00:00
|
|
|
skb_put(nskb, hsize), hsize);
|
2006-06-22 10:02:40 +00:00
|
|
|
|
2021-01-06 22:18:38 +00:00
|
|
|
skb_shinfo(nskb)->flags |= skb_shinfo(head_skb)->flags &
|
|
|
|
SKBFL_SHARED_FRAG;
|
2013-01-25 20:34:37 +00:00
|
|
|
|
2023-08-31 08:17:02 +00:00
|
|
|
if (skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC))
|
2017-12-23 00:00:17 +00:00
|
|
|
goto err;
|
|
|
|
|
2013-11-21 19:10:04 +00:00
|
|
|
while (pos < offset + len) {
|
|
|
|
if (i >= nfrags) {
|
2023-08-31 08:17:02 +00:00
|
|
|
if (skb_orphan_frags(list_skb, GFP_ATOMIC) ||
|
|
|
|
skb_zerocopy_clone(nskb, list_skb,
|
|
|
|
GFP_ATOMIC))
|
|
|
|
goto err;
|
|
|
|
|
2013-11-21 19:10:04 +00:00
|
|
|
i = 0;
|
2014-03-10 17:27:59 +00:00
|
|
|
nfrags = skb_shinfo(list_skb)->nr_frags;
|
|
|
|
frag = skb_shinfo(list_skb)->frags;
|
2014-03-10 17:28:08 +00:00
|
|
|
frag_skb = list_skb;
|
2018-03-21 23:31:03 +00:00
|
|
|
if (!skb_headlen(list_skb)) {
|
|
|
|
BUG_ON(!nfrags);
|
|
|
|
} else {
|
|
|
|
BUG_ON(!list_skb->head_frag);
|
2013-11-21 19:10:04 +00:00
|
|
|
|
2018-03-21 23:31:03 +00:00
|
|
|
/* to make room for head_frag. */
|
|
|
|
i--;
|
|
|
|
frag--;
|
|
|
|
}
|
2017-12-23 00:00:17 +00:00
|
|
|
|
2014-03-10 17:27:59 +00:00
|
|
|
list_skb = list_skb->next;
|
2013-11-21 19:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (unlikely(skb_shinfo(nskb)->nr_frags >=
|
|
|
|
MAX_SKB_FRAGS)) {
|
|
|
|
net_warn_ratelimited(
|
|
|
|
"skb_segment: too many frags: %u %u\n",
|
|
|
|
pos, mss);
|
2018-07-19 23:04:38 +00:00
|
|
|
err = -EINVAL;
|
2013-11-21 19:10:04 +00:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2018-03-21 23:31:03 +00:00
|
|
|
*nskb_frag = (i < 0) ? skb_head_frag_to_page_desc(frag_skb) : *frag;
|
2024-05-02 17:54:22 +00:00
|
|
|
__skb_frag_ref(nskb_frag);
|
2014-03-10 16:29:04 +00:00
|
|
|
size = skb_frag_size(nskb_frag);
|
2006-06-22 10:02:40 +00:00
|
|
|
|
|
|
|
if (pos < offset) {
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off_add(nskb_frag, offset - pos);
|
2014-03-10 16:29:04 +00:00
|
|
|
skb_frag_size_sub(nskb_frag, offset - pos);
|
2006-06-22 10:02:40 +00:00
|
|
|
}
|
|
|
|
|
2008-12-16 07:26:06 +00:00
|
|
|
skb_shinfo(nskb)->nr_frags++;
|
2006-06-22 10:02:40 +00:00
|
|
|
|
|
|
|
if (pos + size <= offset + len) {
|
|
|
|
i++;
|
2014-03-10 16:29:14 +00:00
|
|
|
frag++;
|
2006-06-22 10:02:40 +00:00
|
|
|
pos += size;
|
|
|
|
} else {
|
2014-03-10 16:29:04 +00:00
|
|
|
skb_frag_size_sub(nskb_frag, pos + size - (offset + len));
|
2008-12-16 07:26:06 +00:00
|
|
|
goto skip_fraglist;
|
2006-06-22 10:02:40 +00:00
|
|
|
}
|
|
|
|
|
2014-03-10 16:29:04 +00:00
|
|
|
nskb_frag++;
|
2006-06-22 10:02:40 +00:00
|
|
|
}
|
|
|
|
|
2008-12-16 07:26:06 +00:00
|
|
|
skip_fraglist:
|
2006-06-22 10:02:40 +00:00
|
|
|
nskb->data_len = len - hsize;
|
|
|
|
nskb->len += nskb->data_len;
|
|
|
|
nskb->truesize += nskb->data_len;
|
2013-03-07 09:28:01 +00:00
|
|
|
|
2013-05-19 15:46:49 +00:00
|
|
|
perform_csum_check:
|
2016-02-05 23:27:43 +00:00
|
|
|
if (!csum) {
|
2018-07-19 23:04:38 +00:00
|
|
|
if (skb_has_shared_frag(nskb) &&
|
|
|
|
__skb_linearize(nskb))
|
|
|
|
goto err;
|
|
|
|
|
2016-02-05 23:27:43 +00:00
|
|
|
if (!nskb->remcsum_offload)
|
|
|
|
nskb->ip_summed = CHECKSUM_NONE;
|
2016-02-05 23:27:37 +00:00
|
|
|
SKB_GSO_CB(nskb)->csum =
|
|
|
|
skb_checksum(nskb, doffset,
|
|
|
|
nskb->len - doffset, 0);
|
2014-06-05 00:20:02 +00:00
|
|
|
SKB_GSO_CB(nskb)->csum_start =
|
2016-02-05 23:27:37 +00:00
|
|
|
skb_headroom(nskb) + doffset;
|
2013-03-07 09:28:01 +00:00
|
|
|
}
|
2014-03-10 16:29:19 +00:00
|
|
|
} while ((offset += len) < head_skb->len);
|
2006-06-22 10:02:40 +00:00
|
|
|
|
2014-10-04 03:59:19 +00:00
|
|
|
/* Some callers want to get the end of the list.
|
|
|
|
* Put it in segs->prev to avoid walking the list.
|
|
|
|
* (see validate_xmit_skb_list() for example)
|
|
|
|
*/
|
|
|
|
segs->prev = tail;
|
2014-10-27 17:30:51 +00:00
|
|
|
|
2016-04-11 01:45:03 +00:00
|
|
|
if (partial_segs) {
|
2016-09-19 10:58:47 +00:00
|
|
|
struct sk_buff *iter;
|
2016-04-11 01:45:03 +00:00
|
|
|
int type = skb_shinfo(head_skb)->gso_type;
|
2016-09-19 10:58:47 +00:00
|
|
|
unsigned short gso_size = skb_shinfo(head_skb)->gso_size;
|
2016-04-11 01:45:03 +00:00
|
|
|
|
|
|
|
/* Update type to add partial and then remove dodgy if set */
|
2016-09-19 10:58:47 +00:00
|
|
|
type |= (features & NETIF_F_GSO_PARTIAL) / NETIF_F_GSO_PARTIAL * SKB_GSO_PARTIAL;
|
2016-04-11 01:45:03 +00:00
|
|
|
type &= ~SKB_GSO_DODGY;
|
|
|
|
|
|
|
|
/* Update GSO info and prepare to start updating headers on
|
|
|
|
* our way back down the stack of protocols.
|
|
|
|
*/
|
2016-09-19 10:58:47 +00:00
|
|
|
for (iter = segs; iter; iter = iter->next) {
|
|
|
|
skb_shinfo(iter)->gso_size = gso_size;
|
|
|
|
skb_shinfo(iter)->gso_segs = partial_segs;
|
|
|
|
skb_shinfo(iter)->gso_type = type;
|
|
|
|
SKB_GSO_CB(iter)->data_offset = skb_headroom(iter) + doffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tail->len - doffset <= gso_size)
|
|
|
|
skb_shinfo(tail)->gso_size = 0;
|
|
|
|
else if (tail != segs)
|
|
|
|
skb_shinfo(tail)->gso_segs = DIV_ROUND_UP(tail->len - doffset, gso_size);
|
2016-04-11 01:45:03 +00:00
|
|
|
}
|
|
|
|
|
2014-10-27 17:30:51 +00:00
|
|
|
/* Following permits correct backpressure, for protocols
|
|
|
|
* using skb_set_owner_w().
|
|
|
|
* Idea is to tranfert ownership from head_skb to last segment.
|
|
|
|
*/
|
|
|
|
if (head_skb->destructor == sock_wfree) {
|
|
|
|
swap(tail->truesize, head_skb->truesize);
|
|
|
|
swap(tail->destructor, head_skb->destructor);
|
|
|
|
swap(tail->sk, head_skb->sk);
|
|
|
|
}
|
2006-06-22 10:02:40 +00:00
|
|
|
return segs;
|
|
|
|
|
|
|
|
err:
|
2013-12-20 22:29:08 +00:00
|
|
|
kfree_skb_list(segs);
|
2006-06-22 10:02:40 +00:00
|
|
|
return ERR_PTR(err);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_segment);
|
|
|
|
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
#ifdef CONFIG_SKB_EXTENSIONS
|
|
|
|
#define SKB_EXT_ALIGN_VALUE 8
|
|
|
|
#define SKB_EXT_CHUNKSIZEOF(x) (ALIGN((sizeof(x)), SKB_EXT_ALIGN_VALUE) / SKB_EXT_ALIGN_VALUE)
|
|
|
|
|
|
|
|
static const u8 skb_ext_type_len[] = {
|
|
|
|
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
|
|
|
|
[SKB_EXT_BRIDGE_NF] = SKB_EXT_CHUNKSIZEOF(struct nf_bridge_info),
|
|
|
|
#endif
|
2018-12-18 16:15:27 +00:00
|
|
|
#ifdef CONFIG_XFRM
|
|
|
|
[SKB_EXT_SEC_PATH] = SKB_EXT_CHUNKSIZEOF(struct sec_path),
|
|
|
|
#endif
|
net: openvswitch: Set OvS recirc_id from tc chain index
Offloaded OvS datapath rules are translated one to one to tc rules,
for example the following simplified OvS rule:
recirc_id(0),in_port(dev1),eth_type(0x0800),ct_state(-trk) actions:ct(),recirc(2)
Will be translated to the following tc rule:
$ tc filter add dev dev1 ingress \
prio 1 chain 0 proto ip \
flower tcp ct_state -trk \
action ct pipe \
action goto chain 2
Received packets will first travel though tc, and if they aren't stolen
by it, like in the above rule, they will continue to OvS datapath.
Since we already did some actions (action ct in this case) which might
modify the packets, and updated action stats, we would like to continue
the proccessing with the correct recirc_id in OvS (here recirc_id(2))
where we left off.
To support this, introduce a new skb extension for tc, which
will be used for translating tc chain to ovs recirc_id to
handle these miss cases. Last tc chain index will be set
by tc goto chain action and read by OvS datapath.
Signed-off-by: Paul Blakey <paulb@mellanox.com>
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-09-04 13:56:37 +00:00
|
|
|
#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
|
|
|
|
[TC_SKB_EXT] = SKB_EXT_CHUNKSIZEOF(struct tc_skb_ext),
|
|
|
|
#endif
|
2020-01-09 15:59:19 +00:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP)
|
|
|
|
[SKB_EXT_MPTCP] = SKB_EXT_CHUNKSIZEOF(struct mptcp_ext),
|
|
|
|
#endif
|
2021-10-29 03:01:44 +00:00
|
|
|
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
|
|
|
|
[SKB_EXT_MCTP] = SKB_EXT_CHUNKSIZEOF(struct mctp_flow),
|
|
|
|
#endif
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static __always_inline unsigned int skb_ext_total_length(void)
|
|
|
|
{
|
2023-08-23 09:28:38 +00:00
|
|
|
unsigned int l = SKB_EXT_CHUNKSIZEOF(struct skb_ext);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(skb_ext_type_len); i++)
|
|
|
|
l += skb_ext_type_len[i];
|
|
|
|
|
|
|
|
return l;
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void skb_extensions_init(void)
|
|
|
|
{
|
|
|
|
BUILD_BUG_ON(SKB_EXT_NUM >= 8);
|
2023-12-18 17:06:54 +00:00
|
|
|
#if !IS_ENABLED(CONFIG_KCOV_INSTRUMENT_ALL)
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
BUILD_BUG_ON(skb_ext_total_length() > 255);
|
2023-12-18 17:06:54 +00:00
|
|
|
#endif
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
|
|
|
|
skbuff_ext_cache = kmem_cache_create("skbuff_ext_cache",
|
|
|
|
SKB_EXT_ALIGN_VALUE * skb_ext_total_length(),
|
|
|
|
0,
|
|
|
|
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static void skb_extensions_init(void) {}
|
|
|
|
#endif
|
|
|
|
|
2023-08-15 15:17:36 +00:00
|
|
|
/* The SKB kmem_cache slab is critical for network performance. Never
|
|
|
|
* merge/alias the slab with similar sized objects. This avoids fragmentation
|
|
|
|
* that hurts performance of kmem_cache_{alloc,free}_bulk APIs.
|
|
|
|
*/
|
|
|
|
#ifndef CONFIG_SLUB_TINY
|
|
|
|
#define FLAG_SKB_NO_MERGE SLAB_NO_MERGE
|
|
|
|
#else /* CONFIG_SLUB_TINY - simple loop in kmem_cache_alloc_bulk */
|
|
|
|
#define FLAG_SKB_NO_MERGE 0
|
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
void __init skb_init(void)
|
|
|
|
{
|
2024-03-06 16:00:23 +00:00
|
|
|
net_hotdata.skbuff_cache = kmem_cache_create_usercopy("skbuff_head_cache",
|
2005-04-16 22:20:36 +00:00
|
|
|
sizeof(struct sk_buff),
|
|
|
|
0,
|
2023-08-15 15:17:36 +00:00
|
|
|
SLAB_HWCACHE_ALIGN|SLAB_PANIC|
|
|
|
|
FLAG_SKB_NO_MERGE,
|
2018-02-08 01:44:38 +00:00
|
|
|
offsetof(struct sk_buff, cb),
|
|
|
|
sizeof_field(struct sk_buff, cb),
|
2007-07-20 01:11:58 +00:00
|
|
|
NULL);
|
2024-03-06 16:00:23 +00:00
|
|
|
net_hotdata.skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache",
|
2014-09-29 20:29:15 +00:00
|
|
|
sizeof(struct sk_buff_fclones),
|
2005-08-17 21:57:30 +00:00
|
|
|
0,
|
2006-08-27 02:25:52 +00:00
|
|
|
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
|
2007-07-20 01:11:58 +00:00
|
|
|
NULL);
|
2023-02-08 14:25:08 +00:00
|
|
|
/* usercopy should only access first SKB_SMALL_HEAD_HEADROOM bytes.
|
|
|
|
* struct skb_shared_info is located at the end of skb->head,
|
|
|
|
* and should not be copied to/from user.
|
|
|
|
*/
|
2024-03-06 16:00:23 +00:00
|
|
|
net_hotdata.skb_small_head_cache = kmem_cache_create_usercopy("skbuff_small_head",
|
2023-02-06 17:31:03 +00:00
|
|
|
SKB_SMALL_HEAD_CACHE_SIZE,
|
|
|
|
0,
|
|
|
|
SLAB_HWCACHE_ALIGN | SLAB_PANIC,
|
2023-02-08 14:25:08 +00:00
|
|
|
0,
|
|
|
|
SKB_SMALL_HEAD_HEADROOM,
|
2023-02-06 17:31:03 +00:00
|
|
|
NULL);
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
skb_extensions_init();
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2007-10-31 04:29:29 +00:00
|
|
|
static int
|
skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
This is a defense-in-depth measure in response to bugs like
4d6fa57b4dab ("macsec: avoid heap overflow in skb_to_sgvec"). There's
not only a potential overflow of sglist items, but also a stack overflow
potential, so we fix this by limiting the amount of recursion this function
is allowed to do. Not actually providing a bounded base case is a future
disaster that we can easily avoid here.
As a small matter of house keeping, we take this opportunity to move the
documentation comment over the actual function the documentation is for.
While this could be implemented by using an explicit stack of skbuffs,
when implementing this, the function complexity increased considerably,
and I don't think such complexity and bloat is actually worth it. So,
instead I built this and tested it on x86, x86_64, ARM, ARM64, and MIPS,
and measured the stack usage there. I also reverted the recent MIPS
changes that give it a separate IRQ stack, so that I could experience
some worst-case situations. I found that limiting it to 24 layers deep
yielded a good stack usage with room for safety, as well as being much
deeper than any driver actually ever creates.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-04 02:16:22 +00:00
|
|
|
__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len,
|
|
|
|
unsigned int recursion_level)
|
2007-04-03 03:19:53 +00:00
|
|
|
{
|
2007-04-27 22:21:23 +00:00
|
|
|
int start = skb_headlen(skb);
|
|
|
|
int i, copy = start - offset;
|
2009-06-09 07:18:59 +00:00
|
|
|
struct sk_buff *frag_iter;
|
2007-04-03 03:19:53 +00:00
|
|
|
int elt = 0;
|
|
|
|
|
skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
This is a defense-in-depth measure in response to bugs like
4d6fa57b4dab ("macsec: avoid heap overflow in skb_to_sgvec"). There's
not only a potential overflow of sglist items, but also a stack overflow
potential, so we fix this by limiting the amount of recursion this function
is allowed to do. Not actually providing a bounded base case is a future
disaster that we can easily avoid here.
As a small matter of house keeping, we take this opportunity to move the
documentation comment over the actual function the documentation is for.
While this could be implemented by using an explicit stack of skbuffs,
when implementing this, the function complexity increased considerably,
and I don't think such complexity and bloat is actually worth it. So,
instead I built this and tested it on x86, x86_64, ARM, ARM64, and MIPS,
and measured the stack usage there. I also reverted the recent MIPS
changes that give it a separate IRQ stack, so that I could experience
some worst-case situations. I found that limiting it to 24 layers deep
yielded a good stack usage with room for safety, as well as being much
deeper than any driver actually ever creates.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-04 02:16:22 +00:00
|
|
|
if (unlikely(recursion_level >= 24))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
2007-04-03 03:19:53 +00:00
|
|
|
if (copy > 0) {
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
2007-10-24 09:20:47 +00:00
|
|
|
sg_set_buf(sg, skb->data + offset, copy);
|
2007-04-03 03:19:53 +00:00
|
|
|
elt++;
|
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return elt;
|
|
|
|
offset += copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
2007-04-27 22:21:23 +00:00
|
|
|
int end;
|
2007-04-03 03:19:53 +00:00
|
|
|
|
2008-07-26 04:43:18 +00:00
|
|
|
WARN_ON(start > offset + len);
|
2007-04-27 22:21:23 +00:00
|
|
|
|
2011-10-18 21:00:24 +00:00
|
|
|
end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]);
|
2007-04-03 03:19:53 +00:00
|
|
|
if ((copy = end - offset) > 0) {
|
|
|
|
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
This is a defense-in-depth measure in response to bugs like
4d6fa57b4dab ("macsec: avoid heap overflow in skb_to_sgvec"). There's
not only a potential overflow of sglist items, but also a stack overflow
potential, so we fix this by limiting the amount of recursion this function
is allowed to do. Not actually providing a bounded base case is a future
disaster that we can easily avoid here.
As a small matter of house keeping, we take this opportunity to move the
documentation comment over the actual function the documentation is for.
While this could be implemented by using an explicit stack of skbuffs,
when implementing this, the function complexity increased considerably,
and I don't think such complexity and bloat is actually worth it. So,
instead I built this and tested it on x86, x86_64, ARM, ARM64, and MIPS,
and measured the stack usage there. I also reverted the recent MIPS
changes that give it a separate IRQ stack, so that I could experience
some worst-case situations. I found that limiting it to 24 layers deep
yielded a good stack usage with room for safety, as well as being much
deeper than any driver actually ever creates.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-04 02:16:22 +00:00
|
|
|
if (unlikely(elt && sg_is_last(&sg[elt - 1])))
|
|
|
|
return -EMSGSIZE;
|
2007-04-03 03:19:53 +00:00
|
|
|
|
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
2011-08-22 23:44:58 +00:00
|
|
|
sg_set_page(&sg[elt], skb_frag_page(frag), copy,
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off(frag) + offset - start);
|
2007-04-03 03:19:53 +00:00
|
|
|
elt++;
|
|
|
|
if (!(len -= copy))
|
|
|
|
return elt;
|
|
|
|
offset += copy;
|
|
|
|
}
|
2007-04-27 22:21:23 +00:00
|
|
|
start = end;
|
2007-04-03 03:19:53 +00:00
|
|
|
}
|
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
skb_walk_frags(skb, frag_iter) {
|
skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
This is a defense-in-depth measure in response to bugs like
4d6fa57b4dab ("macsec: avoid heap overflow in skb_to_sgvec"). There's
not only a potential overflow of sglist items, but also a stack overflow
potential, so we fix this by limiting the amount of recursion this function
is allowed to do. Not actually providing a bounded base case is a future
disaster that we can easily avoid here.
As a small matter of house keeping, we take this opportunity to move the
documentation comment over the actual function the documentation is for.
While this could be implemented by using an explicit stack of skbuffs,
when implementing this, the function complexity increased considerably,
and I don't think such complexity and bloat is actually worth it. So,
instead I built this and tested it on x86, x86_64, ARM, ARM64, and MIPS,
and measured the stack usage there. I also reverted the recent MIPS
changes that give it a separate IRQ stack, so that I could experience
some worst-case situations. I found that limiting it to 24 layers deep
yielded a good stack usage with room for safety, as well as being much
deeper than any driver actually ever creates.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-04 02:16:22 +00:00
|
|
|
int end, ret;
|
2007-04-27 22:21:23 +00:00
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
WARN_ON(start > offset + len);
|
2007-04-03 03:19:53 +00:00
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
end = start + frag_iter->len;
|
|
|
|
if ((copy = end - offset) > 0) {
|
skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
This is a defense-in-depth measure in response to bugs like
4d6fa57b4dab ("macsec: avoid heap overflow in skb_to_sgvec"). There's
not only a potential overflow of sglist items, but also a stack overflow
potential, so we fix this by limiting the amount of recursion this function
is allowed to do. Not actually providing a bounded base case is a future
disaster that we can easily avoid here.
As a small matter of house keeping, we take this opportunity to move the
documentation comment over the actual function the documentation is for.
While this could be implemented by using an explicit stack of skbuffs,
when implementing this, the function complexity increased considerably,
and I don't think such complexity and bloat is actually worth it. So,
instead I built this and tested it on x86, x86_64, ARM, ARM64, and MIPS,
and measured the stack usage there. I also reverted the recent MIPS
changes that give it a separate IRQ stack, so that I could experience
some worst-case situations. I found that limiting it to 24 layers deep
yielded a good stack usage with room for safety, as well as being much
deeper than any driver actually ever creates.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-04 02:16:22 +00:00
|
|
|
if (unlikely(elt && sg_is_last(&sg[elt - 1])))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
2009-06-09 07:18:59 +00:00
|
|
|
if (copy > len)
|
|
|
|
copy = len;
|
skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
This is a defense-in-depth measure in response to bugs like
4d6fa57b4dab ("macsec: avoid heap overflow in skb_to_sgvec"). There's
not only a potential overflow of sglist items, but also a stack overflow
potential, so we fix this by limiting the amount of recursion this function
is allowed to do. Not actually providing a bounded base case is a future
disaster that we can easily avoid here.
As a small matter of house keeping, we take this opportunity to move the
documentation comment over the actual function the documentation is for.
While this could be implemented by using an explicit stack of skbuffs,
when implementing this, the function complexity increased considerably,
and I don't think such complexity and bloat is actually worth it. So,
instead I built this and tested it on x86, x86_64, ARM, ARM64, and MIPS,
and measured the stack usage there. I also reverted the recent MIPS
changes that give it a separate IRQ stack, so that I could experience
some worst-case situations. I found that limiting it to 24 layers deep
yielded a good stack usage with room for safety, as well as being much
deeper than any driver actually ever creates.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-04 02:16:22 +00:00
|
|
|
ret = __skb_to_sgvec(frag_iter, sg+elt, offset - start,
|
|
|
|
copy, recursion_level + 1);
|
|
|
|
if (unlikely(ret < 0))
|
|
|
|
return ret;
|
|
|
|
elt += ret;
|
2009-06-09 07:18:59 +00:00
|
|
|
if ((len -= copy) == 0)
|
|
|
|
return elt;
|
|
|
|
offset += copy;
|
2007-04-03 03:19:53 +00:00
|
|
|
}
|
2009-06-09 07:18:59 +00:00
|
|
|
start = end;
|
2007-04-03 03:19:53 +00:00
|
|
|
}
|
|
|
|
BUG_ON(len);
|
|
|
|
return elt;
|
|
|
|
}
|
|
|
|
|
skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
This is a defense-in-depth measure in response to bugs like
4d6fa57b4dab ("macsec: avoid heap overflow in skb_to_sgvec"). There's
not only a potential overflow of sglist items, but also a stack overflow
potential, so we fix this by limiting the amount of recursion this function
is allowed to do. Not actually providing a bounded base case is a future
disaster that we can easily avoid here.
As a small matter of house keeping, we take this opportunity to move the
documentation comment over the actual function the documentation is for.
While this could be implemented by using an explicit stack of skbuffs,
when implementing this, the function complexity increased considerably,
and I don't think such complexity and bloat is actually worth it. So,
instead I built this and tested it on x86, x86_64, ARM, ARM64, and MIPS,
and measured the stack usage there. I also reverted the recent MIPS
changes that give it a separate IRQ stack, so that I could experience
some worst-case situations. I found that limiting it to 24 layers deep
yielded a good stack usage with room for safety, as well as being much
deeper than any driver actually ever creates.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-04 02:16:22 +00:00
|
|
|
/**
|
|
|
|
* skb_to_sgvec - Fill a scatter-gather list from a socket buffer
|
|
|
|
* @skb: Socket buffer containing the buffers to be mapped
|
|
|
|
* @sg: The scatter-gather list to map into
|
|
|
|
* @offset: The offset into the buffer's contents to start mapping
|
|
|
|
* @len: Length of buffer space to be mapped
|
|
|
|
*
|
|
|
|
* Fill the specified scatter-gather list with mappings/pointers into a
|
|
|
|
* region of the buffer space attached to a socket buffer. Returns either
|
|
|
|
* the number of scatterlist items used, or -EMSGSIZE if the contents
|
|
|
|
* could not fit.
|
|
|
|
*/
|
|
|
|
int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
|
|
|
|
{
|
|
|
|
int nsg = __skb_to_sgvec(skb, sg, offset, len, 0);
|
|
|
|
|
|
|
|
if (nsg <= 0)
|
|
|
|
return nsg;
|
|
|
|
|
|
|
|
sg_mark_end(&sg[nsg - 1]);
|
|
|
|
|
|
|
|
return nsg;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_to_sgvec);
|
|
|
|
|
2014-01-18 01:54:23 +00:00
|
|
|
/* As compared with skb_to_sgvec, skb_to_sgvec_nomark only map skb to given
|
|
|
|
* sglist without mark the sg which contain last skb data as the end.
|
|
|
|
* So the caller can mannipulate sg list as will when padding new data after
|
|
|
|
* the first call without calling sg_unmark_end to expend sg list.
|
|
|
|
*
|
|
|
|
* Scenario to use skb_to_sgvec_nomark:
|
|
|
|
* 1. sg_init_table
|
|
|
|
* 2. skb_to_sgvec_nomark(payload1)
|
|
|
|
* 3. skb_to_sgvec_nomark(payload2)
|
|
|
|
*
|
|
|
|
* This is equivalent to:
|
|
|
|
* 1. sg_init_table
|
|
|
|
* 2. skb_to_sgvec(payload1)
|
|
|
|
* 3. sg_unmark_end
|
|
|
|
* 4. skb_to_sgvec(payload2)
|
|
|
|
*
|
|
|
|
* When mapping mutilple payload conditionally, skb_to_sgvec_nomark
|
|
|
|
* is more preferable.
|
|
|
|
*/
|
|
|
|
int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg,
|
|
|
|
int offset, int len)
|
|
|
|
{
|
skbuff: return -EMSGSIZE in skb_to_sgvec to prevent overflow
This is a defense-in-depth measure in response to bugs like
4d6fa57b4dab ("macsec: avoid heap overflow in skb_to_sgvec"). There's
not only a potential overflow of sglist items, but also a stack overflow
potential, so we fix this by limiting the amount of recursion this function
is allowed to do. Not actually providing a bounded base case is a future
disaster that we can easily avoid here.
As a small matter of house keeping, we take this opportunity to move the
documentation comment over the actual function the documentation is for.
While this could be implemented by using an explicit stack of skbuffs,
when implementing this, the function complexity increased considerably,
and I don't think such complexity and bloat is actually worth it. So,
instead I built this and tested it on x86, x86_64, ARM, ARM64, and MIPS,
and measured the stack usage there. I also reverted the recent MIPS
changes that give it a separate IRQ stack, so that I could experience
some worst-case situations. I found that limiting it to 24 layers deep
yielded a good stack usage with room for safety, as well as being much
deeper than any driver actually ever creates.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Howells <dhowells@redhat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-04 02:16:22 +00:00
|
|
|
return __skb_to_sgvec(skb, sg, offset, len, 0);
|
2014-01-18 01:54:23 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_to_sgvec_nomark);
|
|
|
|
|
2007-10-31 04:29:29 +00:00
|
|
|
|
|
|
|
|
2007-04-03 03:19:53 +00:00
|
|
|
/**
|
|
|
|
* skb_cow_data - Check that a socket buffer's data buffers are writable
|
|
|
|
* @skb: The socket buffer to check.
|
|
|
|
* @tailbits: Amount of trailing space to be added
|
|
|
|
* @trailer: Returned pointer to the skb where the @tailbits space begins
|
|
|
|
*
|
|
|
|
* Make sure that the data buffers attached to a socket buffer are
|
|
|
|
* writable. If they are not, private copies are made of the data buffers
|
|
|
|
* and the socket buffer is set to use these instead.
|
|
|
|
*
|
|
|
|
* If @tailbits is given, make sure that there is space to write @tailbits
|
|
|
|
* bytes of data beyond current end of socket buffer. @trailer will be
|
|
|
|
* set to point to the skb in which this space begins.
|
|
|
|
*
|
|
|
|
* The number of scatterlist elements required to completely map the
|
|
|
|
* COW'd and extended socket buffer will be returned.
|
|
|
|
*/
|
|
|
|
int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
|
|
|
|
{
|
|
|
|
int copyflag;
|
|
|
|
int elt;
|
|
|
|
struct sk_buff *skb1, **skb_p;
|
|
|
|
|
|
|
|
/* If skb is cloned or its head is paged, reallocate
|
|
|
|
* head pulling out all the pages (pages are considered not writable
|
|
|
|
* at the moment even if they are anonymous).
|
|
|
|
*/
|
|
|
|
if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) &&
|
2020-08-01 09:30:23 +00:00
|
|
|
!__pskb_pull_tail(skb, __skb_pagelen(skb)))
|
2007-04-03 03:19:53 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
/* Easy case. Most of packets will go this way. */
|
2010-08-23 07:13:46 +00:00
|
|
|
if (!skb_has_frag_list(skb)) {
|
2007-04-03 03:19:53 +00:00
|
|
|
/* A little of trouble, not enough of space for trailer.
|
|
|
|
* This should not happen, when stack is tuned to generate
|
|
|
|
* good frames. OK, on miss we reallocate and reserve even more
|
|
|
|
* space, 128 bytes is fair. */
|
|
|
|
|
|
|
|
if (skb_tailroom(skb) < tailbits &&
|
|
|
|
pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC))
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
/* Voila! */
|
|
|
|
*trailer = skb;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Misery. We are in troubles, going to mincer fragments... */
|
|
|
|
|
|
|
|
elt = 1;
|
|
|
|
skb_p = &skb_shinfo(skb)->frag_list;
|
|
|
|
copyflag = 0;
|
|
|
|
|
|
|
|
while ((skb1 = *skb_p) != NULL) {
|
|
|
|
int ntail = 0;
|
|
|
|
|
|
|
|
/* The fragment is partially pulled by someone,
|
|
|
|
* this can happen on input. Copy it and everything
|
|
|
|
* after it. */
|
|
|
|
|
|
|
|
if (skb_shared(skb1))
|
|
|
|
copyflag = 1;
|
|
|
|
|
|
|
|
/* If the skb is the last, worry about trailer. */
|
|
|
|
|
|
|
|
if (skb1->next == NULL && tailbits) {
|
|
|
|
if (skb_shinfo(skb1)->nr_frags ||
|
2010-08-23 07:13:46 +00:00
|
|
|
skb_has_frag_list(skb1) ||
|
2007-04-03 03:19:53 +00:00
|
|
|
skb_tailroom(skb1) < tailbits)
|
|
|
|
ntail = tailbits + 128;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copyflag ||
|
|
|
|
skb_cloned(skb1) ||
|
|
|
|
ntail ||
|
|
|
|
skb_shinfo(skb1)->nr_frags ||
|
2010-08-23 07:13:46 +00:00
|
|
|
skb_has_frag_list(skb1)) {
|
2007-04-03 03:19:53 +00:00
|
|
|
struct sk_buff *skb2;
|
|
|
|
|
|
|
|
/* Fuck, we are miserable poor guys... */
|
|
|
|
if (ntail == 0)
|
|
|
|
skb2 = skb_copy(skb1, GFP_ATOMIC);
|
|
|
|
else
|
|
|
|
skb2 = skb_copy_expand(skb1,
|
|
|
|
skb_headroom(skb1),
|
|
|
|
ntail,
|
|
|
|
GFP_ATOMIC);
|
|
|
|
if (unlikely(skb2 == NULL))
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
if (skb1->sk)
|
|
|
|
skb_set_owner_w(skb2, skb1->sk);
|
|
|
|
|
|
|
|
/* Looking around. Are we still alive?
|
|
|
|
* OK, link new skb, drop old one */
|
|
|
|
|
|
|
|
skb2->next = skb1->next;
|
|
|
|
*skb_p = skb2;
|
|
|
|
kfree_skb(skb1);
|
|
|
|
skb1 = skb2;
|
|
|
|
}
|
|
|
|
elt++;
|
|
|
|
*trailer = skb1;
|
|
|
|
skb_p = &skb1->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return elt;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL_GPL(skb_cow_data);
|
2007-04-03 03:19:53 +00:00
|
|
|
|
2010-06-01 06:44:05 +00:00
|
|
|
static void sock_rmem_free(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct sock *sk = skb->sk;
|
|
|
|
|
|
|
|
atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
|
|
|
|
}
|
|
|
|
|
2017-03-18 21:02:59 +00:00
|
|
|
static void skb_set_err_queue(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
/* pkt_type of skbs received on local sockets is never PACKET_OUTGOING.
|
|
|
|
* So, it is safe to (mis)use it to mark skbs on the error queue.
|
|
|
|
*/
|
|
|
|
skb->pkt_type = PACKET_OUTGOING;
|
|
|
|
BUILD_BUG_ON(PACKET_OUTGOING == 0);
|
|
|
|
}
|
|
|
|
|
2010-06-01 06:44:05 +00:00
|
|
|
/*
|
|
|
|
* Note: We dont mem charge error packets (no sk_forward_alloc changes)
|
|
|
|
*/
|
|
|
|
int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
|
2019-10-11 03:17:44 +00:00
|
|
|
(unsigned int)READ_ONCE(sk->sk_rcvbuf))
|
2010-06-01 06:44:05 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
skb_orphan(skb);
|
|
|
|
skb->sk = sk;
|
|
|
|
skb->destructor = sock_rmem_free;
|
|
|
|
atomic_add(skb->truesize, &sk->sk_rmem_alloc);
|
2017-03-18 21:02:59 +00:00
|
|
|
skb_set_err_queue(skb);
|
2010-06-01 06:44:05 +00:00
|
|
|
|
2011-05-18 06:21:31 +00:00
|
|
|
/* before exiting rcu section, make sure dst is refcounted */
|
|
|
|
skb_dst_force(skb);
|
|
|
|
|
2010-06-01 06:44:05 +00:00
|
|
|
skb_queue_tail(&sk->sk_error_queue, skb);
|
|
|
|
if (!sock_flag(sk, SOCK_DEAD))
|
2021-06-27 22:48:21 +00:00
|
|
|
sk_error_report(sk);
|
2010-06-01 06:44:05 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(sock_queue_err_skb);
|
|
|
|
|
2016-11-30 19:01:08 +00:00
|
|
|
static bool is_icmp_err_skb(const struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
return skb && (SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
|
|
|
|
SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP6);
|
|
|
|
}
|
|
|
|
|
2014-09-01 01:30:27 +00:00
|
|
|
struct sk_buff *sock_dequeue_err_skb(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct sk_buff_head *q = &sk->sk_error_queue;
|
2016-11-30 19:01:08 +00:00
|
|
|
struct sk_buff *skb, *skb_next = NULL;
|
|
|
|
bool icmp_next = false;
|
2015-02-18 13:47:55 +00:00
|
|
|
unsigned long flags;
|
2014-09-01 01:30:27 +00:00
|
|
|
|
2023-10-05 11:45:04 +00:00
|
|
|
if (skb_queue_empty_lockless(q))
|
|
|
|
return NULL;
|
|
|
|
|
2015-02-18 13:47:55 +00:00
|
|
|
spin_lock_irqsave(&q->lock, flags);
|
2014-09-01 01:30:27 +00:00
|
|
|
skb = __skb_dequeue(q);
|
2017-06-02 16:38:22 +00:00
|
|
|
if (skb && (skb_next = skb_peek(q))) {
|
2016-11-30 19:01:08 +00:00
|
|
|
icmp_next = is_icmp_err_skb(skb_next);
|
2017-06-02 16:38:22 +00:00
|
|
|
if (icmp_next)
|
2020-11-26 15:12:20 +00:00
|
|
|
sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_errno;
|
2017-06-02 16:38:22 +00:00
|
|
|
}
|
2015-02-18 13:47:55 +00:00
|
|
|
spin_unlock_irqrestore(&q->lock, flags);
|
2014-09-01 01:30:27 +00:00
|
|
|
|
2016-11-30 19:01:08 +00:00
|
|
|
if (is_icmp_err_skb(skb) && !icmp_next)
|
|
|
|
sk->sk_err = 0;
|
|
|
|
|
|
|
|
if (skb_next)
|
2021-06-27 22:48:21 +00:00
|
|
|
sk_error_report(sk);
|
2014-09-01 01:30:27 +00:00
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(sock_dequeue_err_skb);
|
|
|
|
|
2014-09-10 22:05:26 +00:00
|
|
|
/**
|
|
|
|
* skb_clone_sk - create clone of skb, and take reference to socket
|
|
|
|
* @skb: the skb to clone
|
|
|
|
*
|
|
|
|
* This function creates a clone of a buffer that holds a reference on
|
|
|
|
* sk_refcnt. Buffers created via this function are meant to be
|
|
|
|
* returned using sock_queue_err_skb, or free via kfree_skb.
|
|
|
|
*
|
|
|
|
* When passing buffers allocated with this function to sock_queue_err_skb
|
|
|
|
* it is necessary to wrap the call with sock_hold/sock_put in order to
|
|
|
|
* prevent the socket from being released prior to being enqueued on
|
|
|
|
* the sk_error_queue.
|
|
|
|
*/
|
2014-09-04 17:31:35 +00:00
|
|
|
struct sk_buff *skb_clone_sk(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct sock *sk = skb->sk;
|
|
|
|
struct sk_buff *clone;
|
|
|
|
|
2017-06-30 10:08:01 +00:00
|
|
|
if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
|
2014-09-04 17:31:35 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
clone = skb_clone(skb, GFP_ATOMIC);
|
|
|
|
if (!clone) {
|
|
|
|
sock_put(sk);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
clone->sk = sk;
|
|
|
|
clone->destructor = sock_efree;
|
|
|
|
|
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_clone_sk);
|
|
|
|
|
2014-09-04 17:31:10 +00:00
|
|
|
static void __skb_complete_tx_timestamp(struct sk_buff *skb,
|
|
|
|
struct sock *sk,
|
2017-03-18 21:03:00 +00:00
|
|
|
int tstype,
|
|
|
|
bool opt_stats)
|
2009-02-12 05:03:37 +00:00
|
|
|
{
|
|
|
|
struct sock_exterr_skb *serr;
|
|
|
|
int err;
|
|
|
|
|
2017-03-18 21:03:00 +00:00
|
|
|
BUILD_BUG_ON(sizeof(struct sock_exterr_skb) > sizeof(skb->cb));
|
|
|
|
|
2009-02-12 05:03:37 +00:00
|
|
|
serr = SKB_EXT_ERR(skb);
|
|
|
|
memset(serr, 0, sizeof(*serr));
|
|
|
|
serr->ee.ee_errno = ENOMSG;
|
|
|
|
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
|
2014-08-05 02:11:48 +00:00
|
|
|
serr->ee.ee_info = tstype;
|
2017-03-18 21:03:00 +00:00
|
|
|
serr->opt_stats = opt_stats;
|
2017-04-12 23:24:35 +00:00
|
|
|
serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0;
|
2023-08-31 13:52:11 +00:00
|
|
|
if (READ_ONCE(sk->sk_tsflags) & SOF_TIMESTAMPING_OPT_ID) {
|
2014-08-05 02:11:47 +00:00
|
|
|
serr->ee.ee_data = skb_shinfo(skb)->tskey;
|
2021-11-15 19:02:33 +00:00
|
|
|
if (sk_is_tcp(sk))
|
2022-02-17 17:05:02 +00:00
|
|
|
serr->ee.ee_data -= atomic_read(&sk->sk_tskey);
|
net-timestamp: TCP timestamping
TCP timestamping extends SO_TIMESTAMPING to bytestreams.
Bytestreams do not have a 1:1 relationship between send() buffers and
network packets. The feature interprets a send call on a bytestream as
a request for a timestamp for the last byte in that send() buffer.
The choice corresponds to a request for a timestamp when all bytes in
the buffer have been sent. That assumption depends on in-order kernel
transmission. This is the common case. That said, it is possible to
construct a traffic shaping tree that would result in reordering.
The guarantee is strong, then, but not ironclad.
This implementation supports send and sendpages (splice). GSO replaces
one large packet with multiple smaller packets. This patch also copies
the option into the correct smaller packet.
This patch does not yet support timestamping on data in an initial TCP
Fast Open SYN, because that takes a very different data path.
If ID generation in ee_data is enabled, bytestream timestamps return a
byte offset, instead of the packet counter for datagrams.
The implementation supports a single timestamp per packet. It silenty
replaces requests for previous timestamps. To avoid missing tstamps,
flush the tcp queue by disabling Nagle, cork and autocork. Missing
tstamps can be detected by offset when the ee_data ID is enabled.
Implementation details:
- On GSO, the timestamping code can be included in the main loop. I
moved it into its own loop to reduce the impact on the common case
to a single branch.
- To avoid leaking the absolute seqno to userspace, the offset
returned in ee_data must always be relative. It is an offset between
an skb and sk field. The first is always set (also for GSO & ACK).
The second must also never be uninitialized. Only allow the ID
option on sockets in the ESTABLISHED state, for which the seqno
is available. Never reset it to zero (instead, move it to the
current seqno when reenabling the option).
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-05 02:11:49 +00:00
|
|
|
}
|
2010-05-29 07:20:48 +00:00
|
|
|
|
2009-02-12 05:03:37 +00:00
|
|
|
err = sock_queue_err_skb(sk, skb);
|
2010-05-29 07:20:48 +00:00
|
|
|
|
2009-02-12 05:03:37 +00:00
|
|
|
if (err)
|
|
|
|
kfree_skb(skb);
|
|
|
|
}
|
2014-09-04 17:31:10 +00:00
|
|
|
|
2015-01-30 18:29:32 +00:00
|
|
|
static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
|
|
|
|
{
|
|
|
|
bool ret;
|
|
|
|
|
2022-08-23 17:46:50 +00:00
|
|
|
if (likely(READ_ONCE(sysctl_tstamp_allow_data) || tsonly))
|
2015-01-30 18:29:32 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
read_lock_bh(&sk->sk_callback_lock);
|
|
|
|
ret = sk->sk_socket && sk->sk_socket->file &&
|
|
|
|
file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW);
|
|
|
|
read_unlock_bh(&sk->sk_callback_lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-09-04 17:31:10 +00:00
|
|
|
void skb_complete_tx_timestamp(struct sk_buff *skb,
|
|
|
|
struct skb_shared_hwtstamps *hwtstamps)
|
|
|
|
{
|
|
|
|
struct sock *sk = skb->sk;
|
|
|
|
|
2015-01-30 18:29:32 +00:00
|
|
|
if (!skb_may_tx_timestamp(sk, false))
|
2017-12-13 19:41:06 +00:00
|
|
|
goto err;
|
2015-01-30 18:29:32 +00:00
|
|
|
|
2017-03-04 05:01:03 +00:00
|
|
|
/* Take a reference to prevent skb_orphan() from freeing the socket,
|
|
|
|
* but only if the socket refcount is not zero.
|
|
|
|
*/
|
2017-06-30 10:08:01 +00:00
|
|
|
if (likely(refcount_inc_not_zero(&sk->sk_refcnt))) {
|
2017-03-04 05:01:03 +00:00
|
|
|
*skb_hwtstamps(skb) = *hwtstamps;
|
2017-03-18 21:03:00 +00:00
|
|
|
__skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND, false);
|
2017-03-04 05:01:03 +00:00
|
|
|
sock_put(sk);
|
2017-12-13 19:41:06 +00:00
|
|
|
return;
|
2017-03-04 05:01:03 +00:00
|
|
|
}
|
2017-12-13 19:41:06 +00:00
|
|
|
|
|
|
|
err:
|
|
|
|
kfree_skb(skb);
|
2014-09-04 17:31:10 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);
|
|
|
|
|
|
|
|
void __skb_tstamp_tx(struct sk_buff *orig_skb,
|
2021-01-20 20:41:55 +00:00
|
|
|
const struct sk_buff *ack_skb,
|
2014-09-04 17:31:10 +00:00
|
|
|
struct skb_shared_hwtstamps *hwtstamps,
|
|
|
|
struct sock *sk, int tstype)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb;
|
2017-03-18 21:03:00 +00:00
|
|
|
bool tsonly, opt_stats = false;
|
2023-08-31 13:52:11 +00:00
|
|
|
u32 tsflags;
|
2014-09-04 17:31:10 +00:00
|
|
|
|
2015-03-11 19:43:55 +00:00
|
|
|
if (!sk)
|
|
|
|
return;
|
|
|
|
|
2023-08-31 13:52:11 +00:00
|
|
|
tsflags = READ_ONCE(sk->sk_tsflags);
|
|
|
|
if (!hwtstamps && !(tsflags & SOF_TIMESTAMPING_OPT_TX_SWHW) &&
|
2017-05-19 15:52:40 +00:00
|
|
|
skb_shinfo(orig_skb)->tx_flags & SKBTX_IN_PROGRESS)
|
|
|
|
return;
|
|
|
|
|
2023-08-31 13:52:11 +00:00
|
|
|
tsonly = tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
|
2015-03-11 19:43:55 +00:00
|
|
|
if (!skb_may_tx_timestamp(sk, tsonly))
|
2014-09-04 17:31:10 +00:00
|
|
|
return;
|
|
|
|
|
2016-11-28 07:07:18 +00:00
|
|
|
if (tsonly) {
|
|
|
|
#ifdef CONFIG_INET
|
2023-08-31 13:52:11 +00:00
|
|
|
if ((tsflags & SOF_TIMESTAMPING_OPT_STATS) &&
|
2021-11-15 19:02:33 +00:00
|
|
|
sk_is_tcp(sk)) {
|
2021-01-20 20:41:55 +00:00
|
|
|
skb = tcp_get_timestamping_opt_stats(sk, orig_skb,
|
|
|
|
ack_skb);
|
2017-03-18 21:03:00 +00:00
|
|
|
opt_stats = true;
|
|
|
|
} else
|
2016-11-28 07:07:18 +00:00
|
|
|
#endif
|
|
|
|
skb = alloc_skb(0, GFP_ATOMIC);
|
|
|
|
} else {
|
2015-01-30 18:29:31 +00:00
|
|
|
skb = skb_clone(orig_skb, GFP_ATOMIC);
|
tcp/udp: Fix memleaks of sk and zerocopy skbs with TX timestamp.
syzkaller reported [0] memory leaks of an UDP socket and ZEROCOPY
skbs. We can reproduce the problem with these sequences:
sk = socket(AF_INET, SOCK_DGRAM, 0)
sk.setsockopt(SOL_SOCKET, SO_TIMESTAMPING, SOF_TIMESTAMPING_TX_SOFTWARE)
sk.setsockopt(SOL_SOCKET, SO_ZEROCOPY, 1)
sk.sendto(b'', MSG_ZEROCOPY, ('127.0.0.1', 53))
sk.close()
sendmsg() calls msg_zerocopy_alloc(), which allocates a skb, sets
skb->cb->ubuf.refcnt to 1, and calls sock_hold(). Here, struct
ubuf_info_msgzc indirectly holds a refcnt of the socket. When the
skb is sent, __skb_tstamp_tx() clones it and puts the clone into
the socket's error queue with the TX timestamp.
When the original skb is received locally, skb_copy_ubufs() calls
skb_unclone(), and pskb_expand_head() increments skb->cb->ubuf.refcnt.
This additional count is decremented while freeing the skb, but struct
ubuf_info_msgzc still has a refcnt, so __msg_zerocopy_callback() is
not called.
The last refcnt is not released unless we retrieve the TX timestamped
skb by recvmsg(). Since we clear the error queue in inet_sock_destruct()
after the socket's refcnt reaches 0, there is a circular dependency.
If we close() the socket holding such skbs, we never call sock_put()
and leak the count, sk, and skb.
TCP has the same problem, and commit e0c8bccd40fc ("net: stream:
purge sk_error_queue in sk_stream_kill_queues()") tried to fix it
by calling skb_queue_purge() during close(). However, there is a
small chance that skb queued in a qdisc or device could be put
into the error queue after the skb_queue_purge() call.
In __skb_tstamp_tx(), the cloned skb should not have a reference
to the ubuf to remove the circular dependency, but skb_clone() does
not call skb_copy_ubufs() for zerocopy skb. So, we need to call
skb_orphan_frags_rx() for the cloned skb to call skb_copy_ubufs().
[0]:
BUG: memory leak
unreferenced object 0xffff88800c6d2d00 (size 1152):
comm "syz-executor392", pid 264, jiffies 4294785440 (age 13.044s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 cd af e8 81 00 00 00 00 ................
02 00 07 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............
backtrace:
[<0000000055636812>] sk_prot_alloc+0x64/0x2a0 net/core/sock.c:2024
[<0000000054d77b7a>] sk_alloc+0x3b/0x800 net/core/sock.c:2083
[<0000000066f3c7e0>] inet_create net/ipv4/af_inet.c:319 [inline]
[<0000000066f3c7e0>] inet_create+0x31e/0xe40 net/ipv4/af_inet.c:245
[<000000009b83af97>] __sock_create+0x2ab/0x550 net/socket.c:1515
[<00000000b9b11231>] sock_create net/socket.c:1566 [inline]
[<00000000b9b11231>] __sys_socket_create net/socket.c:1603 [inline]
[<00000000b9b11231>] __sys_socket_create net/socket.c:1588 [inline]
[<00000000b9b11231>] __sys_socket+0x138/0x250 net/socket.c:1636
[<000000004fb45142>] __do_sys_socket net/socket.c:1649 [inline]
[<000000004fb45142>] __se_sys_socket net/socket.c:1647 [inline]
[<000000004fb45142>] __x64_sys_socket+0x73/0xb0 net/socket.c:1647
[<0000000066999e0e>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[<0000000066999e0e>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80
[<0000000017f238c1>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
BUG: memory leak
unreferenced object 0xffff888017633a00 (size 240):
comm "syz-executor392", pid 264, jiffies 4294785440 (age 13.044s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 2d 6d 0c 80 88 ff ff .........-m.....
backtrace:
[<000000002b1c4368>] __alloc_skb+0x229/0x320 net/core/skbuff.c:497
[<00000000143579a6>] alloc_skb include/linux/skbuff.h:1265 [inline]
[<00000000143579a6>] sock_omalloc+0xaa/0x190 net/core/sock.c:2596
[<00000000be626478>] msg_zerocopy_alloc net/core/skbuff.c:1294 [inline]
[<00000000be626478>] msg_zerocopy_realloc+0x1ce/0x7f0 net/core/skbuff.c:1370
[<00000000cbfc9870>] __ip_append_data+0x2adf/0x3b30 net/ipv4/ip_output.c:1037
[<0000000089869146>] ip_make_skb+0x26c/0x2e0 net/ipv4/ip_output.c:1652
[<00000000098015c2>] udp_sendmsg+0x1bac/0x2390 net/ipv4/udp.c:1253
[<0000000045e0e95e>] inet_sendmsg+0x10a/0x150 net/ipv4/af_inet.c:819
[<000000008d31bfde>] sock_sendmsg_nosec net/socket.c:714 [inline]
[<000000008d31bfde>] sock_sendmsg+0x141/0x190 net/socket.c:734
[<0000000021e21aa4>] __sys_sendto+0x243/0x360 net/socket.c:2117
[<00000000ac0af00c>] __do_sys_sendto net/socket.c:2129 [inline]
[<00000000ac0af00c>] __se_sys_sendto net/socket.c:2125 [inline]
[<00000000ac0af00c>] __x64_sys_sendto+0xe1/0x1c0 net/socket.c:2125
[<0000000066999e0e>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[<0000000066999e0e>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80
[<0000000017f238c1>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
Fixes: f214f915e7db ("tcp: enable MSG_ZEROCOPY")
Fixes: b5947e5d1e71 ("udp: msg_zerocopy")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-04-24 22:20:22 +00:00
|
|
|
|
2023-05-22 15:30:20 +00:00
|
|
|
if (skb_orphan_frags_rx(skb, GFP_ATOMIC)) {
|
|
|
|
kfree_skb(skb);
|
tcp/udp: Fix memleaks of sk and zerocopy skbs with TX timestamp.
syzkaller reported [0] memory leaks of an UDP socket and ZEROCOPY
skbs. We can reproduce the problem with these sequences:
sk = socket(AF_INET, SOCK_DGRAM, 0)
sk.setsockopt(SOL_SOCKET, SO_TIMESTAMPING, SOF_TIMESTAMPING_TX_SOFTWARE)
sk.setsockopt(SOL_SOCKET, SO_ZEROCOPY, 1)
sk.sendto(b'', MSG_ZEROCOPY, ('127.0.0.1', 53))
sk.close()
sendmsg() calls msg_zerocopy_alloc(), which allocates a skb, sets
skb->cb->ubuf.refcnt to 1, and calls sock_hold(). Here, struct
ubuf_info_msgzc indirectly holds a refcnt of the socket. When the
skb is sent, __skb_tstamp_tx() clones it and puts the clone into
the socket's error queue with the TX timestamp.
When the original skb is received locally, skb_copy_ubufs() calls
skb_unclone(), and pskb_expand_head() increments skb->cb->ubuf.refcnt.
This additional count is decremented while freeing the skb, but struct
ubuf_info_msgzc still has a refcnt, so __msg_zerocopy_callback() is
not called.
The last refcnt is not released unless we retrieve the TX timestamped
skb by recvmsg(). Since we clear the error queue in inet_sock_destruct()
after the socket's refcnt reaches 0, there is a circular dependency.
If we close() the socket holding such skbs, we never call sock_put()
and leak the count, sk, and skb.
TCP has the same problem, and commit e0c8bccd40fc ("net: stream:
purge sk_error_queue in sk_stream_kill_queues()") tried to fix it
by calling skb_queue_purge() during close(). However, there is a
small chance that skb queued in a qdisc or device could be put
into the error queue after the skb_queue_purge() call.
In __skb_tstamp_tx(), the cloned skb should not have a reference
to the ubuf to remove the circular dependency, but skb_clone() does
not call skb_copy_ubufs() for zerocopy skb. So, we need to call
skb_orphan_frags_rx() for the cloned skb to call skb_copy_ubufs().
[0]:
BUG: memory leak
unreferenced object 0xffff88800c6d2d00 (size 1152):
comm "syz-executor392", pid 264, jiffies 4294785440 (age 13.044s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 cd af e8 81 00 00 00 00 ................
02 00 07 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............
backtrace:
[<0000000055636812>] sk_prot_alloc+0x64/0x2a0 net/core/sock.c:2024
[<0000000054d77b7a>] sk_alloc+0x3b/0x800 net/core/sock.c:2083
[<0000000066f3c7e0>] inet_create net/ipv4/af_inet.c:319 [inline]
[<0000000066f3c7e0>] inet_create+0x31e/0xe40 net/ipv4/af_inet.c:245
[<000000009b83af97>] __sock_create+0x2ab/0x550 net/socket.c:1515
[<00000000b9b11231>] sock_create net/socket.c:1566 [inline]
[<00000000b9b11231>] __sys_socket_create net/socket.c:1603 [inline]
[<00000000b9b11231>] __sys_socket_create net/socket.c:1588 [inline]
[<00000000b9b11231>] __sys_socket+0x138/0x250 net/socket.c:1636
[<000000004fb45142>] __do_sys_socket net/socket.c:1649 [inline]
[<000000004fb45142>] __se_sys_socket net/socket.c:1647 [inline]
[<000000004fb45142>] __x64_sys_socket+0x73/0xb0 net/socket.c:1647
[<0000000066999e0e>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[<0000000066999e0e>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80
[<0000000017f238c1>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
BUG: memory leak
unreferenced object 0xffff888017633a00 (size 240):
comm "syz-executor392", pid 264, jiffies 4294785440 (age 13.044s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00 00 2d 6d 0c 80 88 ff ff .........-m.....
backtrace:
[<000000002b1c4368>] __alloc_skb+0x229/0x320 net/core/skbuff.c:497
[<00000000143579a6>] alloc_skb include/linux/skbuff.h:1265 [inline]
[<00000000143579a6>] sock_omalloc+0xaa/0x190 net/core/sock.c:2596
[<00000000be626478>] msg_zerocopy_alloc net/core/skbuff.c:1294 [inline]
[<00000000be626478>] msg_zerocopy_realloc+0x1ce/0x7f0 net/core/skbuff.c:1370
[<00000000cbfc9870>] __ip_append_data+0x2adf/0x3b30 net/ipv4/ip_output.c:1037
[<0000000089869146>] ip_make_skb+0x26c/0x2e0 net/ipv4/ip_output.c:1652
[<00000000098015c2>] udp_sendmsg+0x1bac/0x2390 net/ipv4/udp.c:1253
[<0000000045e0e95e>] inet_sendmsg+0x10a/0x150 net/ipv4/af_inet.c:819
[<000000008d31bfde>] sock_sendmsg_nosec net/socket.c:714 [inline]
[<000000008d31bfde>] sock_sendmsg+0x141/0x190 net/socket.c:734
[<0000000021e21aa4>] __sys_sendto+0x243/0x360 net/socket.c:2117
[<00000000ac0af00c>] __do_sys_sendto net/socket.c:2129 [inline]
[<00000000ac0af00c>] __se_sys_sendto net/socket.c:2125 [inline]
[<00000000ac0af00c>] __x64_sys_sendto+0xe1/0x1c0 net/socket.c:2125
[<0000000066999e0e>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[<0000000066999e0e>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80
[<0000000017f238c1>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
Fixes: f214f915e7db ("tcp: enable MSG_ZEROCOPY")
Fixes: b5947e5d1e71 ("udp: msg_zerocopy")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-04-24 22:20:22 +00:00
|
|
|
return;
|
2023-05-22 15:30:20 +00:00
|
|
|
}
|
2016-11-28 07:07:18 +00:00
|
|
|
}
|
2014-09-04 17:31:10 +00:00
|
|
|
if (!skb)
|
|
|
|
return;
|
|
|
|
|
2015-01-30 18:29:31 +00:00
|
|
|
if (tsonly) {
|
2017-06-08 15:35:03 +00:00
|
|
|
skb_shinfo(skb)->tx_flags |= skb_shinfo(orig_skb)->tx_flags &
|
|
|
|
SKBTX_ANY_TSTAMP;
|
2015-01-30 18:29:31 +00:00
|
|
|
skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hwtstamps)
|
|
|
|
*skb_hwtstamps(skb) = *hwtstamps;
|
|
|
|
else
|
2022-03-02 19:55:44 +00:00
|
|
|
__net_timestamp(skb);
|
2015-01-30 18:29:31 +00:00
|
|
|
|
2017-03-18 21:03:00 +00:00
|
|
|
__skb_complete_tx_timestamp(skb, sk, tstype, opt_stats);
|
2014-09-04 17:31:10 +00:00
|
|
|
}
|
2014-08-05 02:11:48 +00:00
|
|
|
EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
|
|
|
|
|
|
|
|
void skb_tstamp_tx(struct sk_buff *orig_skb,
|
|
|
|
struct skb_shared_hwtstamps *hwtstamps)
|
|
|
|
{
|
2021-01-20 20:41:55 +00:00
|
|
|
return __skb_tstamp_tx(orig_skb, NULL, hwtstamps, orig_skb->sk,
|
2014-08-05 02:11:48 +00:00
|
|
|
SCM_TSTAMP_SND);
|
|
|
|
}
|
2009-02-12 05:03:37 +00:00
|
|
|
EXPORT_SYMBOL_GPL(skb_tstamp_tx);
|
|
|
|
|
2023-04-17 15:53:46 +00:00
|
|
|
#ifdef CONFIG_WIRELESS
|
2011-11-09 09:15:42 +00:00
|
|
|
void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
|
|
|
|
{
|
|
|
|
struct sock *sk = skb->sk;
|
|
|
|
struct sock_exterr_skb *serr;
|
2017-03-04 05:01:02 +00:00
|
|
|
int err = 1;
|
2011-11-09 09:15:42 +00:00
|
|
|
|
|
|
|
skb->wifi_acked_valid = 1;
|
|
|
|
skb->wifi_acked = acked;
|
|
|
|
|
|
|
|
serr = SKB_EXT_ERR(skb);
|
|
|
|
memset(serr, 0, sizeof(*serr));
|
|
|
|
serr->ee.ee_errno = ENOMSG;
|
|
|
|
serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
|
|
|
|
|
2017-03-04 05:01:02 +00:00
|
|
|
/* Take a reference to prevent skb_orphan() from freeing the socket,
|
|
|
|
* but only if the socket refcount is not zero.
|
|
|
|
*/
|
2017-06-30 10:08:01 +00:00
|
|
|
if (likely(refcount_inc_not_zero(&sk->sk_refcnt))) {
|
2017-03-04 05:01:02 +00:00
|
|
|
err = sock_queue_err_skb(sk, skb);
|
|
|
|
sock_put(sk);
|
|
|
|
}
|
2011-11-09 09:15:42 +00:00
|
|
|
if (err)
|
|
|
|
kfree_skb(skb);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
|
2023-04-17 15:53:46 +00:00
|
|
|
#endif /* CONFIG_WIRELESS */
|
2011-11-09 09:15:42 +00:00
|
|
|
|
2008-02-05 04:49:54 +00:00
|
|
|
/**
|
|
|
|
* skb_partial_csum_set - set up and verify partial csum values for packet
|
|
|
|
* @skb: the skb to set
|
|
|
|
* @start: the number of bytes after skb->data to start checksumming.
|
|
|
|
* @off: the offset from start to place the checksum.
|
|
|
|
*
|
|
|
|
* For untrusted partially-checksummed packets, we need to make sure the values
|
|
|
|
* for skb->csum_start and skb->csum_offset are valid so we don't oops.
|
|
|
|
*
|
|
|
|
* This function checks and sets those values and skb->ip_summed: if this
|
|
|
|
* returns false you should drop the packet.
|
|
|
|
*/
|
|
|
|
bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
|
|
|
|
{
|
2018-10-10 13:59:35 +00:00
|
|
|
u32 csum_end = (u32)start + (u32)off + sizeof(__sum16);
|
|
|
|
u32 csum_start = skb_headroom(skb) + (u32)start;
|
|
|
|
|
2023-05-05 17:06:18 +00:00
|
|
|
if (unlikely(csum_start >= U16_MAX || csum_end > skb_headlen(skb))) {
|
2018-10-10 13:59:35 +00:00
|
|
|
net_warn_ratelimited("bad partial csum: csum=%u/%u headroom=%u headlen=%u\n",
|
|
|
|
start, off, skb_headroom(skb), skb_headlen(skb));
|
2008-02-05 04:49:54 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
skb->ip_summed = CHECKSUM_PARTIAL;
|
2018-10-10 13:59:35 +00:00
|
|
|
skb->csum_start = csum_start;
|
2008-02-05 04:49:54 +00:00
|
|
|
skb->csum_offset = off;
|
2023-05-05 17:06:18 +00:00
|
|
|
skb->transport_header = csum_start;
|
2008-02-05 04:49:54 +00:00
|
|
|
return true;
|
|
|
|
}
|
2009-02-10 10:09:24 +00:00
|
|
|
EXPORT_SYMBOL_GPL(skb_partial_csum_set);
|
2008-02-05 04:49:54 +00:00
|
|
|
|
2014-01-09 10:02:46 +00:00
|
|
|
static int skb_maybe_pull_tail(struct sk_buff *skb, unsigned int len,
|
|
|
|
unsigned int max)
|
|
|
|
{
|
|
|
|
if (skb_headlen(skb) >= len)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* If we need to pullup then pullup to the max, so we
|
|
|
|
* won't need to do it again.
|
|
|
|
*/
|
|
|
|
if (max > skb->len)
|
|
|
|
max = skb->len;
|
|
|
|
|
|
|
|
if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
if (skb_headlen(skb) < len)
|
|
|
|
return -EPROTO;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-11 13:56:05 +00:00
|
|
|
#define MAX_TCP_HDR_LEN (15 * 4)
|
|
|
|
|
|
|
|
static __sum16 *skb_checksum_setup_ip(struct sk_buff *skb,
|
|
|
|
typeof(IPPROTO_IP) proto,
|
|
|
|
unsigned int off)
|
|
|
|
{
|
2020-02-20 06:23:04 +00:00
|
|
|
int err;
|
2014-03-11 13:56:05 +00:00
|
|
|
|
2020-02-20 06:23:04 +00:00
|
|
|
switch (proto) {
|
2014-03-11 13:56:05 +00:00
|
|
|
case IPPROTO_TCP:
|
|
|
|
err = skb_maybe_pull_tail(skb, off + sizeof(struct tcphdr),
|
|
|
|
off + MAX_TCP_HDR_LEN);
|
|
|
|
if (!err && !skb_partial_csum_set(skb, off,
|
|
|
|
offsetof(struct tcphdr,
|
|
|
|
check)))
|
|
|
|
err = -EPROTO;
|
|
|
|
return err ? ERR_PTR(err) : &tcp_hdr(skb)->check;
|
|
|
|
|
|
|
|
case IPPROTO_UDP:
|
|
|
|
err = skb_maybe_pull_tail(skb, off + sizeof(struct udphdr),
|
|
|
|
off + sizeof(struct udphdr));
|
|
|
|
if (!err && !skb_partial_csum_set(skb, off,
|
|
|
|
offsetof(struct udphdr,
|
|
|
|
check)))
|
|
|
|
err = -EPROTO;
|
|
|
|
return err ? ERR_PTR(err) : &udp_hdr(skb)->check;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERR_PTR(-EPROTO);
|
|
|
|
}
|
|
|
|
|
2014-01-09 10:02:46 +00:00
|
|
|
/* This value should be large enough to cover a tagged ethernet header plus
|
|
|
|
* maximally sized IP and TCP or UDP headers.
|
|
|
|
*/
|
|
|
|
#define MAX_IP_HDR_LEN 128
|
|
|
|
|
2014-03-11 13:56:05 +00:00
|
|
|
static int skb_checksum_setup_ipv4(struct sk_buff *skb, bool recalculate)
|
2014-01-09 10:02:46 +00:00
|
|
|
{
|
|
|
|
unsigned int off;
|
|
|
|
bool fragment;
|
2014-03-11 13:56:05 +00:00
|
|
|
__sum16 *csum;
|
2014-01-09 10:02:46 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
fragment = false;
|
|
|
|
|
|
|
|
err = skb_maybe_pull_tail(skb,
|
|
|
|
sizeof(struct iphdr),
|
|
|
|
MAX_IP_HDR_LEN);
|
|
|
|
if (err < 0)
|
|
|
|
goto out;
|
|
|
|
|
2020-08-06 11:57:18 +00:00
|
|
|
if (ip_is_fragment(ip_hdr(skb)))
|
2014-01-09 10:02:46 +00:00
|
|
|
fragment = true;
|
|
|
|
|
|
|
|
off = ip_hdrlen(skb);
|
|
|
|
|
|
|
|
err = -EPROTO;
|
|
|
|
|
|
|
|
if (fragment)
|
|
|
|
goto out;
|
|
|
|
|
2014-03-11 13:56:05 +00:00
|
|
|
csum = skb_checksum_setup_ip(skb, ip_hdr(skb)->protocol, off);
|
|
|
|
if (IS_ERR(csum))
|
|
|
|
return PTR_ERR(csum);
|
2014-01-09 10:02:46 +00:00
|
|
|
|
2014-03-11 13:56:05 +00:00
|
|
|
if (recalculate)
|
|
|
|
*csum = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
|
|
|
|
ip_hdr(skb)->daddr,
|
|
|
|
skb->len - off,
|
|
|
|
ip_hdr(skb)->protocol, 0);
|
2014-01-09 10:02:46 +00:00
|
|
|
err = 0;
|
|
|
|
|
|
|
|
out:
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This value should be large enough to cover a tagged ethernet header plus
|
|
|
|
* an IPv6 header, all options, and a maximal TCP or UDP header.
|
|
|
|
*/
|
|
|
|
#define MAX_IPV6_HDR_LEN 256
|
|
|
|
|
|
|
|
#define OPT_HDR(type, skb, off) \
|
|
|
|
(type *)(skb_network_header(skb) + (off))
|
|
|
|
|
|
|
|
static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
u8 nexthdr;
|
|
|
|
unsigned int off;
|
|
|
|
unsigned int len;
|
|
|
|
bool fragment;
|
|
|
|
bool done;
|
2014-03-11 13:56:05 +00:00
|
|
|
__sum16 *csum;
|
2014-01-09 10:02:46 +00:00
|
|
|
|
|
|
|
fragment = false;
|
|
|
|
done = false;
|
|
|
|
|
|
|
|
off = sizeof(struct ipv6hdr);
|
|
|
|
|
|
|
|
err = skb_maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN);
|
|
|
|
if (err < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
nexthdr = ipv6_hdr(skb)->nexthdr;
|
|
|
|
|
|
|
|
len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
|
|
|
|
while (off <= len && !done) {
|
|
|
|
switch (nexthdr) {
|
|
|
|
case IPPROTO_DSTOPTS:
|
|
|
|
case IPPROTO_HOPOPTS:
|
|
|
|
case IPPROTO_ROUTING: {
|
|
|
|
struct ipv6_opt_hdr *hp;
|
|
|
|
|
|
|
|
err = skb_maybe_pull_tail(skb,
|
|
|
|
off +
|
|
|
|
sizeof(struct ipv6_opt_hdr),
|
|
|
|
MAX_IPV6_HDR_LEN);
|
|
|
|
if (err < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
|
|
|
|
nexthdr = hp->nexthdr;
|
|
|
|
off += ipv6_optlen(hp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IPPROTO_AH: {
|
|
|
|
struct ip_auth_hdr *hp;
|
|
|
|
|
|
|
|
err = skb_maybe_pull_tail(skb,
|
|
|
|
off +
|
|
|
|
sizeof(struct ip_auth_hdr),
|
|
|
|
MAX_IPV6_HDR_LEN);
|
|
|
|
if (err < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
hp = OPT_HDR(struct ip_auth_hdr, skb, off);
|
|
|
|
nexthdr = hp->nexthdr;
|
|
|
|
off += ipv6_authlen(hp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case IPPROTO_FRAGMENT: {
|
|
|
|
struct frag_hdr *hp;
|
|
|
|
|
|
|
|
err = skb_maybe_pull_tail(skb,
|
|
|
|
off +
|
|
|
|
sizeof(struct frag_hdr),
|
|
|
|
MAX_IPV6_HDR_LEN);
|
|
|
|
if (err < 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
hp = OPT_HDR(struct frag_hdr, skb, off);
|
|
|
|
|
|
|
|
if (hp->frag_off & htons(IP6_OFFSET | IP6_MF))
|
|
|
|
fragment = true;
|
|
|
|
|
|
|
|
nexthdr = hp->nexthdr;
|
|
|
|
off += sizeof(struct frag_hdr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = -EPROTO;
|
|
|
|
|
|
|
|
if (!done || fragment)
|
|
|
|
goto out;
|
|
|
|
|
2014-03-11 13:56:05 +00:00
|
|
|
csum = skb_checksum_setup_ip(skb, nexthdr, off);
|
|
|
|
if (IS_ERR(csum))
|
|
|
|
return PTR_ERR(csum);
|
2014-01-09 10:02:46 +00:00
|
|
|
|
2014-03-11 13:56:05 +00:00
|
|
|
if (recalculate)
|
|
|
|
*csum = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
|
|
|
|
&ipv6_hdr(skb)->daddr,
|
|
|
|
skb->len - off, nexthdr, 0);
|
2014-01-09 10:02:46 +00:00
|
|
|
err = 0;
|
|
|
|
|
|
|
|
out:
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_checksum_setup - set up partial checksum offset
|
|
|
|
* @skb: the skb to set up
|
|
|
|
* @recalculate: if true the pseudo-header checksum will be recalculated
|
|
|
|
*/
|
|
|
|
int skb_checksum_setup(struct sk_buff *skb, bool recalculate)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
switch (skb->protocol) {
|
|
|
|
case htons(ETH_P_IP):
|
2014-03-11 13:56:05 +00:00
|
|
|
err = skb_checksum_setup_ipv4(skb, recalculate);
|
2014-01-09 10:02:46 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case htons(ETH_P_IPV6):
|
|
|
|
err = skb_checksum_setup_ipv6(skb, recalculate);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
err = -EPROTO;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_checksum_setup);
|
|
|
|
|
2015-05-02 12:01:07 +00:00
|
|
|
/**
|
|
|
|
* skb_checksum_maybe_trim - maybe trims the given skb
|
|
|
|
* @skb: the skb to check
|
|
|
|
* @transport_len: the data length beyond the network header
|
|
|
|
*
|
|
|
|
* Checks whether the given skb has data beyond the given transport length.
|
|
|
|
* If so, returns a cloned skb trimmed to this transport length.
|
|
|
|
* Otherwise returns the provided skb. Returns NULL in error cases
|
|
|
|
* (e.g. transport_len exceeds skb length or out-of-memory).
|
|
|
|
*
|
2015-08-13 03:54:07 +00:00
|
|
|
* Caller needs to set the skb transport header and free any returned skb if it
|
|
|
|
* differs from the provided skb.
|
2015-05-02 12:01:07 +00:00
|
|
|
*/
|
|
|
|
static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
|
|
|
|
unsigned int transport_len)
|
|
|
|
{
|
|
|
|
struct sk_buff *skb_chk;
|
|
|
|
unsigned int len = skb_transport_offset(skb) + transport_len;
|
|
|
|
int ret;
|
|
|
|
|
2015-08-13 03:54:07 +00:00
|
|
|
if (skb->len < len)
|
2015-05-02 12:01:07 +00:00
|
|
|
return NULL;
|
2015-08-13 03:54:07 +00:00
|
|
|
else if (skb->len == len)
|
2015-05-02 12:01:07 +00:00
|
|
|
return skb;
|
|
|
|
|
|
|
|
skb_chk = skb_clone(skb, GFP_ATOMIC);
|
|
|
|
if (!skb_chk)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret = pskb_trim_rcsum(skb_chk, len);
|
|
|
|
if (ret) {
|
|
|
|
kfree_skb(skb_chk);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return skb_chk;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_checksum_trimmed - validate checksum of an skb
|
|
|
|
* @skb: the skb to check
|
|
|
|
* @transport_len: the data length beyond the network header
|
|
|
|
* @skb_chkf: checksum function to use
|
|
|
|
*
|
|
|
|
* Applies the given checksum function skb_chkf to the provided skb.
|
|
|
|
* Returns a checked and maybe trimmed skb. Returns NULL on error.
|
|
|
|
*
|
|
|
|
* If the skb has data beyond the given transport length, then a
|
|
|
|
* trimmed & cloned skb is checked and returned.
|
|
|
|
*
|
2015-08-13 03:54:07 +00:00
|
|
|
* Caller needs to set the skb transport header and free any returned skb if it
|
|
|
|
* differs from the provided skb.
|
2015-05-02 12:01:07 +00:00
|
|
|
*/
|
|
|
|
struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,
|
|
|
|
unsigned int transport_len,
|
|
|
|
__sum16(*skb_chkf)(struct sk_buff *skb))
|
|
|
|
{
|
|
|
|
struct sk_buff *skb_chk;
|
|
|
|
unsigned int offset = skb_transport_offset(skb);
|
2015-05-04 22:19:35 +00:00
|
|
|
__sum16 ret;
|
2015-05-02 12:01:07 +00:00
|
|
|
|
|
|
|
skb_chk = skb_checksum_maybe_trim(skb, transport_len);
|
|
|
|
if (!skb_chk)
|
2015-08-13 03:54:07 +00:00
|
|
|
goto err;
|
2015-05-02 12:01:07 +00:00
|
|
|
|
2015-08-13 03:54:07 +00:00
|
|
|
if (!pskb_may_pull(skb_chk, offset))
|
|
|
|
goto err;
|
2015-05-02 12:01:07 +00:00
|
|
|
|
2016-02-24 03:21:42 +00:00
|
|
|
skb_pull_rcsum(skb_chk, offset);
|
2015-05-02 12:01:07 +00:00
|
|
|
ret = skb_chkf(skb_chk);
|
2016-02-24 03:21:42 +00:00
|
|
|
skb_push_rcsum(skb_chk, offset);
|
2015-05-02 12:01:07 +00:00
|
|
|
|
2015-08-13 03:54:07 +00:00
|
|
|
if (ret)
|
|
|
|
goto err;
|
2015-05-02 12:01:07 +00:00
|
|
|
|
|
|
|
return skb_chk;
|
2015-08-13 03:54:07 +00:00
|
|
|
|
|
|
|
err:
|
|
|
|
if (skb_chk && skb_chk != skb)
|
|
|
|
kfree_skb(skb_chk);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
2015-05-02 12:01:07 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_checksum_trimmed);
|
|
|
|
|
2008-06-19 23:22:28 +00:00
|
|
|
void __skb_warn_lro_forwarding(const struct sk_buff *skb)
|
|
|
|
{
|
2012-05-13 21:56:26 +00:00
|
|
|
net_warn_ratelimited("%s: received packets cannot be forwarded while LRO is enabled\n",
|
|
|
|
skb->dev->name);
|
2008-06-19 23:22:28 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__skb_warn_lro_forwarding);
|
2012-05-19 03:02:02 +00:00
|
|
|
|
|
|
|
void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
|
|
|
|
{
|
2012-10-22 09:03:40 +00:00
|
|
|
if (head_stolen) {
|
|
|
|
skb_release_head_state(skb);
|
2024-03-06 16:00:23 +00:00
|
|
|
kmem_cache_free(net_hotdata.skbuff_cache, skb);
|
2012-10-22 09:03:40 +00:00
|
|
|
} else {
|
2012-05-19 03:02:02 +00:00
|
|
|
__kfree_skb(skb);
|
2012-10-22 09:03:40 +00:00
|
|
|
}
|
2012-05-19 03:02:02 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(kfree_skb_partial);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_try_coalesce - try to merge skb to prior one
|
|
|
|
* @to: prior buffer
|
|
|
|
* @from: buffer to add
|
|
|
|
* @fragstolen: pointer to boolean
|
2012-06-08 14:01:44 +00:00
|
|
|
* @delta_truesize: how much more was allocated than was requested
|
2012-05-19 03:02:02 +00:00
|
|
|
*/
|
|
|
|
bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
|
|
|
|
bool *fragstolen, int *delta_truesize)
|
|
|
|
{
|
2017-10-04 17:48:35 +00:00
|
|
|
struct skb_shared_info *to_shinfo, *from_shinfo;
|
2012-05-19 03:02:02 +00:00
|
|
|
int i, delta, len = from->len;
|
|
|
|
|
|
|
|
*fragstolen = false;
|
|
|
|
|
|
|
|
if (skb_cloned(to))
|
|
|
|
return false;
|
|
|
|
|
2023-04-13 09:03:53 +00:00
|
|
|
/* In general, avoid mixing page_pool and non-page_pool allocated
|
skbuff: Optimization of SKB coalescing for page pool
In order to address the issues encountered with commit 1effe8ca4e34
("skbuff: fix coalescing for page_pool fragment recycling"), the
combination of the following condition was excluded from skb coalescing:
from->pp_recycle = 1
from->cloned = 1
to->pp_recycle = 1
However, with page pool environments, the aforementioned combination can
be quite common(ex. NetworkMananger may lead to the additional
packet_type being registered, thus the cloning). In scenarios with a
higher number of small packets, it can significantly affect the success
rate of coalescing. For example, considering packets of 256 bytes size,
our comparison of coalescing success rate is as follows:
Without page pool: 70%
With page pool: 13%
Consequently, this has an impact on performance:
Without page pool: 2.57 Gbits/sec
With page pool: 2.26 Gbits/sec
Therefore, it seems worthwhile to optimize this scenario and enable
coalescing of this particular combination. To achieve this, we need to
ensure the correct increment of the "from" SKB page's page pool
reference count (pp_ref_count).
Following this optimization, the success rate of coalescing measured in
our environment has improved as follows:
With page pool: 60%
This success rate is approaching the rate achieved without using page
pool, and the performance has also been improved:
With page pool: 2.52 Gbits/sec
Below is the performance comparison for small packets before and after
this optimization. We observe no impact to packets larger than 4K.
packet size before after improved
(bytes) (Gbits/sec) (Gbits/sec)
128 1.19 1.27 7.13%
256 2.26 2.52 11.75%
512 4.13 4.81 16.50%
1024 6.17 6.73 9.05%
2048 14.54 15.47 6.45%
4096 25.44 27.87 9.52%
Signed-off-by: Liang Chen <liangchen.linux@gmail.com>
Reviewed-by: Yunsheng Lin <linyunsheng@huawei.com>
Suggested-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Mina Almasry <almasrymina@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-12-15 03:30:11 +00:00
|
|
|
* pages within the same SKB. In theory we could take full
|
|
|
|
* references if @from is cloned and !@to->pp_recycle but its
|
|
|
|
* tricky (due to potential race with the clone disappearing) and
|
|
|
|
* rare, so not worth dealing with.
|
2021-06-07 19:02:38 +00:00
|
|
|
*/
|
skbuff: Optimization of SKB coalescing for page pool
In order to address the issues encountered with commit 1effe8ca4e34
("skbuff: fix coalescing for page_pool fragment recycling"), the
combination of the following condition was excluded from skb coalescing:
from->pp_recycle = 1
from->cloned = 1
to->pp_recycle = 1
However, with page pool environments, the aforementioned combination can
be quite common(ex. NetworkMananger may lead to the additional
packet_type being registered, thus the cloning). In scenarios with a
higher number of small packets, it can significantly affect the success
rate of coalescing. For example, considering packets of 256 bytes size,
our comparison of coalescing success rate is as follows:
Without page pool: 70%
With page pool: 13%
Consequently, this has an impact on performance:
Without page pool: 2.57 Gbits/sec
With page pool: 2.26 Gbits/sec
Therefore, it seems worthwhile to optimize this scenario and enable
coalescing of this particular combination. To achieve this, we need to
ensure the correct increment of the "from" SKB page's page pool
reference count (pp_ref_count).
Following this optimization, the success rate of coalescing measured in
our environment has improved as follows:
With page pool: 60%
This success rate is approaching the rate achieved without using page
pool, and the performance has also been improved:
With page pool: 2.52 Gbits/sec
Below is the performance comparison for small packets before and after
this optimization. We observe no impact to packets larger than 4K.
packet size before after improved
(bytes) (Gbits/sec) (Gbits/sec)
128 1.19 1.27 7.13%
256 2.26 2.52 11.75%
512 4.13 4.81 16.50%
1024 6.17 6.73 9.05%
2048 14.54 15.47 6.45%
4096 25.44 27.87 9.52%
Signed-off-by: Liang Chen <liangchen.linux@gmail.com>
Reviewed-by: Yunsheng Lin <linyunsheng@huawei.com>
Suggested-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Mina Almasry <almasrymina@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-12-15 03:30:11 +00:00
|
|
|
if (to->pp_recycle != from->pp_recycle)
|
2021-06-07 19:02:38 +00:00
|
|
|
return false;
|
|
|
|
|
2012-05-19 03:02:02 +00:00
|
|
|
if (len <= skb_tailroom(to)) {
|
2014-09-15 11:19:52 +00:00
|
|
|
if (len)
|
|
|
|
BUG_ON(skb_copy_bits(from, 0, skb_put(to, len), len));
|
2012-05-19 03:02:02 +00:00
|
|
|
*delta_truesize = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-10-04 17:48:35 +00:00
|
|
|
to_shinfo = skb_shinfo(to);
|
|
|
|
from_shinfo = skb_shinfo(from);
|
|
|
|
if (to_shinfo->frag_list || from_shinfo->frag_list)
|
2012-05-19 03:02:02 +00:00
|
|
|
return false;
|
sock: enable MSG_ZEROCOPY
Prepare the datapath for refcounted ubuf_info. Clone ubuf_info with
skb_zerocopy_clone() wherever needed due to skb split, merge, resize
or clone.
Split skb_orphan_frags into two variants. The split, merge, .. paths
support reference counted zerocopy buffers, so do not do a deep copy.
Add skb_orphan_frags_rx for paths that may loop packets to receive
sockets. That is not allowed, as it may cause unbounded latency.
Deep copy all zerocopy copy buffers, ref-counted or not, in this path.
The exact locations to modify were chosen by exhaustively searching
through all code that might modify skb_frag references and/or the
the SKBTX_DEV_ZEROCOPY tx_flags bit.
The changes err on the safe side, in two ways.
(1) legacy ubuf_info paths virtio and tap are not modified. They keep
a 1:1 ubuf_info to sk_buff relationship. Calls to skb_orphan_frags
still call skb_copy_ubufs and thus copy frags in this case.
(2) not all copies deep in the stack are addressed yet. skb_shift,
skb_split and skb_try_coalesce can be refined to avoid copying.
These are not in the hot path and this patch is hairy enough as
is, so that is left for future refinement.
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-03 20:29:41 +00:00
|
|
|
if (skb_zcopy(to) || skb_zcopy(from))
|
|
|
|
return false;
|
2012-05-19 03:02:02 +00:00
|
|
|
|
|
|
|
if (skb_headlen(from) != 0) {
|
|
|
|
struct page *page;
|
|
|
|
unsigned int offset;
|
|
|
|
|
2017-10-04 17:48:35 +00:00
|
|
|
if (to_shinfo->nr_frags +
|
|
|
|
from_shinfo->nr_frags >= MAX_SKB_FRAGS)
|
2012-05-19 03:02:02 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (skb_head_is_locked(from))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
delta = from->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff));
|
|
|
|
|
|
|
|
page = virt_to_head_page(from->head);
|
|
|
|
offset = from->data - (unsigned char *)page_address(page);
|
|
|
|
|
2017-10-04 17:48:35 +00:00
|
|
|
skb_fill_page_desc(to, to_shinfo->nr_frags,
|
2012-05-19 03:02:02 +00:00
|
|
|
page, offset, skb_headlen(from));
|
|
|
|
*fragstolen = true;
|
|
|
|
} else {
|
2017-10-04 17:48:35 +00:00
|
|
|
if (to_shinfo->nr_frags +
|
|
|
|
from_shinfo->nr_frags > MAX_SKB_FRAGS)
|
2012-05-19 03:02:02 +00:00
|
|
|
return false;
|
|
|
|
|
2012-09-28 20:15:30 +00:00
|
|
|
delta = from->truesize - SKB_TRUESIZE(skb_end_offset(from));
|
2012-05-19 03:02:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WARN_ON_ONCE(delta < len);
|
|
|
|
|
2017-10-04 17:48:35 +00:00
|
|
|
memcpy(to_shinfo->frags + to_shinfo->nr_frags,
|
|
|
|
from_shinfo->frags,
|
|
|
|
from_shinfo->nr_frags * sizeof(skb_frag_t));
|
|
|
|
to_shinfo->nr_frags += from_shinfo->nr_frags;
|
2012-05-19 03:02:02 +00:00
|
|
|
|
|
|
|
if (!skb_cloned(from))
|
2017-10-04 17:48:35 +00:00
|
|
|
from_shinfo->nr_frags = 0;
|
2012-05-19 03:02:02 +00:00
|
|
|
|
2012-09-18 16:53:21 +00:00
|
|
|
/* if the skb is not cloned this does nothing
|
|
|
|
* since we set nr_frags to 0.
|
|
|
|
*/
|
2024-05-02 17:54:22 +00:00
|
|
|
if (skb_pp_frag_ref(from)) {
|
|
|
|
for (i = 0; i < from_shinfo->nr_frags; i++)
|
|
|
|
__skb_frag_ref(&from_shinfo->frags[i]);
|
|
|
|
}
|
2012-05-19 03:02:02 +00:00
|
|
|
|
|
|
|
to->truesize += delta;
|
|
|
|
to->len += len;
|
|
|
|
to->data_len += len;
|
|
|
|
|
|
|
|
*delta_truesize = delta;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_try_coalesce);
|
2013-06-26 14:11:27 +00:00
|
|
|
|
|
|
|
/**
|
2013-09-02 13:34:56 +00:00
|
|
|
* skb_scrub_packet - scrub an skb
|
2013-06-26 14:11:27 +00:00
|
|
|
*
|
|
|
|
* @skb: buffer to clean
|
2013-09-02 13:34:56 +00:00
|
|
|
* @xnet: packet is crossing netns
|
|
|
|
*
|
|
|
|
* skb_scrub_packet can be used after encapsulating or decapsulting a packet
|
|
|
|
* into/from a tunnel. Some information have to be cleared during these
|
|
|
|
* operations.
|
|
|
|
* skb_scrub_packet can also be used to clean a skb before injecting it in
|
|
|
|
* another namespace (@xnet == true). We have to clear all information in the
|
|
|
|
* skb that could impact namespace isolation.
|
2013-06-26 14:11:27 +00:00
|
|
|
*/
|
2013-09-02 13:34:56 +00:00
|
|
|
void skb_scrub_packet(struct sk_buff *skb, bool xnet)
|
2013-06-26 14:11:27 +00:00
|
|
|
{
|
|
|
|
skb->pkt_type = PACKET_HOST;
|
|
|
|
skb->skb_iif = 0;
|
2014-05-04 23:39:18 +00:00
|
|
|
skb->ignore_df = 0;
|
2013-06-26 14:11:27 +00:00
|
|
|
skb_dst_drop(skb);
|
2019-09-26 18:37:05 +00:00
|
|
|
skb_ext_reset(skb);
|
2019-09-29 18:54:03 +00:00
|
|
|
nf_reset_ct(skb);
|
2013-06-26 14:11:27 +00:00
|
|
|
nf_reset_trace(skb);
|
skbuff: Do not scrub skb mark within the same name space
On Wed, Apr 15, 2015 at 05:41:26PM +0200, Nicolas Dichtel wrote:
> Le 15/04/2015 15:57, Herbert Xu a écrit :
> >On Wed, Apr 15, 2015 at 06:22:29PM +0800, Herbert Xu wrote:
> [snip]
> >Subject: skbuff: Do not scrub skb mark within the same name space
> >
> >The commit ea23192e8e577dfc51e0f4fc5ca113af334edff9 ("tunnels:
> Maybe add a Fixes tag?
> Fixes: ea23192e8e57 ("tunnels: harmonize cleanup done on skb on rx path")
>
> >harmonize cleanup done on skb on rx path") broke anyone trying to
> >use netfilter marking across IPv4 tunnels. While most of the
> >fields that are cleared by skb_scrub_packet don't matter, the
> >netfilter mark must be preserved.
> >
> >This patch rearranges skb_scurb_packet to preserve the mark field.
> nit: s/scurb/scrub
>
> Else it's fine for me.
Sure.
PS I used the wrong email for James the first time around. So
let me repeat the question here. Should secmark be preserved
or cleared across tunnels within the same name space? In fact,
do our security models even support name spaces?
---8<---
The commit ea23192e8e577dfc51e0f4fc5ca113af334edff9 ("tunnels:
harmonize cleanup done on skb on rx path") broke anyone trying to
use netfilter marking across IPv4 tunnels. While most of the
fields that are cleared by skb_scrub_packet don't matter, the
netfilter mark must be preserved.
This patch rearranges skb_scrub_packet to preserve the mark field.
Fixes: ea23192e8e57 ("tunnels: harmonize cleanup done on skb on rx path")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-04-16 01:03:27 +00:00
|
|
|
|
2018-11-19 16:11:07 +00:00
|
|
|
#ifdef CONFIG_NET_SWITCHDEV
|
|
|
|
skb->offload_fwd_mark = 0;
|
2018-12-04 08:15:10 +00:00
|
|
|
skb->offload_l3_fwd_mark = 0;
|
2018-11-19 16:11:07 +00:00
|
|
|
#endif
|
|
|
|
|
skbuff: Do not scrub skb mark within the same name space
On Wed, Apr 15, 2015 at 05:41:26PM +0200, Nicolas Dichtel wrote:
> Le 15/04/2015 15:57, Herbert Xu a écrit :
> >On Wed, Apr 15, 2015 at 06:22:29PM +0800, Herbert Xu wrote:
> [snip]
> >Subject: skbuff: Do not scrub skb mark within the same name space
> >
> >The commit ea23192e8e577dfc51e0f4fc5ca113af334edff9 ("tunnels:
> Maybe add a Fixes tag?
> Fixes: ea23192e8e57 ("tunnels: harmonize cleanup done on skb on rx path")
>
> >harmonize cleanup done on skb on rx path") broke anyone trying to
> >use netfilter marking across IPv4 tunnels. While most of the
> >fields that are cleared by skb_scrub_packet don't matter, the
> >netfilter mark must be preserved.
> >
> >This patch rearranges skb_scurb_packet to preserve the mark field.
> nit: s/scurb/scrub
>
> Else it's fine for me.
Sure.
PS I used the wrong email for James the first time around. So
let me repeat the question here. Should secmark be preserved
or cleared across tunnels within the same name space? In fact,
do our security models even support name spaces?
---8<---
The commit ea23192e8e577dfc51e0f4fc5ca113af334edff9 ("tunnels:
harmonize cleanup done on skb on rx path") broke anyone trying to
use netfilter marking across IPv4 tunnels. While most of the
fields that are cleared by skb_scrub_packet don't matter, the
netfilter mark must be preserved.
This patch rearranges skb_scrub_packet to preserve the mark field.
Fixes: ea23192e8e57 ("tunnels: harmonize cleanup done on skb on rx path")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-04-16 01:03:27 +00:00
|
|
|
if (!xnet)
|
|
|
|
return;
|
|
|
|
|
2017-10-26 08:57:05 +00:00
|
|
|
ipvs_reset(skb);
|
skbuff: Do not scrub skb mark within the same name space
On Wed, Apr 15, 2015 at 05:41:26PM +0200, Nicolas Dichtel wrote:
> Le 15/04/2015 15:57, Herbert Xu a écrit :
> >On Wed, Apr 15, 2015 at 06:22:29PM +0800, Herbert Xu wrote:
> [snip]
> >Subject: skbuff: Do not scrub skb mark within the same name space
> >
> >The commit ea23192e8e577dfc51e0f4fc5ca113af334edff9 ("tunnels:
> Maybe add a Fixes tag?
> Fixes: ea23192e8e57 ("tunnels: harmonize cleanup done on skb on rx path")
>
> >harmonize cleanup done on skb on rx path") broke anyone trying to
> >use netfilter marking across IPv4 tunnels. While most of the
> >fields that are cleared by skb_scrub_packet don't matter, the
> >netfilter mark must be preserved.
> >
> >This patch rearranges skb_scurb_packet to preserve the mark field.
> nit: s/scurb/scrub
>
> Else it's fine for me.
Sure.
PS I used the wrong email for James the first time around. So
let me repeat the question here. Should secmark be preserved
or cleared across tunnels within the same name space? In fact,
do our security models even support name spaces?
---8<---
The commit ea23192e8e577dfc51e0f4fc5ca113af334edff9 ("tunnels:
harmonize cleanup done on skb on rx path") broke anyone trying to
use netfilter marking across IPv4 tunnels. While most of the
fields that are cleared by skb_scrub_packet don't matter, the
netfilter mark must be preserved.
This patch rearranges skb_scrub_packet to preserve the mark field.
Fixes: ea23192e8e57 ("tunnels: harmonize cleanup done on skb on rx path")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-04-16 01:03:27 +00:00
|
|
|
skb->mark = 0;
|
2022-03-02 19:55:31 +00:00
|
|
|
skb_clear_tstamp(skb);
|
2013-06-26 14:11:27 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_scrub_packet);
|
2014-01-26 09:58:16 +00:00
|
|
|
|
net: Always untag vlan-tagged traffic on input.
Currently the functionality to untag traffic on input resides
as part of the vlan module and is build only when VLAN support
is enabled in the kernel. When VLAN is disabled, the function
vlan_untag() turns into a stub and doesn't really untag the
packets. This seems to create an interesting interaction
between VMs supporting checksum offloading and some network drivers.
There are some drivers that do not allow the user to change
tx-vlan-offload feature of the driver. These drivers also seem
to assume that any VLAN-tagged traffic they transmit will
have the vlan information in the vlan_tci and not in the vlan
header already in the skb. When transmitting skbs that already
have tagged data with partial checksum set, the checksum doesn't
appear to be updated correctly by the card thus resulting in a
failure to establish TCP connections.
The following is a packet trace taken on the receiver where a
sender is a VM with a VLAN configued. The host VM is running on
doest not have VLAN support and the outging interface on the
host is tg3:
10:12:43.503055 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27243,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x48d9), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294837885 ecr 0,nop,wscale 7], length 0
10:12:44.505556 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27244,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x44ee), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294838888 ecr 0,nop,wscale 7], length 0
This connection finally times out.
I've only access to the TG3 hardware in this configuration thus have
only tested this with TG3 driver. There are a lot of other drivers
that do not permit user changes to vlan acceleration features, and
I don't know if they all suffere from a similar issue.
The patch attempt to fix this another way. It moves the vlan header
stipping code out of the vlan module and always builds it into the
kernel network core. This way, even if vlan is not supported on
a virtualizatoin host, the virtual machines running on top of such
host will still work with VLANs enabled.
CC: Patrick McHardy <kaber@trash.net>
CC: Nithin Nayak Sujir <nsujir@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
CC: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-08 18:42:13 +00:00
|
|
|
static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
|
|
|
|
{
|
2019-04-16 01:22:28 +00:00
|
|
|
int mac_len, meta_len;
|
|
|
|
void *meta;
|
2018-03-13 05:51:27 +00:00
|
|
|
|
net: Always untag vlan-tagged traffic on input.
Currently the functionality to untag traffic on input resides
as part of the vlan module and is build only when VLAN support
is enabled in the kernel. When VLAN is disabled, the function
vlan_untag() turns into a stub and doesn't really untag the
packets. This seems to create an interesting interaction
between VMs supporting checksum offloading and some network drivers.
There are some drivers that do not allow the user to change
tx-vlan-offload feature of the driver. These drivers also seem
to assume that any VLAN-tagged traffic they transmit will
have the vlan information in the vlan_tci and not in the vlan
header already in the skb. When transmitting skbs that already
have tagged data with partial checksum set, the checksum doesn't
appear to be updated correctly by the card thus resulting in a
failure to establish TCP connections.
The following is a packet trace taken on the receiver where a
sender is a VM with a VLAN configued. The host VM is running on
doest not have VLAN support and the outging interface on the
host is tg3:
10:12:43.503055 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27243,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x48d9), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294837885 ecr 0,nop,wscale 7], length 0
10:12:44.505556 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27244,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x44ee), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294838888 ecr 0,nop,wscale 7], length 0
This connection finally times out.
I've only access to the TG3 hardware in this configuration thus have
only tested this with TG3 driver. There are a lot of other drivers
that do not permit user changes to vlan acceleration features, and
I don't know if they all suffere from a similar issue.
The patch attempt to fix this another way. It moves the vlan header
stipping code out of the vlan module and always builds it into the
kernel network core. This way, even if vlan is not supported on
a virtualizatoin host, the virtual machines running on top of such
host will still work with VLANs enabled.
CC: Patrick McHardy <kaber@trash.net>
CC: Nithin Nayak Sujir <nsujir@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
CC: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-08 18:42:13 +00:00
|
|
|
if (skb_cow(skb, skb_headroom(skb)) < 0) {
|
|
|
|
kfree_skb(skb);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-03-13 05:51:27 +00:00
|
|
|
mac_len = skb->data - skb_mac_header(skb);
|
2018-03-29 10:05:29 +00:00
|
|
|
if (likely(mac_len > VLAN_HLEN + ETH_TLEN)) {
|
|
|
|
memmove(skb_mac_header(skb) + VLAN_HLEN, skb_mac_header(skb),
|
|
|
|
mac_len - VLAN_HLEN - ETH_TLEN);
|
|
|
|
}
|
2019-04-16 01:22:28 +00:00
|
|
|
|
|
|
|
meta_len = skb_metadata_len(skb);
|
|
|
|
if (meta_len) {
|
|
|
|
meta = skb_metadata_end(skb) - meta_len;
|
|
|
|
memmove(meta + VLAN_HLEN, meta, meta_len);
|
|
|
|
}
|
|
|
|
|
net: Always untag vlan-tagged traffic on input.
Currently the functionality to untag traffic on input resides
as part of the vlan module and is build only when VLAN support
is enabled in the kernel. When VLAN is disabled, the function
vlan_untag() turns into a stub and doesn't really untag the
packets. This seems to create an interesting interaction
between VMs supporting checksum offloading and some network drivers.
There are some drivers that do not allow the user to change
tx-vlan-offload feature of the driver. These drivers also seem
to assume that any VLAN-tagged traffic they transmit will
have the vlan information in the vlan_tci and not in the vlan
header already in the skb. When transmitting skbs that already
have tagged data with partial checksum set, the checksum doesn't
appear to be updated correctly by the card thus resulting in a
failure to establish TCP connections.
The following is a packet trace taken on the receiver where a
sender is a VM with a VLAN configued. The host VM is running on
doest not have VLAN support and the outging interface on the
host is tg3:
10:12:43.503055 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27243,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x48d9), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294837885 ecr 0,nop,wscale 7], length 0
10:12:44.505556 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27244,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x44ee), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294838888 ecr 0,nop,wscale 7], length 0
This connection finally times out.
I've only access to the TG3 hardware in this configuration thus have
only tested this with TG3 driver. There are a lot of other drivers
that do not permit user changes to vlan acceleration features, and
I don't know if they all suffere from a similar issue.
The patch attempt to fix this another way. It moves the vlan header
stipping code out of the vlan module and always builds it into the
kernel network core. This way, even if vlan is not supported on
a virtualizatoin host, the virtual machines running on top of such
host will still work with VLANs enabled.
CC: Patrick McHardy <kaber@trash.net>
CC: Nithin Nayak Sujir <nsujir@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
CC: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-08 18:42:13 +00:00
|
|
|
skb->mac_header += VLAN_HLEN;
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sk_buff *skb_vlan_untag(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct vlan_hdr *vhdr;
|
|
|
|
u16 vlan_tci;
|
|
|
|
|
2015-01-13 16:13:44 +00:00
|
|
|
if (unlikely(skb_vlan_tag_present(skb))) {
|
net: Always untag vlan-tagged traffic on input.
Currently the functionality to untag traffic on input resides
as part of the vlan module and is build only when VLAN support
is enabled in the kernel. When VLAN is disabled, the function
vlan_untag() turns into a stub and doesn't really untag the
packets. This seems to create an interesting interaction
between VMs supporting checksum offloading and some network drivers.
There are some drivers that do not allow the user to change
tx-vlan-offload feature of the driver. These drivers also seem
to assume that any VLAN-tagged traffic they transmit will
have the vlan information in the vlan_tci and not in the vlan
header already in the skb. When transmitting skbs that already
have tagged data with partial checksum set, the checksum doesn't
appear to be updated correctly by the card thus resulting in a
failure to establish TCP connections.
The following is a packet trace taken on the receiver where a
sender is a VM with a VLAN configued. The host VM is running on
doest not have VLAN support and the outging interface on the
host is tg3:
10:12:43.503055 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27243,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x48d9), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294837885 ecr 0,nop,wscale 7], length 0
10:12:44.505556 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27244,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x44ee), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294838888 ecr 0,nop,wscale 7], length 0
This connection finally times out.
I've only access to the TG3 hardware in this configuration thus have
only tested this with TG3 driver. There are a lot of other drivers
that do not permit user changes to vlan acceleration features, and
I don't know if they all suffere from a similar issue.
The patch attempt to fix this another way. It moves the vlan header
stipping code out of the vlan module and always builds it into the
kernel network core. This way, even if vlan is not supported on
a virtualizatoin host, the virtual machines running on top of such
host will still work with VLANs enabled.
CC: Patrick McHardy <kaber@trash.net>
CC: Nithin Nayak Sujir <nsujir@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
CC: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-08 18:42:13 +00:00
|
|
|
/* vlan_tci is already set-up so leave this for another time */
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb = skb_share_check(skb, GFP_ATOMIC);
|
|
|
|
if (unlikely(!skb))
|
|
|
|
goto err_free;
|
2020-08-15 08:44:31 +00:00
|
|
|
/* We may access the two bytes after vlan_hdr in vlan_set_encap_proto(). */
|
|
|
|
if (unlikely(!pskb_may_pull(skb, VLAN_HLEN + sizeof(unsigned short))))
|
net: Always untag vlan-tagged traffic on input.
Currently the functionality to untag traffic on input resides
as part of the vlan module and is build only when VLAN support
is enabled in the kernel. When VLAN is disabled, the function
vlan_untag() turns into a stub and doesn't really untag the
packets. This seems to create an interesting interaction
between VMs supporting checksum offloading and some network drivers.
There are some drivers that do not allow the user to change
tx-vlan-offload feature of the driver. These drivers also seem
to assume that any VLAN-tagged traffic they transmit will
have the vlan information in the vlan_tci and not in the vlan
header already in the skb. When transmitting skbs that already
have tagged data with partial checksum set, the checksum doesn't
appear to be updated correctly by the card thus resulting in a
failure to establish TCP connections.
The following is a packet trace taken on the receiver where a
sender is a VM with a VLAN configued. The host VM is running on
doest not have VLAN support and the outging interface on the
host is tg3:
10:12:43.503055 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27243,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x48d9), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294837885 ecr 0,nop,wscale 7], length 0
10:12:44.505556 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27244,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x44ee), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294838888 ecr 0,nop,wscale 7], length 0
This connection finally times out.
I've only access to the TG3 hardware in this configuration thus have
only tested this with TG3 driver. There are a lot of other drivers
that do not permit user changes to vlan acceleration features, and
I don't know if they all suffere from a similar issue.
The patch attempt to fix this another way. It moves the vlan header
stipping code out of the vlan module and always builds it into the
kernel network core. This way, even if vlan is not supported on
a virtualizatoin host, the virtual machines running on top of such
host will still work with VLANs enabled.
CC: Patrick McHardy <kaber@trash.net>
CC: Nithin Nayak Sujir <nsujir@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
CC: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-08 18:42:13 +00:00
|
|
|
goto err_free;
|
|
|
|
|
|
|
|
vhdr = (struct vlan_hdr *)skb->data;
|
|
|
|
vlan_tci = ntohs(vhdr->h_vlan_TCI);
|
|
|
|
__vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci);
|
|
|
|
|
|
|
|
skb_pull_rcsum(skb, VLAN_HLEN);
|
|
|
|
vlan_set_encap_proto(skb, vhdr);
|
|
|
|
|
|
|
|
skb = skb_reorder_vlan_header(skb);
|
|
|
|
if (unlikely(!skb))
|
|
|
|
goto err_free;
|
|
|
|
|
|
|
|
skb_reset_network_header(skb);
|
2020-11-09 23:47:23 +00:00
|
|
|
if (!skb_transport_header_was_set(skb))
|
|
|
|
skb_reset_transport_header(skb);
|
net: Always untag vlan-tagged traffic on input.
Currently the functionality to untag traffic on input resides
as part of the vlan module and is build only when VLAN support
is enabled in the kernel. When VLAN is disabled, the function
vlan_untag() turns into a stub and doesn't really untag the
packets. This seems to create an interesting interaction
between VMs supporting checksum offloading and some network drivers.
There are some drivers that do not allow the user to change
tx-vlan-offload feature of the driver. These drivers also seem
to assume that any VLAN-tagged traffic they transmit will
have the vlan information in the vlan_tci and not in the vlan
header already in the skb. When transmitting skbs that already
have tagged data with partial checksum set, the checksum doesn't
appear to be updated correctly by the card thus resulting in a
failure to establish TCP connections.
The following is a packet trace taken on the receiver where a
sender is a VM with a VLAN configued. The host VM is running on
doest not have VLAN support and the outging interface on the
host is tg3:
10:12:43.503055 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27243,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x48d9), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294837885 ecr 0,nop,wscale 7], length 0
10:12:44.505556 52:54:00:ae:42:3f > 28:d2:44:7d:c2:de, ethertype 802.1Q
(0x8100), length 78: vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 27244,
offset 0, flags [DF], proto TCP (6), length 60)
10.0.100.1.58545 > 10.0.100.10.ircu-2: Flags [S], cksum 0xdc39 (incorrect
-> 0x44ee), seq 1069378582, win 29200, options [mss 1460,sackOK,TS val
4294838888 ecr 0,nop,wscale 7], length 0
This connection finally times out.
I've only access to the TG3 hardware in this configuration thus have
only tested this with TG3 driver. There are a lot of other drivers
that do not permit user changes to vlan acceleration features, and
I don't know if they all suffere from a similar issue.
The patch attempt to fix this another way. It moves the vlan header
stipping code out of the vlan module and always builds it into the
kernel network core. This way, even if vlan is not supported on
a virtualizatoin host, the virtual machines running on top of such
host will still work with VLANs enabled.
CC: Patrick McHardy <kaber@trash.net>
CC: Nithin Nayak Sujir <nsujir@broadcom.com>
CC: Michael Chan <mchan@broadcom.com>
CC: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-08-08 18:42:13 +00:00
|
|
|
skb_reset_mac_len(skb);
|
|
|
|
|
|
|
|
return skb;
|
|
|
|
|
|
|
|
err_free:
|
|
|
|
kfree_skb(skb);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_vlan_untag);
|
2014-09-17 11:49:49 +00:00
|
|
|
|
2022-04-16 10:58:00 +00:00
|
|
|
int skb_ensure_writable(struct sk_buff *skb, unsigned int write_len)
|
2014-11-19 13:05:01 +00:00
|
|
|
{
|
|
|
|
if (!pskb_may_pull(skb, write_len))
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
if (!skb_cloned(skb) || skb_clone_writable(skb, write_len))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_ensure_writable);
|
|
|
|
|
2023-12-19 14:53:25 +00:00
|
|
|
int skb_ensure_writable_head_tail(struct sk_buff *skb, struct net_device *dev)
|
|
|
|
{
|
|
|
|
int needed_headroom = dev->needed_headroom;
|
|
|
|
int needed_tailroom = dev->needed_tailroom;
|
|
|
|
|
|
|
|
/* For tail taggers, we need to pad short frames ourselves, to ensure
|
|
|
|
* that the tail tag does not fail at its role of being at the end of
|
|
|
|
* the packet, once the conduit interface pads the frame. Account for
|
|
|
|
* that pad length here, and pad later.
|
|
|
|
*/
|
|
|
|
if (unlikely(needed_tailroom && skb->len < ETH_ZLEN))
|
|
|
|
needed_tailroom += ETH_ZLEN - skb->len;
|
|
|
|
/* skb_headroom() returns unsigned int... */
|
|
|
|
needed_headroom = max_t(int, needed_headroom - skb_headroom(skb), 0);
|
|
|
|
needed_tailroom = max_t(int, needed_tailroom - skb_tailroom(skb), 0);
|
|
|
|
|
|
|
|
if (likely(!needed_headroom && !needed_tailroom && !skb_cloned(skb)))
|
|
|
|
/* No reallocation needed, yay! */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return pskb_expand_head(skb, needed_headroom, needed_tailroom,
|
|
|
|
GFP_ATOMIC);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_ensure_writable_head_tail);
|
|
|
|
|
2016-09-19 16:11:09 +00:00
|
|
|
/* remove VLAN header from packet and update csum accordingly.
|
|
|
|
* expects a non skb_vlan_tag_present skb with a vlan tag payload
|
|
|
|
*/
|
|
|
|
int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci)
|
2014-11-19 13:05:02 +00:00
|
|
|
{
|
2016-09-29 09:10:41 +00:00
|
|
|
int offset = skb->data - skb_mac_header(skb);
|
2014-11-19 13:05:02 +00:00
|
|
|
int err;
|
|
|
|
|
2016-09-29 09:10:41 +00:00
|
|
|
if (WARN_ONCE(offset,
|
|
|
|
"__skb_vlan_pop got skb with skb->data not at mac header (offset %d)\n",
|
|
|
|
offset)) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2014-11-19 13:05:02 +00:00
|
|
|
err = skb_ensure_writable(skb, VLAN_ETH_HLEN);
|
|
|
|
if (unlikely(err))
|
2016-09-29 09:10:41 +00:00
|
|
|
return err;
|
2014-11-19 13:05:02 +00:00
|
|
|
|
|
|
|
skb_postpull_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
|
|
|
|
|
net: dsa: tag_ocelot: call only the relevant portion of __skb_vlan_pop() on TX
ocelot_xmit_get_vlan_info() calls __skb_vlan_pop() as the most
appropriate helper I could find which strips away a VLAN header.
That's all I need it to do, but __skb_vlan_pop() has more logic, which
will become incompatible with the future revert of commit 6d1ccff62780
("net: reset mac header in dev_start_xmit()").
Namely, it performs a sanity check on skb_mac_header(), which will stop
being set after the above revert, so it will return an error instead of
removing the VLAN tag.
ocelot_xmit_get_vlan_info() gets called in 2 circumstances:
(1) the port is under a VLAN-aware bridge and the bridge sends
VLAN-tagged packets
(2) the port is under a VLAN-aware bridge and somebody else (an 8021q
upper) sends VLAN-tagged packets (using a VID that isn't in the
bridge vlan tables)
In case (1), there is actually no bug to defend against, because
br_dev_xmit() calls skb_reset_mac_header() and things continue to work.
However, in case (2), illustrated using the commands below, it can be
seen that our intervention is needed, since __skb_vlan_pop() complains:
$ ip link add br0 type bridge vlan_filtering 1 && ip link set br0 up
$ ip link set $eth master br0 && ip link set $eth up
$ ip link add link $eth name $eth.100 type vlan id 100 && ip link set $eth.100 up
$ ip addr add 192.168.100.1/24 dev $eth.100
I could fend off the checks in __skb_vlan_pop() with some
skb_mac_header_was_set() calls, but seeing how few callers of
__skb_vlan_pop() there are from TX paths, that seems rather
unproductive.
As an alternative solution, extract the bare minimum logic to strip a
VLAN header, and move it to a new helper named vlan_remove_tag(), close
to the definition of vlan_insert_tag(). Document it appropriately and
make ocelot_xmit_get_vlan_info() call this smaller helper instead.
Seeing that it doesn't appear illegal to test skb->protocol in the TX
path, I guess it would be a good for vlan_remove_tag() to also absorb
the vlan_set_encap_proto() function call.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2023-04-20 22:56:01 +00:00
|
|
|
vlan_remove_tag(skb, vlan_tci);
|
2014-11-19 13:05:02 +00:00
|
|
|
|
|
|
|
skb->mac_header += VLAN_HLEN;
|
|
|
|
|
|
|
|
if (skb_network_offset(skb) < ETH_HLEN)
|
|
|
|
skb_set_network_header(skb, ETH_HLEN);
|
|
|
|
|
|
|
|
skb_reset_mac_len(skb);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
2016-09-19 16:11:09 +00:00
|
|
|
EXPORT_SYMBOL(__skb_vlan_pop);
|
2014-11-19 13:05:02 +00:00
|
|
|
|
2016-09-29 09:10:41 +00:00
|
|
|
/* Pop a vlan tag either from hwaccel or from payload.
|
|
|
|
* Expects skb->data at mac header.
|
|
|
|
*/
|
2014-11-19 13:05:02 +00:00
|
|
|
int skb_vlan_pop(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
u16 vlan_tci;
|
|
|
|
__be16 vlan_proto;
|
|
|
|
int err;
|
|
|
|
|
2015-01-13 16:13:44 +00:00
|
|
|
if (likely(skb_vlan_tag_present(skb))) {
|
2018-11-08 23:18:02 +00:00
|
|
|
__vlan_hwaccel_clear_tag(skb);
|
2014-11-19 13:05:02 +00:00
|
|
|
} else {
|
2016-09-20 09:48:37 +00:00
|
|
|
if (unlikely(!eth_type_vlan(skb->protocol)))
|
2014-11-19 13:05:02 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err = __skb_vlan_pop(skb, &vlan_tci);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
/* move next vlan tag to hw accel tag */
|
2016-09-20 09:48:37 +00:00
|
|
|
if (likely(!eth_type_vlan(skb->protocol)))
|
2014-11-19 13:05:02 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
vlan_proto = skb->protocol;
|
|
|
|
err = __skb_vlan_pop(skb, &vlan_tci);
|
|
|
|
if (unlikely(err))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_vlan_pop);
|
|
|
|
|
2016-09-29 09:10:41 +00:00
|
|
|
/* Push a vlan tag either into hwaccel or into payload (if hwaccel tag present).
|
|
|
|
* Expects skb->data at mac header.
|
|
|
|
*/
|
2014-11-19 13:05:02 +00:00
|
|
|
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
|
|
|
|
{
|
2015-01-13 16:13:44 +00:00
|
|
|
if (skb_vlan_tag_present(skb)) {
|
2016-09-29 09:10:41 +00:00
|
|
|
int offset = skb->data - skb_mac_header(skb);
|
2014-11-19 13:05:02 +00:00
|
|
|
int err;
|
|
|
|
|
2016-09-29 09:10:41 +00:00
|
|
|
if (WARN_ONCE(offset,
|
|
|
|
"skb_vlan_push got skb with skb->data not at mac header (offset %d)\n",
|
|
|
|
offset)) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2014-11-19 13:05:02 +00:00
|
|
|
err = __vlan_insert_tag(skb, skb->vlan_proto,
|
2015-01-13 16:13:44 +00:00
|
|
|
skb_vlan_tag_get(skb));
|
2016-09-29 09:10:41 +00:00
|
|
|
if (err)
|
2014-11-19 13:05:02 +00:00
|
|
|
return err;
|
2016-04-16 00:27:58 +00:00
|
|
|
|
2014-11-19 13:05:02 +00:00
|
|
|
skb->protocol = skb->vlan_proto;
|
|
|
|
skb->mac_len += VLAN_HLEN;
|
|
|
|
|
2016-02-19 23:29:30 +00:00
|
|
|
skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
|
2014-11-19 13:05:02 +00:00
|
|
|
}
|
|
|
|
__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_vlan_push);
|
|
|
|
|
2020-10-02 22:44:28 +00:00
|
|
|
/**
|
|
|
|
* skb_eth_pop() - Drop the Ethernet header at the head of a packet
|
|
|
|
*
|
|
|
|
* @skb: Socket buffer to modify
|
|
|
|
*
|
|
|
|
* Drop the Ethernet header of @skb.
|
|
|
|
*
|
|
|
|
* Expects that skb->data points to the mac header and that no VLAN tags are
|
|
|
|
* present.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -errno otherwise.
|
|
|
|
*/
|
|
|
|
int skb_eth_pop(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
if (!pskb_may_pull(skb, ETH_HLEN) || skb_vlan_tagged(skb) ||
|
|
|
|
skb_network_offset(skb) < ETH_HLEN)
|
|
|
|
return -EPROTO;
|
|
|
|
|
|
|
|
skb_pull_rcsum(skb, ETH_HLEN);
|
|
|
|
skb_reset_mac_header(skb);
|
|
|
|
skb_reset_mac_len(skb);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_eth_pop);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_eth_push() - Add a new Ethernet header at the head of a packet
|
|
|
|
*
|
|
|
|
* @skb: Socket buffer to modify
|
|
|
|
* @dst: Destination MAC address of the new header
|
|
|
|
* @src: Source MAC address of the new header
|
|
|
|
*
|
|
|
|
* Prepend @skb with a new Ethernet header.
|
|
|
|
*
|
|
|
|
* Expects that skb->data points to the mac header, which must be empty.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -errno otherwise.
|
|
|
|
*/
|
|
|
|
int skb_eth_push(struct sk_buff *skb, const unsigned char *dst,
|
|
|
|
const unsigned char *src)
|
|
|
|
{
|
|
|
|
struct ethhdr *eth;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (skb_network_offset(skb) || skb_vlan_tag_present(skb))
|
|
|
|
return -EPROTO;
|
|
|
|
|
|
|
|
err = skb_cow_head(skb, sizeof(*eth));
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
skb_push(skb, sizeof(*eth));
|
|
|
|
skb_reset_mac_header(skb);
|
|
|
|
skb_reset_mac_len(skb);
|
|
|
|
|
|
|
|
eth = eth_hdr(skb);
|
|
|
|
ether_addr_copy(eth->h_dest, dst);
|
|
|
|
ether_addr_copy(eth->h_source, src);
|
|
|
|
eth->h_proto = skb->protocol;
|
|
|
|
|
|
|
|
skb_postpush_rcsum(skb, eth, sizeof(*eth));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_eth_push);
|
|
|
|
|
2019-07-07 14:01:54 +00:00
|
|
|
/* Update the ethertype of hdr and the skb csum value if required. */
|
|
|
|
static void skb_mod_eth_type(struct sk_buff *skb, struct ethhdr *hdr,
|
|
|
|
__be16 ethertype)
|
|
|
|
{
|
|
|
|
if (skb->ip_summed == CHECKSUM_COMPLETE) {
|
|
|
|
__be16 diff[] = { ~hdr->h_proto, ethertype };
|
|
|
|
|
|
|
|
skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
|
|
|
|
}
|
|
|
|
|
|
|
|
hdr->h_proto = ethertype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-12-21 03:20:01 +00:00
|
|
|
* skb_mpls_push() - push a new MPLS header after mac_len bytes from start of
|
|
|
|
* the packet
|
2019-07-07 14:01:54 +00:00
|
|
|
*
|
|
|
|
* @skb: buffer
|
|
|
|
* @mpls_lse: MPLS label stack entry to push
|
|
|
|
* @mpls_proto: ethertype of the new MPLS header (expects 0x8847 or 0x8848)
|
2019-10-12 11:55:07 +00:00
|
|
|
* @mac_len: length of the MAC header
|
2019-12-21 03:20:01 +00:00
|
|
|
* @ethernet: flag to indicate if the resulting packet after skb_mpls_push is
|
|
|
|
* ethernet
|
2019-07-07 14:01:54 +00:00
|
|
|
*
|
|
|
|
* Expects skb->data at mac header.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -errno otherwise.
|
|
|
|
*/
|
2019-10-12 11:55:07 +00:00
|
|
|
int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto,
|
net: Fixed updating of ethertype in skb_mpls_push()
The skb_mpls_push was not updating ethertype of an ethernet packet if
the packet was originally received from a non ARPHRD_ETHER device.
In the below OVS data path flow, since the device corresponding to
port 7 is an l3 device (ARPHRD_NONE) the skb_mpls_push function does
not update the ethertype of the packet even though the previous
push_eth action had added an ethernet header to the packet.
recirc_id(0),in_port(7),eth_type(0x0800),ipv4(tos=0/0xfc,ttl=64,frag=no),
actions:push_eth(src=00:00:00:00:00:00,dst=00:00:00:00:00:00),
push_mpls(label=13,tc=0,ttl=64,bos=1,eth_type=0x8847),4
Fixes: 8822e270d697 ("net: core: move push MPLS functionality from OvS to core helper")
Signed-off-by: Martin Varghese <martin.varghese@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-12-05 00:27:22 +00:00
|
|
|
int mac_len, bool ethernet)
|
2019-07-07 14:01:54 +00:00
|
|
|
{
|
|
|
|
struct mpls_shim_hdr *lse;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (unlikely(!eth_p_mpls(mpls_proto)))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Networking stack does not allow simultaneous Tunnel and MPLS GSO. */
|
|
|
|
if (skb->encapsulation)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
err = skb_cow_head(skb, MPLS_HLEN);
|
|
|
|
if (unlikely(err))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (!skb->inner_protocol) {
|
2019-12-21 03:20:01 +00:00
|
|
|
skb_set_inner_network_header(skb, skb_network_offset(skb));
|
2019-07-07 14:01:54 +00:00
|
|
|
skb_set_inner_protocol(skb, skb->protocol);
|
|
|
|
}
|
|
|
|
|
|
|
|
skb_push(skb, MPLS_HLEN);
|
|
|
|
memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
|
2019-10-12 11:55:07 +00:00
|
|
|
mac_len);
|
2019-07-07 14:01:54 +00:00
|
|
|
skb_reset_mac_header(skb);
|
2019-10-12 11:55:07 +00:00
|
|
|
skb_set_network_header(skb, mac_len);
|
2019-12-21 03:20:01 +00:00
|
|
|
skb_reset_mac_len(skb);
|
2019-07-07 14:01:54 +00:00
|
|
|
|
|
|
|
lse = mpls_hdr(skb);
|
|
|
|
lse->label_stack_entry = mpls_lse;
|
|
|
|
skb_postpush_rcsum(skb, lse, MPLS_HLEN);
|
|
|
|
|
2020-10-02 19:53:08 +00:00
|
|
|
if (ethernet && mac_len >= ETH_HLEN)
|
2019-07-07 14:01:54 +00:00
|
|
|
skb_mod_eth_type(skb, eth_hdr(skb), mpls_proto);
|
|
|
|
skb->protocol = mpls_proto;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_mpls_push);
|
|
|
|
|
2019-07-07 14:01:55 +00:00
|
|
|
/**
|
|
|
|
* skb_mpls_pop() - pop the outermost MPLS header
|
|
|
|
*
|
|
|
|
* @skb: buffer
|
|
|
|
* @next_proto: ethertype of header after popped MPLS header
|
2019-10-12 11:55:07 +00:00
|
|
|
* @mac_len: length of the MAC header
|
2019-12-21 03:20:23 +00:00
|
|
|
* @ethernet: flag to indicate if the packet is ethernet
|
2019-07-07 14:01:55 +00:00
|
|
|
*
|
|
|
|
* Expects skb->data at mac header.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -errno otherwise.
|
|
|
|
*/
|
Fixed updating of ethertype in function skb_mpls_pop
The skb_mpls_pop was not updating ethertype of an ethernet packet if the
packet was originally received from a non ARPHRD_ETHER device.
In the below OVS data path flow, since the device corresponding to port 7
is an l3 device (ARPHRD_NONE) the skb_mpls_pop function does not update
the ethertype of the packet even though the previous push_eth action had
added an ethernet header to the packet.
recirc_id(0),in_port(7),eth_type(0x8847),
mpls(label=12/0xfffff,tc=0/0,ttl=0/0x0,bos=1/1),
actions:push_eth(src=00:00:00:00:00:00,dst=00:00:00:00:00:00),
pop_mpls(eth_type=0x800),4
Fixes: ed246cee09b9 ("net: core: move pop MPLS functionality from OvS to core helper")
Signed-off-by: Martin Varghese <martin.varghese@nokia.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-12-02 05:19:51 +00:00
|
|
|
int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len,
|
|
|
|
bool ethernet)
|
2019-07-07 14:01:55 +00:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (unlikely(!eth_p_mpls(skb->protocol)))
|
2019-10-12 11:55:06 +00:00
|
|
|
return 0;
|
2019-07-07 14:01:55 +00:00
|
|
|
|
2019-10-12 11:55:07 +00:00
|
|
|
err = skb_ensure_writable(skb, mac_len + MPLS_HLEN);
|
2019-07-07 14:01:55 +00:00
|
|
|
if (unlikely(err))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
skb_postpull_rcsum(skb, mpls_hdr(skb), MPLS_HLEN);
|
|
|
|
memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb),
|
2019-10-12 11:55:07 +00:00
|
|
|
mac_len);
|
2019-07-07 14:01:55 +00:00
|
|
|
|
|
|
|
__skb_pull(skb, MPLS_HLEN);
|
|
|
|
skb_reset_mac_header(skb);
|
2019-10-12 11:55:07 +00:00
|
|
|
skb_set_network_header(skb, mac_len);
|
2019-07-07 14:01:55 +00:00
|
|
|
|
2020-10-02 19:53:08 +00:00
|
|
|
if (ethernet && mac_len >= ETH_HLEN) {
|
2019-07-07 14:01:55 +00:00
|
|
|
struct ethhdr *hdr;
|
|
|
|
|
|
|
|
/* use mpls_hdr() to get ethertype to account for VLANs. */
|
|
|
|
hdr = (struct ethhdr *)((void *)mpls_hdr(skb) - ETH_HLEN);
|
|
|
|
skb_mod_eth_type(skb, hdr, next_proto);
|
|
|
|
}
|
|
|
|
skb->protocol = next_proto;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_mpls_pop);
|
|
|
|
|
2019-07-07 14:01:56 +00:00
|
|
|
/**
|
|
|
|
* skb_mpls_update_lse() - modify outermost MPLS header and update csum
|
|
|
|
*
|
|
|
|
* @skb: buffer
|
|
|
|
* @mpls_lse: new MPLS label stack entry to update to
|
|
|
|
*
|
|
|
|
* Expects skb->data at mac header.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -errno otherwise.
|
|
|
|
*/
|
|
|
|
int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (unlikely(!eth_p_mpls(skb->protocol)))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
|
|
|
|
if (unlikely(err))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (skb->ip_summed == CHECKSUM_COMPLETE) {
|
|
|
|
__be32 diff[] = { ~mpls_hdr(skb)->label_stack_entry, mpls_lse };
|
|
|
|
|
|
|
|
skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
|
|
|
|
}
|
|
|
|
|
|
|
|
mpls_hdr(skb)->label_stack_entry = mpls_lse;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_mpls_update_lse);
|
|
|
|
|
2019-07-07 14:01:57 +00:00
|
|
|
/**
|
|
|
|
* skb_mpls_dec_ttl() - decrement the TTL of the outermost MPLS header
|
|
|
|
*
|
|
|
|
* @skb: buffer
|
|
|
|
*
|
|
|
|
* Expects skb->data at mac header.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -errno otherwise.
|
|
|
|
*/
|
|
|
|
int skb_mpls_dec_ttl(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
u32 lse;
|
|
|
|
u8 ttl;
|
|
|
|
|
|
|
|
if (unlikely(!eth_p_mpls(skb->protocol)))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2020-12-03 09:58:21 +00:00
|
|
|
if (!pskb_may_pull(skb, skb_network_offset(skb) + MPLS_HLEN))
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2019-07-07 14:01:57 +00:00
|
|
|
lse = be32_to_cpu(mpls_hdr(skb)->label_stack_entry);
|
|
|
|
ttl = (lse & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT;
|
|
|
|
if (!--ttl)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
lse &= ~MPLS_LS_TTL_MASK;
|
|
|
|
lse |= ttl << MPLS_LS_TTL_SHIFT;
|
|
|
|
|
|
|
|
return skb_mpls_update_lse(skb, cpu_to_be32(lse));
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(skb_mpls_dec_ttl);
|
|
|
|
|
2014-09-17 11:49:49 +00:00
|
|
|
/**
|
|
|
|
* alloc_skb_with_frags - allocate skb with page frags
|
|
|
|
*
|
2014-10-09 03:58:08 +00:00
|
|
|
* @header_len: size of linear part
|
|
|
|
* @data_len: needed length in frags
|
2023-08-01 20:52:51 +00:00
|
|
|
* @order: max page order desired.
|
2014-10-09 03:58:08 +00:00
|
|
|
* @errcode: pointer to error code if any
|
|
|
|
* @gfp_mask: allocation mask
|
2014-09-17 11:49:49 +00:00
|
|
|
*
|
|
|
|
* This can be used to allocate a paged skb, given a maximal order for frags.
|
|
|
|
*/
|
|
|
|
struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
|
|
|
|
unsigned long data_len,
|
2023-08-01 20:52:51 +00:00
|
|
|
int order,
|
2014-09-17 11:49:49 +00:00
|
|
|
int *errcode,
|
|
|
|
gfp_t gfp_mask)
|
|
|
|
{
|
|
|
|
unsigned long chunk;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
struct page *page;
|
2023-08-01 20:52:51 +00:00
|
|
|
int nr_frags = 0;
|
2014-09-17 11:49:49 +00:00
|
|
|
|
|
|
|
*errcode = -EMSGSIZE;
|
2023-08-01 20:52:51 +00:00
|
|
|
if (unlikely(data_len > MAX_SKB_FRAGS * (PAGE_SIZE << order)))
|
2014-09-17 11:49:49 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*errcode = -ENOBUFS;
|
net, skbuff: do not prefer skb allocation fails early
Commit dcda9b04713c ("mm, tree wide: replace __GFP_REPEAT by
__GFP_RETRY_MAYFAIL with more useful semantic") replaced __GFP_REPEAT in
alloc_skb_with_frags() with __GFP_RETRY_MAYFAIL when the allocation may
directly reclaim.
The previous behavior would require reclaim up to 1 << order pages for
skb aligned header_len of order > PAGE_ALLOC_COSTLY_ORDER before failing,
otherwise the allocations in alloc_skb() would loop in the page allocator
looking for memory. __GFP_RETRY_MAYFAIL makes both allocations failable
under memory pressure, including for the HEAD allocation.
This can cause, among many other things, write() to fail with ENOTCONN
during RPC when under memory pressure.
These allocations should succeed as they did previous to dcda9b04713c
even if it requires calling the oom killer and additional looping in the
page allocator to find memory. There is no way to specify the previous
behavior of __GFP_REPEAT, but it's unlikely to be necessary since the
previous behavior only guaranteed that 1 << order pages would be reclaimed
before failing for order > PAGE_ALLOC_COSTLY_ORDER. That reclaim is not
guaranteed to be contiguous memory, so repeating for such large orders is
usually not beneficial.
Removing the setting of __GFP_RETRY_MAYFAIL to restore the previous
behavior, specifically not allowing alloc_skb() to fail for small orders
and oom kill if necessary rather than allowing RPCs to fail.
Fixes: dcda9b04713c ("mm, tree wide: replace __GFP_REPEAT by __GFP_RETRY_MAYFAIL with more useful semantic")
Signed-off-by: David Rientjes <rientjes@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-01-02 21:01:43 +00:00
|
|
|
skb = alloc_skb(header_len, gfp_mask);
|
2014-09-17 11:49:49 +00:00
|
|
|
if (!skb)
|
|
|
|
return NULL;
|
|
|
|
|
2023-08-01 20:52:51 +00:00
|
|
|
while (data_len) {
|
|
|
|
if (nr_frags == MAX_SKB_FRAGS - 1)
|
|
|
|
goto failure;
|
|
|
|
while (order && PAGE_ALIGN(data_len) < (PAGE_SIZE << order))
|
2014-09-17 11:49:49 +00:00
|
|
|
order--;
|
2023-08-01 20:52:51 +00:00
|
|
|
|
|
|
|
if (order) {
|
|
|
|
page = alloc_pages((gfp_mask & ~__GFP_DIRECT_RECLAIM) |
|
|
|
|
__GFP_COMP |
|
|
|
|
__GFP_NOWARN,
|
|
|
|
order);
|
|
|
|
if (!page) {
|
|
|
|
order--;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
page = alloc_page(gfp_mask);
|
|
|
|
if (!page)
|
|
|
|
goto failure;
|
2014-09-17 11:49:49 +00:00
|
|
|
}
|
|
|
|
chunk = min_t(unsigned long, data_len,
|
|
|
|
PAGE_SIZE << order);
|
2023-08-01 20:52:51 +00:00
|
|
|
skb_fill_page_desc(skb, nr_frags, page, 0, chunk);
|
|
|
|
nr_frags++;
|
|
|
|
skb->truesize += (PAGE_SIZE << order);
|
2014-09-17 11:49:49 +00:00
|
|
|
data_len -= chunk;
|
|
|
|
}
|
|
|
|
return skb;
|
|
|
|
|
|
|
|
failure:
|
|
|
|
kfree_skb(skb);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(alloc_skb_with_frags);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
|
|
|
|
/* carve out the first off bytes from skb when off < headlen */
|
|
|
|
static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
|
|
|
|
const int headlen, gfp_t gfp_mask)
|
|
|
|
{
|
|
|
|
int i;
|
2022-10-25 22:39:35 +00:00
|
|
|
unsigned int size = skb_end_offset(skb);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
int new_hlen = headlen - off;
|
|
|
|
u8 *data;
|
|
|
|
|
|
|
|
if (skb_pfmemalloc(skb))
|
|
|
|
gfp_mask |= __GFP_MEMALLOC;
|
2022-10-25 22:39:35 +00:00
|
|
|
|
2023-02-06 17:31:02 +00:00
|
|
|
data = kmalloc_reserve(&size, gfp_mask, NUMA_NO_NODE, NULL);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
if (!data)
|
|
|
|
return -ENOMEM;
|
2022-10-25 22:39:35 +00:00
|
|
|
size = SKB_WITH_OVERHEAD(size);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
|
|
|
|
/* Copy real data, and all frags */
|
|
|
|
skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
|
|
|
|
skb->len -= off;
|
|
|
|
|
|
|
|
memcpy((struct skb_shared_info *)(data + size),
|
|
|
|
skb_shinfo(skb),
|
|
|
|
offsetof(struct skb_shared_info,
|
|
|
|
frags[skb_shinfo(skb)->nr_frags]));
|
|
|
|
if (skb_cloned(skb)) {
|
|
|
|
/* drop the old head gracefully */
|
|
|
|
if (skb_orphan_frags(skb, gfp_mask)) {
|
2023-02-06 17:31:03 +00:00
|
|
|
skb_kfree_head(data, size);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
|
|
|
|
skb_frag_ref(skb, i);
|
|
|
|
if (skb_has_frag_list(skb))
|
|
|
|
skb_clone_fraglist(skb);
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_data(skb, SKB_CONSUMED);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
} else {
|
|
|
|
/* we can reuse existing recount- all we did was
|
|
|
|
* relocate values
|
|
|
|
*/
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_free_head(skb);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
skb->head = data;
|
|
|
|
skb->data = data;
|
|
|
|
skb->head_frag = 0;
|
2022-02-22 03:21:12 +00:00
|
|
|
skb_set_end_offset(skb, size);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
skb_set_tail_pointer(skb, skb_headlen(skb));
|
|
|
|
skb_headers_offset_update(skb, 0);
|
|
|
|
skb->cloned = 0;
|
|
|
|
skb->hdr_len = 0;
|
|
|
|
skb->nohdr = 0;
|
|
|
|
atomic_set(&skb_shinfo(skb)->dataref, 1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pskb_carve(struct sk_buff *skb, const u32 off, gfp_t gfp);
|
|
|
|
|
|
|
|
/* carve out the first eat bytes from skb's frag_list. May recurse into
|
|
|
|
* pskb_carve()
|
|
|
|
*/
|
|
|
|
static int pskb_carve_frag_list(struct sk_buff *skb,
|
|
|
|
struct skb_shared_info *shinfo, int eat,
|
|
|
|
gfp_t gfp_mask)
|
|
|
|
{
|
|
|
|
struct sk_buff *list = shinfo->frag_list;
|
|
|
|
struct sk_buff *clone = NULL;
|
|
|
|
struct sk_buff *insp = NULL;
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (!list) {
|
|
|
|
pr_err("Not enough bytes to eat. Want %d\n", eat);
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
if (list->len <= eat) {
|
|
|
|
/* Eaten as whole. */
|
|
|
|
eat -= list->len;
|
|
|
|
list = list->next;
|
|
|
|
insp = list;
|
|
|
|
} else {
|
|
|
|
/* Eaten partially. */
|
|
|
|
if (skb_shared(list)) {
|
|
|
|
clone = skb_clone(list, gfp_mask);
|
|
|
|
if (!clone)
|
|
|
|
return -ENOMEM;
|
|
|
|
insp = list->next;
|
|
|
|
list = clone;
|
|
|
|
} else {
|
|
|
|
/* This may be pulled without problems. */
|
|
|
|
insp = list;
|
|
|
|
}
|
|
|
|
if (pskb_carve(list, eat, gfp_mask) < 0) {
|
|
|
|
kfree_skb(clone);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (eat);
|
|
|
|
|
|
|
|
/* Free pulled out fragments. */
|
|
|
|
while ((list = shinfo->frag_list) != insp) {
|
|
|
|
shinfo->frag_list = list->next;
|
2022-02-20 15:40:52 +00:00
|
|
|
consume_skb(list);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
}
|
|
|
|
/* And insert new clone at head. */
|
|
|
|
if (clone) {
|
|
|
|
clone->next = list;
|
|
|
|
shinfo->frag_list = clone;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* carve off first len bytes from skb. Split line (off) is in the
|
|
|
|
* non-linear part of skb
|
|
|
|
*/
|
|
|
|
static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
|
|
|
|
int pos, gfp_t gfp_mask)
|
|
|
|
{
|
|
|
|
int i, k = 0;
|
2022-10-25 22:39:35 +00:00
|
|
|
unsigned int size = skb_end_offset(skb);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
u8 *data;
|
|
|
|
const int nfrags = skb_shinfo(skb)->nr_frags;
|
|
|
|
struct skb_shared_info *shinfo;
|
|
|
|
|
|
|
|
if (skb_pfmemalloc(skb))
|
|
|
|
gfp_mask |= __GFP_MEMALLOC;
|
2022-10-25 22:39:35 +00:00
|
|
|
|
2023-02-06 17:31:02 +00:00
|
|
|
data = kmalloc_reserve(&size, gfp_mask, NUMA_NO_NODE, NULL);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
if (!data)
|
|
|
|
return -ENOMEM;
|
2022-10-25 22:39:35 +00:00
|
|
|
size = SKB_WITH_OVERHEAD(size);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
|
|
|
|
memcpy((struct skb_shared_info *)(data + size),
|
2020-08-15 08:48:53 +00:00
|
|
|
skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
if (skb_orphan_frags(skb, gfp_mask)) {
|
2023-02-06 17:31:03 +00:00
|
|
|
skb_kfree_head(data, size);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
shinfo = (struct skb_shared_info *)(data + size);
|
|
|
|
for (i = 0; i < nfrags; i++) {
|
|
|
|
int fsize = skb_frag_size(&skb_shinfo(skb)->frags[i]);
|
|
|
|
|
|
|
|
if (pos + fsize > off) {
|
|
|
|
shinfo->frags[k] = skb_shinfo(skb)->frags[i];
|
|
|
|
|
|
|
|
if (pos < off) {
|
|
|
|
/* Split frag.
|
|
|
|
* We have two variants in this case:
|
|
|
|
* 1. Move all the frag to the second
|
|
|
|
* part, if it is possible. F.e.
|
|
|
|
* this approach is mandatory for TUX,
|
|
|
|
* where splitting is expensive.
|
|
|
|
* 2. Split is accurately. We make this.
|
|
|
|
*/
|
2019-07-30 14:40:33 +00:00
|
|
|
skb_frag_off_add(&shinfo->frags[0], off - pos);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
skb_frag_size_sub(&shinfo->frags[0], off - pos);
|
|
|
|
}
|
|
|
|
skb_frag_ref(skb, i);
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
pos += fsize;
|
|
|
|
}
|
|
|
|
shinfo->nr_frags = k;
|
|
|
|
if (skb_has_frag_list(skb))
|
|
|
|
skb_clone_fraglist(skb);
|
|
|
|
|
2020-08-15 08:46:41 +00:00
|
|
|
/* split line is in frag list */
|
|
|
|
if (k == 0 && pskb_carve_frag_list(skb, shinfo, off - pos, gfp_mask)) {
|
|
|
|
/* skb_frag_unref() is not needed here as shinfo->nr_frags = 0. */
|
|
|
|
if (skb_has_frag_list(skb))
|
|
|
|
kfree_skb_list(skb_shinfo(skb)->frag_list);
|
2023-02-06 17:31:03 +00:00
|
|
|
skb_kfree_head(data, size);
|
2020-08-15 08:46:41 +00:00
|
|
|
return -ENOMEM;
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
}
|
2024-03-29 16:55:06 +00:00
|
|
|
skb_release_data(skb, SKB_CONSUMED);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
|
|
|
|
skb->head = data;
|
|
|
|
skb->head_frag = 0;
|
|
|
|
skb->data = data;
|
2022-02-22 03:21:12 +00:00
|
|
|
skb_set_end_offset(skb, size);
|
skbuff: Add pskb_extract() helper function
A pattern of skb usage seen in modules such as RDS-TCP is to
extract `to_copy' bytes from the received TCP segment, starting
at some offset `off' into a new skb `clone'. This is done in
the ->data_ready callback, where the clone skb is queued up for rx on
the PF_RDS socket, while the parent TCP segment is returned unchanged
back to the TCP engine.
The existing code uses the sequence
clone = skb_clone(..);
pskb_pull(clone, off, ..);
pskb_trim(clone, to_copy, ..);
with the intention of discarding the first `off' bytes. However,
skb_clone() + pskb_pull() implies pksb_expand_head(), which ends
up doing a redundant memcpy of bytes that will then get discarded
in __pskb_pull_tail().
To avoid this inefficiency, this commit adds pskb_extract() that
creates the clone, and memcpy's only the relevant header/frag/frag_list
to the start of `clone'. pskb_trim() is then invoked to trim clone
down to the requested to_copy bytes.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-04-23 01:36:35 +00:00
|
|
|
skb_reset_tail_pointer(skb);
|
|
|
|
skb_headers_offset_update(skb, 0);
|
|
|
|
skb->cloned = 0;
|
|
|
|
skb->hdr_len = 0;
|
|
|
|
skb->nohdr = 0;
|
|
|
|
skb->len -= off;
|
|
|
|
skb->data_len = skb->len;
|
|
|
|
atomic_set(&skb_shinfo(skb)->dataref, 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove len bytes from the beginning of the skb */
|
|
|
|
static int pskb_carve(struct sk_buff *skb, const u32 len, gfp_t gfp)
|
|
|
|
{
|
|
|
|
int headlen = skb_headlen(skb);
|
|
|
|
|
|
|
|
if (len < headlen)
|
|
|
|
return pskb_carve_inside_header(skb, len, headlen, gfp);
|
|
|
|
else
|
|
|
|
return pskb_carve_inside_nonlinear(skb, len, headlen, gfp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Extract to_copy bytes starting at off from skb, and return this in
|
|
|
|
* a new skb
|
|
|
|
*/
|
|
|
|
struct sk_buff *pskb_extract(struct sk_buff *skb, int off,
|
|
|
|
int to_copy, gfp_t gfp)
|
|
|
|
{
|
|
|
|
struct sk_buff *clone = skb_clone(skb, gfp);
|
|
|
|
|
|
|
|
if (!clone)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (pskb_carve(clone, off, gfp) < 0 ||
|
|
|
|
pskb_trim(clone, to_copy)) {
|
|
|
|
kfree_skb(clone);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(pskb_extract);
|
udp: under rx pressure, try to condense skbs
Under UDP flood, many softirq producers try to add packets to
UDP receive queue, and one user thread is burning one cpu trying
to dequeue packets as fast as possible.
Two parts of the per packet cost are :
- copying payload from kernel space to user space,
- freeing memory pieces associated with skb.
If socket is under pressure, softirq handler(s) can try to pull in
skb->head the payload of the packet if it fits.
Meaning the softirq handler(s) can free/reuse the page fragment
immediately, instead of letting udp_recvmsg() do this hundreds of usec
later, possibly from another node.
Additional gains :
- We reduce skb->truesize and thus can store more packets per SO_RCVBUF
- We avoid cache line misses at copyout() time and consume_skb() time,
and avoid one put_page() with potential alien freeing on NUMA hosts.
This comes at the cost of a copy, bounded to available tail room, which
is usually small. (We might have to fix GRO_MAX_HEAD which looks bigger
than necessary)
This patch gave me about 5 % increase in throughput in my tests.
skb_condense() helper could probably used in other contexts.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-12-07 17:19:33 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_condense - try to get rid of fragments/frag_list if possible
|
|
|
|
* @skb: buffer
|
|
|
|
*
|
|
|
|
* Can be used to save memory before skb is added to a busy queue.
|
|
|
|
* If packet has bytes in frags and enough tail room in skb->head,
|
|
|
|
* pull all of them, so that we can free the frags right now and adjust
|
|
|
|
* truesize.
|
|
|
|
* Notes:
|
|
|
|
* We do not reallocate skb->head thus can not fail.
|
|
|
|
* Caller must re-evaluate skb->truesize if needed.
|
|
|
|
*/
|
|
|
|
void skb_condense(struct sk_buff *skb)
|
|
|
|
{
|
2016-12-09 16:02:05 +00:00
|
|
|
if (skb->data_len) {
|
|
|
|
if (skb->data_len > skb->end - skb->tail ||
|
|
|
|
skb_cloned(skb))
|
|
|
|
return;
|
udp: under rx pressure, try to condense skbs
Under UDP flood, many softirq producers try to add packets to
UDP receive queue, and one user thread is burning one cpu trying
to dequeue packets as fast as possible.
Two parts of the per packet cost are :
- copying payload from kernel space to user space,
- freeing memory pieces associated with skb.
If socket is under pressure, softirq handler(s) can try to pull in
skb->head the payload of the packet if it fits.
Meaning the softirq handler(s) can free/reuse the page fragment
immediately, instead of letting udp_recvmsg() do this hundreds of usec
later, possibly from another node.
Additional gains :
- We reduce skb->truesize and thus can store more packets per SO_RCVBUF
- We avoid cache line misses at copyout() time and consume_skb() time,
and avoid one put_page() with potential alien freeing on NUMA hosts.
This comes at the cost of a copy, bounded to available tail room, which
is usually small. (We might have to fix GRO_MAX_HEAD which looks bigger
than necessary)
This patch gave me about 5 % increase in throughput in my tests.
skb_condense() helper could probably used in other contexts.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-12-07 17:19:33 +00:00
|
|
|
|
2016-12-09 16:02:05 +00:00
|
|
|
/* Nice, we can free page frag(s) right now */
|
|
|
|
__pskb_pull_tail(skb, skb->data_len);
|
|
|
|
}
|
|
|
|
/* At this point, skb->truesize might be over estimated,
|
|
|
|
* because skb had a fragment, and fragments do not tell
|
|
|
|
* their truesize.
|
|
|
|
* When we pulled its content into skb->head, fragment
|
|
|
|
* was freed, but __pskb_pull_tail() could not possibly
|
|
|
|
* adjust skb->truesize, not knowing the frag truesize.
|
udp: under rx pressure, try to condense skbs
Under UDP flood, many softirq producers try to add packets to
UDP receive queue, and one user thread is burning one cpu trying
to dequeue packets as fast as possible.
Two parts of the per packet cost are :
- copying payload from kernel space to user space,
- freeing memory pieces associated with skb.
If socket is under pressure, softirq handler(s) can try to pull in
skb->head the payload of the packet if it fits.
Meaning the softirq handler(s) can free/reuse the page fragment
immediately, instead of letting udp_recvmsg() do this hundreds of usec
later, possibly from another node.
Additional gains :
- We reduce skb->truesize and thus can store more packets per SO_RCVBUF
- We avoid cache line misses at copyout() time and consume_skb() time,
and avoid one put_page() with potential alien freeing on NUMA hosts.
This comes at the cost of a copy, bounded to available tail room, which
is usually small. (We might have to fix GRO_MAX_HEAD which looks bigger
than necessary)
This patch gave me about 5 % increase in throughput in my tests.
skb_condense() helper could probably used in other contexts.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2016-12-07 17:19:33 +00:00
|
|
|
*/
|
|
|
|
skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));
|
|
|
|
}
|
2022-05-07 09:06:13 +00:00
|
|
|
EXPORT_SYMBOL(skb_condense);
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
|
|
|
|
#ifdef CONFIG_SKB_EXTENSIONS
|
|
|
|
static void *skb_ext_get_ptr(struct skb_ext *ext, enum skb_ext_id id)
|
|
|
|
{
|
|
|
|
return (void *)ext + (ext->offset[id] * SKB_EXT_ALIGN_VALUE);
|
|
|
|
}
|
|
|
|
|
2020-01-09 15:59:24 +00:00
|
|
|
/**
|
|
|
|
* __skb_ext_alloc - allocate a new skb extensions storage
|
|
|
|
*
|
2020-05-16 08:46:23 +00:00
|
|
|
* @flags: See kmalloc().
|
|
|
|
*
|
2020-01-09 15:59:24 +00:00
|
|
|
* Returns the newly allocated pointer. The pointer can later attached to a
|
|
|
|
* skb via __skb_ext_set().
|
|
|
|
* Note: caller must handle the skb_ext as an opaque data.
|
|
|
|
*/
|
2020-05-16 08:46:23 +00:00
|
|
|
struct skb_ext *__skb_ext_alloc(gfp_t flags)
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
{
|
2020-05-16 08:46:23 +00:00
|
|
|
struct skb_ext *new = kmem_cache_alloc(skbuff_ext_cache, flags);
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
|
|
|
|
if (new) {
|
|
|
|
memset(new->offset, 0, sizeof(new->offset));
|
|
|
|
refcount_set(&new->refcnt, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2018-12-18 16:15:27 +00:00
|
|
|
static struct skb_ext *skb_ext_maybe_cow(struct skb_ext *old,
|
|
|
|
unsigned int old_active)
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
{
|
|
|
|
struct skb_ext *new;
|
|
|
|
|
|
|
|
if (refcount_read(&old->refcnt) == 1)
|
|
|
|
return old;
|
|
|
|
|
|
|
|
new = kmem_cache_alloc(skbuff_ext_cache, GFP_ATOMIC);
|
|
|
|
if (!new)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memcpy(new, old, old->chunks * SKB_EXT_ALIGN_VALUE);
|
|
|
|
refcount_set(&new->refcnt, 1);
|
|
|
|
|
2018-12-18 16:15:27 +00:00
|
|
|
#ifdef CONFIG_XFRM
|
|
|
|
if (old_active & (1 << SKB_EXT_SEC_PATH)) {
|
|
|
|
struct sec_path *sp = skb_ext_get_ptr(old, SKB_EXT_SEC_PATH);
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < sp->len; i++)
|
|
|
|
xfrm_state_hold(sp->xvec[i]);
|
|
|
|
}
|
2024-02-19 09:51:54 +00:00
|
|
|
#endif
|
|
|
|
#ifdef CONFIG_MCTP_FLOWS
|
|
|
|
if (old_active & (1 << SKB_EXT_MCTP)) {
|
|
|
|
struct mctp_flow *flow = skb_ext_get_ptr(old, SKB_EXT_MCTP);
|
|
|
|
|
|
|
|
if (flow->key)
|
|
|
|
refcount_inc(&flow->key->refs);
|
|
|
|
}
|
2018-12-18 16:15:27 +00:00
|
|
|
#endif
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
__skb_ext_put(old);
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2020-01-09 15:59:24 +00:00
|
|
|
/**
|
|
|
|
* __skb_ext_set - attach the specified extension storage to this skb
|
|
|
|
* @skb: buffer
|
|
|
|
* @id: extension id
|
|
|
|
* @ext: extension storage previously allocated via __skb_ext_alloc()
|
|
|
|
*
|
|
|
|
* Existing extensions, if any, are cleared.
|
|
|
|
*
|
|
|
|
* Returns the pointer to the extension.
|
|
|
|
*/
|
|
|
|
void *__skb_ext_set(struct sk_buff *skb, enum skb_ext_id id,
|
|
|
|
struct skb_ext *ext)
|
|
|
|
{
|
|
|
|
unsigned int newlen, newoff = SKB_EXT_CHUNKSIZEOF(*ext);
|
|
|
|
|
|
|
|
skb_ext_put(skb);
|
|
|
|
newlen = newoff + skb_ext_type_len[id];
|
|
|
|
ext->chunks = newlen;
|
|
|
|
ext->offset[id] = newoff;
|
|
|
|
skb->extensions = ext;
|
|
|
|
skb->active_extensions = 1 << id;
|
|
|
|
return skb_ext_get_ptr(ext, id);
|
|
|
|
}
|
|
|
|
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
/**
|
|
|
|
* skb_ext_add - allocate space for given extension, COW if needed
|
|
|
|
* @skb: buffer
|
|
|
|
* @id: extension to allocate space for
|
|
|
|
*
|
|
|
|
* Allocates enough space for the given extension.
|
|
|
|
* If the extension is already present, a pointer to that extension
|
|
|
|
* is returned.
|
|
|
|
*
|
|
|
|
* If the skb was cloned, COW applies and the returned memory can be
|
|
|
|
* modified without changing the extension space of clones buffers.
|
|
|
|
*
|
|
|
|
* Returns pointer to the extension or NULL on allocation failure.
|
|
|
|
*/
|
|
|
|
void *skb_ext_add(struct sk_buff *skb, enum skb_ext_id id)
|
|
|
|
{
|
|
|
|
struct skb_ext *new, *old = NULL;
|
|
|
|
unsigned int newlen, newoff;
|
|
|
|
|
|
|
|
if (skb->active_extensions) {
|
|
|
|
old = skb->extensions;
|
|
|
|
|
2018-12-18 16:15:27 +00:00
|
|
|
new = skb_ext_maybe_cow(old, skb->active_extensions);
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
if (!new)
|
|
|
|
return NULL;
|
|
|
|
|
2018-12-21 18:03:15 +00:00
|
|
|
if (__skb_ext_exist(new, id))
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
goto set_active;
|
|
|
|
|
2018-12-21 18:03:13 +00:00
|
|
|
newoff = new->chunks;
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
} else {
|
|
|
|
newoff = SKB_EXT_CHUNKSIZEOF(*new);
|
|
|
|
|
2020-05-16 08:46:23 +00:00
|
|
|
new = __skb_ext_alloc(GFP_ATOMIC);
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
if (!new)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
newlen = newoff + skb_ext_type_len[id];
|
|
|
|
new->chunks = newlen;
|
|
|
|
new->offset[id] = newoff;
|
|
|
|
set_active:
|
2021-07-28 16:24:01 +00:00
|
|
|
skb->slow_gro = 1;
|
2018-12-21 18:03:15 +00:00
|
|
|
skb->extensions = new;
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
skb->active_extensions |= 1 << id;
|
|
|
|
return skb_ext_get_ptr(new, id);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_ext_add);
|
|
|
|
|
2018-12-18 16:15:27 +00:00
|
|
|
#ifdef CONFIG_XFRM
|
|
|
|
static void skb_ext_put_sp(struct sec_path *sp)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < sp->len; i++)
|
|
|
|
xfrm_state_put(sp->xvec[i]);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-10-29 03:01:44 +00:00
|
|
|
#ifdef CONFIG_MCTP_FLOWS
|
|
|
|
static void skb_ext_put_mctp(struct mctp_flow *flow)
|
|
|
|
{
|
|
|
|
if (flow->key)
|
|
|
|
mctp_key_unref(flow->key);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id)
|
|
|
|
{
|
|
|
|
struct skb_ext *ext = skb->extensions;
|
|
|
|
|
|
|
|
skb->active_extensions &= ~(1 << id);
|
|
|
|
if (skb->active_extensions == 0) {
|
|
|
|
skb->extensions = NULL;
|
|
|
|
__skb_ext_put(ext);
|
2018-12-18 16:15:27 +00:00
|
|
|
#ifdef CONFIG_XFRM
|
|
|
|
} else if (id == SKB_EXT_SEC_PATH &&
|
|
|
|
refcount_read(&ext->refcnt) == 1) {
|
|
|
|
struct sec_path *sp = skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH);
|
|
|
|
|
|
|
|
skb_ext_put_sp(sp);
|
|
|
|
sp->len = 0;
|
|
|
|
#endif
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__skb_ext_del);
|
|
|
|
|
|
|
|
void __skb_ext_put(struct skb_ext *ext)
|
|
|
|
{
|
|
|
|
/* If this is last clone, nothing can increment
|
|
|
|
* it after check passes. Avoids one atomic op.
|
|
|
|
*/
|
|
|
|
if (refcount_read(&ext->refcnt) == 1)
|
|
|
|
goto free_now;
|
|
|
|
|
|
|
|
if (!refcount_dec_and_test(&ext->refcnt))
|
|
|
|
return;
|
|
|
|
free_now:
|
2018-12-18 16:15:27 +00:00
|
|
|
#ifdef CONFIG_XFRM
|
|
|
|
if (__skb_ext_exist(ext, SKB_EXT_SEC_PATH))
|
|
|
|
skb_ext_put_sp(skb_ext_get_ptr(ext, SKB_EXT_SEC_PATH));
|
|
|
|
#endif
|
2021-10-29 03:01:44 +00:00
|
|
|
#ifdef CONFIG_MCTP_FLOWS
|
|
|
|
if (__skb_ext_exist(ext, SKB_EXT_MCTP))
|
|
|
|
skb_ext_put_mctp(skb_ext_get_ptr(ext, SKB_EXT_MCTP));
|
|
|
|
#endif
|
2018-12-18 16:15:27 +00:00
|
|
|
|
sk_buff: add skb extension infrastructure
This adds an optional extension infrastructure, with ispec (xfrm) and
bridge netfilter as first users.
objdiff shows no changes if kernel is built without xfrm and br_netfilter
support.
The third (planned future) user is Multipath TCP which is still
out-of-tree.
MPTCP needs to map logical mptcp sequence numbers to the tcp sequence
numbers used by individual subflows.
This DSS mapping is read/written from tcp option space on receive and
written to tcp option space on transmitted tcp packets that are part of
and MPTCP connection.
Extending skb_shared_info or adding a private data field to skb fclones
doesn't work for incoming skb, so a different DSS propagation method would
be required for the receive side.
mptcp has same requirements as secpath/bridge netfilter:
1. extension memory is released when the sk_buff is free'd.
2. data is shared after cloning an skb (clone inherits extension)
3. adding extension to an skb will COW the extension buffer if needed.
The "MPTCP upstreaming" effort adds SKB_EXT_MPTCP extension to store the
mapping for tx and rx processing.
Two new members are added to sk_buff:
1. 'active_extensions' byte (filling a hole), telling which extensions
are available for this skb.
This has two purposes.
a) avoids the need to initialize the pointer.
b) allows to "delete" an extension by clearing its bit
value in ->active_extensions.
While it would be possible to store the active_extensions byte
in the extension struct instead of sk_buff, there is one problem
with this:
When an extension has to be disabled, we can always clear the
bit in skb->active_extensions. But in case it would be stored in the
extension buffer itself, we might have to COW it first, if
we are dealing with a cloned skb. On kmalloc failure we would
be unable to turn an extension off.
2. extension pointer, located at the end of the sk_buff.
If the active_extensions byte is 0, the pointer is undefined,
it is not initialized on skb allocation.
This adds extra code to skb clone and free paths (to deal with
refcount/free of extension area) but this replaces similar code that
manages skb->nf_bridge and skb->sp structs in the followup patches of
the series.
It is possible to add support for extensions that are not preseved on
clones/copies.
To do this, it would be needed to define a bitmask of all extensions that
need copy/cow semantics, and change __skb_ext_copy() to check
->active_extensions & SKB_EXT_PRESERVE_ON_CLONE, then just set
->active_extensions to 0 on the new clone.
This isn't done here because all extensions that get added here
need the copy/cow semantics.
v2:
Allocate entire extension space using kmem_cache.
Upside is that this allows better tracking of used memory,
downside is that we will allocate more space than strictly needed in
most cases (its unlikely that all extensions are active/needed at same
time for same skb).
The allocated memory (except the small extension header) is not cleared,
so no additonal overhead aside from memory usage.
Avoid atomic_dec_and_test operation on skb_ext_put()
by using similar trick as kfree_skbmem() does with fclone_ref:
If recount is 1, there is no concurrent user and we can free right away.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-12-18 16:15:16 +00:00
|
|
|
kmem_cache_free(skbuff_ext_cache, ext);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(__skb_ext_put);
|
|
|
|
#endif /* CONFIG_SKB_EXTENSIONS */
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
|
2024-04-10 01:28:09 +00:00
|
|
|
static void kfree_skb_napi_cache(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
/* if SKB is a clone, don't handle this case */
|
|
|
|
if (skb->fclone != SKB_FCLONE_UNAVAILABLE) {
|
|
|
|
__kfree_skb(skb);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
local_bh_disable();
|
2024-04-10 01:28:10 +00:00
|
|
|
__napi_kfree_skb(skb, SKB_CONSUMED);
|
2024-04-10 01:28:09 +00:00
|
|
|
local_bh_enable();
|
|
|
|
}
|
|
|
|
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
/**
|
|
|
|
* skb_attempt_defer_free - queue skb for remote freeing
|
|
|
|
* @skb: buffer
|
|
|
|
*
|
|
|
|
* Put @skb in a per-cpu list, using the cpu which
|
|
|
|
* allocated the skb/pages to reduce false sharing
|
|
|
|
* and memory zone spinlock contention.
|
|
|
|
*/
|
|
|
|
void skb_attempt_defer_free(struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
int cpu = skb->alloc_cpu;
|
|
|
|
struct softnet_data *sd;
|
2022-05-16 04:24:55 +00:00
|
|
|
unsigned int defer_max;
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
bool kick;
|
|
|
|
|
2024-04-12 03:07:18 +00:00
|
|
|
if (cpu == raw_smp_processor_id() ||
|
|
|
|
WARN_ON_ONCE(cpu >= nr_cpu_ids) ||
|
|
|
|
!cpu_online(cpu)) {
|
2024-04-10 01:28:09 +00:00
|
|
|
nodefer: kfree_skb_napi_cache(skb);
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-21 09:43:53 +00:00
|
|
|
DEBUG_NET_WARN_ON_ONCE(skb_dst(skb));
|
|
|
|
DEBUG_NET_WARN_ON_ONCE(skb->destructor);
|
|
|
|
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
sd = &per_cpu(softnet_data, cpu);
|
2024-04-29 13:40:22 +00:00
|
|
|
defer_max = READ_ONCE(net_hotdata.sysctl_skb_defer_max);
|
2022-05-16 04:24:55 +00:00
|
|
|
if (READ_ONCE(sd->defer_count) >= defer_max)
|
|
|
|
goto nodefer;
|
|
|
|
|
2023-04-21 09:43:54 +00:00
|
|
|
spin_lock_bh(&sd->defer_lock);
|
2022-05-16 04:24:55 +00:00
|
|
|
/* Send an IPI every time queue reaches half capacity. */
|
|
|
|
kick = sd->defer_count == (defer_max >> 1);
|
2022-05-18 18:55:22 +00:00
|
|
|
/* Paired with the READ_ONCE() few lines above */
|
|
|
|
WRITE_ONCE(sd->defer_count, sd->defer_count + 1);
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
|
2022-05-18 18:55:22 +00:00
|
|
|
skb->next = sd->defer_list;
|
|
|
|
/* Paired with READ_ONCE() in skb_defer_free_flush() */
|
|
|
|
WRITE_ONCE(sd->defer_list, skb);
|
2023-04-21 09:43:54 +00:00
|
|
|
spin_unlock_bh(&sd->defer_lock);
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
|
|
|
|
/* Make sure to trigger NET_RX_SOFTIRQ on the remote CPU
|
|
|
|
* if we are unlucky enough (this seems very unlikely).
|
|
|
|
*/
|
2024-03-25 07:40:30 +00:00
|
|
|
if (unlikely(kick))
|
|
|
|
kick_defer_list_purge(sd, cpu);
|
net: generalize skb freeing deferral to per-cpu lists
Logic added in commit f35f821935d8 ("tcp: defer skb freeing after socket
lock is released") helped bulk TCP flows to move the cost of skbs
frees outside of critical section where socket lock was held.
But for RPC traffic, or hosts with RFS enabled, the solution is far from
being ideal.
For RPC traffic, recvmsg() has to return to user space right after
skb payload has been consumed, meaning that BH handler has no chance
to pick the skb before recvmsg() thread. This issue is more visible
with BIG TCP, as more RPC fit one skb.
For RFS, even if BH handler picks the skbs, they are still picked
from the cpu on which user thread is running.
Ideally, it is better to free the skbs (and associated page frags)
on the cpu that originally allocated them.
This patch removes the per socket anchor (sk->defer_list) and
instead uses a per-cpu list, which will hold more skbs per round.
This new per-cpu list is drained at the end of net_action_rx(),
after incoming packets have been processed, to lower latencies.
In normal conditions, skbs are added to the per-cpu list with
no further action. In the (unlikely) cases where the cpu does not
run net_action_rx() handler fast enough, we use an IPI to raise
NET_RX_SOFTIRQ on the remote cpu.
Also, we do not bother draining the per-cpu list from dev_cpu_dead()
This is because skbs in this list have no requirement on how fast
they should be freed.
Note that we can add in the future a small per-cpu cache
if we see any contention on sd->defer_lock.
Tested on a pair of hosts with 100Gbit NIC, RFS enabled,
and /proc/sys/net/ipv4/tcp_rmem[2] tuned to 16MB to work around
page recycling strategy used by NIC driver (its page pool capacity
being too small compared to number of skbs/pages held in sockets
receive queues)
Note that this tuning was only done to demonstrate worse
conditions for skb freeing for this particular test.
These conditions can happen in more general production workload.
10 runs of one TCP_STREAM flow
Before:
Average throughput: 49685 Mbit.
Kernel profiles on cpu running user thread recvmsg() show high cost for
skb freeing related functions (*)
57.81% [kernel] [k] copy_user_enhanced_fast_string
(*) 12.87% [kernel] [k] skb_release_data
(*) 4.25% [kernel] [k] __free_one_page
(*) 3.57% [kernel] [k] __list_del_entry_valid
1.85% [kernel] [k] __netif_receive_skb_core
1.60% [kernel] [k] __skb_datagram_iter
(*) 1.59% [kernel] [k] free_unref_page_commit
(*) 1.16% [kernel] [k] __slab_free
1.16% [kernel] [k] _copy_to_iter
(*) 1.01% [kernel] [k] kfree
(*) 0.88% [kernel] [k] free_unref_page
0.57% [kernel] [k] ip6_rcv_core
0.55% [kernel] [k] ip6t_do_table
0.54% [kernel] [k] flush_smp_call_function_queue
(*) 0.54% [kernel] [k] free_pcppages_bulk
0.51% [kernel] [k] llist_reverse_order
0.38% [kernel] [k] process_backlog
(*) 0.38% [kernel] [k] free_pcp_prepare
0.37% [kernel] [k] tcp_recvmsg_locked
(*) 0.37% [kernel] [k] __list_add_valid
0.34% [kernel] [k] sock_rfree
0.34% [kernel] [k] _raw_spin_lock_irq
(*) 0.33% [kernel] [k] __page_cache_release
0.33% [kernel] [k] tcp_v6_rcv
(*) 0.33% [kernel] [k] __put_page
(*) 0.29% [kernel] [k] __mod_zone_page_state
0.27% [kernel] [k] _raw_spin_lock
After patch:
Average throughput: 73076 Mbit.
Kernel profiles on cpu running user thread recvmsg() looks better:
81.35% [kernel] [k] copy_user_enhanced_fast_string
1.95% [kernel] [k] _copy_to_iter
1.95% [kernel] [k] __skb_datagram_iter
1.27% [kernel] [k] __netif_receive_skb_core
1.03% [kernel] [k] ip6t_do_table
0.60% [kernel] [k] sock_rfree
0.50% [kernel] [k] tcp_v6_rcv
0.47% [kernel] [k] ip6_rcv_core
0.45% [kernel] [k] read_tsc
0.44% [kernel] [k] _raw_spin_lock_irqsave
0.37% [kernel] [k] _raw_spin_lock
0.37% [kernel] [k] native_irq_return_iret
0.33% [kernel] [k] __inet6_lookup_established
0.31% [kernel] [k] ip6_protocol_deliver_rcu
0.29% [kernel] [k] tcp_rcv_established
0.29% [kernel] [k] llist_reverse_order
v2: kdoc issue (kernel bots)
do not defer if (alloc_cpu == smp_processor_id()) (Paolo)
replace the sk_buff_head with a single-linked list (Jakub)
add a READ_ONCE()/WRITE_ONCE() for the lockless read of sd->defer_list
Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20220422201237.416238-1-eric.dumazet@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2022-04-22 20:12:37 +00:00
|
|
|
}
|
2023-05-22 12:11:12 +00:00
|
|
|
|
|
|
|
static void skb_splice_csum_page(struct sk_buff *skb, struct page *page,
|
|
|
|
size_t offset, size_t len)
|
|
|
|
{
|
|
|
|
const char *kaddr;
|
|
|
|
__wsum csum;
|
|
|
|
|
|
|
|
kaddr = kmap_local_page(page);
|
|
|
|
csum = csum_partial(kaddr + offset, len, 0);
|
|
|
|
kunmap_local(kaddr);
|
|
|
|
skb->csum = csum_block_add(skb->csum, csum, skb->len);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* skb_splice_from_iter - Splice (or copy) pages to skbuff
|
|
|
|
* @skb: The buffer to add pages to
|
|
|
|
* @iter: Iterator representing the pages to be added
|
|
|
|
* @maxsize: Maximum amount of pages to be added
|
|
|
|
* @gfp: Allocation flags
|
|
|
|
*
|
|
|
|
* This is a common helper function for supporting MSG_SPLICE_PAGES. It
|
|
|
|
* extracts pages from an iterator and adds them to the socket buffer if
|
|
|
|
* possible, copying them to fragments if not possible (such as if they're slab
|
|
|
|
* pages).
|
|
|
|
*
|
|
|
|
* Returns the amount of data spliced/copied or -EMSGSIZE if there's
|
|
|
|
* insufficient space in the buffer to transfer anything.
|
|
|
|
*/
|
|
|
|
ssize_t skb_splice_from_iter(struct sk_buff *skb, struct iov_iter *iter,
|
|
|
|
ssize_t maxsize, gfp_t gfp)
|
|
|
|
{
|
2024-04-29 13:40:21 +00:00
|
|
|
size_t frag_limit = READ_ONCE(net_hotdata.sysctl_max_skb_frags);
|
2023-05-22 12:11:12 +00:00
|
|
|
struct page *pages[8], **ppages = pages;
|
|
|
|
ssize_t spliced = 0, ret = 0;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
while (iter->count > 0) {
|
2023-05-26 13:39:15 +00:00
|
|
|
ssize_t space, nr, len;
|
|
|
|
size_t off;
|
2023-05-22 12:11:12 +00:00
|
|
|
|
|
|
|
ret = -EMSGSIZE;
|
|
|
|
space = frag_limit - skb_shinfo(skb)->nr_frags;
|
|
|
|
if (space < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* We might be able to coalesce without increasing nr_frags */
|
|
|
|
nr = clamp_t(size_t, space, 1, ARRAY_SIZE(pages));
|
|
|
|
|
|
|
|
len = iov_iter_extract_pages(iter, &ppages, maxsize, nr, 0, &off);
|
|
|
|
if (len <= 0) {
|
|
|
|
ret = len ?: -EIO;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
do {
|
|
|
|
struct page *page = pages[i++];
|
|
|
|
size_t part = min_t(size_t, PAGE_SIZE - off, len);
|
|
|
|
|
|
|
|
ret = -EIO;
|
|
|
|
if (WARN_ON_ONCE(!sendpage_ok(page)))
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = skb_append_pagefrags(skb, page, off, part,
|
|
|
|
frag_limit);
|
|
|
|
if (ret < 0) {
|
|
|
|
iov_iter_revert(iter, len);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skb->ip_summed == CHECKSUM_NONE)
|
|
|
|
skb_splice_csum_page(skb, page, off, part);
|
|
|
|
|
|
|
|
off = 0;
|
|
|
|
spliced += part;
|
|
|
|
maxsize -= part;
|
|
|
|
len -= part;
|
|
|
|
} while (len > 0);
|
|
|
|
|
|
|
|
if (maxsize <= 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
skb_len_add(skb, spliced);
|
|
|
|
return spliced ?: ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(skb_splice_from_iter);
|
2023-09-25 12:03:06 +00:00
|
|
|
|
|
|
|
static __always_inline
|
|
|
|
size_t memcpy_from_iter_csum(void *iter_from, size_t progress,
|
|
|
|
size_t len, void *to, void *priv2)
|
|
|
|
{
|
|
|
|
__wsum *csum = priv2;
|
2023-09-25 12:03:07 +00:00
|
|
|
__wsum next = csum_partial_copy_nocheck(iter_from, to + progress, len);
|
2023-09-25 12:03:06 +00:00
|
|
|
|
2023-09-25 12:03:07 +00:00
|
|
|
*csum = csum_block_add(*csum, next, progress);
|
2023-09-25 12:03:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __always_inline
|
|
|
|
size_t copy_from_user_iter_csum(void __user *iter_from, size_t progress,
|
|
|
|
size_t len, void *to, void *priv2)
|
|
|
|
{
|
|
|
|
__wsum next, *csum = priv2;
|
|
|
|
|
|
|
|
next = csum_and_copy_from_user(iter_from, to + progress, len);
|
|
|
|
*csum = csum_block_add(*csum, next, progress);
|
|
|
|
return next ? 0 : len;
|
|
|
|
}
|
|
|
|
|
2023-09-25 12:03:08 +00:00
|
|
|
bool csum_and_copy_from_iter_full(void *addr, size_t bytes,
|
|
|
|
__wsum *csum, struct iov_iter *i)
|
2023-09-25 12:03:06 +00:00
|
|
|
{
|
2023-09-25 12:03:08 +00:00
|
|
|
size_t copied;
|
|
|
|
|
2023-09-25 12:03:06 +00:00
|
|
|
if (WARN_ON_ONCE(!i->data_source))
|
2023-09-25 12:03:08 +00:00
|
|
|
return false;
|
|
|
|
copied = iterate_and_advance2(i, bytes, addr, csum,
|
|
|
|
copy_from_user_iter_csum,
|
|
|
|
memcpy_from_iter_csum);
|
|
|
|
if (likely(copied == bytes))
|
|
|
|
return true;
|
|
|
|
iov_iter_revert(i, copied);
|
|
|
|
return false;
|
2023-09-25 12:03:06 +00:00
|
|
|
}
|
2023-09-25 12:03:08 +00:00
|
|
|
EXPORT_SYMBOL(csum_and_copy_from_iter_full);
|